33 - no power management events |
33 - no power management events |
34 - no support for swap interval |
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? |
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. |
36 * \todo OSDeinitMutex should be called in case getEGL fails. |
37 *//*-------------------------------------------------------------------*/ |
37 *//*-------------------------------------------------------------------*/ |
|
38 #include "eglapi.h" |
38 |
39 |
39 #include "egl.h" |
40 #include "egl.h" |
40 #include "openvg.h" |
41 #include "openvg.h" |
41 #include "riArray.h" |
42 #include "riArray.h" |
42 #include "riMath.h" |
43 #include "riMath.h" |
43 #include "riContext.h" |
44 #include "riContext.h" |
44 #include "riImage.h" |
45 #include "riImage.h" |
|
46 #include "riMiniEGL.h" |
|
47 #include "riDefs.h" |
45 |
48 |
46 #ifdef BUILD_WITH_PRIVATE_EGL |
49 #ifdef BUILD_WITH_PRIVATE_EGL |
47 #include "eglinternal.h" |
50 #include "eglinternal.h" |
48 #endif |
51 #endif |
49 |
52 |
50 #ifdef BUILD_WITH_PRIVATE_OPENVG |
53 #ifdef BUILD_WITH_PRIVATE_OPENVG |
51 #include "openvginternal.h" |
54 #include "openvginternal.h" |
52 #endif |
55 #endif |
53 |
56 |
54 //============================================================================================== |
57 #ifdef EGL_COMPOSITION |
55 |
58 #include "eglsync.h" |
|
59 // |
|
60 #include <w32std.h> |
|
61 #include <graphics/surfacemanager.h> |
|
62 #include <graphics/surfaceconfiguration.h> |
|
63 #include <graphics/suerror.h> |
|
64 #include <graphics/surface_hints.h> |
|
65 #include <graphics/surfaceupdateclient.h> |
|
66 #include <e32hashtab.h> |
|
67 #endif |
|
68 |
|
69 using namespace OpenVGRI; |
|
70 //// class EGL |
|
71 EGL::EGL() : |
|
72 m_threads(), |
|
73 m_currentThreads(), |
|
74 m_displays(), |
|
75 m_referenceCount(0) |
|
76 { |
|
77 } |
|
78 EGL::~EGL() |
|
79 { |
|
80 for(int i=0;i<m_displays.size();i++) |
|
81 { |
|
82 RI_DELETE(m_displays[i]); |
|
83 } |
|
84 for(int i=0;i<m_threads.size();i++) |
|
85 { |
|
86 RI_DELETE(m_threads[i]); |
|
87 } |
|
88 //currentThreads contain just pointers to threads we just deleted |
|
89 } |
|
90 |
|
91 /*-------------------------------------------------------------------*//*! |
|
92 * \brief |
|
93 * \param |
|
94 * \return |
|
95 * \note |
|
96 *//*-------------------------------------------------------------------*/ |
56 namespace OpenVGRI |
97 namespace OpenVGRI |
57 { |
98 { |
58 |
99 EGL* getEGL() |
59 void* OSGetCurrentThreadID(void); |
100 { |
60 void OSAcquireMutex(void); |
101 |
61 void OSReleaseMutex(void); |
102 |
62 void OSDeinitMutex(void); |
103 //use TLS to store static global g_egl |
63 |
104 EGL* pEgl=NULL; |
64 EGLDisplay OSGetDisplay(EGLNativeDisplayType display_id); |
105 if((pEgl = static_cast<EGL*>(Dll::Tls()))==NULL) |
65 void* OSCreateWindowContext(EGLNativeWindowType window); |
106 { |
66 void OSDestroyWindowContext(void* context); |
107 //create TLS instance |
67 bool OSIsWindow(const void* context); |
108 pEgl = RI_NEW(EGL, ()); |
68 void OSGetWindowSize(const void* context, int& width, int& height); |
109 Dll::SetTls(pEgl); |
69 void OSBlitToWindow(void* context, const Drawable* drawable); |
110 } |
70 EGLBoolean OSGetNativePixmapInfo(NativePixmapType pixmap, int* width, int* height, int* stride, VGImageFormat* format, int** data); |
111 return pEgl; |
71 |
112 |
72 |
113 |
73 /*-------------------------------------------------------------------*//*! |
114 } |
74 * \brief |
115 static void releaseEGL() |
75 * \param |
116 { |
76 * \return |
117 EGL* pEgl = static_cast<EGL*>(Dll::Tls()); |
77 * \note |
118 if (pEgl) |
78 *//*-------------------------------------------------------------------*/ |
119 delete pEgl; |
79 |
120 Dll::SetTls(NULL); |
80 class RIEGLConfig |
121 |
81 { |
122 } |
82 public: |
123 //helper functions |
83 RIEGLConfig() : m_desc(Color::formatToDescriptor(VG_sRGBA_8888)), m_configID(0) {} |
124 RIEGLContext* CastToRIEGLContext(EGLContext aCtxId) |
84 ~RIEGLConfig() {} |
125 { |
85 void set(int r, int g, int b, int a, int l, int bpp, int samples, int maskBits, int ID) |
126 return (RIEGLContext*)(aCtxId); |
86 { |
127 } |
87 m_desc.redBits = r; |
128 EGLContext CastFromRIEGLContext(RIEGLContext* aCtx) |
88 m_desc.greenBits = g; |
129 { |
89 m_desc.blueBits = b; |
130 return (EGLContext)(aCtx); |
90 m_desc.alphaBits = a; |
131 } |
91 m_desc.luminanceBits = l; |
132 |
92 m_desc.alphaShift = 0; |
133 RIEGLSurface* CastToRIEGLSurface(EGLSurface aSurfaceId) |
93 m_desc.luminanceShift = 0; |
134 { |
94 m_desc.blueShift = b ? a : 0; |
135 return (RIEGLSurface*)(aSurfaceId); |
95 m_desc.greenShift = g ? a + b : 0; |
136 } |
96 m_desc.redShift = r ? a + b + g : 0; |
137 EGLSurface CastFromRIEGLSurface(RIEGLSurface* aSurface) |
97 m_desc.format = (VGImageFormat)-1; |
138 { |
98 m_desc.internalFormat = l ? Color::sLA : Color::sRGBA; |
139 return (EGLSurface)(aSurface); |
99 m_desc.bitsPerPixel = bpp; |
140 } |
100 RI_ASSERT(Color::isValidDescriptor(m_desc)); |
141 |
101 m_samples = samples; |
142 Image* CastToImage(EGLClientBuffer aBufferId) |
102 m_maskBits = maskBits; |
143 { |
103 m_configID = ID; |
144 return (Image*)(aBufferId); |
104 m_config = (EGLConfig)ID; |
145 } |
105 } |
146 |
106 |
147 EGLClientBuffer CastFromImage(Image* aBUffer) |
107 Color::Descriptor configToDescriptor(bool sRGB, bool premultiplied) const |
148 { |
|
149 return (EGLClientBuffer)(aBUffer); |
|
150 } |
|
151 //// |
|
152 } // namespace OpenVGRI |
|
153 /*-------------------------------------------------------------------*//*! |
|
154 * \brief Given a display ID, return the corresponding object, or NULL |
|
155 * if the ID hasn't been initialized. |
|
156 * \param |
|
157 * \return |
|
158 * \note if egl has been initialized for this display, the display ID can |
|
159 * be found from egl->m_displays |
|
160 *//*-------------------------------------------------------------------*/ |
|
161 RIEGLDisplay* EGL::getDisplay(const EGLDisplay displayID) |
|
162 { |
|
163 for(int i=0;i<m_displays.size();i++) |
|
164 { |
|
165 if(displayID == m_displays[i]->getID()) |
|
166 { |
|
167 if (CreateDisplayInfo(displayID)) |
|
168 { |
|
169 return m_displays[i]; |
|
170 } |
|
171 } |
|
172 } |
|
173 return NULL; //error: the display hasn't been eglInitialized |
|
174 } |
|
175 |
|
176 /* |
|
177 Create an information object for an opened Display. |
|
178 */ |
|
179 TBool EGL::CreateDisplayInfo(const EGLDisplay aDisplayID) |
|
180 { |
|
181 TBool result = EFalse; |
|
182 EGL_TRACE("EGL::CreateDisplayInfo begin aDisplay=%d", aDisplayID); |
|
183 iDisplayMapLock.WriteLock(); |
|
184 |
|
185 if (NULL != iDisplayMap.Find( aDisplayID)) |
|
186 { |
|
187 result = ETrue; |
|
188 } |
|
189 else |
|
190 { |
|
191 TInt err = KErrNoMemory; |
|
192 CEglDisplayInfo* dispInfo = new CEglDisplayInfo; |
|
193 |
|
194 if (dispInfo) |
|
195 { |
|
196 err = iDisplayMap.Insert(aDisplayID, dispInfo); |
|
197 EGL_TRACE("EGL::CreateDisplayInfo - DisplayMap insert error %d", err); |
|
198 EGLPANIC_ASSERT_DEBUG(err == KErrNone, EEglPanicDisplayMapInsertFailed); |
|
199 |
|
200 //added for egl sync extension benefit |
|
201 if (iEglSyncExtension) |
|
202 { |
|
203 err = iEglSyncExtension->EglSyncDisplayCreate(aDisplayID); |
|
204 EGL_TRACE("EGL::CreateDisplayInfo - EglSyncDisplayCreate error %d", err); |
|
205 EGLPANIC_ASSERT_DEBUG(err == KErrNone, EEglPanicEglSyncDisplayCreateFailed); |
|
206 |
|
207 if (err) |
|
208 { |
|
209 iDisplayMap.Remove(aDisplayID); |
|
210 } |
|
211 } |
|
212 } |
|
213 |
|
214 if (err == KErrNone) |
|
215 { |
|
216 result = ETrue; |
|
217 } |
|
218 } |
|
219 iDisplayMapLock.Unlock(); |
|
220 |
|
221 EGL_TRACE("EGL::CreateDisplayInfo end, result=%d", result); |
|
222 return result; |
|
223 } |
|
224 |
|
225 /*-------------------------------------------------------------------*//*! |
|
226 * \brief Creates the EGL sync instance |
|
227 * \ingroup eglSync |
|
228 *//*-------------------------------------------------------------------*/ |
|
229 |
|
230 EGLint EGL::InitialiseExtensions() |
|
231 { |
|
232 iEglSyncExtension = CEglSyncExtension::Create(*this); |
|
233 return EGL_SUCCESS; |
|
234 } |
|
235 |
|
236 // API supporting EGL sync extension |
|
237 /*-------------------------------------------------------------------*//*! |
|
238 * \brief Query and request to lock a specified display |
|
239 * \ingroup eglSync |
|
240 * \param aEglDisplay a display identifier |
|
241 * \return EGL_SUCCESS if successful; |
|
242 * EGL_BAD_DISPLAY is not a name of a valid EGLDisplay |
|
243 * EGL_NOT_INITIALIZED if the display object associated |
|
244 * with the <aEglDisplay> has not been initialized |
|
245 *//*-------------------------------------------------------------------*/ |
|
246 |
|
247 EGLint EGL::FindAndLockDisplay(EGLDisplay aDisplayID) |
|
248 { |
|
249 EGLint result = EGL_BAD_DISPLAY; |
|
250 EGL_TRACE("EGL::FindAndLockDisplay aDisplay=%d", aDisplayID); |
|
251 iDisplayMapLock.ReadLock(); |
|
252 CEglDisplayInfo** pDisp = iDisplayMap.Find(aDisplayID); |
|
253 if (pDisp && *pDisp) |
|
254 { |
|
255 CEglDisplayInfo* disp = *pDisp; |
|
256 if (disp->iInitialized) |
|
257 { |
|
258 EGL_TRACE("EGL::FindAndLockDisplay display found"); |
|
259 result = EGL_SUCCESS; |
|
260 } |
|
261 else |
|
262 { |
|
263 EGL_TRACE("EGL::FindAndLockDisplay display not initialized"); |
|
264 result = EGL_NOT_INITIALIZED; |
|
265 } |
|
266 } |
|
267 else |
|
268 { |
|
269 EGL_TRACE("EGL::FindAndLockDisplay cannot find display"); |
|
270 } |
|
271 if (result != EGL_SUCCESS) |
|
272 { |
|
273 iDisplayMapLock.Unlock(); |
|
274 } |
|
275 return result; |
|
276 } |
|
277 |
|
278 /*-------------------------------------------------------------------*//*! |
|
279 * \brief Releases the lock associated with a valid EGLDisplay |
|
280 * \ingroup eglSync |
|
281 * \param aEglDisplay a display identifier |
|
282 *//*-------------------------------------------------------------------*/ |
|
283 |
|
284 void EGL::ReleaseDisplayLock(EGLDisplay aDisplayID) |
|
285 { |
|
286 EGL_TRACE("EGL::ReleaseDisplayLock aDisplay=%d", aDisplayID); |
|
287 iDisplayMapLock.Unlock(); |
|
288 } |
|
289 |
|
290 /*-------------------------------------------------------------------*//*! |
|
291 * \brief return EGLDisplay for the current context |
|
292 * \param |
|
293 * \return |
|
294 * \note |
|
295 *//*-------------------------------------------------------------------*/ |
|
296 |
|
297 EGLDisplay EGL::findDisplay(EGLContext ctx) const |
|
298 { |
|
299 for(int i=0;i<m_displays.size();i++) |
|
300 { |
|
301 if(m_displays[i]->contextExists(ctx)) |
|
302 return m_displays[i]->getID(); |
|
303 } |
|
304 return EGL_NO_DISPLAY; |
|
305 } |
|
306 |
|
307 /*-------------------------------------------------------------------*//*! |
|
308 * \brief return an EGL thread struct for the thread made current, or |
|
309 * NULL if there's no current context. |
|
310 * \param |
|
311 * \return |
|
312 * \note |
|
313 *//*-------------------------------------------------------------------*/ |
|
314 |
|
315 RIEGLThread* EGL::getCurrentThread() const |
|
316 { |
|
317 void* currentThreadID = OSGetCurrentThreadID(); |
|
318 for(int i=0;i<m_currentThreads.size();i++) |
|
319 { |
|
320 if(currentThreadID == m_currentThreads[i]->getThreadID()) |
|
321 return m_currentThreads[i]; |
|
322 } |
|
323 return NULL; //thread is not current |
|
324 } |
|
325 |
|
326 /*-------------------------------------------------------------------*//*! |
|
327 * \brief return an EGL thread struct corresponding to current OS thread. |
|
328 * \param |
|
329 * \return |
|
330 * \note |
|
331 *//*-------------------------------------------------------------------*/ |
|
332 |
|
333 RIEGLThread* EGL::getThread() |
|
334 { |
|
335 void* currentThreadID = OSGetCurrentThreadID(); |
|
336 for(int i=0;i<m_threads.size();i++) |
|
337 { |
|
338 if(currentThreadID == m_threads[i]->getThreadID()) |
|
339 return m_threads[i]; |
|
340 } |
|
341 |
|
342 //EGL doesn't have a struct for the thread yet, add it to EGL's list |
|
343 RIEGLThread* newThread = NULL; |
|
344 try |
|
345 { |
|
346 newThread = RI_NEW(RIEGLThread, (OSGetCurrentThreadID())); //throws bad_alloc |
|
347 m_threads.push_back(newThread); //throws bad_alloc |
|
348 return newThread; |
|
349 } |
|
350 catch(std::bad_alloc) |
|
351 { |
|
352 RI_DELETE(newThread); |
|
353 return NULL; |
|
354 } |
|
355 } |
|
356 |
|
357 /*-------------------------------------------------------------------*//*! |
|
358 * \brief destroy an EGL thread struct |
|
359 * \param |
|
360 * \return |
|
361 * \note |
|
362 *//*-------------------------------------------------------------------*/ |
|
363 |
|
364 void EGL::destroyThread() |
|
365 { |
|
366 void* currentThreadID = OSGetCurrentThreadID(); |
|
367 for(int i=0;i<m_threads.size();i++) |
|
368 { |
|
369 if(currentThreadID == m_threads[i]->getThreadID()) |
|
370 { |
|
371 RIEGLThread* thread = m_threads[i]; |
|
372 bool res = m_threads.remove(thread); |
|
373 RI_ASSERT(res); |
|
374 RI_UNREF(res); |
|
375 RI_DELETE(thread); |
|
376 break; |
|
377 } |
|
378 } |
|
379 } |
|
380 |
|
381 /*-------------------------------------------------------------------*//*! |
|
382 * \brief |
|
383 * \param |
|
384 * \return |
|
385 * \note |
|
386 *//*-------------------------------------------------------------------*/ |
|
387 |
|
388 bool EGL::isInUse(const void* image) const |
|
389 { |
|
390 for(int i=0;i<m_currentThreads.size();i++) |
108 { |
391 { |
109 Color::Descriptor desc = m_desc; |
392 RIEGLSurface* s = m_currentThreads[i]->getCurrentSurface(); |
110 unsigned int f = m_desc.luminanceBits ? Color::LUMINANCE : 0; |
393 if(s && s->getDrawable() && s->getDrawable()->isInUse((Image*)image)) |
111 f |= sRGB ? Color::NONLINEAR : 0; |
394 return true; |
112 f |= premultiplied ? Color::PREMULTIPLIED : 0; |
|
113 desc.internalFormat = (Color::InternalFormat)f; |
|
114 return desc; |
|
115 } |
395 } |
116 |
396 return false; |
117 //EGL RED SIZE bits of Red in the color buffer |
397 } |
118 //EGL GREEN SIZE bits of Green in the color buffer |
398 // |
119 //EGL BLUE SIZE bits of Blue in the color buffer |
|
120 //EGL ALPHA SIZE bits of Alpha in the color buffer |
|
121 //EGL LUMINANCE SIZE bits of Luminance in the color buffer |
|
122 Color::Descriptor m_desc; |
|
123 int m_samples; |
|
124 int m_maskBits; |
|
125 EGLint m_configID; //EGL CONFIG ID unique EGLConfig identifier |
|
126 EGLConfig m_config; |
|
127 //EGL BUFFER SIZE depth of the color buffer (sum of channel bits) |
|
128 //EGL ALPHA MASK SIZE number alpha mask bits (always 8) |
|
129 //EGL BIND TO TEXTURE RGB boolean True if bindable to RGB textures. (always EGL_FALSE) |
|
130 //EGL BIND TO TEXTURE RGBA boolean True if bindable to RGBA textures. (always EGL_FALSE) |
|
131 //EGL COLOR BUFFER TYPE enum color buffer type (EGL_RGB_BUFFER, EGL_LUMINANCE_BUFFER) |
|
132 //EGL CONFIG CAVEAT enum any caveats for the configuration (always EGL_NONE) |
|
133 //EGL DEPTH SIZE integer bits of Z in the depth buffer (always 0) |
|
134 //EGL LEVEL integer frame buffer level (always 0) |
|
135 //EGL MAX PBUFFER WIDTH integer maximum width of pbuffer (always INT_MAX) |
|
136 //EGL MAX PBUFFER HEIGHT integer maximum height of pbuffer (always INT_MAX) |
|
137 //EGL MAX PBUFFER PIXELS integer maximum size of pbuffer (always INT_MAX) |
|
138 //EGL MAX SWAP INTERVAL integer maximum swap interval (always 1) |
|
139 //EGL MIN SWAP INTERVAL integer minimum swap interval (always 1) |
|
140 //EGL NATIVE RENDERABLE boolean EGL TRUE if native rendering APIs can render to surface (always EGL_FALSE) |
|
141 //EGL NATIVE VISUAL ID integer handle of corresponding native visual (always 0) |
|
142 //EGL NATIVE VISUAL TYPE integer native visual type of the associated visual (always EGL_NONE) |
|
143 //EGL RENDERABLE TYPE bitmask which client rendering APIs are supported. (always EGL_OPENVG_BIT) |
|
144 //EGL SAMPLE BUFFERS integer number of multisample buffers (always 0) |
|
145 //EGL SAMPLES integer number of samples per pixel (always 0) |
|
146 //EGL STENCIL SIZE integer bits of Stencil in the stencil buffer (always 0) |
|
147 //EGL SURFACE TYPE bitmask which types of EGL surfaces are supported. (always EGL WINDOW BIT | EGL PIXMAP BIT | EGL PBUFFER BIT) |
|
148 //EGL TRANSPARENT TYPE enum type of transparency supported (always EGL_NONE) |
|
149 //EGL TRANSPARENT RED VALUE integer transparent red value (undefined) |
|
150 //EGL TRANSPARENT GREEN VALUE integer transparent green value (undefined) |
|
151 //EGL TRANSPARENT BLUE VALUE integer transparent blue value (undefined) |
|
152 }; |
|
153 |
|
154 /*-------------------------------------------------------------------*//*! |
|
155 * \brief |
|
156 * \param |
|
157 * \return |
|
158 * \note |
|
159 *//*-------------------------------------------------------------------*/ |
|
160 |
|
161 class RIEGLContext |
|
162 { |
|
163 public: |
|
164 RIEGLContext(OpenVGRI::VGContext* vgctx, const EGLConfig config); |
|
165 ~RIEGLContext(); |
|
166 void addReference() { m_referenceCount++; } |
|
167 int removeReference() { m_referenceCount--; RI_ASSERT(m_referenceCount >= 0); return m_referenceCount; } |
|
168 |
|
169 VGContext* getVGContext() const { return m_vgContext; } |
|
170 EGLConfig getConfig() const { return m_config; } |
|
171 private: |
|
172 RIEGLContext(const RIEGLContext&); |
|
173 RIEGLContext& operator=(const RIEGLContext&); |
|
174 VGContext* m_vgContext; |
|
175 const EGLConfig m_config; |
|
176 int m_referenceCount; |
|
177 }; |
|
178 |
|
179 RIEGLContext* CastToRIEGLContext(EGLContext aCtxId); |
|
180 EGLContext CastFromRIEGLContext(RIEGLContext* aCtx); |
|
181 |
|
182 RIEGLContext::RIEGLContext(OpenVGRI::VGContext* vgctx, const EGLConfig config) : |
399 RIEGLContext::RIEGLContext(OpenVGRI::VGContext* vgctx, const EGLConfig config) : |
183 m_vgContext(vgctx), |
400 m_vgContext(vgctx), |
184 m_config(config), |
401 m_config(config), |
185 m_referenceCount(0) |
402 m_referenceCount(0) |
186 { |
403 { |
478 |
599 |
479 RIEGLThread::~RIEGLThread() |
600 RIEGLThread::~RIEGLThread() |
480 { |
601 { |
481 } |
602 } |
482 |
603 |
483 |
604 namespace OpenVGRI |
484 |
605 { |
485 |
606 //// |
486 |
|
487 Image* CastToImage(EGLClientBuffer aBufferId); |
|
488 EGLClientBuffer CastFromImage(Image* aBUffer); |
|
489 |
|
490 /*-------------------------------------------------------------------*//*! |
|
491 * \brief |
|
492 * \param |
|
493 * \return |
|
494 * \note |
|
495 *//*-------------------------------------------------------------------*/ |
|
496 |
|
497 class EGL |
|
498 { |
|
499 public: |
|
500 EGL(); |
|
501 ~EGL(); |
|
502 |
|
503 void addReference() { m_referenceCount++; } |
|
504 int removeReference() { m_referenceCount--; RI_ASSERT(m_referenceCount >= 0); return m_referenceCount; } |
|
505 |
|
506 void addDisplay(RIEGLDisplay* display) { RI_ASSERT(display); m_displays.push_back(display); } //throws bad alloc |
|
507 void removeDisplay(RIEGLDisplay* display) { RI_ASSERT(display); bool res = m_displays.remove(display); RI_ASSERT(res); RI_UNREF(res); } |
|
508 RIEGLDisplay* getDisplay(const EGLDisplay displayID) const; |
|
509 EGLDisplay findDisplay(const EGLContext ctx) const; |
|
510 |
|
511 void addCurrentThread(RIEGLThread* thread) { RI_ASSERT(thread); m_currentThreads.push_back(thread); } //throws bad alloc |
|
512 void removeCurrentThread(RIEGLThread* thread) { RI_ASSERT(thread); bool res = m_currentThreads.remove(thread); RI_ASSERT(res); RI_UNREF(res); } |
|
513 RIEGLThread* getCurrentThread() const; |
|
514 |
|
515 RIEGLThread* getThread(); |
|
516 void destroyThread(); |
|
517 |
|
518 bool isInUse(const void* image) const; |
|
519 |
|
520 private: |
|
521 EGL(const EGL&); // Not allowed. |
|
522 const EGL& operator=(const EGL&); // Not allowed. |
|
523 |
|
524 Array<RIEGLThread*> m_threads; //threads that have called EGL |
|
525 Array<RIEGLThread*> m_currentThreads; //threads that have a bound context |
|
526 Array<RIEGLDisplay*> m_displays; |
|
527 |
|
528 int m_referenceCount; |
|
529 }; |
|
530 |
|
531 EGL::EGL() : |
|
532 m_threads(), |
|
533 m_currentThreads(), |
|
534 m_displays(), |
|
535 m_referenceCount(0) |
|
536 { |
|
537 } |
|
538 EGL::~EGL() |
|
539 { |
|
540 for(int i=0;i<m_displays.size();i++) |
|
541 { |
|
542 RI_DELETE(m_displays[i]); |
|
543 } |
|
544 for(int i=0;i<m_threads.size();i++) |
|
545 { |
|
546 RI_DELETE(m_threads[i]); |
|
547 } |
|
548 //currentThreads contain just pointers to threads we just deleted |
|
549 } |
|
550 |
|
551 /*-------------------------------------------------------------------*//*! |
|
552 * \brief |
|
553 * \param |
|
554 * \return |
|
555 * \note |
|
556 *//*-------------------------------------------------------------------*/ |
|
557 |
|
558 //static EGL* g_egl = NULL; //never use this directly |
|
559 EGL* getEGL() |
|
560 { |
|
561 /*if(!g_egl) |
|
562 { |
|
563 try |
|
564 { |
|
565 g_egl = RI_NEW(EGL, ()); //throws bad_alloc |
|
566 g_egl->addReference(); |
|
567 } |
|
568 catch(std::bad_alloc) |
|
569 { |
|
570 g_egl = NULL; |
|
571 } |
|
572 } |
|
573 return g_egl; |
|
574 */ |
|
575 |
|
576 |
|
577 //use TLS to store static global g_egl |
|
578 EGL* pEgl=NULL; |
|
579 if((pEgl = static_cast<EGL*>(Dll::Tls()))==NULL) |
|
580 { |
|
581 //create TLS instance |
|
582 pEgl = RI_NEW(EGL, ()); |
|
583 Dll::SetTls(pEgl); |
|
584 } |
|
585 return pEgl; |
|
586 |
|
587 |
|
588 } |
|
589 static void releaseEGL() |
|
590 { |
|
591 /* |
|
592 if(g_egl) |
|
593 { |
|
594 if(!g_egl->removeReference()) |
|
595 { |
|
596 RI_DELETE(g_egl); |
|
597 g_egl = NULL; |
|
598 } |
|
599 } |
|
600 */ |
|
601 EGL* pEgl = static_cast<EGL*>(Dll::Tls()); |
|
602 if (pEgl) |
|
603 delete pEgl; |
|
604 Dll::SetTls(NULL); |
|
605 |
|
606 } |
|
607 |
|
608 /*-------------------------------------------------------------------*//*! |
|
609 * \brief Given a display ID, return the corresponding object, or NULL |
|
610 * if the ID hasn't been initialized. |
|
611 * \param |
|
612 * \return |
|
613 * \note if egl has been initialized for this display, the display ID can |
|
614 * be found from egl->m_displays |
|
615 *//*-------------------------------------------------------------------*/ |
|
616 |
|
617 RIEGLDisplay* EGL::getDisplay(EGLDisplay displayID) const |
|
618 { |
|
619 for(int i=0;i<m_displays.size();i++) |
|
620 { |
|
621 if(displayID == m_displays[i]->getID()) |
|
622 return m_displays[i]; |
|
623 } |
|
624 return NULL; //error: the display hasn't been eglInitialized |
|
625 } |
|
626 |
|
627 /*-------------------------------------------------------------------*//*! |
|
628 * \brief return EGLDisplay for the current context |
|
629 * \param |
|
630 * \return |
|
631 * \note |
|
632 *//*-------------------------------------------------------------------*/ |
|
633 |
|
634 EGLDisplay EGL::findDisplay(EGLContext ctx) const |
|
635 { |
|
636 for(int i=0;i<m_displays.size();i++) |
|
637 { |
|
638 if(m_displays[i]->contextExists(ctx)) |
|
639 return m_displays[i]->getID(); |
|
640 } |
|
641 return EGL_NO_DISPLAY; |
|
642 } |
|
643 |
|
644 /*-------------------------------------------------------------------*//*! |
|
645 * \brief return an EGL thread struct for the thread made current, or |
|
646 * NULL if there's no current context. |
|
647 * \param |
|
648 * \return |
|
649 * \note |
|
650 *//*-------------------------------------------------------------------*/ |
|
651 |
|
652 RIEGLThread* EGL::getCurrentThread() const |
|
653 { |
|
654 void* currentThreadID = OSGetCurrentThreadID(); |
|
655 for(int i=0;i<m_currentThreads.size();i++) |
|
656 { |
|
657 if(currentThreadID == m_currentThreads[i]->getThreadID()) |
|
658 return m_currentThreads[i]; |
|
659 } |
|
660 return NULL; //thread is not current |
|
661 } |
|
662 |
|
663 /*-------------------------------------------------------------------*//*! |
|
664 * \brief return an EGL thread struct corresponding to current OS thread. |
|
665 * \param |
|
666 * \return |
|
667 * \note |
|
668 *//*-------------------------------------------------------------------*/ |
|
669 |
|
670 RIEGLThread* EGL::getThread() |
|
671 { |
|
672 void* currentThreadID = OSGetCurrentThreadID(); |
|
673 for(int i=0;i<m_threads.size();i++) |
|
674 { |
|
675 if(currentThreadID == m_threads[i]->getThreadID()) |
|
676 return m_threads[i]; |
|
677 } |
|
678 |
|
679 //EGL doesn't have a struct for the thread yet, add it to EGL's list |
|
680 RIEGLThread* newThread = NULL; |
|
681 try |
|
682 { |
|
683 newThread = RI_NEW(RIEGLThread, (OSGetCurrentThreadID())); //throws bad_alloc |
|
684 m_threads.push_back(newThread); //throws bad_alloc |
|
685 return newThread; |
|
686 } |
|
687 catch(std::bad_alloc) |
|
688 { |
|
689 RI_DELETE(newThread); |
|
690 return NULL; |
|
691 } |
|
692 } |
|
693 |
|
694 /*-------------------------------------------------------------------*//*! |
|
695 * \brief destroy an EGL thread struct |
|
696 * \param |
|
697 * \return |
|
698 * \note |
|
699 *//*-------------------------------------------------------------------*/ |
|
700 |
|
701 void EGL::destroyThread() |
|
702 { |
|
703 void* currentThreadID = OSGetCurrentThreadID(); |
|
704 for(int i=0;i<m_threads.size();i++) |
|
705 { |
|
706 if(currentThreadID == m_threads[i]->getThreadID()) |
|
707 { |
|
708 RIEGLThread* thread = m_threads[i]; |
|
709 bool res = m_threads.remove(thread); |
|
710 RI_ASSERT(res); |
|
711 RI_UNREF(res); |
|
712 RI_DELETE(thread); |
|
713 break; |
|
714 } |
|
715 } |
|
716 } |
|
717 |
|
718 /*-------------------------------------------------------------------*//*! |
|
719 * \brief |
|
720 * \param |
|
721 * \return |
|
722 * \note |
|
723 *//*-------------------------------------------------------------------*/ |
|
724 |
|
725 bool EGL::isInUse(const void* image) const |
|
726 { |
|
727 for(int i=0;i<m_currentThreads.size();i++) |
|
728 { |
|
729 RIEGLSurface* s = m_currentThreads[i]->getCurrentSurface(); |
|
730 if(s && s->getDrawable() && s->getDrawable()->isInUse((Image*)image)) |
|
731 return true; |
|
732 } |
|
733 return false; |
|
734 } |
|
735 |
|
736 /*-------------------------------------------------------------------*//*! |
|
737 * \brief |
|
738 * \param |
|
739 * \return |
|
740 * \note |
|
741 *//*-------------------------------------------------------------------*/ |
|
742 |
|
743 #define EGL_GET_DISPLAY(DISPLAY, RETVAL) \ |
|
744 OSAcquireMutex(); \ |
|
745 EGL* egl = getEGL(); \ |
|
746 if(!egl) \ |
|
747 { \ |
|
748 OSReleaseMutex(); \ |
|
749 return RETVAL; \ |
|
750 } \ |
|
751 RIEGLDisplay* display = egl->getDisplay(DISPLAY); \ |
|
752 |
|
753 #define EGL_GET_EGL(RETVAL) \ |
|
754 OSAcquireMutex(); \ |
|
755 EGL* egl = getEGL(); \ |
|
756 if(!egl) \ |
|
757 { \ |
|
758 OSReleaseMutex(); \ |
|
759 return RETVAL; \ |
|
760 } \ |
|
761 |
|
762 #define EGL_IF_ERROR(COND, ERRORCODE, RETVAL) \ |
|
763 if(COND) { eglSetError(egl, ERRORCODE); OSReleaseMutex(); return RETVAL; } \ |
|
764 |
|
765 #define EGL_RETURN(ERRORCODE, RETVAL) \ |
|
766 { \ |
|
767 eglSetError(egl, ERRORCODE); \ |
|
768 OSReleaseMutex(); \ |
|
769 return RETVAL; \ |
|
770 } |
|
771 |
|
772 // Note: egl error handling model differs from OpenVG. The latest error is stored instead of the oldest one. |
607 // Note: egl error handling model differs from OpenVG. The latest error is stored instead of the oldest one. |
773 static void eglSetError(EGL* egl, EGLint error) |
608 //static void eglSetError(EGL* egl, EGLint error) |
|
609 void eglSetError(EGL* egl, EGLint error) |
774 { |
610 { |
775 RIEGLThread* thread = egl->getThread(); |
611 RIEGLThread* thread = egl->getThread(); |
776 if(thread) |
612 if(thread) |
777 thread->setError(error); |
613 thread->setError(error); |
778 } |
614 } |
1490 OSDestroyWindowContext(wc); |
1290 OSDestroyWindowContext(wc); |
1491 RI_DELETE(d); |
1291 RI_DELETE(d); |
1492 RI_DELETE(s); |
1292 RI_DELETE(s); |
1493 EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_SURFACE); |
1293 EGL_RETURN(EGL_BAD_ALLOC, EGL_NO_SURFACE); |
1494 } |
1294 } |
|
1295 #ifdef EGL_COMPOSITION |
|
1296 RIEGLThread* thread = egl->getThread(); |
|
1297 RI_ASSERT(thread); |
|
1298 |
|
1299 |
|
1300 //egl->iDisplayMapLock.WriteLock(); |
|
1301 CEglDisplayInfo** pDispInfo; |
|
1302 pDispInfo = egl->iDisplayMap.Find(dpy); // make sure iDisplayInfo is populated in CreateDisplay!! |
|
1303 |
|
1304 if (pDispInfo && *pDispInfo) |
|
1305 { |
|
1306 TSurfaceInfo& surfaceInfo = egl->GetSurfaceInfo(); |
|
1307 // so we don't have to pass alphaFormat to CreateSurface we set it here... not sure if needed anyway |
|
1308 surfaceInfo.iAlphaFormat = alphaFormat; |
|
1309 |
|
1310 if(EGL_TRUE != egl->EglInternalFunction_CreateSurface(/*aThreadState,*/ dpy, (EGLSurface)s, config, win, surfaceInfo)) |
|
1311 EGL_RETURN(EGL_BAD_SURFACE, NULL); |
|
1312 |
|
1313 (*pDispInfo)->iSurfaceMap.Insert(surfaceInfo.iSurface, &surfaceInfo); |
|
1314 |
|
1315 TSurfaceConfiguration surfaceConfig; |
|
1316 surfaceConfig.SetSurfaceId(surfaceInfo.iSurfaceId); |
|
1317 |
|
1318 if(surfaceInfo.iNativeWindow.IsWindow()) |
|
1319 { |
|
1320 RWindow* window = (RWindow*)(win); |
|
1321 RWsSession& session = *window->Session(); |
|
1322 session.RegisterSurface(surfaceInfo.iScreenNumber, surfaceInfo.iSurfaceId); |
|
1323 window->SetBackgroundSurface(surfaceConfig, ETrue); |
|
1324 } |
|
1325 else |
|
1326 { |
|
1327 // Now what?? Nothing is good enough? |
|
1328 // Simply no composition if not RWindow? |
|
1329 EGL_TRACE("eglCreateWindowSurface - Native Window NOT RWindow - no composition"); |
|
1330 } |
|
1331 |
|
1332 TRequestStatus status = KRequestPending; |
|
1333 TTimeStamp timestampLocalToThread; |
|
1334 // session needs to be established... and it is in InternalFunction_CreateSurface |
|
1335 /* |
|
1336 * When double-buffering is used, the client renders to one buffer (called A in this example) while the other buffer (B) is on the screen and vice versa. In order for this to work correctly and to be free of tearing artefacts, the client must use the following sequence: |
|
1337 |
|
1338 1. Render the graphics content to buffer A, and call NotifyWhenAvailable() followed by SubmitUpdate() for buffer A. |
|
1339 2. Render the graphics content to buffer B, and call NotifyWhenAvailable() followed by SubmitUpdate() for buffer B. |
|
1340 3. Wait for notification that buffer A is available. When it becomes available, render further content to it and call NotifyWhenAvailable() followed by SubmitUpdate() for buffer A. |
|
1341 4. Wait for notification that buffer B is available. When it becomes available, render further content to it and call NotifyWhenAvailable() followed by SubmitUpdate() for buffer B. |
|
1342 5. Repeat steps 3 and 4 for as long as required. |
|
1343 |
|
1344 After sending the first two buffers to the composition engine, the client waits for notification before sending a further buffer. The composition engine always returns notification after receiving a new buffer even if an error condition is detected. |
|
1345 */ |
|
1346 surfaceInfo.iSurfaceUpdateSession.NotifyWhenDisplayed(status, timestampLocalToThread); |
|
1347 surfaceInfo.iSurfaceUpdateSession.SubmitUpdate(surfaceInfo.iScreenNumber,surfaceInfo.iSurfaceId, 0); |
|
1348 surfaceInfo.iSurfaceUpdateSession.SubmitUpdate(surfaceInfo.iScreenNumber,surfaceInfo.iSurfaceId, 1); |
|
1349 User::WaitForRequest(status); |
|
1350 } |
|
1351 |
|
1352 |
|
1353 |
|
1354 //egl->iDisplayMapLock.Unlock(); |
|
1355 |
|
1356 //thread->setError(EGL_SUCCESS); // done by EGL_RETURN macro? |
|
1357 #endif |
1495 EGL_RETURN(EGL_SUCCESS, (EGLSurface)s); |
1358 EGL_RETURN(EGL_SUCCESS, (EGLSurface)s); |
1496 } |
1359 } |
|
1360 |
|
1361 // ----------------------------------------------------------------------------- |
|
1362 // |
|
1363 // ----------------------------------------------------------------------------- |
|
1364 // |
|
1365 TBool EGL::EglInternalFunction_CreateSurface(/*TEglThreadState& aThreadState,*/ EGLDisplay aDisplay, EGLSurface aSurface, EGLConfig aConfig, |
|
1366 EGLNativeWindowType aNativeWindow, TSurfaceInfo& aSurfaceInfo) |
|
1367 { |
|
1368 |
|
1369 aSurfaceInfo.iNativeWindow.SetNativeWindow(aNativeWindow); |
|
1370 aSurfaceInfo.iSurfaceType = ESurfaceTypeWindow; |
|
1371 aSurfaceInfo.iSize = aSurfaceInfo.iNativeWindow.SizeInPixels(); |
|
1372 |
|
1373 aSurfaceInfo.iConfigId = aConfig; |
|
1374 aSurfaceInfo.iSurface = aSurface; |
|
1375 |
|
1376 aSurfaceInfo.iStride = 4 * aSurfaceInfo.iSize.iWidth; // Number of bytes between start of one line and start of next |
|
1377 |
|
1378 |
|
1379 RSurfaceManager::TSurfaceCreationAttributesBuf buf; |
|
1380 RSurfaceManager::TSurfaceCreationAttributes& attributes = buf(); |
|
1381 // Set surafce attributes |
|
1382 attributes.iSize = aSurfaceInfo.iSize; |
|
1383 attributes.iBuffers = 2; // double-buffering is used |
|
1384 attributes.iPixelFormat = EUidPixelFormatARGB_8888; // this is a guess; either query or hardcode to match syborg |
|
1385 //attributes.iPixelFormat = EUidPixelFormatARGB_8888_PRE; // this is a guess; either query or hardcode |
|
1386 /** Minimum or required number of bytes between start of one line andstart of next. */ |
|
1387 attributes.iStride = aSurfaceInfo.iStride; |
|
1388 /** Minimum or required offset to the first buffer from the base of the chunk. |
|
1389 * Typically this will be set to 0. The value specified for the offset must comply with the alignment specified in iAlignment. |
|
1390 * If iAlignment is page aligned, this value will be rounded up to a multiple of the page size when the surface is created, |
|
1391 * therefore the surface info must be queried for the actual value used. */ |
|
1392 attributes.iOffsetToFirstBuffer = 0; |
|
1393 /** Alignment applied to the base address of each buffer in the surface: |
|
1394 * 1, 2, 4, 8 ,16, 32, 64 bytes or EPageAligned. */ |
|
1395 attributes.iAlignment = RSurfaceManager::EPageAligned; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned |
|
1396 /** Number of hints in the array iSurfaceHints. |
|
1397 * The number should not exceed the maximum number supported by the surface manager, |
|
1398 * see GetSurfaceManagerAttrib(EMaxNumberOfHints). */ |
|
1399 attributes.iHintCount=0; |
|
1400 /** Array of hints which should be associated with the surface. |
|
1401 * This array must not contain duplicate hint keys. */ |
|
1402 attributes.iSurfaceHints = NULL; |
|
1403 /** Minimum or required offset between the start of one buffer and the |
|
1404 start of the next one in bytes. When set to 0 the surface manager will |
|
1405 choose how buffers are laid out within the chunk. If it is too small |
|
1406 and doesn't fit with the alignment, CreateSurface() will return KErrArgument. */ |
|
1407 attributes.iOffsetBetweenBuffers = 0; |
|
1408 /** Require physically contiguous memory. |
|
1409 * This value will be ignored if using a chunk which already exists. */ |
|
1410 attributes.iContiguous = ETrue; |
|
1411 /** Caching attribute to create chunk memory. |
|
1412 * This value will be ignored if using a chunk which already exists. */ |
|
1413 attributes.iCacheAttrib = RSurfaceManager::ECached; // Cache attributes |
|
1414 /** Should the surface be mappable. |
|
1415 * If EFalse any call to MapSurface() will fail with KErrNotSupported |
|
1416 * Note, some architectures may not support mappable surfaces. */ |
|
1417 attributes.iMappable = ETrue; |
|
1418 // |
|
1419 aSurfaceInfo.iScreenNumber = aSurfaceInfo.iNativeWindow.ScreenNumber(); |
|
1420 |
|
1421 // Create the surface |
|
1422 |
|
1423 aSurfaceInfo.iSurfaceManager.Open(); |
|
1424 aSurfaceInfo.iSurfaceManager.CreateSurface(buf, aSurfaceInfo.iSurfaceId); |
|
1425 |
|
1426 TInt err = aSurfaceInfo.iSurfaceManager.MapSurface(aSurfaceInfo.iSurfaceId, aSurfaceInfo.iChunk); |
|
1427 |
|
1428 EGL_TRACE("EGL::EglInternalFunction_CreateSurface surface manager returned chunk %x and ret val %d", aSurfaceInfo.iChunk, err); |
|
1429 |
|
1430 |
|
1431 |
|
1432 if ( !EglInternalFunction_CallSetSurfaceParams(/*aThreadState,*/ aDisplay, aSurface, aSurfaceInfo) ) |
|
1433 { |
|
1434 EGL_TRACE("CGuestEGL::EglInternalFunction_CreateSurface end failure"); |
|
1435 |
|
1436 return EGL_FALSE; |
|
1437 } |
|
1438 aSurfaceInfo.iSurfaceUpdateSession.Connect(); |
|
1439 EGL_TRACE("CGuestEGL::EglInternalFunction_CreateSurface end success"); |
|
1440 |
|
1441 return EGL_TRUE; |
|
1442 } |
|
1443 |
|
1444 // ----------------------------------------------------------------------------- |
|
1445 // |
|
1446 // ----------------------------------------------------------------------------- |
|
1447 // |
|
1448 TBool EGL::EglInternalFunction_CallSetSurfaceParams(/*aThreadState,*/EGLDisplay aDisplay,EGLSurface aSurface,TSurfaceInfo& aSurfaceInfo) |
|
1449 { |
|
1450 EGL_GET_EGL(EGL_FALSE); |
|
1451 /* |
|
1452 EGL_GET_DISPLAY(aDisplay, EGL_NO_SURFACE); |
|
1453 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_NO_SURFACE); |
|
1454 //RI_ASSERT( display->ProcessId() == process->Id() ); |
|
1455 RIEGLSurface* surface = display->getSurface( aSurface ); |
|
1456 EGL_IF_ERROR(!display, EGL_NOT_INITIALIZED, EGL_BAD_SURFACE); |
|
1457 */ |
|
1458 RI_ASSERT( aSurfaceInfo.iSurfaceType == ESurfaceTypeWindow ); |
|
1459 |
|
1460 //TODO: resizing? |
|
1461 |
|
1462 #ifdef BUILD_WITH_PRIVATE_EGL |
|
1463 if(!do_eglQuerySurface(aDisplay, aSurface, EGL_VG_ALPHA_FORMAT, &aSurfaceInfo.iAlphaFormat)) |
|
1464 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1465 if(!do_eglGetConfigAttrib(aDisplay, aSurfaceInfo.iConfigId, EGL_BUFFER_SIZE, &aSurfaceInfo.iColorBits)) |
|
1466 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1467 if(!do_eglGetConfigAttrib(aDisplay, aSurfaceInfo.iConfigId, EGL_RED_SIZE, &aSurfaceInfo.iRedBits)) |
|
1468 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1469 if(!do_eglGetConfigAttrib(aDisplay, aSurfaceInfo.iConfigId, EGL_GREEN_SIZE, &aSurfaceInfo.iGreenBits)) |
|
1470 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1471 if(!do_eglGetConfigAttrib(aDisplay, aSurfaceInfo.iConfigId, EGL_BLUE_SIZE, &aSurfaceInfo.iBlueBits)) |
|
1472 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1473 if(!do_eglGetConfigAttrib(aDisplay, aSurfaceInfo.iConfigId, EGL_ALPHA_SIZE, &aSurfaceInfo.iAlphaBits)) |
|
1474 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1475 #else |
|
1476 if(!eglQuerySurface(aDisplay, aSurface, EGL_VG_ALPHA_FORMAT, &aSurfaceInfo.iAlphaFormat)) |
|
1477 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1478 if(!eglGetConfigAttrib(aDisplay, aSurfaceInfo.iConfigId, EGL_BUFFER_SIZE, &aSurfaceInfo.iColorBits)) |
|
1479 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1480 if(!eglGetConfigAttrib(aDisplay, aSurfaceInfo.iConfigId, EGL_RED_SIZE, &aSurfaceInfo.iRedBits)) |
|
1481 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1482 if(!eglGetConfigAttrib(aDisplay, aSurfaceInfo.iConfigId, EGL_GREEN_SIZE, &aSurfaceInfo.iGreenBits)) |
|
1483 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1484 if(!eglGetConfigAttrib(aDisplay, aSurfaceInfo.iConfigId, EGL_BLUE_SIZE, &aSurfaceInfo.iBlueBits)) |
|
1485 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1486 if(!eglGetConfigAttrib(aDisplay, aSurfaceInfo.iConfigId, EGL_ALPHA_SIZE, &aSurfaceInfo.iAlphaBits)) |
|
1487 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1488 #endif |
|
1489 |
|
1490 |
|
1491 EGL_TRACE("EGL::EglInternalFunction_CallSetSurfaceParams Win surface details: width=%d height=%d colorbits=%d red=%d green=%d blue=%d alpha=%d alphaformat=0x%x", |
|
1492 aSurfaceInfo.iSize.iWidth, aSurfaceInfo.iSize.iHeight, aSurfaceInfo.iColorBits, aSurfaceInfo.iRedBits, |
|
1493 aSurfaceInfo.iGreenBits, aSurfaceInfo.iBlueBits, aSurfaceInfo.iAlphaBits, aSurfaceInfo.iAlphaFormat); |
|
1494 TInt err; |
|
1495 TSize size; |
|
1496 |
|
1497 TInt offsetToFirstBuffer = -1; |
|
1498 TInt offsetToSecondBuffer = -1; |
|
1499 err = aSurfaceInfo.iSurfaceManager.GetBufferOffset(aSurfaceInfo.iSurfaceId,0,offsetToFirstBuffer); |
|
1500 if(err!=KErrNone) |
|
1501 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1502 err = aSurfaceInfo.iSurfaceManager.GetBufferOffset(aSurfaceInfo.iSurfaceId,1,offsetToSecondBuffer); |
|
1503 if(err!=KErrNone) |
|
1504 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE ); |
|
1505 EGL_TRACE("EGL::EglInternalFunction_CallSetSurfaceParams offsetToFirstBuffer=0x%x offsetToSecondBuffer=0x%x", |
|
1506 offsetToFirstBuffer,offsetToSecondBuffer); |
|
1507 |
|
1508 |
|
1509 /* Store the pointer to the pixel data */ |
|
1510 aSurfaceInfo.iBuffer0 = aSurfaceInfo.iChunk.Base() + offsetToFirstBuffer; |
|
1511 aSurfaceInfo.iBuffer1 = aSurfaceInfo.iChunk.Base() + offsetToSecondBuffer; |
|
1512 |
|
1513 aSurfaceInfo.iFrontBuffer = 0; // start rendering buffer 0 as a front buffer |
|
1514 |
|
1515 //TODO: what else? |
|
1516 EGL_RETURN(EGL_SUCCESS,EGL_TRUE); |
|
1517 } |
|
1518 |
|
1519 // ----------------------------------------------------------------------------- |
|
1520 // |
|
1521 // ----------------------------------------------------------------------------- |
|
1522 // |
|
1523 TSurfaceInfo* EGL::EglInternalFunction_GetPlatformSurface( EGLDisplay display, EGLSurface surface ) |
|
1524 { |
|
1525 EGL_TRACE( "EGL::EglInternalFunction_GetPlatformSurface"); |
|
1526 TSurfaceInfo* result = NULL; |
|
1527 |
|
1528 iDisplayMapLock.ReadLock(); |
|
1529 |
|
1530 CEglDisplayInfo** pDispInfo = iDisplayMap.Find( display ); |
|
1531 if (pDispInfo && *pDispInfo) |
|
1532 { |
|
1533 TSurfaceInfo** pSurfaceInfo = (*pDispInfo)->iSurfaceMap.Find( surface ); |
|
1534 if (pSurfaceInfo) |
|
1535 { |
|
1536 result = *pSurfaceInfo; |
|
1537 } |
|
1538 } |
|
1539 |
|
1540 // TODO on success should probably Unlock() the surface in the caller |
|
1541 iDisplayMapLock.Unlock(); |
|
1542 |
|
1543 /* TODO review calling code, to see if this suggestion makes sense |
|
1544 if (result == NULL) |
|
1545 { |
|
1546 EGL_RAISE_ERROR( EGL_BAD_SURFACE, NULL); //Enable this when all surfaces are in surface map |
|
1547 } |
|
1548 */ |
|
1549 return result; |
|
1550 } |
|
1551 |
|
1552 EGLBoolean EGL::EglInternalFunction_SurfaceResized(/*TEglThreadState&,*/ TSurfaceInfo&, int, int) |
|
1553 { |
|
1554 return EFalse; // stub code |
|
1555 } |
1497 |
1556 |
1498 /*-------------------------------------------------------------------*//*! |
1557 /*-------------------------------------------------------------------*//*! |
1499 * \brief |
1558 * \brief |
1500 * \param |
1559 * \param |
1501 * \return |
1560 * \return |
1892 #else |
1951 #else |
1893 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) |
1952 EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) |
1894 #endif |
1953 #endif |
1895 { |
1954 { |
1896 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
1955 EGL_GET_DISPLAY(dpy, EGL_FALSE); |
|
1956 // From guestEGL - eglMakeCurrent |
|
1957 if (ctx == EGL_NO_CONTEXT) |
|
1958 { |
|
1959 // what now?? |
|
1960 EGL_TRACE("eglMakeCurrent context NO_CONTEXT"); |
|
1961 if ( (draw != EGL_NO_SURFACE) || (read != EGL_NO_SURFACE) ) |
|
1962 { |
|
1963 EGL_RETURN(EGL_BAD_SURFACE, EGL_FALSE); |
|
1964 } |
|
1965 } |
|
1966 else |
|
1967 { |
|
1968 if ( (draw == EGL_NO_SURFACE) || (read == EGL_NO_SURFACE) ) |
|
1969 { |
|
1970 EGL_RETURN(EGL_BAD_SURFACE, EGL_FALSE); |
|
1971 |
|
1972 } |
|
1973 // ToDo use new CEglContext code |
|
1974 const TInt KMaxSurfaces( 2 ); |
|
1975 EGLSurface surfaces[KMaxSurfaces]; |
|
1976 TSurfaceInfo* surfaceInfo[KMaxSurfaces] = {NULL, NULL}; |
|
1977 surfaces[0] = draw; |
|
1978 if (draw != read) |
|
1979 { |
|
1980 surfaces[1] = read; |
|
1981 } |
|
1982 else |
|
1983 { |
|
1984 surfaces[1] = EGL_NO_SURFACE; |
|
1985 } |
|
1986 |
|
1987 for ( TInt i = 0; i < KMaxSurfaces; i++ ) |
|
1988 { |
|
1989 if ( EGL_NO_SURFACE != surfaces[i] ) |
|
1990 { |
|
1991 EGL_TRACE("eglMakeCurrent check surface %d", surfaces[i] ); |
|
1992 surfaceInfo[i] = getEGL()->EglInternalFunction_GetPlatformSurface( dpy, surfaces[i] ); |
|
1993 EGL_TRACE("eglMakeCurrent surfaces[%d] is %x", i, surfaces[i]); |
|
1994 //EGL_CHECK_ERROR( surfaceInfo, EGL_BAD_SURFACE , EGL_FALSE ); |
|
1995 if ( surfaceInfo[i] ) |
|
1996 { |
|
1997 TSize newSize; |
|
1998 switch (surfaceInfo[i]->iSurfaceType) |
|
1999 { |
|
2000 case ESurfaceTypePixmapFbsBitmap: |
|
2001 EGLPANIC_ASSERT_DEBUG(surfaceInfo[i]->iFbsBitmap, EEglPanicTemp); |
|
2002 newSize = surfaceInfo[i]->iFbsBitmap->SizeInPixels(); |
|
2003 break; |
|
2004 case ESurfaceTypeWindow: |
|
2005 EGLPANIC_ASSERT_DEBUG(surfaceInfo[i]->iNativeWindow, EEglPanicTemp); |
|
2006 newSize = surfaceInfo[i]->iNativeWindow.SizeInPixels(); |
|
2007 break; |
|
2008 default: |
|
2009 // size cannot change for other surface types |
|
2010 newSize = surfaceInfo[i]->iSize; |
|
2011 break; |
|
2012 } |
|
2013 if (newSize != surfaceInfo[i]->iSize) |
|
2014 { |
|
2015 EGL_TRACE("eglMakeCurrent resize surface"); |
|
2016 if ( !getEGL()->EglInternalFunction_SurfaceResized(/*aThreadState,*/ *surfaceInfo[i], dpy, surfaces[i] ) ) |
|
2017 { |
|
2018 return EGL_FALSE; |
|
2019 } |
|
2020 surfaceInfo[i]->iSize = newSize; |
|
2021 } |
|
2022 } |
|
2023 } |
|
2024 } |
|
2025 |
|
2026 // adapt to only some surfaces having CEglSurfaceInfo objects so far |
|
2027 EGLSurface drawId = surfaceInfo[0] ? surfaceInfo[0]->iSurface : draw; |
|
2028 EGLSurface readId = read; |
|
2029 if ((read == draw) && surfaceInfo[0]) |
|
2030 { |
|
2031 readId = surfaceInfo[0]->iSurface; |
|
2032 } |
|
2033 else if (surfaceInfo[1]) |
|
2034 { |
|
2035 readId = surfaceInfo[1]->iSurface; |
|
2036 } |
|
2037 |
|
2038 EGL_TRACE(" eglMakeCurrent surfaces[0]=0x%x, surfaces[1]=0x%x", surfaces[0], surfaces[1]); |
|
2039 EGL_TRACE(" eglMakeCurrent surfacesInfo[0]=0x%x, surfacesInfo[0].iSurface=0x%x", |
|
2040 surfaceInfo[0], surfaceInfo[0] ? surfaceInfo[0]->iSurface : NULL); |
|
2041 EGL_TRACE(" eglMakeCurrent surfacesInfo[1]=0x%x, surfacesInfo[1].iSurface=0x%x", |
|
2042 surfaceInfo[1], surfaceInfo[1] ? surfaceInfo[1]->iSurface : NULL); |
|
2043 |
|
2044 EGL_TRACE("CGuestEGL::eglMakeCurrent call host"); |
|
2045 // now we need to use readId and drawId |
|
2046 draw = drawId; |
|
2047 read = readId; |
|
2048 } |
|
2049 // end from guestEGL |
|
2050 /* following is original EGL... very much different to hostEGL! |
|
2051 * is that an issue? |
|
2052 * Works only with one buffer... draw only used from now on? |
|
2053 */ |
1897 EGL_IF_ERROR(ctx != EGL_NO_CONTEXT && !display->contextExists(ctx), EGL_BAD_CONTEXT, EGL_FALSE); |
2054 EGL_IF_ERROR(ctx != EGL_NO_CONTEXT && !display->contextExists(ctx), EGL_BAD_CONTEXT, EGL_FALSE); |
1898 EGL_IF_ERROR(draw != EGL_NO_SURFACE && !display->surfaceExists(draw), EGL_BAD_SURFACE, EGL_FALSE); |
2055 EGL_IF_ERROR(draw != EGL_NO_SURFACE && !display->surfaceExists(draw), EGL_BAD_SURFACE, EGL_FALSE); |
1899 EGL_IF_ERROR(read != EGL_NO_SURFACE && !display->surfaceExists(read), EGL_BAD_SURFACE, EGL_FALSE); |
2056 EGL_IF_ERROR(read != EGL_NO_SURFACE && !display->surfaceExists(read), EGL_BAD_SURFACE, EGL_FALSE); |
1900 EGL_IF_ERROR(draw != read, EGL_BAD_MATCH, EGL_FALSE); //TODO what's the proper error code? |
2057 EGL_IF_ERROR(draw != read, EGL_BAD_MATCH, EGL_FALSE); //TODO what's the proper error code? |
1901 EGL_IF_ERROR((draw != EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT) || (draw == EGL_NO_SURFACE && ctx != EGL_NO_CONTEXT), EGL_BAD_MATCH, EGL_FALSE); |
2058 EGL_IF_ERROR((draw != EGL_NO_SURFACE && ctx == EGL_NO_CONTEXT) || (draw == EGL_NO_SURFACE && ctx != EGL_NO_CONTEXT), EGL_BAD_MATCH, EGL_FALSE); |
2202 #ifdef BUILD_WITH_PRIVATE_OPENVG |
2375 #ifdef BUILD_WITH_PRIVATE_OPENVG |
2203 /*do_vg*/vgFlush(); |
2376 /*do_vg*/vgFlush(); |
2204 #else |
2377 #else |
2205 vgFlush(); |
2378 vgFlush(); |
2206 #endif |
2379 #endif |
2207 |
2380 |
|
2381 EGLint currentApi = currentThread->getBoundAPI(); |
|
2382 RIEGLContext* context = currentThread->getCurrentContext(); |
|
2383 switch( currentApi ) |
|
2384 { |
|
2385 case EGL_OPENVG_API: |
|
2386 { |
|
2387 //if( thread->CurrentVGContext() != surface->BoundContext() ) |
|
2388 if( currentThread->getCurrentContext()->getVGContext() != s->getOSWindowContext() ) // getOSWindowContext?? |
|
2389 { |
|
2390 //EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE ); |
|
2391 EGL_TRACE("eglSwapBuffers EGL_BAD_SURFACE for EGL_OPENVG_API "); |
|
2392 //EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE); // commnted out as the check against OSWindowContext seems wrong |
|
2393 } |
|
2394 break; |
|
2395 } |
|
2396 case EGL_OPENGL_ES_API: |
|
2397 { |
|
2398 /* |
|
2399 if( thread->CurrentGLESContext() != surface->BoundContext() ) |
|
2400 { |
|
2401 EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_SURFACE ); |
|
2402 } |
|
2403 */ |
|
2404 EGL_RETURN(EGL_BAD_SURFACE,EGL_FALSE); |
|
2405 // \todo other GLES stuff? |
|
2406 } |
|
2407 } |
|
2408 |
|
2409 |
|
2410 |
|
2411 /* |
|
2412 * ToDo |
|
2413 * from hostegl |
|
2414 if( !(CEGLOs::IsValidNativeWindow(((CEGLWindowSurface*)surface)->NativeType())) ) |
|
2415 */ |
2208 if(!s->getOSWindowContext()) |
2416 if(!s->getOSWindowContext()) |
2209 { //do nothing for other than window surfaces (NOTE: single-buffered window surfaces should return immediately as well) |
2417 { //do nothing for other than window surfaces (NOTE: single-buffered window surfaces should return immediately as well) |
2210 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
2418 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
2211 } |
2419 } |
2212 |
2420 if( surfaceInfo->iSurfaceType != ESurfaceTypeWindow || s->getRenderBuffer() == EGL_SINGLE_BUFFER ) |
|
2421 { |
|
2422 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
2423 } |
|
2424 |
2213 int windowWidth = 0, windowHeight = 0; |
2425 int windowWidth = 0, windowHeight = 0; |
2214 OSGetWindowSize(s->getOSWindowContext(), windowWidth, windowHeight); |
2426 OSGetWindowSize(s->getOSWindowContext(), windowWidth, windowHeight); |
2215 |
2427 /* |
|
2428 * TODO |
|
2429 * what we need to do for resize to work? |
|
2430 */ |
2216 if(windowWidth != s->getDrawable()->getWidth() || windowHeight != s->getDrawable()->getHeight()) |
2431 if(windowWidth != s->getDrawable()->getWidth() || windowHeight != s->getDrawable()->getHeight()) |
2217 { //resize the back buffer |
2432 { //resize the back buffer |
2218 RIEGLContext* c = currentThread->getCurrentContext(); |
2433 RIEGLContext* c = currentThread->getCurrentContext(); |
2219 RI_ASSERT(c); |
2434 RI_ASSERT(c); |
|
2435 /* from hostEGL |
|
2436 if( !(surface->Resize(w, h)) ) |
|
2437 { |
|
2438 EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC ); |
|
2439 } |
|
2440 */ |
2220 try |
2441 try |
2221 { |
2442 { |
2222 s->getDrawable()->resize(windowWidth, windowHeight); //throws bad_alloc |
2443 s->getDrawable()->resize(windowWidth, windowHeight); //throws bad_alloc |
2223 } |
2444 } |
2224 catch(std::bad_alloc) |
2445 catch(std::bad_alloc) |
2225 { |
2446 { |
2226 c->getVGContext()->setDefaultDrawable(NULL); |
2447 c->getVGContext()->setDefaultDrawable(NULL); |
2227 EGL_RETURN(EGL_BAD_ALLOC, EGL_FALSE); |
2448 EGL_RETURN(EGL_BAD_ALLOC, EGL_FALSE); |
2228 } |
2449 } |
2229 } |
2450 if( windowWidth <= 0 || windowHeight <= 0 ) |
2230 |
2451 { |
|
2452 // invisible window => do nothing |
|
2453 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
2454 } |
|
2455 /* |
|
2456 * what is this for? From hostEgl... |
|
2457 |
|
2458 if( surface->VGClientSurface() && state->VGInterface() ) |
|
2459 { |
|
2460 if( !(state->VGInterface()->ResizeSurface(thread->CurrentVGContext()->ClientContext(), |
|
2461 surface->VGClientSurface(), w, h, surface->VGBuffers())) ) |
|
2462 { |
|
2463 EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ALLOC ); |
|
2464 } |
|
2465 } |
|
2466 */ |
|
2467 } |
|
2468 |
|
2469 |
|
2470 // |
|
2471 |
|
2472 void* buf = NULL; |
|
2473 if (surfaceInfo->iFrontBuffer == 0) |
|
2474 { |
|
2475 buf = surfaceInfo->iBuffer1; |
|
2476 } |
|
2477 else |
|
2478 { |
|
2479 buf = surfaceInfo->iBuffer0; |
|
2480 } |
|
2481 |
|
2482 // |
|
2483 switch( currentApi ) |
|
2484 { |
|
2485 case EGL_OPENVG_API: |
|
2486 { |
|
2487 //VGImageFormat format = VG_sARGB_8888_PRE; // hack!! |
|
2488 VGImageFormat format = VG_sARGB_8888; // hack!! |
|
2489 //VGImageFormat format = VG_sRGBA_8888; // hack!! |
|
2490 // |
|
2491 vgReadPixels(buf,surfaceInfo->iStride,format,0,0,windowWidth,windowHeight); |
|
2492 break; |
|
2493 } |
|
2494 case EGL_OPENGL_ES_API: |
|
2495 { |
|
2496 /* |
|
2497 if( surface->BoundContext() && !(state->GLESInterface(surface->BoundContext()->ClientVersion())) ) |
|
2498 { |
|
2499 // \todo error code? |
|
2500 EGLI_LEAVE_RET( EGL_FALSE, EGL_BAD_ACCESS ); |
|
2501 } |
|
2502 */ |
|
2503 EGL_RETURN(EGL_BAD_ACCESS, EGL_FALSE); |
|
2504 } |
|
2505 } |
|
2506 // |
2231 OSBlitToWindow(s->getOSWindowContext(), s->getDrawable()); |
2507 OSBlitToWindow(s->getOSWindowContext(), s->getDrawable()); |
2232 |
2508 getEGL()->EglInternalFunction_SwapBuffers(dpy, surface); |
2233 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
2509 |
|
2510 |
|
2511 EGL_RETURN(EGL_SUCCESS, EGL_TRUE); |
|
2512 } |
|
2513 |
|
2514 TBool EGL::EglInternalFunction_SwapBuffers(EGLDisplay aDisplay, EGLSurface aSurface) |
|
2515 { |
|
2516 TSize size = iSurfaceInfo.iNativeWindow.SizeInPixels(); |
|
2517 |
|
2518 TRequestStatus status; |
|
2519 TTimeStamp timestampLocalToThread; |
|
2520 // session needs to be established |
|
2521 iSurfaceInfo.iSurfaceUpdateSession.NotifyWhenDisplayed(status, timestampLocalToThread); |
|
2522 // what to do if native window is not RWindow??? |
|
2523 if (iSurfaceInfo.iFrontBuffer == 0) |
|
2524 { |
|
2525 iSurfaceInfo.iFrontBuffer = 1; |
|
2526 } |
|
2527 else |
|
2528 { |
|
2529 iSurfaceInfo.iFrontBuffer = 0; |
|
2530 } |
|
2531 iSurfaceInfo.iSurfaceUpdateSession.SubmitUpdate(iSurfaceInfo.iScreenNumber,iSurfaceInfo.iSurfaceId, iSurfaceInfo.iFrontBuffer); |
|
2532 User::WaitForRequest(status); |
|
2533 |
|
2534 if (size != iSurfaceInfo.iSize) |
|
2535 { |
|
2536 EGL_TRACE("EGL::EglInternalFunction_SwapBuffers Surface Resized size=%d,%d, iSurfaceInfo.iSize=%d,%d", |
|
2537 size.iHeight, size.iWidth, iSurfaceInfo.iSize.iHeight, iSurfaceInfo.iSize.iWidth); |
|
2538 |
|
2539 return EglInternalFunction_SurfaceResized(/*aThreadState,*/ iSurfaceInfo, aDisplay, aSurface); // TODO handling of resize |
|
2540 } |
|
2541 return EGL_TRUE; |
2234 } |
2542 } |
2235 |
2543 |
2236 /*-------------------------------------------------------------------*//*! |
2544 /*-------------------------------------------------------------------*//*! |
2237 * \brief |
2545 * \brief |
2238 * \param |
2546 * \param |