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