38 ** $QT_END_LICENSE$ |
38 ** $QT_END_LICENSE$ |
39 ** |
39 ** |
40 ****************************************************************************/ |
40 ****************************************************************************/ |
41 |
41 |
42 #include <QtOpenGL/qgl.h> |
42 #include <QtOpenGL/qgl.h> |
|
43 #include <QtOpenGL/qglpixelbuffer.h> |
43 #include "qgl_p.h" |
44 #include "qgl_p.h" |
44 #include "qgl_egl_p.h" |
45 #include "qgl_egl_p.h" |
|
46 #include "qglpixelbuffer_p.h" |
|
47 |
|
48 #ifdef Q_WS_X11 |
|
49 #include <QtGui/private/qpixmap_x11_p.h> |
|
50 #endif |
45 |
51 |
46 QT_BEGIN_NAMESPACE |
52 QT_BEGIN_NAMESPACE |
47 |
53 |
48 // Set device configuration attributes from a QGLFormat instance. |
54 void qt_eglproperties_set_glformat(QEglProperties& eglProperties, const QGLFormat& glFormat) |
49 void qt_egl_set_format(QEglProperties& props, int deviceType, const QGLFormat& f) |
55 { |
50 { |
56 int redSize = glFormat.redBufferSize(); |
51 if (deviceType == QInternal::Pixmap || deviceType == QInternal::Image) |
57 int greenSize = glFormat.greenBufferSize(); |
52 props.setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT); |
58 int blueSize = glFormat.blueBufferSize(); |
53 else if (deviceType == QInternal::Pbuffer) |
59 int alphaSize = glFormat.alphaBufferSize(); |
54 props.setValue(EGL_SURFACE_TYPE, EGL_PBUFFER_BIT); |
60 int depthSize = glFormat.depthBufferSize(); |
55 else |
61 int stencilSize = glFormat.stencilBufferSize(); |
56 props.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT); |
62 int sampleCount = glFormat.samples(); |
57 |
63 |
58 // Set the pixel format to that contained in the QGLFormat |
64 // QGLFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that |
59 // if the system hasn't already chosen a fixed format to |
65 // type has been requested. So we must check QGLFormat's booleans too if size is -1: |
60 // match the pixmap, widget, etc. |
66 if (glFormat.alpha() && alphaSize <= 0) |
61 if (props.value(EGL_RED_SIZE) == 0 || f.redBufferSize() != -1) |
67 alphaSize = 1; |
62 props.setValue(EGL_RED_SIZE, f.redBufferSize() == -1 ? 1 : f.redBufferSize()); |
68 if (glFormat.depth() && depthSize <= 0) |
63 if (props.value(EGL_GREEN_SIZE) == 0 || f.greenBufferSize() != -1) |
69 depthSize = 1; |
64 props.setValue(EGL_GREEN_SIZE, f.greenBufferSize() == -1 ? 1 : f.greenBufferSize()); |
70 if (glFormat.stencil() && stencilSize <= 0) |
65 if (props.value(EGL_BLUE_SIZE) == 0 || f.blueBufferSize() != -1) |
71 stencilSize = 1; |
66 props.setValue(EGL_BLUE_SIZE, f.blueBufferSize() == -1 ? 1 : f.blueBufferSize()); |
72 if (glFormat.sampleBuffers() && sampleCount <= 0) |
67 if (f.alpha()) { |
73 sampleCount = 1; |
68 if (props.value(EGL_ALPHA_SIZE) == 0 || f.alphaBufferSize() != -1) |
74 |
69 props.setValue(EGL_ALPHA_SIZE, f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize()); |
75 // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide |
70 } |
76 // the best performance. The EGL config selection algorithm is a bit stange in this regard: |
71 |
77 // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard |
72 if (f.depth()) |
78 // 32-bit configs completely from the selection. So it then comes to the sorting algorithm. |
73 props.setValue(EGL_DEPTH_SIZE, f.depthBufferSize() == -1 ? 1 : f.depthBufferSize()); |
79 // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort |
74 if (f.stencil()) |
80 // order is special and described as "by larger _total_ number of color bits.". So EGL will |
75 props.setValue(EGL_STENCIL_SIZE, f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize()); |
81 // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on |
76 if (f.sampleBuffers()) { |
82 // to say "If the requested number of bits in attrib_list for a particular component is 0, |
77 props.setValue(EGL_SAMPLE_BUFFERS, 1); |
83 // then the number of bits for that component is not considered". This part of the spec also |
78 props.setValue(EGL_SAMPLES, f.samples() == -1 ? 1 : f.samples()); |
84 // seems to imply that setting the red/green/blue bits to zero means none of the components |
79 } else { |
85 // are considered and EGL disregards the entire sorting rule. It then looks to the next |
80 props.setValue(EGL_SAMPLE_BUFFERS, 0); |
86 // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being |
81 } |
87 // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are |
82 if (deviceType == QInternal::Widget) |
88 // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit, |
83 props.setValue(EGL_LEVEL, f.plane()); |
89 // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that |
|
90 // if the application sets the red/green/blue size to 5/6/5 on the QGLFormat, they will |
|
91 // probably get a 32-bit config, even when there's an RGB565 config avaliable. Oh well. |
|
92 |
|
93 // Now normalize the values so -1 becomes 0 |
|
94 redSize = redSize > 0 ? redSize : 0; |
|
95 greenSize = greenSize > 0 ? greenSize : 0; |
|
96 blueSize = blueSize > 0 ? blueSize : 0; |
|
97 alphaSize = alphaSize > 0 ? alphaSize : 0; |
|
98 depthSize = depthSize > 0 ? depthSize : 0; |
|
99 stencilSize = stencilSize > 0 ? stencilSize : 0; |
|
100 sampleCount = sampleCount > 0 ? sampleCount : 0; |
|
101 |
|
102 eglProperties.setValue(EGL_RED_SIZE, redSize); |
|
103 eglProperties.setValue(EGL_GREEN_SIZE, greenSize); |
|
104 eglProperties.setValue(EGL_BLUE_SIZE, blueSize); |
|
105 eglProperties.setValue(EGL_ALPHA_SIZE, alphaSize); |
|
106 eglProperties.setValue(EGL_DEPTH_SIZE, depthSize); |
|
107 eglProperties.setValue(EGL_STENCIL_SIZE, stencilSize); |
|
108 eglProperties.setValue(EGL_SAMPLES, sampleCount); |
|
109 eglProperties.setValue(EGL_SAMPLE_BUFFERS, sampleCount ? 1 : 0); |
84 } |
110 } |
85 |
111 |
86 // Updates "format" with the parameters of the selected configuration. |
112 // Updates "format" with the parameters of the selected configuration. |
87 void qt_egl_update_format(const QEglContext& context, QGLFormat& format) |
113 void qt_glformat_from_eglconfig(QGLFormat& format, const EGLConfig config) |
88 { |
114 { |
89 EGLint value = 0; |
115 EGLint redSize = 0; |
90 |
116 EGLint greenSize = 0; |
91 if (context.configAttrib(EGL_RED_SIZE, &value)) |
117 EGLint blueSize = 0; |
92 format.setRedBufferSize(value); |
118 EGLint alphaSize = 0; |
93 if (context.configAttrib(EGL_GREEN_SIZE, &value)) |
119 EGLint depthSize = 0; |
94 format.setGreenBufferSize(value); |
120 EGLint stencilSize = 0; |
95 if (context.configAttrib(EGL_BLUE_SIZE, &value)) |
121 EGLint sampleCount = 0; |
96 format.setBlueBufferSize(value); |
122 EGLint level = 0; |
97 if (context.configAttrib(EGL_ALPHA_SIZE, &value)) { |
123 |
98 format.setAlpha(value != 0); |
124 EGLDisplay display = QEgl::display(); |
99 if (format.alpha()) |
125 eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize); |
100 format.setAlphaBufferSize(value); |
126 eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize); |
101 } |
127 eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize); |
102 |
128 eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize); |
103 if (context.configAttrib(EGL_DEPTH_SIZE, &value)) { |
129 eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize); |
104 format.setDepth(value != 0); |
130 eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize); |
105 if (format.depth()) |
131 eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount); |
106 format.setDepthBufferSize(value); |
132 eglGetConfigAttrib(display, config, EGL_LEVEL, &level); |
107 } |
133 |
108 |
134 format.setRedBufferSize(redSize); |
109 if (context.configAttrib(EGL_LEVEL, &value)) |
135 format.setGreenBufferSize(greenSize); |
110 format.setPlane(value); |
136 format.setBlueBufferSize(blueSize); |
111 |
137 format.setAlphaBufferSize(alphaSize); |
112 if (context.configAttrib(EGL_SAMPLE_BUFFERS, &value)) { |
138 format.setDepthBufferSize(depthSize); |
113 format.setSampleBuffers(value != 0); |
139 format.setStencilBufferSize(stencilSize); |
114 if (format.sampleBuffers()) { |
140 format.setSamples(sampleCount); |
115 context.configAttrib(EGL_SAMPLES, &value); |
141 format.setPlane(level + 1); // EGL calls level 0 "normal" whereas Qt calls 1 "normal" |
116 format.setSamples(value); |
142 format.setDirectRendering(true); // All EGL contexts are direct-rendered |
117 } |
143 format.setRgba(true); // EGL doesn't support colour index rendering |
118 } |
144 format.setStereo(false); // EGL doesn't support stereo buffers |
119 |
145 format.setAccumBufferSize(0); // EGL doesn't support accululation buffers |
120 if (context.configAttrib(EGL_STENCIL_SIZE, &value)) { |
|
121 format.setStencil(value != 0); |
|
122 if (format.stencil()) |
|
123 format.setStencilBufferSize(value); |
|
124 } |
|
125 |
146 |
126 // Clear the EGL error state because some of the above may |
147 // Clear the EGL error state because some of the above may |
127 // have errored out because the attribute is not applicable |
148 // have errored out because the attribute is not applicable |
128 // to the surface type. Such errors don't matter. |
149 // to the surface type. Such errors don't matter. |
129 context.clearError(); |
150 eglGetError(); |
130 } |
151 } |
131 |
152 |
132 bool QGLFormat::hasOpenGL() |
153 bool QGLFormat::hasOpenGL() |
133 { |
154 { |
134 return true; |
155 return true; |