|
1 /*------------------------------------------------------------------------ |
|
2 * |
|
3 * EGL 1.3 |
|
4 * ------- |
|
5 * |
|
6 * Copyright (c) 2007 The Khronos Group Inc. |
|
7 * Portions copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
8 * |
|
9 * Permission is hereby granted, free of charge, to any person obtaining a |
|
10 * copy of this software and /or associated documentation files |
|
11 * (the "Materials "), to deal in the Materials without restriction, |
|
12 * including without limitation the rights to use, copy, modify, merge, |
|
13 * publish, distribute, sublicense, and/or sell copies of the Materials, |
|
14 * and to permit persons to whom the Materials are furnished to do so, |
|
15 * subject to the following conditions: |
|
16 * |
|
17 * The above copyright notice and this permission notice shall be included |
|
18 * in all copies or substantial portions of the Materials. |
|
19 * |
|
20 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
23 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
|
24 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
|
25 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR |
|
26 * THE USE OR OTHER DEALINGS IN THE MATERIALS. |
|
27 * |
|
28 *//** |
|
29 * \file |
|
30 * \brief Simple implementation of EGL 1.3 |
|
31 * \note caveats: |
|
32 - always renders into the backbuffer and blits it to window (no single buffered rendering) |
|
33 - no native Windows or Mac OS X pixmap support |
|
34 - no power management events |
|
35 - no support for swap interval |
|
36 * \todo what happens in egl functions when eglTerminate has been called but the context and surface are still in use? |
|
37 * \todo OSDeinitMutex should be called in case getEGL fails. |
|
38 *//*-------------------------------------------------------------------*/ |
|
39 |
|
40 #include "EGL/egl.h" |
|
41 #include "openvg.h" |
|
42 #include "riArray.h" |
|
43 #include "riMath.h" |
|
44 #include "riContext.h" |
|
45 #include "riImage.h" |
|
46 |
|
47 #include "riEGLOS.h" |
|
48 |
|
49 // Temp: A blitter is kept in the egl context for surface copies, but it will |
|
50 // be placed into the EGL to VG interface in the future. |
|
51 #ifndef __SFDYNAMICBLITTER_H |
|
52 # include "sfDynamicBlitter.h" |
|
53 #endif |
|
54 |
|
55 |
|
56 //============================================================================================== |
|
57 |
|
58 namespace OpenVGRI |
|
59 { |
|
60 |
|
61 #if 0 |
|
62 void* OSGetCurrentThreadID(void); |
|
63 void OSAcquireMutex(void); |
|
64 void OSReleaseMutex(void); |
|
65 void OSDeinitMutex(void); |
|
66 |
|
67 EGLDisplay OSGetDisplay(EGLNativeDisplayType display_id); |
|
68 void* OSCreateWindowContext(EGLNativeWindowType window); |
|
69 void OSDestroyWindowContext(void* context); |
|
70 bool OSIsWindow(const void* context); |
|
71 void OSGetWindowSize(const void* context, int& width, int& height); |
|
72 void OSBlitToWindow(void* context, const Drawable* drawable); |
|
73 #else |
|
74 |
|
75 |
|
76 #endif |
|
77 |
|
78 /*-------------------------------------------------------------------*//*! |
|
79 * \brief |
|
80 * \param |
|
81 * \return |
|
82 * \note |
|
83 *//*-------------------------------------------------------------------*/ |
|
84 |
|
85 class RIEGLConfig |
|
86 { |
|
87 public: |
|
88 RIEGLConfig() : m_desc(Color::formatToDescriptor(VG_sRGBA_8888)), m_configID(0) {} |
|
89 ~RIEGLConfig() {} |
|
90 void set(int r, int g, int b, int a, int l, int bpp, int samples, int maskBits, int ID) |
|
91 { |
|
92 Color::Shape shape; |
|
93 m_desc.redBits = r; |
|
94 m_desc.greenBits = g; |
|
95 m_desc.blueBits = b; |
|
96 m_desc.alphaBits = a; |
|
97 m_desc.luminanceBits = l; |
|
98 #if !defined(_WIN32) && 0 |
|
99 m_desc.alphaShift = 0; |
|
100 m_desc.luminanceShift = 0; |
|
101 m_desc.blueShift = b ? a : 0; |
|
102 m_desc.greenShift = g ? a + b : 0; |
|
103 m_desc.redShift = r ? a + b + g : 0; |
|
104 #else |
|
105 m_desc.luminanceShift = 0; |
|
106 m_desc.redShift = 0; |
|
107 m_desc.greenShift = g ? r : 0; |
|
108 m_desc.blueShift = b ? r + g : 0; |
|
109 m_desc.alphaShift = a ? r + g + b : 0; |
|
110 |
|
111 #endif |
|
112 m_desc.internalFormat = l ? (a ? Color::sLA : Color::lLA) : ((r || g || b ) ? Color::sRGBA : Color::lRGBA); |
|
113 |
|
114 m_desc.bitsPerPixel = bpp; |
|
115 m_desc.bytesPerPixel = bpp / 8; |
|
116 |
|
117 { |
|
118 // Determine shape |
|
119 if (m_desc.hasAlpha()) |
|
120 { |
|
121 if (m_desc.redBits > 0) |
|
122 shape = Color::SHAPE_ARGB; |
|
123 else if (m_desc.isLuminance()) |
|
124 shape = Color::SHAPE_AL; |
|
125 else |
|
126 { |
|
127 RI_ASSERT(m_desc.isAlphaOnly()); |
|
128 shape = Color::SHAPE_A; |
|
129 } |
|
130 } else |
|
131 { |
|
132 if (m_desc.redBits > 0) |
|
133 { |
|
134 if (m_desc.bitsPerPixel == 32) |
|
135 shape = Color::SHAPE_XRGB; |
|
136 else |
|
137 { |
|
138 RI_ASSERT(m_desc.bitsPerPixel == 24 || m_desc.bitsPerPixel == 16); |
|
139 shape = Color::SHAPE_RGB; |
|
140 } |
|
141 } else if (m_desc.isLuminance()) |
|
142 { |
|
143 shape = Color::SHAPE_L; |
|
144 } else |
|
145 { |
|
146 RI_ASSERT(false); |
|
147 } |
|
148 } |
|
149 } |
|
150 |
|
151 m_desc.shape = shape; |
|
152 //m_desc.format = Color::descriptorToVGImageFormat(m_desc); |
|
153 m_desc.vgFormat = (VGImageFormat)-1; |
|
154 RI_ASSERT(Color::isValidDescriptor(m_desc)); |
|
155 m_samples = samples; |
|
156 m_maskBits = maskBits; |
|
157 m_configID = ID; |
|
158 m_config = (EGLConfig)ID; |
|
159 } |
|
160 |
|
161 Color::Descriptor configToDescriptor(bool sRGB, bool premultiplied) const |
|
162 { |
|
163 Color::Descriptor desc = m_desc; |
|
164 unsigned int f = m_desc.luminanceBits ? Color::LUMINANCE : 0; |
|
165 f |= sRGB ? Color::NONLINEAR : 0; |
|
166 f |= premultiplied ? Color::PREMULTIPLIED : 0; |
|
167 desc.internalFormat = (Color::InternalFormat)f; |
|
168 return desc; |
|
169 } |
|
170 |
|
171 //EGL RED SIZE bits of Red in the color buffer |
|
172 //EGL GREEN SIZE bits of Green in the color buffer |
|
173 //EGL BLUE SIZE bits of Blue in the color buffer |
|
174 //EGL ALPHA SIZE bits of Alpha in the color buffer |
|
175 //EGL LUMINANCE SIZE bits of Luminance in the color buffer |
|
176 Color::Descriptor m_desc; |
|
177 int m_samples; |
|
178 int m_maskBits; |
|
179 EGLint m_configID; //EGL CONFIG ID unique EGLConfig identifier |
|
180 EGLConfig m_config; |
|
181 //EGL BUFFER SIZE depth of the color buffer (sum of channel bits) |
|
182 //EGL ALPHA MASK SIZE number alpha mask bits (always 8) |
|
183 //EGL BIND TO TEXTURE RGB boolean True if bindable to RGB textures. (always EGL_FALSE) |
|
184 //EGL BIND TO TEXTURE RGBA boolean True if bindable to RGBA textures. (always EGL_FALSE) |
|
185 //EGL COLOR BUFFER TYPE enum color buffer type (EGL_RGB_BUFFER, EGL_LUMINANCE_BUFFER) |
|
186 //EGL CONFIG CAVEAT enum any caveats for the configuration (always EGL_NONE) |
|
187 //EGL DEPTH SIZE integer bits of Z in the depth buffer (always 0) |
|
188 //EGL LEVEL integer frame buffer level (always 0) |
|
189 //EGL MAX PBUFFER WIDTH integer maximum width of pbuffer (always INT_MAX) |
|
190 //EGL MAX PBUFFER HEIGHT integer maximum height of pbuffer (always INT_MAX) |
|
191 //EGL MAX PBUFFER PIXELS integer maximum size of pbuffer (always INT_MAX) |
|
192 //EGL MAX SWAP INTERVAL integer maximum swap interval (always 1) |
|
193 //EGL MIN SWAP INTERVAL integer minimum swap interval (always 1) |
|
194 //EGL NATIVE RENDERABLE boolean EGL TRUE if native rendering APIs can render to surface (always EGL_FALSE) |
|
195 //EGL NATIVE VISUAL ID integer handle of corresponding native visual (always 0) |
|
196 //EGL NATIVE VISUAL TYPE integer native visual type of the associated visual (always EGL_NONE) |
|
197 //EGL RENDERABLE TYPE bitmask which client rendering APIs are supported. (always EGL_OPENVG_BIT) |
|
198 //EGL SAMPLE BUFFERS integer number of multisample buffers (always 0) |
|
199 //EGL SAMPLES integer number of samples per pixel (always 0) |
|
200 //EGL STENCIL SIZE integer bits of Stencil in the stencil buffer (always 0) |
|
201 //EGL SURFACE TYPE bitmask which types of EGL surfaces are supported. (always EGL WINDOW BIT | EGL PIXMAP BIT | EGL PBUFFER BIT) |
|
202 //EGL TRANSPARENT TYPE enum type of transparency supported (always EGL_NONE) |
|
203 //EGL TRANSPARENT RED VALUE integer transparent red value (undefined) |
|
204 //EGL TRANSPARENT GREEN VALUE integer transparent green value (undefined) |
|
205 //EGL TRANSPARENT BLUE VALUE integer transparent blue value (undefined) |
|
206 }; |
|
207 |
|
208 /*-------------------------------------------------------------------*//*! |
|
209 * \brief |
|
210 * \param |
|
211 * \return |
|
212 * \note |
|
213 *//*-------------------------------------------------------------------*/ |
|
214 |
|
215 class RIEGLContext |
|
216 { |
|
217 public: |
|
218 RIEGLContext(OpenVGRI::VGContext* vgctx, const EGLConfig config); |
|
219 ~RIEGLContext(); |
|
220 void addReference() { m_referenceCount++; } |
|
221 int removeReference() { m_referenceCount--; RI_ASSERT(m_referenceCount >= 0); return m_referenceCount; } |
|
222 |
|
223 VGContext* getVGContext() const { return m_vgContext; } |
|
224 EGLConfig getConfig() const { return m_config; } |
|
225 DynamicBlitter& getBlitter() { return m_blitter; } |
|
226 private: |
|
227 RIEGLContext(const RIEGLContext&); |
|
228 RIEGLContext& operator=(const RIEGLContext&); |
|
229 VGContext* m_vgContext; |
|
230 const EGLConfig m_config; |
|
231 int m_referenceCount; |
|
232 DynamicBlitter m_blitter; |
|
233 }; |
|
234 |
|
235 RIEGLContext::RIEGLContext(OpenVGRI::VGContext* vgctx, const EGLConfig config) : |
|
236 m_vgContext(vgctx), |
|
237 m_config(config), |
|
238 m_referenceCount(0) |
|
239 { |
|
240 } |
|
241 RIEGLContext::~RIEGLContext() |
|
242 { |
|
243 RI_ASSERT(m_referenceCount == 0); |
|
244 RI_DELETE(m_vgContext); |
|
245 } |
|
246 |
|
247 /*-------------------------------------------------------------------*//*! |
|
248 * \brief |
|
249 * \param |
|
250 * \return |
|
251 * \note |
|
252 *//*-------------------------------------------------------------------*/ |
|
253 |
|
254 class RIEGLSurface |
|
255 { |
|
256 public: |
|
257 RIEGLSurface(void* OSWindowContext, const EGLConfig config, Drawable* drawable, bool largestPbuffer, int renderBuffer); |
|
258 ~RIEGLSurface(); |
|
259 void addReference() { m_referenceCount++; } |
|
260 int removeReference() { m_referenceCount--; RI_ASSERT(m_referenceCount >= 0); return m_referenceCount; } |
|
261 |
|
262 void* getOSWindowContext() const { return m_OSWindowContext; } |
|
263 EGLConfig getConfig() const { return m_config; } |
|
264 Drawable* getDrawable() const { return m_drawable; } |
|
265 bool isLargestPbuffer() const { return m_largestPbuffer; } |
|
266 int getRenderBuffer() const { return m_renderBuffer; } |
|
267 |
|
268 private: |
|
269 RIEGLSurface(const RIEGLSurface&); |
|
270 RIEGLSurface& operator=(const RIEGLSurface&); |
|
271 void* m_OSWindowContext; |
|
272 const EGLConfig m_config; |
|
273 Drawable* m_drawable; |
|
274 bool m_largestPbuffer; |
|
275 int m_renderBuffer; //EGL_BACK_BUFFER or EGL_SINGLE_BUFFER |
|
276 int m_referenceCount; |
|
277 }; |
|
278 |
|
279 RIEGLSurface::RIEGLSurface(void* OSWindowContext, const EGLConfig config, Drawable* drawable, bool largestPbuffer, int renderBuffer) : |
|
280 m_OSWindowContext(OSWindowContext), |
|
281 m_config(config), |
|
282 m_drawable(drawable), |
|
283 m_largestPbuffer(largestPbuffer), |
|
284 m_renderBuffer(renderBuffer), |
|
285 m_referenceCount(0) |
|
286 { |
|
287 RI_ASSERT(m_renderBuffer == EGL_BACK_BUFFER); //only back buffer rendering is supported |
|
288 m_drawable->addReference(); |
|
289 } |
|
290 |
|
291 RIEGLSurface::~RIEGLSurface() |
|
292 { |
|
293 RI_ASSERT(m_referenceCount == 0); |
|
294 OSDestroyWindowContext((OSWindowContext*)m_OSWindowContext); |
|
295 if(m_drawable) |
|
296 { |
|
297 if(!m_drawable->removeReference()) |
|
298 RI_DELETE(m_drawable); |
|
299 } |
|
300 } |
|
301 |
|
302 /*-------------------------------------------------------------------*//*! |
|
303 * \brief |
|
304 * \param |
|
305 * \return |
|
306 * \note |
|
307 *//*-------------------------------------------------------------------*/ |
|
308 |
|
309 #define EGL_NUMCONFIGS 5 |
|
310 |
|
311 class RIEGLDisplay |
|
312 { |
|
313 public: |
|
314 RIEGLDisplay(EGLDisplay id); |
|
315 ~RIEGLDisplay(); |
|
316 |
|
317 int getNumConfigs() const { return EGL_NUMCONFIGS; } |
|
318 const RIEGLConfig& getConfig(int i) const { RI_ASSERT(i >= 0 && i < EGL_NUMCONFIGS); return m_configs[i]; } |
|
319 const RIEGLConfig& getConfig(const EGLConfig config) const { for(int i=0;i<EGL_NUMCONFIGS;i++) { if(m_configs[i].m_config == config) return m_configs[i]; } RI_ASSERT(0); return m_configs[0]; } |
|
320 |
|
321 EGLDisplay getID() const { return m_id; } |
|
322 |
|
323 void addContext(RIEGLContext* ctx) { RI_ASSERT(ctx); m_contexts.push_back(ctx); } //throws bad_alloc |
|
324 void removeContext(RIEGLContext* ctx) { RI_ASSERT(ctx); bool res = m_contexts.remove(ctx); RI_ASSERT(res); RI_UNREF(res); } |
|
325 |
|
326 void addSurface(RIEGLSurface* srf) { RI_ASSERT(srf); m_surfaces.push_back(srf); } //throws bad_alloc |
|
327 void removeSurface(RIEGLSurface* srf) { RI_ASSERT(srf); bool res = m_surfaces.remove(srf); RI_ASSERT(res); RI_UNREF(res); } |
|
328 |
|
329 EGLBoolean contextExists(const EGLContext ctx) const; |
|
330 EGLBoolean surfaceExists(const EGLSurface srf) const; |
|
331 EGLBoolean configExists(const EGLConfig cfg) const; |
|
332 |
|
333 private: |
|
334 RIEGLDisplay(const RIEGLDisplay& t); |
|
335 RIEGLDisplay& operator=(const RIEGLDisplay&t); |
|
336 |
|
337 EGLDisplay m_id; |
|
338 |
|
339 Array<RIEGLContext*> m_contexts; |
|
340 Array<RIEGLSurface*> m_surfaces; |
|
341 |
|
342 RIEGLConfig m_configs[EGL_NUMCONFIGS]; |
|
343 }; |
|
344 |
|
345 RIEGLDisplay::RIEGLDisplay(EGLDisplay id) : |
|
346 m_id(id), |
|
347 m_contexts(), |
|
348 m_surfaces() |
|
349 { |
|
350 |
|
351 //sorted by RGB/LUMINANCE (exact), larger total number of color bits (at least), buffer size (at least), config ID (exact) |
|
352 //NOTE: 16 bit configs need to be sorted on the fly if the request ignores some channels |
|
353 //NOTE: config IDs start from 1 |
|
354 // R B G A L bpp samples maskBits ID |
|
355 int i = 0; |
|
356 m_configs[i].set(8, 8, 8, 8, 0, 32, 1, 8, i+1); i++; //EGL_RGB_BUFFER, buffer size = 32 |
|
357 m_configs[i].set(8, 8, 8, 0, 0, 32, 1, 8, i+1); i++; // RGBX |
|
358 m_configs[i].set(5, 6, 5, 0, 0, 16, 1, 8, i+1); i++; // 565 |
|
359 m_configs[i].set(0, 0, 0, 0, 8, 8, 1, 8, i+1); i++; // L8 |
|
360 m_configs[i].set(0, 0, 0, 8, 0, 8, 1, 8, i+1); i++; // A8 |
|
361 // \note The reference implementation does not support LA16 config, so it is currently |
|
362 // not possible to test it. See if the format fits the specification. |
|
363 //m_configs[i].set(0, 0, 0, 8, 8, 16, 1, 8, i+1); i++; // LA16 |
|
364 #if 0 |
|
365 m_configs[i].set(8, 8, 8, 8, 0, 32, 1, 8, i+1); i++; //EGL_RGB_BUFFER, buffer size = 32 |
|
366 m_configs[i].set(8, 8, 8, 0, 0, 32, 1, 8, i+1); i++; // RGBX |
|
367 m_configs[i].set(8, 8, 8, 0, 0, 32, 1, 8, i+1); i++; //EGL_RGB_BUFFER, buffer size = 24 |
|
368 //m_configs[i].set(5, 5, 5, 1, 0, 16, 1, 4, i+1); i++; //EGL_RGB_BUFFER, buffer size = 16 |
|
369 m_configs[i].set(5, 6, 5, 0, 0, 16, 1, 4, i+1); i++; //EGL_RGB_BUFFER, buffer size = 16 |
|
370 //m_configs[i].set(4, 4, 4, 4, 0, 16, 1, 4, i+1); i++; //EGL_RGB_BUFFER, buffer size = 16 |
|
371 m_configs[i].set(0, 0, 0, 8, 0, 8, 1, 8, i+1); i++; //EGL_RGB_BUFFER, buffer size = 8 |
|
372 m_configs[i].set(0, 0, 0, 4, 0, 4, 1, 4, i+1); i++; //EGL_RGB_BUFFER, buffer size = 8 |
|
373 m_configs[i].set(0, 0, 0, 1, 0, 1, 1, 1, i+1); i++; //EGL_RGB_BUFFER, buffer size = 8 |
|
374 m_configs[i].set(0, 0, 0, 0, 8, 8, 1, 8, i+1); i++; //EGL_LUMINANCE_BUFFER, buffer size = 8 |
|
375 //m_configs[i].set(0, 0, 0, 0, 1, 1, 1, 1, i+1); i++; //EGL_LUMINANCE_BUFFER, buffer size = 1 |
|
376 |
|
377 //configs without mask |
|
378 m_configs[i].set(8, 8, 8, 8, 0, 32, 1, 0, i+1); i++; //EGL_RGB_BUFFER, buffer size = 32 |
|
379 m_configs[i].set(8, 8, 8, 0, 0, 32, 1, 0, i+1); i++; //EGL_RGB_BUFFER, buffer size = 24 |
|
380 //m_configs[i].set(5, 5, 5, 1, 0, 16, 1, 0, i+1); i++; //EGL_RGB_BUFFER, buffer size = 16 |
|
381 m_configs[i].set(5, 6, 5, 0, 0, 16, 1, 0, i+1); i++; //EGL_RGB_BUFFER, buffer size = 16 |
|
382 //m_configs[i].set(4, 4, 4, 4, 0, 16, 1, 0, i+1); i++; //EGL_RGB_BUFFER, buffer size = 16 |
|
383 m_configs[i].set(0, 0, 0, 8, 0, 8, 1, 0, i+1); i++; //EGL_RGB_BUFFER, buffer size = 8 |
|
384 m_configs[i].set(0, 0, 0, 4, 0, 4, 1, 0, i+1); i++; //EGL_RGB_BUFFER, buffer size = 8 |
|
385 m_configs[i].set(0, 0, 0, 1, 0, 1, 1, 0, i+1); i++; //EGL_RGB_BUFFER, buffer size = 8 |
|
386 m_configs[i].set(0, 0, 0, 0, 8, 8, 1, 0, i+1); i++; //EGL_LUMINANCE_BUFFER, buffer size = 8 |
|
387 //m_configs[i].set(0, 0, 0, 0, 1, 1, 1, 0, 20); //EGL_LUMINANCE_BUFFER, buffer size = 1 |
|
388 #endif |
|
389 |
|
390 RI_ASSERT(EGL_NUMCONFIGS == i); |
|
391 |
|
392 /* |
|
393 attrib default criteria order priority |
|
394 -------------------------------------------------------------- |
|
395 EGL_COLOR_BUFFER_TYPE EGL_RGB_BUFFER Exact None 2 |
|
396 EGL_RED_SIZE 0 AtLeast Special 3 |
|
397 EGL_GREEN_SIZE 0 AtLeast Special 3 |
|
398 EGL_BLUE_SIZE 0 AtLeast Special 3 |
|
399 EGL_LUMINANCE_SIZE 0 AtLeast Special 3 |
|
400 EGL_ALPHA_SIZE 0 AtLeast Special 3 |
|
401 EGL_BUFFER_SIZE 0 AtLeast Smaller 4 |
|
402 EGL_ALPHA_MASK_SIZE 0 AtLeast Smaller 9 |
|
403 EGL_CONFIG_ID EGL_DONT_CARE Exact Smaller 11 |
|
404 */ |
|
405 } |
|
406 |
|
407 RIEGLDisplay::~RIEGLDisplay() |
|
408 { |
|
409 //mark everything for deletion, but don't delete the current context and surface |
|
410 for(int i=0;i<m_contexts.size();i++) |
|
411 { |
|
412 if(!m_contexts[i]->removeReference()) |
|
413 RI_DELETE(m_contexts[i]); |
|
414 } |
|
415 m_contexts.clear(); //remove all contexts from the list (makes further references to the current contexts invalid) |
|
416 |
|
417 for(int i=0;i<m_surfaces.size();i++) |
|
418 { |
|
419 if(!m_surfaces[i]->removeReference()) |
|
420 RI_DELETE(m_surfaces[i]); |
|
421 } |
|
422 m_surfaces.clear(); //remove all surfaces from the list (makes further references to the current surfaces invalid) |
|
423 } |
|
424 |
|
425 EGLBoolean RIEGLDisplay::contextExists(const EGLContext ctx) const |
|
426 { |
|
427 for(int i=0;i<m_contexts.size();i++) |
|
428 { |
|
429 if(m_contexts[i] == ctx) |
|
430 return EGL_TRUE; |
|
431 } |
|
432 return EGL_FALSE; |
|
433 } |
|
434 |
|
435 EGLBoolean RIEGLDisplay::surfaceExists(const EGLSurface surf) const |
|
436 { |
|
437 for(int i=0;i<m_surfaces.size();i++) |
|
438 { |
|
439 if(m_surfaces[i] == surf) |
|
440 return EGL_TRUE; |
|
441 } |
|
442 return EGL_FALSE; |
|
443 } |
|
444 |
|
445 EGLBoolean RIEGLDisplay::configExists(const EGLConfig config) const |
|
446 { |
|
447 for(int i=0;i<EGL_NUMCONFIGS;i++) |
|
448 { |
|
449 if(m_configs[i].m_config == config) |
|
450 return EGL_TRUE; |
|
451 } |
|
452 return EGL_FALSE; |
|
453 } |
|
454 |
|
455 /*-------------------------------------------------------------------*//*! |
|
456 * \brief |
|
457 * \param |
|
458 * \return |
|
459 * \note |
|
460 *//*-------------------------------------------------------------------*/ |
|
461 |
|
462 class RIEGLThread |
|
463 { |
|
464 public: |
|
465 RIEGLThread(void* currentThreadID); |
|
466 ~RIEGLThread(); |
|
467 |
|
468 void* getThreadID() const { return m_threadID; } |
|
469 |
|
470 void makeCurrent(RIEGLContext* c, RIEGLSurface* s) { m_context = c; m_surface = s; } |
|
471 RIEGLContext* getCurrentContext() const { return m_context; } |
|
472 RIEGLSurface* getCurrentSurface() const { return m_surface; } |
|
473 |
|
474 void setError(EGLint error) { m_error = error; } |
|
475 EGLint getError() const { return m_error; } |
|
476 |
|
477 void bindAPI(EGLint api) { m_boundAPI = api; } |
|
478 EGLint getBoundAPI() const { return m_boundAPI; } |
|
479 |
|
480 private: |
|
481 RIEGLThread(const RIEGLThread&); |
|
482 RIEGLThread operator=(const RIEGLThread&); |
|
483 |
|
484 RIEGLContext* m_context; |
|
485 RIEGLSurface* m_surface; |
|
486 EGLint m_error; |
|
487 void* m_threadID; |
|
488 EGLint m_boundAPI; |
|
489 }; |
|
490 |
|
491 RIEGLThread::RIEGLThread(void* currentThreadID) : |
|
492 m_context(NULL), |
|
493 m_surface(NULL), |
|
494 m_error(EGL_SUCCESS), |
|
495 m_threadID(currentThreadID), |
|
496 m_boundAPI(EGL_NONE) |
|
497 { |
|
498 } |
|
499 |
|
500 RIEGLThread::~RIEGLThread() |
|
501 { |
|
502 } |
|
503 |
|
504 /*-------------------------------------------------------------------*//*! |
|
505 * \brief |
|
506 * \param |
|
507 * \return |
|
508 * \note |
|
509 *//*-------------------------------------------------------------------*/ |
|
510 |
|
511 class EGL |
|
512 { |
|
513 public: |
|
514 EGL(); |
|
515 ~EGL(); |
|
516 |
|
517 void addReference() { m_referenceCount++; } |
|
518 int removeReference() { m_referenceCount--; RI_ASSERT(m_referenceCount >= 0); return m_referenceCount; } |
|
519 |
|
520 void addDisplay(RIEGLDisplay* display) { RI_ASSERT(display); m_displays.push_back(display); } //throws bad alloc |
|
521 void removeDisplay(RIEGLDisplay* display) { RI_ASSERT(display); bool res = m_displays.remove(display); RI_ASSERT(res); RI_UNREF(res); } |
|
522 RIEGLDisplay* getDisplay(const EGLDisplay displayID) const; |
|
523 EGLDisplay findDisplay(const EGLContext ctx) const; |
|
524 |
|
525 void addCurrentThread(RIEGLThread* thread) { RI_ASSERT(thread); m_currentThreads.push_back(thread); } //throws bad alloc |
|
526 void removeCurrentThread(RIEGLThread* thread) { RI_ASSERT(thread); bool res = m_currentThreads.remove(thread); RI_ASSERT(res); RI_UNREF(res); } |
|
527 RIEGLThread* getCurrentThread() const; |
|
528 |
|
529 RIEGLThread* getThread(); |
|
530 void destroyThread(); |
|
531 |
|
532 bool isInUse(const void* image) const; |
|
533 |
|
534 private: |
|
535 EGL(const EGL&); // Not allowed. |
|
536 const EGL& operator=(const EGL&); // Not allowed. |
|
537 |
|
538 Array<RIEGLThread*> m_threads; //threads that have called EGL |
|
539 Array<RIEGLThread*> m_currentThreads; //threads that have a bound context |
|
540 Array<RIEGLDisplay*> m_displays; |
|
541 |
|
542 int m_referenceCount; |
|
543 }; |
|
544 |
|
545 EGL::EGL() : |
|
546 m_threads(), |
|
547 m_currentThreads(), |
|
548 m_displays(), |
|
549 m_referenceCount(0) |
|
550 { |
|
551 } |
|
552 EGL::~EGL() |
|
553 { |
|
554 for(int i=0;i<m_displays.size();i++) |
|
555 { |
|
556 RI_DELETE(m_displays[i]); |
|
557 } |
|
558 for(int i=0;i<m_threads.size();i++) |
|
559 { |
|
560 RI_DELETE(m_threads[i]); |
|
561 } |
|
562 //currentThreads contain just pointers to threads we just deleted |
|
563 } |
|
564 |
|
565 /*-------------------------------------------------------------------*//*! |
|
566 * \brief |
|
567 * \param |
|
568 * \return |
|
569 * \note |
|
570 *//*-------------------------------------------------------------------*/ |
|
571 |
|
572 static EGL* g_egl = NULL; //never use this directly |
|
573 static EGL* getEGL() |
|
574 { |
|
575 if(!g_egl) |
|
576 { |
|
577 try |
|
578 { |
|
579 g_egl = RI_NEW(EGL, ()); //throws bad_alloc |
|
580 g_egl->addReference(); |
|
581 } |
|
582 catch(std::bad_alloc) |
|
583 { |
|
584 g_egl = NULL; |
|
585 } |
|
586 } |
|
587 return g_egl; |
|
588 } |
|
589 static void releaseEGL() |
|
590 { |
|
591 if(g_egl) |
|
592 { |
|
593 if(!g_egl->removeReference()) |
|
594 { |
|
595 RI_DELETE(g_egl); |
|
596 g_egl = NULL; |
|
597 } |
|
598 } |
|
599 } |
|
600 |
|
601 /*-------------------------------------------------------------------*//*! |
|
602 * \brief Given a display ID, return the corresponding object, or NULL |
|
603 * if the ID hasn't been initialized. |
|
604 * \param |
|
605 * \return |
|
606 * \note if egl has been initialized for this display, the display ID can |
|
607 * be found from egl->m_displays |
|
608 *//*-------------------------------------------------------------------*/ |
|
609 |
|
610 RIEGLDisplay* EGL::getDisplay(EGLDisplay displayID) const |
|
611 { |
|
612 for(int i=0;i<m_displays.size();i++) |
|
613 { |
|
614 if(displayID == m_displays[i]->getID()) |
|
615 return m_displays[i]; |
|
616 } |
|
617 return NULL; //error: the display hasn't been eglInitialized |
|
618 } |
|
619 |
|
620 /*-------------------------------------------------------------------*//*! |
|
621 * \brief return EGLDisplay for the current context |
|
622 * \param |
|
623 * \return |
|
624 * \note |
|
625 *//*-------------------------------------------------------------------*/ |
|
626 |
|
627 EGLDisplay EGL::findDisplay(EGLContext ctx) const |
|
628 { |
|
629 for(int i=0;i<m_displays.size();i++) |
|
630 { |
|
631 if(m_displays[i]->contextExists(ctx)) |
|
632 return m_displays[i]->getID(); |
|
633 } |
|
634 return EGL_NO_DISPLAY; |
|
635 } |
|
636 |
|
637 /*-------------------------------------------------------------------*//*! |
|
638 * \brief return an EGL thread struct for the thread made current, or |
|
639 * NULL if there's no current context. |
|
640 * \param |
|
641 * \return |
|
642 * \note |
|
643 *//*-------------------------------------------------------------------*/ |
|
644 |
|
645 RIEGLThread* EGL::getCurrentThread() const |
|
646 { |
|
647 void* currentThreadID = OSGetCurrentThreadID(); |
|
648 for(int i=0;i<m_currentThreads.size();i++) |
|
649 { |
|
650 if(currentThreadID == m_currentThreads[i]->getThreadID()) |
|
651 return m_currentThreads[i]; |
|
652 } |
|
653 return NULL; //thread is not current |
|
654 } |
|
655 |
|
656 /*-------------------------------------------------------------------*//*! |
|
657 * \brief return an EGL thread struct corresponding to current OS thread. |
|
658 * \param |
|
659 * \return |
|
660 * \note |
|
661 *//*-------------------------------------------------------------------*/ |
|
662 |
|
663 RIEGLThread* EGL::getThread() |
|
664 { |
|
665 void* currentThreadID = OSGetCurrentThreadID(); |
|
666 for(int i=0;i<m_threads.size();i++) |
|
667 { |
|
668 if(currentThreadID == m_threads[i]->getThreadID()) |
|
669 return m_threads[i]; |
|
670 } |
|
671 |
|
672 //EGL doesn't have a struct for the thread yet, add it to EGL's list |
|
673 RIEGLThread* newThread = NULL; |
|
674 try |
|
675 { |
|
676 newThread = RI_NEW(RIEGLThread, (OSGetCurrentThreadID())); //throws bad_alloc |
|
677 m_threads.push_back(newThread); //throws bad_alloc |
|
678 return newThread; |
|
679 } |
|
680 catch(std::bad_alloc) |
|
681 { |
|
682 RI_DELETE(newThread); |
|
683 return NULL; |
|
684 } |
|
685 } |
|
686 |
|
687 /*-------------------------------------------------------------------*//*! |
|
688 * \brief destroy an EGL thread struct |
|
689 * \param |
|
690 * \return |
|
691 * \note |
|
692 *//*-------------------------------------------------------------------*/ |
|
693 |
|
694 void EGL::destroyThread() |
|
695 { |
|
696 void* currentThreadID = OSGetCurrentThreadID(); |
|
697 for(int i=0;i<m_threads.size();i++) |
|
698 { |
|
699 if(currentThreadID == m_threads[i]->getThreadID()) |
|
700 { |
|
701 RIEGLThread* thread = m_threads[i]; |
|
702 bool res = m_threads.remove(thread); |
|
703 RI_ASSERT(res); |
|
704 RI_UNREF(res); |
|
705 RI_DELETE(thread); |
|
706 break; |
|
707 } |
|
708 } |
|
709 } |
|
710 |
|
711 /*-------------------------------------------------------------------*//*! |
|
712 * \brief |
|
713 * \param |
|
714 * \return |
|
715 * \note |
|
716 *//*-------------------------------------------------------------------*/ |
|
717 |
|
718 bool EGL::isInUse(const void* image) const |
|
719 { |
|
720 for(int i=0;i<m_currentThreads.size();i++) |
|
721 { |
|
722 RIEGLSurface* s = m_currentThreads[i]->getCurrentSurface(); |
|
723 if(s && s->getDrawable() && s->getDrawable()->isInUse((Image*)image)) |
|
724 return true; |
|
725 } |
|
726 return false; |
|
727 } |
|
728 |
|
729 /*-------------------------------------------------------------------*//*! |
|
730 * \brief |
|
731 * \param |
|
732 * \return |
|
733 * \note |
|
734 *//*-------------------------------------------------------------------*/ |
|
735 |
|
736 #define EGL_GET_DISPLAY(DISPLAY, RETVAL) \ |
|
737 OSAcquireMutex(); \ |
|
738 EGL* egl = getEGL(); \ |
|
739 if(!egl) \ |
|
740 { \ |
|
741 OSReleaseMutex(); \ |
|
742 return RETVAL; \ |
|
743 } \ |
|
744 RIEGLDisplay* display = egl->getDisplay(DISPLAY); \ |
|
745 |
|
746 #define EGL_GET_EGL(RETVAL) \ |
|
747 OSAcquireMutex(); \ |
|
748 EGL* egl = getEGL(); \ |
|
749 if(!egl) \ |
|
750 { \ |
|
751 OSReleaseMutex(); \ |
|
752 return RETVAL; \ |
|
753 } \ |
|
754 |
|
755 #define EGL_IF_ERROR(COND, ERRORCODE, RETVAL) \ |
|
756 if(COND) { eglSetError(egl, ERRORCODE); OSReleaseMutex(); return RETVAL; } \ |
|
757 |
|
758 #define EGL_RETURN(ERRORCODE, RETVAL) \ |
|
759 { \ |
|
760 eglSetError(egl, ERRORCODE); \ |
|
761 OSReleaseMutex(); \ |
|
762 return RETVAL; \ |
|
763 } |
|
764 |
|
765 // Note: egl error handling model differs from OpenVG. The latest error is stored instead of the oldest one. |
|
766 static void eglSetError(EGL* egl, EGLint error) |
|
767 { |
|
768 RIEGLThread* thread = egl->getThread(); |
|
769 if(thread) |
|
770 thread->setError(error); |
|
771 } |
|
772 |
|
773 /*-------------------------------------------------------------------*//*! |
|
774 * \brief Returns the OpenVG context current to the calling thread. |
|
775 * \param |
|
776 * \return |
|
777 * \note This function is always called from a mutexed API function |
|
778 *//*-------------------------------------------------------------------*/ |
|
779 |
|
780 void* eglvgGetCurrentVGContext(void) |
|
781 { |
|
782 EGL* egl = getEGL(); |
|
783 if(egl) |
|
784 { |
|
785 RIEGLThread* thread = egl->getCurrentThread(); |
|
786 if(thread) |
|
787 { |
|
788 RI_ASSERT(thread->getCurrentContext() && thread->getCurrentSurface()); |
|
789 return thread->getCurrentContext()->getVGContext(); |
|
790 } |
|
791 } |
|
792 return NULL; //not initialized or made current |
|
793 } |
|
794 |
|
795 bool eglvgLockSurface(bool read, bool write) |
|
796 { |
|
797 (void)read; |
|
798 (void)write; |
|
799 return true; |
|
800 } |
|
801 |
|
802 bool eglvgUnlockSurface() |
|
803 { |
|
804 return true; |
|
805 } |
|
806 |
|
807 /*-------------------------------------------------------------------*//*! |
|
808 * \brief Check if the image is current in any of the displays |
|
809 * \param |
|
810 * \return |
|
811 * \note This function is always called from a mutexed API function |
|
812 *//*-------------------------------------------------------------------*/ |
|
813 |
|
814 bool eglvgIsInUse(void* image) |
|
815 { |
|
816 EGL* egl = getEGL(); |
|
817 if(egl) |
|
818 { |
|
819 return egl->isInUse(image); |
|
820 } |
|
821 return false; |
|
822 } |
|
823 |
|
824 //============================================================================================== |
|
825 |
|
826 } //namespace OpenVGRI |
|
827 |
|
828 using namespace OpenVGRI; |
|
829 |
|
830 |
|
831 |
|
832 |
|
833 |
|
834 /*-------------------------------------------------------------------*//*! |
|
835 * \brief |
|
836 * \param |
|
837 * \return |
|
838 * \note |
|
839 *//*-------------------------------------------------------------------*/ |
|
840 |
|
841 EGLint EGLAPIENTRY eglGetError() |
|
842 { |
|
843 OSAcquireMutex(); |
|
844 EGLint ret = EGL_SUCCESS; |
|
845 EGL* egl = getEGL(); |
|
846 if(egl) |
|
847 { |
|
848 RIEGLThread* thread = egl->getThread(); |
|
849 if(thread) |
|
850 ret = thread->getError(); //initialized, return error code |
|
851 } |
|
852 else ret = EGL_NOT_INITIALIZED; |
|
853 OSReleaseMutex(); |
|
854 return ret; |
|
855 } |
|
856 |
|
857 /*-------------------------------------------------------------------*//*! |
|
858 * \brief |
|
859 * \param |
|
860 * \return |
|
861 * \note |
|
862 *//*-------------------------------------------------------------------*/ |
|
863 |
|
864 EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) |
|
865 { |
|
866 return OSGetDisplay(display_id); |
|
867 } |
|
868 |
|
869 /*-------------------------------------------------------------------*//*! |
|
870 * \brief |
|
871 * \param |
|
872 * \return |
|
873 * \note |
|
874 *//*-------------------------------------------------------------------*/ |
|
875 |
|
876 EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) |
|
877 { |
|
878 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
879 EGL_IF_ERROR(display, EGL_SUCCESS, EGL_TRUE); //already initialized |
|
880 |
|
881 //create the current display |
|
882 //if a context and a surface are bound by the time of eglTerminate, they remain bound until eglMakeCurrent is called |
|
883 RIEGLDisplay* newDisplay = NULL; |
|
884 try |
|
885 { |
|
886 newDisplay = RI_NEW(RIEGLDisplay, (dpy)); //throws bad_alloc |
|
887 egl->addDisplay(newDisplay); //throws bad_alloc |
|
888 display = newDisplay; |
|
889 RI_ASSERT(display); |
|
890 } |
|
891 catch(std::bad_alloc) |
|
892 { |
|
893 RI_DELETE(newDisplay); |
|
894 EGL_RETURN(EGL_BAD_ALLOC, EGL_FALSE); |
|
895 } |
|
896 |
|
897 if(major) *major = 1; |
|
898 if(minor) *minor = 2; |
|
899 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
900 } |
|
901 |
|
902 /*-------------------------------------------------------------------*//*! |
|
903 * \brief |
|
904 * \param |
|
905 * \return |
|
906 * \note |
|
907 *//*-------------------------------------------------------------------*/ |
|
908 |
|
909 EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) |
|
910 { |
|
911 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
912 EGL_IF_ERROR(!display, EGL_SUCCESS, EGL_TRUE); |
|
913 egl->removeDisplay(display); |
|
914 RI_DELETE(display); |
|
915 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
916 } |
|
917 |
|
918 /*-------------------------------------------------------------------*//*! |
|
919 * \brief |
|
920 * \param |
|
921 * \return |
|
922 * \note |
|
923 *//*-------------------------------------------------------------------*/ |
|
924 |
|
925 const char* EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) |
|
926 { |
|
927 EGL_GET_DISPLAY(dpy, NULL); |
|
928 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, NULL); |
|
929 |
|
930 static const char apis[] = "OpenVG"; |
|
931 static const char extensions[] = ""; |
|
932 static const char vendor[] = "Khronos Group"; |
|
933 static const char version[] = "1.3"; |
|
934 |
|
935 const char* ret = NULL; |
|
936 switch(name) |
|
937 { |
|
938 case EGL_CLIENT_APIS: |
|
939 ret = apis; |
|
940 break; |
|
941 |
|
942 case EGL_EXTENSIONS: |
|
943 ret = extensions; |
|
944 break; |
|
945 |
|
946 case EGL_VENDOR: |
|
947 ret = vendor; |
|
948 break; |
|
949 |
|
950 case EGL_VERSION: |
|
951 ret = version; |
|
952 break; |
|
953 |
|
954 default: |
|
955 EGL_RETURN(EGL_BAD_PARAMETER, NULL); |
|
956 } |
|
957 EGL_RETURN(EGL_SUCCESS, ret); |
|
958 } |
|
959 |
|
960 /*-------------------------------------------------------------------*//*! |
|
961 * \brief |
|
962 * \param |
|
963 * \return |
|
964 * \note |
|
965 *//*-------------------------------------------------------------------*/ |
|
966 |
|
967 EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) |
|
968 { |
|
969 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
970 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE); |
|
971 EGL_IF_ERROR(!num_config, EGL_BAD_PARAMETER, EGL_FALSE); |
|
972 if(!configs) |
|
973 { |
|
974 *num_config = display->getNumConfigs(); |
|
975 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
976 } |
|
977 *num_config = RI_INT_MIN(config_size, display->getNumConfigs()); |
|
978 for(int i=0;i<*num_config;i++) |
|
979 configs[i] = display->getConfig(i).m_config; |
|
980 |
|
981 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
982 } |
|
983 |
|
984 /*-------------------------------------------------------------------*//*! |
|
985 * \brief |
|
986 * \param |
|
987 * \return |
|
988 * \note |
|
989 *//*-------------------------------------------------------------------*/ |
|
990 |
|
991 static bool smaller(EGLint c, EGLint filter) |
|
992 { |
|
993 return (filter != EGL_DONT_CARE) && (c < filter); |
|
994 } |
|
995 |
|
996 EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) |
|
997 { |
|
998 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
999 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE); |
|
1000 EGL_IF_ERROR(!num_config, EGL_BAD_PARAMETER, EGL_FALSE); |
|
1001 |
|
1002 if(!configs) |
|
1003 { |
|
1004 *num_config = display->getNumConfigs(); |
|
1005 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1006 } |
|
1007 *num_config = 0; |
|
1008 if(!config_size) |
|
1009 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1010 |
|
1011 int bufferSize = 0; |
|
1012 int redSize = 0; |
|
1013 int greenSize = 0; |
|
1014 int blueSize = 0; |
|
1015 int luminanceSize = 0; |
|
1016 int alphaSize = 0; |
|
1017 int alphaMaskSize = 0; |
|
1018 int colorBufferType = EGL_RGB_BUFFER; |
|
1019 int configID = EGL_DONT_CARE; |
|
1020 int sampleBuffers = 0; |
|
1021 int samples = 0; |
|
1022 if(attrib_list) |
|
1023 { |
|
1024 for(int i=0;attrib_list[i] != EGL_NONE;i+=2) |
|
1025 { |
|
1026 switch(attrib_list[i]) |
|
1027 { |
|
1028 case EGL_BUFFER_SIZE: //depth of the color buffer |
|
1029 bufferSize = attrib_list[i+1]; |
|
1030 break; |
|
1031 case EGL_RED_SIZE: //bits of Red in the color buffer |
|
1032 redSize = attrib_list[i+1]; |
|
1033 break; |
|
1034 case EGL_GREEN_SIZE: //bits of Green in the color buffer |
|
1035 greenSize = attrib_list[i+1]; |
|
1036 break; |
|
1037 case EGL_BLUE_SIZE: //bits of Blue in the color buffer |
|
1038 blueSize = attrib_list[i+1]; |
|
1039 break; |
|
1040 case EGL_LUMINANCE_SIZE: //bits of Luminance in the color buffer |
|
1041 luminanceSize = attrib_list[i+1]; |
|
1042 break; |
|
1043 case EGL_ALPHA_SIZE: //bits of Alpha in the color buffer |
|
1044 alphaSize = attrib_list[i+1]; |
|
1045 break; |
|
1046 case EGL_ALPHA_MASK_SIZE: //bits of Alpha in the alpha mask buffer |
|
1047 alphaMaskSize = attrib_list[i+1]; |
|
1048 if(attrib_list[i+1] > 8) |
|
1049 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); //not supported |
|
1050 break; |
|
1051 case EGL_COLOR_BUFFER_TYPE: //enum color buffer type (EGL_RGB_BUFFER, EGL_LUMINANCE_BUFFER) |
|
1052 EGL_IF_ERROR(attrib_list[i+1] != EGL_RGB_BUFFER && attrib_list[i+1] != EGL_LUMINANCE_BUFFER && attrib_list[i+1] != EGL_DONT_CARE, EGL_BAD_ATTRIBUTE, EGL_FALSE); |
|
1053 colorBufferType = attrib_list[i+1]; |
|
1054 break; |
|
1055 case EGL_CONFIG_ID: //unique EGLConfig identifier |
|
1056 configID = attrib_list[i+1]; |
|
1057 break; |
|
1058 |
|
1059 case EGL_SAMPLE_BUFFERS: //integer number of multisample buffers |
|
1060 sampleBuffers = attrib_list[i+1]; |
|
1061 break; |
|
1062 case EGL_SAMPLES: //integer number of samples per pixel |
|
1063 samples = attrib_list[i+1]; |
|
1064 break; |
|
1065 |
|
1066 case EGL_BIND_TO_TEXTURE_RGB: //boolean True if bindable to RGB textures. (always EGL_FALSE) |
|
1067 case EGL_BIND_TO_TEXTURE_RGBA: //boolean True if bindable to RGBA textures. (always EGL_FALSE) |
|
1068 case EGL_DEPTH_SIZE: //integer bits of Z in the depth buffer (always 0) |
|
1069 case EGL_LEVEL: //integer frame buffer level (always 0) |
|
1070 case EGL_NATIVE_RENDERABLE: //boolean EGL TRUE if native rendering APIs can render to surface (always EGL_FALSE) |
|
1071 case EGL_STENCIL_SIZE: //integer bits of Stencil in the stencil buffer (always 0) |
|
1072 if(attrib_list[i+1]) |
|
1073 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); //not supported |
|
1074 break; |
|
1075 |
|
1076 case EGL_CONFIG_CAVEAT: //enum any caveats for the configuration (always EGL_NONE) |
|
1077 case EGL_NATIVE_VISUAL_TYPE: //integer native visual type of the associated visual (always EGL_NONE) |
|
1078 if(attrib_list[i+1] != EGL_NONE) |
|
1079 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); //not supported |
|
1080 break; |
|
1081 |
|
1082 case EGL_MAX_SWAP_INTERVAL: //integer maximum swap interval (always 1) |
|
1083 case EGL_MIN_SWAP_INTERVAL: //integer minimum swap interval (always 1) |
|
1084 if(attrib_list[i+1] != 1) |
|
1085 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); //not supported |
|
1086 break; |
|
1087 |
|
1088 case EGL_RENDERABLE_TYPE: //bitmask which client rendering APIs are supported. (always EGL_OPENVG_BIT) |
|
1089 if(!(attrib_list[i+1] & EGL_OPENVG_BIT)) |
|
1090 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); //not supported |
|
1091 break; |
|
1092 |
|
1093 case EGL_SURFACE_TYPE: //bitmask which types of EGL surfaces are supported. (always EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT | EGL_VG_COLORSPACE_LINEAR_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT) |
|
1094 break; //all types are always supported |
|
1095 |
|
1096 case EGL_TRANSPARENT_TYPE: //enum type of transparency supported (always EGL_NONE) |
|
1097 case EGL_NATIVE_VISUAL_ID: //integer handle of corresponding native visual (always 0) |
|
1098 case EGL_MAX_PBUFFER_WIDTH: //integer maximum width of pbuffer (always INT_MAX) |
|
1099 case EGL_MAX_PBUFFER_HEIGHT: //integer maximum height of pbuffer (always INT_MAX) |
|
1100 case EGL_MAX_PBUFFER_PIXELS: //integer maximum size of pbuffer (always INT_MAX) |
|
1101 case EGL_TRANSPARENT_RED_VALUE: //integer transparent red value (undefined) |
|
1102 case EGL_TRANSPARENT_GREEN_VALUE: //integer transparent green value (undefined) |
|
1103 case EGL_TRANSPARENT_BLUE_VALUE: //integer transparent blue value (undefined) |
|
1104 break; //ignored |
|
1105 |
|
1106 default: |
|
1107 EGL_RETURN(EGL_BAD_ATTRIBUTE, EGL_FALSE); //unknown attribute |
|
1108 } |
|
1109 } |
|
1110 } |
|
1111 |
|
1112 if(configID && configID != EGL_DONT_CARE) |
|
1113 { //if CONFIG_ID is defined, ignore the rest of the attribs |
|
1114 for(int i=0;i<EGL_NUMCONFIGS;i++) |
|
1115 { |
|
1116 if(display->getConfig(i).m_configID == configID) |
|
1117 { |
|
1118 *num_config = 1; |
|
1119 *configs = display->getConfig(i).m_config; |
|
1120 } |
|
1121 } |
|
1122 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1123 } |
|
1124 |
|
1125 //go through all configs, add passed configs to return list |
|
1126 //TODO take alpha mask size into account |
|
1127 EGLConfig found[EGL_NUMCONFIGS]; |
|
1128 int keys[EGL_NUMCONFIGS]; |
|
1129 int numFound = 0; |
|
1130 for(int i=0;i<display->getNumConfigs();i++) |
|
1131 { |
|
1132 const RIEGLConfig& c = display->getConfig(i); |
|
1133 |
|
1134 int configMaskBits = c.m_maskBits; |
|
1135 int colorBits = c.m_desc.redBits + c.m_desc.greenBits + c.m_desc.blueBits; |
|
1136 int luminanceBits = c.m_desc.luminanceBits; |
|
1137 int configBufferSize; |
|
1138 if(colorBits) |
|
1139 { |
|
1140 RI_ASSERT(!luminanceBits); |
|
1141 colorBits += c.m_desc.alphaBits; |
|
1142 configBufferSize = colorBits; |
|
1143 } |
|
1144 else if(luminanceBits) |
|
1145 { |
|
1146 luminanceBits += c.m_desc.alphaBits; |
|
1147 configBufferSize = luminanceBits; |
|
1148 } |
|
1149 else |
|
1150 { //alpha only surface |
|
1151 colorBits = c.m_desc.alphaBits; |
|
1152 luminanceBits = c.m_desc.alphaBits; |
|
1153 configBufferSize = colorBits; |
|
1154 } |
|
1155 |
|
1156 if (smaller(configBufferSize, bufferSize)) |
|
1157 continue; |
|
1158 |
|
1159 int configSampleBuffers = c.m_samples == 1 ? 0 : 1; |
|
1160 if (smaller(configSampleBuffers, sampleBuffers)) |
|
1161 continue; |
|
1162 if (smaller(c.m_samples, samples)) |
|
1163 continue; |
|
1164 |
|
1165 if (smaller(c.m_desc.redBits, redSize) |
|
1166 || smaller(c.m_desc.greenBits, greenSize) |
|
1167 || smaller(c.m_desc.blueBits, blueSize) |
|
1168 || smaller(c.m_desc.alphaBits, alphaSize) ) |
|
1169 continue; |
|
1170 |
|
1171 if (smaller(c.m_desc.luminanceBits, luminanceSize)) |
|
1172 continue; |
|
1173 |
|
1174 if (smaller(configMaskBits, alphaMaskSize)) |
|
1175 continue; |
|
1176 |
|
1177 if ((colorBufferType == EGL_RGB_BUFFER && !colorBits) || |
|
1178 (colorBufferType == EGL_LUMINANCE_BUFFER && !luminanceBits)) |
|
1179 continue; |
|
1180 |
|
1181 // \todo Add the alphaMaskSize into the sort order also! |
|
1182 int sortKey = c.m_configID; //sort from smaller to larger |
|
1183 int sortBits = 0; |
|
1184 if(redSize != 0 && redSize != EGL_DONT_CARE) |
|
1185 sortBits += c.m_desc.redBits; |
|
1186 if(greenSize != 0 && greenSize != EGL_DONT_CARE) |
|
1187 sortBits += c.m_desc.greenBits; |
|
1188 if(blueSize != 0 && blueSize != EGL_DONT_CARE) |
|
1189 sortBits += c.m_desc.blueBits; |
|
1190 if(alphaSize != 0 && alphaSize != EGL_DONT_CARE) |
|
1191 sortBits += c.m_desc.alphaBits; |
|
1192 if(luminanceSize != 0 && luminanceSize != EGL_DONT_CARE) |
|
1193 sortBits += c.m_desc.luminanceBits; |
|
1194 RI_ASSERT(c.m_configID <= EGL_NUMCONFIGS); //if there are more configs, increase the shift value |
|
1195 RI_ASSERT(sortBits <= 32); |
|
1196 sortKey += (32-sortBits) << 4; //sort from larger to smaller |
|
1197 |
|
1198 found[numFound] = c.m_config; |
|
1199 keys[numFound++] = sortKey; |
|
1200 } |
|
1201 if(!numFound) |
|
1202 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1203 |
|
1204 //sort return list into increasing order |
|
1205 for(int e=0;e<numFound-1;e++) |
|
1206 { |
|
1207 for(int f=e+1;f<numFound;f++) |
|
1208 { |
|
1209 if(keys[e] > keys[f]) |
|
1210 { |
|
1211 EGLConfig tmp = found[e]; |
|
1212 found[e] = found[f]; |
|
1213 found[f] = tmp; |
|
1214 RI_INT_SWAP(keys[e], keys[f]); |
|
1215 } |
|
1216 } |
|
1217 } |
|
1218 |
|
1219 //write configs into return array |
|
1220 numFound = RI_INT_MIN(numFound, config_size); |
|
1221 for(int i=0;i<numFound;i++) |
|
1222 { |
|
1223 configs[i] = found[i]; |
|
1224 } |
|
1225 *num_config = numFound; |
|
1226 |
|
1227 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1228 } |
|
1229 |
|
1230 /*-------------------------------------------------------------------*//*! |
|
1231 * \brief |
|
1232 * \param |
|
1233 * \return |
|
1234 * \note |
|
1235 *//*-------------------------------------------------------------------*/ |
|
1236 |
|
1237 EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) |
|
1238 { |
|
1239 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
1240 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE); |
|
1241 EGL_IF_ERROR(!display->configExists(config), EGL_BAD_CONFIG, EGL_FALSE); |
|
1242 const RIEGLConfig& c = display->getConfig(config); |
|
1243 switch(attribute) |
|
1244 { |
|
1245 case EGL_BUFFER_SIZE: |
|
1246 *value = RI_INT_MAX(c.m_desc.redBits + c.m_desc.greenBits + c.m_desc.blueBits + c.m_desc.alphaBits, c.m_desc.luminanceBits + c.m_desc.alphaBits); |
|
1247 break; |
|
1248 |
|
1249 case EGL_RED_SIZE: |
|
1250 *value = c.m_desc.redBits; |
|
1251 break; |
|
1252 |
|
1253 case EGL_GREEN_SIZE: |
|
1254 *value = c.m_desc.greenBits; |
|
1255 break; |
|
1256 |
|
1257 case EGL_BLUE_SIZE: |
|
1258 *value = c.m_desc.blueBits; |
|
1259 break; |
|
1260 |
|
1261 case EGL_LUMINANCE_SIZE: |
|
1262 *value = c.m_desc.luminanceBits; |
|
1263 break; |
|
1264 |
|
1265 case EGL_ALPHA_SIZE: |
|
1266 *value = c.m_desc.alphaBits; |
|
1267 break; |
|
1268 |
|
1269 case EGL_ALPHA_MASK_SIZE: |
|
1270 *value = c.m_maskBits; |
|
1271 break; |
|
1272 |
|
1273 case EGL_BIND_TO_TEXTURE_RGB: |
|
1274 case EGL_BIND_TO_TEXTURE_RGBA: |
|
1275 *value = EGL_FALSE; |
|
1276 break; |
|
1277 |
|
1278 case EGL_COLOR_BUFFER_TYPE: |
|
1279 if(c.m_desc.redBits) |
|
1280 *value = EGL_RGB_BUFFER; |
|
1281 else |
|
1282 *value = EGL_LUMINANCE_BUFFER; |
|
1283 break; |
|
1284 |
|
1285 case EGL_CONFIG_CAVEAT: |
|
1286 *value = EGL_NONE; |
|
1287 break; |
|
1288 |
|
1289 case EGL_CONFIG_ID: |
|
1290 *value = c.m_configID; |
|
1291 break; |
|
1292 |
|
1293 case EGL_DEPTH_SIZE: |
|
1294 *value = 0; |
|
1295 break; |
|
1296 |
|
1297 case EGL_LEVEL: |
|
1298 *value = 0; |
|
1299 break; |
|
1300 |
|
1301 case EGL_MAX_PBUFFER_WIDTH: |
|
1302 case EGL_MAX_PBUFFER_HEIGHT: |
|
1303 *value = 16384; //NOTE arbitrary maximum |
|
1304 break; |
|
1305 |
|
1306 case EGL_MAX_PBUFFER_PIXELS: |
|
1307 *value = 16384*16384; //NOTE arbitrary maximum |
|
1308 break; |
|
1309 |
|
1310 case EGL_MAX_SWAP_INTERVAL: |
|
1311 case EGL_MIN_SWAP_INTERVAL: |
|
1312 *value = 1; |
|
1313 break; |
|
1314 |
|
1315 case EGL_NATIVE_RENDERABLE: |
|
1316 *value = EGL_FALSE; |
|
1317 break; |
|
1318 |
|
1319 case EGL_NATIVE_VISUAL_ID: |
|
1320 *value = 0; |
|
1321 break; |
|
1322 |
|
1323 case EGL_NATIVE_VISUAL_TYPE: |
|
1324 *value = EGL_NONE; |
|
1325 break; |
|
1326 |
|
1327 case EGL_RENDERABLE_TYPE: |
|
1328 *value = EGL_OPENVG_BIT; |
|
1329 break; |
|
1330 |
|
1331 case EGL_SAMPLE_BUFFERS: |
|
1332 *value = c.m_samples > 1 ? 1 : 0; |
|
1333 break; |
|
1334 |
|
1335 case EGL_SAMPLES: |
|
1336 *value = c.m_samples > 1 ? c.m_samples : 0; |
|
1337 break; |
|
1338 |
|
1339 case EGL_STENCIL_SIZE: |
|
1340 *value = 0; |
|
1341 break; |
|
1342 |
|
1343 case EGL_SURFACE_TYPE: |
|
1344 *value = EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT | EGL_VG_COLORSPACE_LINEAR_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT; |
|
1345 break; |
|
1346 |
|
1347 case EGL_TRANSPARENT_TYPE: |
|
1348 *value = EGL_NONE; |
|
1349 break; |
|
1350 |
|
1351 case EGL_TRANSPARENT_RED_VALUE: |
|
1352 case EGL_TRANSPARENT_GREEN_VALUE: |
|
1353 case EGL_TRANSPARENT_BLUE_VALUE: |
|
1354 *value = 0; |
|
1355 break; |
|
1356 |
|
1357 case EGL_CONFORMANT: |
|
1358 *value = EGL_OPENVG_BIT; //TODO return proper value |
|
1359 break; |
|
1360 |
|
1361 default: |
|
1362 EGL_RETURN(EGL_BAD_ATTRIBUTE, EGL_FALSE); |
|
1363 } |
|
1364 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1365 } |
|
1366 |
|
1367 /*-------------------------------------------------------------------*//*! |
|
1368 * \brief |
|
1369 * \param |
|
1370 * \return |
|
1371 * \note |
|
1372 *//*-------------------------------------------------------------------*/ |
|
1373 |
|
1374 EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) |
|
1375 { |
|
1376 EGL_GET_DISPLAY(dpy, EGL_NO_SURFACE); |
|
1377 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_NO_SURFACE); |
|
1378 EGL_IF_ERROR(!display->configExists(config), EGL_BAD_CONFIG, EGL_NO_SURFACE); |
|
1379 |
|
1380 int renderBuffer = EGL_BACK_BUFFER; |
|
1381 int colorSpace = EGL_VG_COLORSPACE_sRGB; |
|
1382 int alphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE; |
|
1383 if(attrib_list) |
|
1384 { |
|
1385 for(int i=0;attrib_list[i] != EGL_NONE;i+=2) |
|
1386 { |
|
1387 switch(attrib_list[i]) |
|
1388 { |
|
1389 case EGL_RENDER_BUFFER: |
|
1390 renderBuffer = attrib_list[i+1]; |
|
1391 break; |
|
1392 |
|
1393 case EGL_VG_COLORSPACE: |
|
1394 colorSpace = attrib_list[i+1]; |
|
1395 break; |
|
1396 |
|
1397 case EGL_VG_ALPHA_FORMAT: |
|
1398 alphaFormat = attrib_list[i+1]; |
|
1399 break; |
|
1400 |
|
1401 default: |
|
1402 EGL_RETURN(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); |
|
1403 } |
|
1404 } |
|
1405 } |
|
1406 //we ignore the renderBuffer parameter since we can only render to double buffered surfaces |
|
1407 |
|
1408 //TODO If the attributes of win do not correspond to config, then an EGL BAD MATCH error is generated. |
|
1409 //TODO If there is already an EGLConfig associated with win (as a result of a previous eglCreateWindowSurface call), then an EGL BAD ALLOC error is generated |
|
1410 |
|
1411 void* wc = NULL; |
|
1412 OpenVGRI::Drawable* d = NULL; |
|
1413 RIEGLSurface* s = NULL; |
|
1414 try |
|
1415 { |
|
1416 wc = OSCreateWindowContext((EGLNativeWindowType)win); |
|
1417 RI_ASSERT(wc); |
|
1418 //TODO what should happen if window width or height is zero? |
|
1419 int windowWidth = 0, windowHeight = 0; |
|
1420 OSGetWindowSize((OSWindowContext*)wc, windowWidth, windowHeight); |
|
1421 bool isWindow = OSIsWindow((const OSWindowContext*)wc); |
|
1422 if(windowWidth <= 0 || windowHeight <= 0 || !isWindow) |
|
1423 { |
|
1424 OSDestroyWindowContext((OSWindowContext*)wc); |
|
1425 EGL_IF_ERROR(!isWindow, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); |
|
1426 EGL_IF_ERROR(windowWidth <= 0 || windowHeight <= 0, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); |
|
1427 } |
|
1428 Color::Descriptor colorDescriptor = display->getConfig(config).configToDescriptor((colorSpace == EGL_VG_COLORSPACE_LINEAR) ? false : true, (alphaFormat == EGL_VG_ALPHA_FORMAT_PRE) ? true : false); |
|
1429 d = RI_NEW(OpenVGRI::Drawable, (colorDescriptor, windowWidth, windowHeight, display->getConfig(config).m_samples, display->getConfig(config).m_maskBits)); //throws bad_alloc |
|
1430 RI_ASSERT(d); |
|
1431 s = RI_NEW(RIEGLSurface,(wc, config, d, false, renderBuffer)); //throws bad_alloc |
|
1432 RI_ASSERT(s); |
|
1433 s->addReference(); |
|
1434 display->addSurface(s); //throws bad_alloc |
|
1435 } |
|
1436 catch(std::bad_alloc) |
|
1437 { |
|
1438 OSDestroyWindowContext((OSWindowContext*)wc); |
|
1439 RI_DELETE(d); |
|
1440 RI_DELETE(s); |
|
1441 EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_SURFACE); |
|
1442 } |
|
1443 EGL_RETURN(EGL_SUCCESS, (EGLSurface)s); |
|
1444 } |
|
1445 |
|
1446 /*-------------------------------------------------------------------*//*! |
|
1447 * \brief |
|
1448 * \param |
|
1449 * \return |
|
1450 * \note |
|
1451 *//*-------------------------------------------------------------------*/ |
|
1452 |
|
1453 EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) |
|
1454 { |
|
1455 EGL_GET_DISPLAY(dpy, EGL_NO_SURFACE); |
|
1456 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_NO_SURFACE); |
|
1457 EGL_IF_ERROR(!display->configExists(config), EGL_BAD_CONFIG, EGL_NO_SURFACE); |
|
1458 |
|
1459 int width = 0, height = 0; |
|
1460 bool largestPbuffer = false; |
|
1461 int colorSpace = EGL_VG_COLORSPACE_sRGB; |
|
1462 int alphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE; |
|
1463 if(attrib_list) |
|
1464 { |
|
1465 for(int i=0;attrib_list[i] != EGL_NONE;i+=2) |
|
1466 { |
|
1467 switch(attrib_list[i]) |
|
1468 { |
|
1469 case EGL_WIDTH: |
|
1470 width = attrib_list[i+1]; |
|
1471 break; |
|
1472 |
|
1473 case EGL_HEIGHT: |
|
1474 height = attrib_list[i+1]; |
|
1475 break; |
|
1476 |
|
1477 case EGL_LARGEST_PBUFFER: |
|
1478 largestPbuffer = attrib_list[i+1] ? true : false; |
|
1479 break; |
|
1480 |
|
1481 case EGL_VG_COLORSPACE: |
|
1482 colorSpace = attrib_list[i+1]; |
|
1483 break; |
|
1484 |
|
1485 case EGL_VG_ALPHA_FORMAT: |
|
1486 alphaFormat = attrib_list[i+1]; |
|
1487 break; |
|
1488 |
|
1489 case EGL_TEXTURE_FORMAT: //config doesn't support OpenGL ES |
|
1490 case EGL_TEXTURE_TARGET: //config doesn't support OpenGL ES |
|
1491 case EGL_MIPMAP_TEXTURE: //config doesn't support OpenGL ES |
|
1492 default: |
|
1493 EGL_RETURN(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); |
|
1494 break; |
|
1495 } |
|
1496 } |
|
1497 } |
|
1498 EGL_IF_ERROR(width <= 0 || height <= 0, EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); |
|
1499 |
|
1500 OpenVGRI::Drawable* d = NULL; |
|
1501 RIEGLSurface* s = NULL; |
|
1502 try |
|
1503 { |
|
1504 d = RI_NEW(OpenVGRI::Drawable, (display->getConfig(config).configToDescriptor((colorSpace == EGL_VG_COLORSPACE_LINEAR) ? false : true, (alphaFormat == EGL_VG_ALPHA_FORMAT_PRE) ? true : false), width, height, display->getConfig(config).m_samples, display->getConfig(config).m_maskBits)); //throws bad_alloc |
|
1505 RI_ASSERT(d); |
|
1506 s = RI_NEW(RIEGLSurface,(NULL, config, d, largestPbuffer, EGL_BACK_BUFFER)); //throws bad_alloc |
|
1507 RI_ASSERT(s); |
|
1508 s->addReference(); |
|
1509 display->addSurface(s); //throws bad_alloc |
|
1510 } |
|
1511 catch(std::bad_alloc) |
|
1512 { |
|
1513 RI_DELETE(d); |
|
1514 RI_DELETE(s); |
|
1515 EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_SURFACE); |
|
1516 } |
|
1517 EGL_RETURN(EGL_SUCCESS, (EGLSurface)s); |
|
1518 } |
|
1519 |
|
1520 /*-------------------------------------------------------------------*//*! |
|
1521 * \brief |
|
1522 * \param |
|
1523 * \return |
|
1524 * \note |
|
1525 *//*-------------------------------------------------------------------*/ |
|
1526 |
|
1527 EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) |
|
1528 { |
|
1529 EGL_GET_DISPLAY(dpy, EGL_NO_SURFACE); |
|
1530 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_NO_SURFACE); |
|
1531 EGL_IF_ERROR(buftype != EGL_OPENVG_IMAGE, EGL_BAD_PARAMETER, EGL_NO_SURFACE); |
|
1532 EGL_IF_ERROR(!buffer, EGL_BAD_PARAMETER, EGL_NO_SURFACE); //TODO should also check if buffer really is a valid VGImage object (needs VG context for that) |
|
1533 Image* image = (Image*)buffer; |
|
1534 EGL_IF_ERROR(image->isInUse(), EGL_BAD_ACCESS, EGL_NO_SURFACE); //buffer is in use by OpenVG |
|
1535 EGL_IF_ERROR(!display->configExists(config), EGL_BAD_CONFIG, EGL_NO_SURFACE); |
|
1536 EGL_IF_ERROR(attrib_list && attrib_list[0] != EGL_NONE, EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); //there are no valid attribs for OpenVG |
|
1537 const Color::Descriptor& bc = ((Image*)buffer)->getDescriptor(); |
|
1538 const Color::Descriptor& cc = display->getConfig(config).m_desc; |
|
1539 EGL_IF_ERROR(bc.redBits != cc.redBits || bc.greenBits != cc.greenBits || bc.blueBits != cc.blueBits || |
|
1540 bc.alphaBits != cc.alphaBits || bc.luminanceBits != cc.luminanceBits, EGL_BAD_MATCH, EGL_NO_SURFACE); |
|
1541 |
|
1542 //TODO If buffer is already bound to another pbuffer, an EGL BAD ACCESS error is generated. |
|
1543 |
|
1544 OpenVGRI::Drawable* d = NULL; |
|
1545 RIEGLSurface* s = NULL; |
|
1546 try |
|
1547 { |
|
1548 d = RI_NEW(OpenVGRI::Drawable, (image, display->getConfig(config).m_maskBits)); |
|
1549 RI_ASSERT(d); |
|
1550 s = RI_NEW(RIEGLSurface,(NULL, config, d, false, EGL_BACK_BUFFER)); //throws bad_alloc |
|
1551 RI_ASSERT(s); |
|
1552 s->addReference(); |
|
1553 display->addSurface(s); //throws bad_alloc |
|
1554 } |
|
1555 catch(std::bad_alloc) |
|
1556 { |
|
1557 RI_DELETE(d); |
|
1558 RI_DELETE(s); |
|
1559 EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_SURFACE); |
|
1560 } |
|
1561 EGL_RETURN(EGL_SUCCESS, (EGLSurface)s); |
|
1562 } |
|
1563 |
|
1564 /*-------------------------------------------------------------------*//*! |
|
1565 * \brief |
|
1566 * \param |
|
1567 * \return |
|
1568 * \note |
|
1569 *//*-------------------------------------------------------------------*/ |
|
1570 |
|
1571 EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) |
|
1572 { |
|
1573 // Seems that this function has not been implemented correctly in the RI: |
|
1574 // cannot assume that EGLNativePixmapType has format, data, etc. |
|
1575 #if 0 |
|
1576 EGL_GET_DISPLAY(dpy, EGL_NO_SURFACE); |
|
1577 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_NO_SURFACE); |
|
1578 EGL_IF_ERROR(!display->configExists(config), EGL_BAD_CONFIG, EGL_NO_SURFACE); |
|
1579 EGL_IF_ERROR(!pixmap || !isValidImageFormat(pixmap->format) || !pixmap->data || pixmap->width <= 0 || pixmap->height <= 0, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); |
|
1580 RI_UNREF(attrib_list); |
|
1581 EGL_IF_ERROR(display->getConfig(config).m_samples != 1, EGL_BAD_MATCH, EGL_NO_SURFACE); |
|
1582 |
|
1583 //TODO If there is already an EGLSurface associated with pixmap (as a result of a previous eglCreatePixmapSurface call), then a EGL BAD ALLOC error is generated. |
|
1584 |
|
1585 Drawable* d = NULL; |
|
1586 RIEGLSurface* s = NULL; |
|
1587 try |
|
1588 { |
|
1589 d = RI_NEW(Drawable, (Color::formatToDescriptor((VGImageFormat)pixmap->format), pixmap->width, pixmap->height, pixmap->stride, (RIuint8*)pixmap->data, display->getConfig(config).m_maskBits)); //throws bad_alloc |
|
1590 RI_ASSERT(d); |
|
1591 s = RI_NEW(RIEGLSurface,(NULL, config, d, false, EGL_BACK_BUFFER)); //throws bad_alloc |
|
1592 RI_ASSERT(s); |
|
1593 s->addReference(); |
|
1594 display->addSurface(s); //throws bad_alloc |
|
1595 } |
|
1596 catch(std::bad_alloc) |
|
1597 { |
|
1598 RI_DELETE(d); |
|
1599 RI_DELETE(s); |
|
1600 EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_SURFACE); |
|
1601 } |
|
1602 EGL_RETURN(EGL_SUCCESS, (EGLSurface)s); |
|
1603 #else |
|
1604 (void)dpy; |
|
1605 (void)config; |
|
1606 (void)pixmap; |
|
1607 (void)attrib_list; |
|
1608 return 0; |
|
1609 #endif |
|
1610 } |
|
1611 |
|
1612 /*-------------------------------------------------------------------*//*! |
|
1613 * \brief |
|
1614 * \param |
|
1615 * \return |
|
1616 * \note |
|
1617 *//*-------------------------------------------------------------------*/ |
|
1618 |
|
1619 EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface) |
|
1620 { |
|
1621 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
1622 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE); |
|
1623 EGL_IF_ERROR(!display->surfaceExists(surface), EGL_BAD_SURFACE, EGL_FALSE); |
|
1624 |
|
1625 display->removeSurface((RIEGLSurface*)surface); |
|
1626 if(!((RIEGLSurface*)surface)->removeReference()) |
|
1627 RI_DELETE((RIEGLSurface*)surface); |
|
1628 |
|
1629 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1630 } |
|
1631 |
|
1632 /*-------------------------------------------------------------------*//*! |
|
1633 * \brief |
|
1634 * \param |
|
1635 * \return |
|
1636 * \note |
|
1637 *//*-------------------------------------------------------------------*/ |
|
1638 |
|
1639 EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) |
|
1640 { |
|
1641 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
1642 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE); |
|
1643 EGL_IF_ERROR(!display->surfaceExists(surface), EGL_BAD_SURFACE, EGL_FALSE); |
|
1644 RI_UNREF(attribute); |
|
1645 RI_UNREF(value); |
|
1646 //do nothing |
|
1647 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1648 } |
|
1649 |
|
1650 /*-------------------------------------------------------------------*//*! |
|
1651 * \brief |
|
1652 * \param |
|
1653 * \return |
|
1654 * \note |
|
1655 *//*-------------------------------------------------------------------*/ |
|
1656 |
|
1657 EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) |
|
1658 { |
|
1659 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
1660 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE); |
|
1661 EGL_IF_ERROR(!display->surfaceExists(surface), EGL_BAD_SURFACE, EGL_FALSE); |
|
1662 //TODO give an error if value is NULL? |
|
1663 |
|
1664 RIEGLSurface* s = (RIEGLSurface*)surface; |
|
1665 switch(attribute) |
|
1666 { |
|
1667 case EGL_VG_ALPHA_FORMAT: |
|
1668 *value = (s->getDrawable()->getDescriptor().isPremultiplied()) ? EGL_VG_ALPHA_FORMAT_PRE : EGL_VG_ALPHA_FORMAT_NONPRE; |
|
1669 break; |
|
1670 |
|
1671 case EGL_VG_COLORSPACE: |
|
1672 *value = (s->getDrawable()->getDescriptor().isNonlinear()) ? EGL_VG_COLORSPACE_sRGB : EGL_VG_COLORSPACE_LINEAR; |
|
1673 break; |
|
1674 |
|
1675 case EGL_CONFIG_ID: |
|
1676 *value = display->getConfig(s->getConfig()).m_configID; |
|
1677 break; |
|
1678 |
|
1679 case EGL_HEIGHT: |
|
1680 *value = s->getDrawable()->getHeight(); |
|
1681 break; |
|
1682 |
|
1683 case EGL_HORIZONTAL_RESOLUTION: |
|
1684 *value = EGL_UNKNOWN; //TODO Horizontal dot pitch |
|
1685 break; |
|
1686 |
|
1687 case EGL_LARGEST_PBUFFER: |
|
1688 if(!s->getOSWindowContext()) |
|
1689 *value = s->isLargestPbuffer() ? EGL_TRUE : EGL_FALSE; |
|
1690 break; |
|
1691 |
|
1692 case EGL_MIPMAP_TEXTURE: |
|
1693 if(!s->getOSWindowContext()) |
|
1694 *value = EGL_FALSE; |
|
1695 break; |
|
1696 |
|
1697 case EGL_MIPMAP_LEVEL: |
|
1698 if(!s->getOSWindowContext()) |
|
1699 *value = 0; |
|
1700 break; |
|
1701 |
|
1702 case EGL_PIXEL_ASPECT_RATIO: |
|
1703 *value = EGL_UNKNOWN; //TODO Display aspect ratio |
|
1704 break; |
|
1705 |
|
1706 case EGL_RENDER_BUFFER: |
|
1707 *value = s->getRenderBuffer(); |
|
1708 break; |
|
1709 |
|
1710 case EGL_SWAP_BEHAVIOR: |
|
1711 *value = EGL_BUFFER_PRESERVED; |
|
1712 break; |
|
1713 |
|
1714 case EGL_TEXTURE_FORMAT: |
|
1715 if(!s->getOSWindowContext()) |
|
1716 *value = EGL_NO_TEXTURE; |
|
1717 break; |
|
1718 |
|
1719 case EGL_TEXTURE_TARGET: |
|
1720 if(!s->getOSWindowContext()) |
|
1721 *value = EGL_NO_TEXTURE; |
|
1722 break; |
|
1723 |
|
1724 case EGL_VERTICAL_RESOLUTION: |
|
1725 *value = EGL_UNKNOWN; //TODO Vertical dot pitch |
|
1726 break; |
|
1727 |
|
1728 case EGL_WIDTH: |
|
1729 *value = s->getDrawable()->getWidth(); |
|
1730 break; |
|
1731 |
|
1732 default: |
|
1733 EGL_RETURN(EGL_BAD_ATTRIBUTE, EGL_FALSE); |
|
1734 } |
|
1735 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1736 } |
|
1737 |
|
1738 /*-------------------------------------------------------------------*//*! |
|
1739 * \brief |
|
1740 * \param |
|
1741 * \return |
|
1742 * \note |
|
1743 *//*-------------------------------------------------------------------*/ |
|
1744 |
|
1745 EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) |
|
1746 { |
|
1747 EGL_GET_DISPLAY(dpy, EGL_NO_CONTEXT); |
|
1748 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_NO_CONTEXT); |
|
1749 EGL_IF_ERROR(!display->configExists(config), EGL_BAD_CONFIG, EGL_NO_CONTEXT); |
|
1750 RI_UNREF(attrib_list); |
|
1751 |
|
1752 RIEGLThread* thread = egl->getThread(); |
|
1753 if(!thread) |
|
1754 EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_CONTEXT); |
|
1755 |
|
1756 //creation of OpenGL ES contexts is not allowed in this implementation |
|
1757 if(thread->getBoundAPI() != EGL_OPENVG_API) |
|
1758 EGL_RETURN(EGL_BAD_MATCH, EGL_NO_CONTEXT); |
|
1759 |
|
1760 OpenVGRI::VGContext* vgctx = NULL; |
|
1761 RIEGLContext* c = NULL; |
|
1762 try |
|
1763 { |
|
1764 vgctx = RI_NEW(OpenVGRI::VGContext, (share_context ? ((RIEGLContext*)share_context)->getVGContext() : NULL)); //throws bad_alloc |
|
1765 c = RI_NEW(RIEGLContext, (vgctx, config)); //throws bad_alloc |
|
1766 c->addReference(); |
|
1767 display->addContext(c); //throws bad_alloc |
|
1768 } |
|
1769 catch(std::bad_alloc) |
|
1770 { |
|
1771 RI_DELETE(vgctx); |
|
1772 RI_DELETE(c); |
|
1773 EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_CONTEXT); |
|
1774 } |
|
1775 |
|
1776 EGL_RETURN(EGL_SUCCESS, (EGLContext)c); |
|
1777 } |
|
1778 |
|
1779 /*-------------------------------------------------------------------*//*! |
|
1780 * \brief |
|
1781 * \param |
|
1782 * \return |
|
1783 * \note |
|
1784 *//*-------------------------------------------------------------------*/ |
|
1785 |
|
1786 EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx) |
|
1787 { |
|
1788 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
1789 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE); |
|
1790 EGL_IF_ERROR(!display->contextExists(ctx), EGL_BAD_CONTEXT, EGL_FALSE); |
|
1791 |
|
1792 RIEGLContext* context = (RIEGLContext*)ctx; |
|
1793 display->removeContext(context); |
|
1794 if(!context->removeReference() ) |
|
1795 RI_DELETE(context); |
|
1796 |
|
1797 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1798 } |
|
1799 |
|
1800 /*-------------------------------------------------------------------*//*! |
|
1801 * \brief |
|
1802 * \param |
|
1803 * \return |
|
1804 * \note |
|
1805 *//*-------------------------------------------------------------------*/ |
|
1806 |
|
1807 EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) |
|
1808 { |
|
1809 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
1810 EGL_IF_ERROR(ctx != EGL_NO_CONTEXT && !display->contextExists(ctx), EGL_BAD_CONTEXT, EGL_FALSE); |
|
1811 EGL_IF_ERROR(draw != EGL_NO_SURFACE && !display->surfaceExists(draw), EGL_BAD_SURFACE, EGL_FALSE); |
|
1812 EGL_IF_ERROR(read != EGL_NO_SURFACE && !display->surfaceExists(read), EGL_BAD_SURFACE, EGL_FALSE); |
|
1813 EGL_IF_ERROR(draw != read, EGL_BAD_MATCH, EGL_FALSE); //TODO what's the proper error code? |
|
1814 EGL_IF_ERROR((draw != EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT) || (draw == EGL_NO_SURFACE && ctx != EGL_NO_CONTEXT), EGL_BAD_MATCH, EGL_FALSE); |
|
1815 |
|
1816 RIEGLSurface* s = NULL; |
|
1817 RIEGLContext* c = NULL; |
|
1818 if(draw != EGL_NO_SURFACE && ctx != EGL_NO_CONTEXT) |
|
1819 { |
|
1820 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE); |
|
1821 |
|
1822 s = (RIEGLSurface*)draw; |
|
1823 c = (RIEGLContext*)ctx; |
|
1824 |
|
1825 //If either draw or read are pbuffers created with eglCreatePbufferFromClientBuffer, and the underlying bound client API buffers |
|
1826 //are in use by the client API that created them, an EGL BAD ACCESS error is generated. |
|
1827 EGL_IF_ERROR(s->getDrawable()->isInUse(), EGL_BAD_ACCESS, EGL_FALSE); |
|
1828 |
|
1829 |
|
1830 //TODO properly check compatibility of surface and context: |
|
1831 //-both have RGB or LUMINANCE configs |
|
1832 //-buffer bit depths match |
|
1833 //-configs support OpenVG |
|
1834 //-both have the same display |
|
1835 EGL_IF_ERROR(s->getConfig() != c->getConfig(), EGL_BAD_MATCH, EGL_FALSE); |
|
1836 //TODO check if context or surfaces are already bound to another thread |
|
1837 |
|
1838 //If a native window underlying either draw or read is no longer valid, an EGL BAD NATIVE WINDOW error is generated. |
|
1839 EGL_IF_ERROR(s->getOSWindowContext() && !OSIsWindow((const OSWindowContext*)s->getOSWindowContext()), EGL_BAD_NATIVE_WINDOW, EGL_FALSE); |
|
1840 |
|
1841 //TODO If the previous context of the calling display has unflushed commands, and the previous surface is no longer valid, an EGL BAD CURRENT SURFACE error is generated. (can this happen?) |
|
1842 //TODO If the ancillary buffers for draw and read cannot be allocated, an EGL BAD ALLOC error is generated. (mask buffer?) |
|
1843 } |
|
1844 |
|
1845 //check if the thread is current |
|
1846 RIEGLThread* thread = egl->getCurrentThread(); |
|
1847 if(thread) |
|
1848 { //thread is current, release the old bindinds and remove the thread from the current thread list |
|
1849 RIEGLContext* pc = thread->getCurrentContext(); |
|
1850 RIEGLSurface* ps = thread->getCurrentSurface(); |
|
1851 if(pc) |
|
1852 { |
|
1853 vgFlush(); |
|
1854 pc->getVGContext()->setDefaultDrawable(NULL); |
|
1855 if(!pc->removeReference()) |
|
1856 RI_DELETE(pc); |
|
1857 } |
|
1858 if(ps) |
|
1859 { |
|
1860 if(!ps->removeReference()) |
|
1861 RI_DELETE(ps); |
|
1862 } |
|
1863 |
|
1864 egl->removeCurrentThread(thread); |
|
1865 } |
|
1866 |
|
1867 if( c && s ) |
|
1868 { |
|
1869 //bind context and surface to the current display |
|
1870 RIEGLThread* newThread = egl->getThread(); |
|
1871 if(!newThread) |
|
1872 EGL_RETURN(EGL_BAD_ALLOC, EGL_FALSE); |
|
1873 newThread->makeCurrent(c, s); |
|
1874 c->getVGContext()->setDefaultDrawable(s->getDrawable()); |
|
1875 |
|
1876 try |
|
1877 { |
|
1878 egl->addCurrentThread(newThread); //throws bad_alloc |
|
1879 } |
|
1880 catch(std::bad_alloc) |
|
1881 { |
|
1882 EGL_RETURN(EGL_BAD_ALLOC, EGL_FALSE); |
|
1883 } |
|
1884 |
|
1885 c->addReference(); |
|
1886 s->addReference(); |
|
1887 } |
|
1888 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1889 } |
|
1890 |
|
1891 /*-------------------------------------------------------------------*//*! |
|
1892 * \brief |
|
1893 * \param |
|
1894 * \return |
|
1895 * \note |
|
1896 *//*-------------------------------------------------------------------*/ |
|
1897 |
|
1898 EGLContext EGLAPIENTRY eglGetCurrentContext() |
|
1899 { |
|
1900 EGL_GET_EGL(EGL_NO_CONTEXT); |
|
1901 EGLContext ret = EGL_NO_CONTEXT; |
|
1902 RIEGLThread* thread = egl->getCurrentThread(); |
|
1903 if(thread && thread->getBoundAPI() == EGL_OPENVG_API) |
|
1904 { |
|
1905 ret = thread->getCurrentContext(); |
|
1906 RI_ASSERT(ret); |
|
1907 } |
|
1908 EGL_RETURN(EGL_SUCCESS, ret); |
|
1909 } |
|
1910 |
|
1911 /*-------------------------------------------------------------------*//*! |
|
1912 * \brief |
|
1913 * \param |
|
1914 * \return |
|
1915 * \note |
|
1916 *//*-------------------------------------------------------------------*/ |
|
1917 |
|
1918 EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) |
|
1919 { |
|
1920 EGL_GET_EGL(EGL_NO_SURFACE); |
|
1921 EGL_IF_ERROR(readdraw != EGL_READ && readdraw != EGL_DRAW, EGL_BAD_PARAMETER, EGL_NO_SURFACE); |
|
1922 EGLContext ret = EGL_NO_SURFACE; |
|
1923 RIEGLThread* thread = egl->getCurrentThread(); |
|
1924 if(thread && thread->getBoundAPI() == EGL_OPENVG_API) |
|
1925 { |
|
1926 ret = thread->getCurrentSurface(); |
|
1927 RI_ASSERT(ret); |
|
1928 } |
|
1929 EGL_RETURN(EGL_SUCCESS, ret); |
|
1930 } |
|
1931 |
|
1932 /*-------------------------------------------------------------------*//*! |
|
1933 * \brief Returns the current display |
|
1934 * \param |
|
1935 * \return |
|
1936 * \note |
|
1937 *//*-------------------------------------------------------------------*/ |
|
1938 |
|
1939 EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) |
|
1940 { |
|
1941 EGL_GET_EGL(EGL_NO_DISPLAY); |
|
1942 |
|
1943 RIEGLThread* thread = egl->getCurrentThread(); |
|
1944 if(!thread || thread->getBoundAPI() != EGL_OPENVG_API) |
|
1945 EGL_RETURN(EGL_SUCCESS, EGL_NO_DISPLAY); |
|
1946 |
|
1947 RIEGLContext* ctx = thread->getCurrentContext(); |
|
1948 RI_ASSERT(ctx); |
|
1949 EGLDisplay ret = egl->findDisplay(ctx); |
|
1950 EGL_RETURN(EGL_SUCCESS, ret); |
|
1951 } |
|
1952 |
|
1953 /*-------------------------------------------------------------------*//*! |
|
1954 * \brief |
|
1955 * \param |
|
1956 * \return |
|
1957 * \note |
|
1958 *//*-------------------------------------------------------------------*/ |
|
1959 |
|
1960 EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value) |
|
1961 { |
|
1962 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
1963 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE); |
|
1964 EGL_IF_ERROR(!display->contextExists(ctx), EGL_BAD_CONTEXT, EGL_FALSE); |
|
1965 EGL_IF_ERROR(attribute != EGL_CONFIG_ID && attribute != EGL_CONTEXT_CLIENT_TYPE, EGL_BAD_ATTRIBUTE, EGL_FALSE); |
|
1966 if(attribute == EGL_CONFIG_ID) |
|
1967 *value = display->getConfig(((RIEGLContext*)ctx)->getConfig()).m_configID; |
|
1968 if(attribute == EGL_CONTEXT_CLIENT_TYPE) |
|
1969 *value = EGL_OPENVG_API; |
|
1970 // \todo [kalle 05/Jul/05] Handling of EGL_RENDER_BUFFER attribute is missing. |
|
1971 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1972 } |
|
1973 |
|
1974 /*-------------------------------------------------------------------*//*! |
|
1975 * \brief |
|
1976 * \param |
|
1977 * \return |
|
1978 * \note |
|
1979 *//*-------------------------------------------------------------------*/ |
|
1980 |
|
1981 EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) |
|
1982 { |
|
1983 EGL_GET_EGL(EGL_FALSE); |
|
1984 EGL_IF_ERROR(api != EGL_OPENVG_API && api != EGL_OPENGL_ES_API, EGL_BAD_PARAMETER, EGL_FALSE); |
|
1985 RIEGLThread* thread = egl->getThread(); |
|
1986 if(thread) |
|
1987 thread->bindAPI(api); |
|
1988 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
1989 } |
|
1990 |
|
1991 /*-------------------------------------------------------------------*//*! |
|
1992 * \brief |
|
1993 * \param |
|
1994 * \return |
|
1995 * \note |
|
1996 *//*-------------------------------------------------------------------*/ |
|
1997 |
|
1998 EGLenum EGLAPIENTRY eglQueryAPI(void) |
|
1999 { |
|
2000 EGL_GET_EGL(EGL_NONE); |
|
2001 RIEGLThread* thread = egl->getThread(); |
|
2002 if(thread) |
|
2003 EGL_RETURN(EGL_SUCCESS, thread->getBoundAPI()); |
|
2004 EGL_RETURN(EGL_SUCCESS, EGL_NONE); |
|
2005 } |
|
2006 |
|
2007 /*-------------------------------------------------------------------*//*! |
|
2008 * \brief |
|
2009 * \param |
|
2010 * \return |
|
2011 * \note |
|
2012 *//*-------------------------------------------------------------------*/ |
|
2013 |
|
2014 EGLBoolean EGLAPIENTRY eglWaitClient() |
|
2015 { |
|
2016 EGL_GET_EGL(EGL_FALSE); |
|
2017 RIEGLThread* thread = egl->getCurrentThread(); |
|
2018 if(thread && thread->getBoundAPI() == EGL_OPENVG_API) |
|
2019 vgFinish(); |
|
2020 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
2021 } |
|
2022 |
|
2023 /*-------------------------------------------------------------------*//*! |
|
2024 * \brief Waits for OpenGL ES |
|
2025 * \param |
|
2026 * \return |
|
2027 * \note |
|
2028 *//*-------------------------------------------------------------------*/ |
|
2029 |
|
2030 EGLBoolean EGLAPIENTRY eglWaitGL(void) |
|
2031 { |
|
2032 return EGL_TRUE; |
|
2033 } |
|
2034 |
|
2035 /*-------------------------------------------------------------------*//*! |
|
2036 * \brief |
|
2037 * \param |
|
2038 * \return |
|
2039 * \note We don't support native rendering |
|
2040 *//*-------------------------------------------------------------------*/ |
|
2041 |
|
2042 EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine) |
|
2043 { |
|
2044 RI_UNREF(engine); |
|
2045 return EGL_TRUE; |
|
2046 } |
|
2047 |
|
2048 /*-------------------------------------------------------------------*//*! |
|
2049 * \brief |
|
2050 * \param |
|
2051 * \return |
|
2052 * \note |
|
2053 *//*-------------------------------------------------------------------*/ |
|
2054 |
|
2055 EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) |
|
2056 { |
|
2057 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
2058 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE); |
|
2059 EGL_IF_ERROR(!display->surfaceExists(surface), EGL_BAD_SURFACE, EGL_FALSE); |
|
2060 |
|
2061 RIEGLSurface* s = (RIEGLSurface*)surface; |
|
2062 |
|
2063 RIEGLThread* currentThread = egl->getCurrentThread(); |
|
2064 EGL_IF_ERROR(!currentThread || currentThread->getCurrentSurface() != s, EGL_BAD_SURFACE, EGL_FALSE); |
|
2065 EGL_IF_ERROR(!OSIsWindow((const OSWindowContext*)s->getOSWindowContext()), EGL_BAD_NATIVE_WINDOW, EGL_FALSE); |
|
2066 |
|
2067 vgFlush(); |
|
2068 |
|
2069 if(!s->getOSWindowContext()) |
|
2070 { //do nothing for other than window surfaces (NOTE: single-buffered window surfaces should return immediately as well) |
|
2071 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
2072 } |
|
2073 |
|
2074 int windowWidth = 0, windowHeight = 0; |
|
2075 OSGetWindowSize((OSWindowContext*)s->getOSWindowContext(), windowWidth, windowHeight); |
|
2076 |
|
2077 if(windowWidth != s->getDrawable()->getWidth() || windowHeight != s->getDrawable()->getHeight()) |
|
2078 { //resize the back buffer |
|
2079 RIEGLContext* c = currentThread->getCurrentContext(); |
|
2080 RI_ASSERT(c); |
|
2081 try |
|
2082 { |
|
2083 s->getDrawable()->resize(c->getVGContext(), windowWidth, windowHeight); //throws bad_alloc |
|
2084 } |
|
2085 catch(std::bad_alloc) |
|
2086 { |
|
2087 c->getVGContext()->setDefaultDrawable(NULL); |
|
2088 EGL_RETURN(EGL_BAD_ALLOC, EGL_FALSE); |
|
2089 } |
|
2090 } |
|
2091 |
|
2092 OSBlitToWindow((OSWindowContext*)s->getOSWindowContext(), s->getDrawable()); |
|
2093 |
|
2094 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
2095 } |
|
2096 |
|
2097 /*-------------------------------------------------------------------*//*! |
|
2098 * \brief |
|
2099 * \param |
|
2100 * \return |
|
2101 * \note |
|
2102 *//*-------------------------------------------------------------------*/ |
|
2103 |
|
2104 EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) |
|
2105 { |
|
2106 // This RI implementation does not make sense. |
|
2107 #if 0 |
|
2108 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
2109 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE); |
|
2110 EGL_IF_ERROR(!display->surfaceExists(surface), EGL_BAD_SURFACE, EGL_FALSE); |
|
2111 EGL_IF_ERROR(!target || !isValidImageFormat(target->format) || !target->data || target->width <= 0 || target->height <= 0, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE); |
|
2112 RIEGLThread* currentThread = egl->getCurrentThread(); |
|
2113 RIEGLContext* c = currentThread->getCurrentContext(); |
|
2114 RI_ASSERT(c); |
|
2115 try |
|
2116 { |
|
2117 Image output(Color::formatToDescriptor((VGImageFormat)target->format), target->width, target->height, target->stride, (RIuint8*)target->data); |
|
2118 output.addReference(); |
|
2119 output.blit(c->getVGContext(), ((RIEGLSurface*)surface)->getDrawable()->getColorBuffer()->getImage(), 0, 0, 0, 0, target->width, target->height); //throws bad_alloc |
|
2120 output.removeReference(); |
|
2121 } |
|
2122 catch(std::bad_alloc) |
|
2123 { |
|
2124 } |
|
2125 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
2126 #else |
|
2127 (void)dpy; |
|
2128 (void)surface; |
|
2129 (void)target; |
|
2130 return EGL_FALSE; |
|
2131 #endif |
|
2132 } |
|
2133 |
|
2134 /*-------------------------------------------------------------------*//*! |
|
2135 * \brief |
|
2136 * \param |
|
2137 * \return |
|
2138 * \note We support only swap interval one |
|
2139 *//*-------------------------------------------------------------------*/ |
|
2140 |
|
2141 EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval) |
|
2142 { |
|
2143 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
2144 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_FALSE); |
|
2145 RI_UNREF(interval); |
|
2146 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
2147 } |
|
2148 |
|
2149 /*-------------------------------------------------------------------*//*! |
|
2150 * \brief |
|
2151 * \param |
|
2152 * \return |
|
2153 * \note |
|
2154 *//*-------------------------------------------------------------------*/ |
|
2155 |
|
2156 typedef void RI_Proc(); |
|
2157 |
|
2158 __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname) |
|
2159 { |
|
2160 if(!procname) |
|
2161 return NULL; |
|
2162 return NULL; |
|
2163 } |
|
2164 |
|
2165 /*-------------------------------------------------------------------*//*! |
|
2166 * \brief |
|
2167 * \param |
|
2168 * \return |
|
2169 * \note |
|
2170 *//*-------------------------------------------------------------------*/ |
|
2171 |
|
2172 EGLBoolean EGLAPIENTRY eglReleaseThread(void) |
|
2173 { |
|
2174 EGL_GET_EGL(EGL_FALSE); |
|
2175 |
|
2176 //check if the thread is current |
|
2177 RIEGLThread* thread = egl->getCurrentThread(); |
|
2178 if(thread) |
|
2179 { //thread is current, release the old bindings and remove the thread from the current thread list |
|
2180 RIEGLContext* pc = thread->getCurrentContext(); |
|
2181 RIEGLSurface* ps = thread->getCurrentSurface(); |
|
2182 if(pc) |
|
2183 { |
|
2184 vgFlush(); |
|
2185 pc->getVGContext()->setDefaultDrawable(NULL); |
|
2186 if(!pc->removeReference()) |
|
2187 RI_DELETE(pc); |
|
2188 } |
|
2189 if(ps) |
|
2190 { |
|
2191 if(!ps->removeReference()) |
|
2192 RI_DELETE(ps); |
|
2193 } |
|
2194 |
|
2195 egl->removeCurrentThread(thread); |
|
2196 } |
|
2197 |
|
2198 //destroy EGL's thread struct |
|
2199 egl->destroyThread(); |
|
2200 |
|
2201 //destroy the EGL instance |
|
2202 releaseEGL(); |
|
2203 |
|
2204 OSReleaseMutex(); |
|
2205 OSDeinitMutex(); |
|
2206 |
|
2207 return EGL_SUCCESS; |
|
2208 } |
|
2209 |
|
2210 #undef EGL_NUMCONFIGS |