1 /******************************************************************************
2
3 @File KEGL/PVRShellAPI.cpp
4
5 @Title KEGL/PVRShellAPI
6
7 @Version
8
9 @Copyright Copyright (c) Imagination Technologies Limited.
10
11 @Platform Independent
12
13 @Description Makes programming for 3D APIs easier by wrapping surface
14 initialization, Texture allocation and other functions for use by a demo.
15
16 ******************************************************************************/
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stdarg.h>
22
23 #include "PVRShell.h"
24 #include "PVRShellAPI.h"
25 #include "PVRShellOS.h"
26 #include "PVRShellImpl.h"
27
28 // No Doxygen for CPP files, due to documentation duplication
29 /// @cond NO_DOXYGEN
30
31 #ifndef EGL_CONTEXT_LOST_IMG
32 /*! Extended error code EGL_CONTEXT_LOST_IMG generated when power management event has occurred. */
33 #define EGL_CONTEXT_LOST_IMG 0x300E
34 #endif
35
36 #ifndef EGL_CONTEXT_PRIORITY_LEVEL_IMG
37 /*! An extensions added to the list of attributes for the context to give it a priority hint */
38 #define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
39 /*! Request the context is created with high priority */
40 #define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
41 /*! Request the context is created with medium priority */
42 #define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
43 /*! Request the context is created with low priority */
44 #define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
45 #endif
46
47 /*****************************************************************************
48 Declarations
49 *****************************************************************************/
50 static bool PVRShellIsExtensionSupported(EGLDisplay dpy, const char *extension);
51
52 #if defined GL_ES_VERSION_2_0 && !defined EGL_VERSION_1_3
53 #error OpenGL ES 2 requires egl.h version 1.3 or higher
54 #endif
55
56 /****************************************************************************
57 ** Class: PVRShellInitAPI
58 ****************************************************************************/
59
60 /*****************************************************************************
61 * Function Name : ActivatePreferences
62 * Description : Activates the user set preferences (like v-sync)
63 *****************************************************************************/
ApiActivatePreferences()64 void PVRShellInit::ApiActivatePreferences()
65 {
66
67 #ifdef EGL_VERSION_1_1
68 eglSwapInterval(m_EGLDisplay, m_pShell->m_pShellData->nSwapInterval);
69 #endif
70 }
71
72 /*****************************************************************************
73 * Function Name : ApiInitAPI
74 * Returns : true for success
75 * Description : Initialise the 3D API
76 *****************************************************************************/
ApiInitAPI()77 bool PVRShellInit::ApiInitAPI()
78 {
79 int bDone;
80
81 m_NDT = (EGLNativeDisplayType)OsGetNativeDisplayType();
82 m_NPT = (EGLNativePixmapType) OsGetNativePixmapType();
83 m_NWT = (EGLNativeWindowType) OsGetNativeWindowType();
84
85 m_EGLContext = 0;
86
87 do
88 {
89 bDone = true;
90
91 m_EGLDisplay = eglGetDisplay(m_NDT);
92
93 if(m_EGLDisplay == EGL_NO_DISPLAY)
94 {
95 #if defined(BUILD_OGLES2) || defined(BUILD_OGLES3)
96 m_EGLDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);
97 #else
98 m_EGLDisplay = eglGetDisplay((NativeDisplayType)EGL_DEFAULT_DISPLAY);
99 #endif
100 }
101
102 if(!eglInitialize(m_EGLDisplay, &m_MajorVersion, &m_MinorVersion))
103 {
104 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to initialise EGL\n");
105 m_pShell->PVRShellOutputDebug("PVRShell: EGL Error (%s)\n", StringFrom_eglGetError());
106 return false;
107 }
108
109 m_pShell->PVRShellOutputDebug("PVRShell: EGL %d.%d initialized\n", m_MajorVersion, m_MinorVersion);
110
111 // Check Extension availability after EGL initialization
112 if (m_MajorVersion > 1 || (m_MajorVersion == 1 && m_MinorVersion >= 1))
113 {
114 m_bPowerManagementSupported = true;
115 }
116 else
117 {
118 m_bPowerManagementSupported = PVRShellIsExtensionSupported(m_EGLDisplay,"EGL_IMG_power_management");
119 }
120
121 do
122 {
123 #if defined(BUILD_OGL)
124 if(!eglBindAPI(EGL_OPENGL_API))
125 {
126 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to bind OpenGL API\n");
127 return false;
128 }
129 #else
130 #if defined EGL_VERSION_1_3 && defined GL_ES_VERSION_2_0
131 if(!eglBindAPI(EGL_OPENGL_ES_API))
132 {
133 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to bind OpenGL ES API\n");
134 return false;
135 }
136 #endif
137 #endif
138 // Find an EGL config
139 m_EGLConfig = SelectEGLConfiguration(m_pShell->m_pShellData);
140 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_CONFIG_ID, &m_iConfig);
141
142 // Destroy the context if we already created one
143 if (m_EGLContext)
144 {
145 eglDestroyContext(m_EGLDisplay, m_EGLContext);
146 }
147
148 // Attempt to create a context
149 EGLint ai32ContextAttribs[48];
150 int i = 0;
151
152 #if defined(BUILD_OGLES3)
153 ai32ContextAttribs[i++] = EGL_CONTEXT_CLIENT_VERSION;
154 ai32ContextAttribs[i++] = 3;
155 #else
156 #if defined(EGL_VERSION_1_3) && defined(GL_ES_VERSION_2_0)
157 ai32ContextAttribs[i++] = EGL_CONTEXT_CLIENT_VERSION;
158 ai32ContextAttribs[i++] = 2;
159 #endif
160 #endif
161
162 #if defined(BUILD_OGL)
163 //Attempt to create an OpenGL 3.2 context.
164 if (PVRShellIsExtensionSupported(m_EGLDisplay, "EGL_KHR_create_context"))
165 {
166 ai32ContextAttribs[i++] = EGL_CONTEXT_MAJOR_VERSION_KHR;
167 ai32ContextAttribs[i++] = 3;
168 ai32ContextAttribs[i++] = EGL_CONTEXT_MINOR_VERSION_KHR;
169 ai32ContextAttribs[i++] = 2;
170 ai32ContextAttribs[i++] = EGL_CONTEXT_FLAGS_KHR;
171 ai32ContextAttribs[i++] = EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
172 ai32ContextAttribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
173 ai32ContextAttribs[i++] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
174 }
175 #endif
176
177 #if defined(BUILD_OGLES) || defined(BUILD_OGLES2) || defined(BUILD_OGLES3)
178 if(PVRShellIsExtensionSupported(m_EGLDisplay,"EGL_IMG_context_priority"))
179 {
180 ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_LEVEL_IMG;
181 switch(m_pShell->PVRShellGet(prefPriority))
182 {
183 case 0: ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_LOW_IMG; break;
184 case 1: ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_MEDIUM_IMG; break;
185 default:ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_HIGH_IMG; break;
186 }
187 }
188 #endif
189 ai32ContextAttribs[i] = EGL_NONE;
190
191 if (m_EGLContext == EGL_NO_CONTEXT)
192 {
193 m_EGLContext = eglCreateContext(m_EGLDisplay, m_EGLConfig, NULL, ai32ContextAttribs);
194 }
195
196 if(m_EGLContext == EGL_NO_CONTEXT)
197 {
198 if(m_iRequestedConfig > 0)
199 {
200 // We failed to create a context
201 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to create a context\n");
202 return false;
203 }
204 else if(m_pShell->m_pShellData->bNeedPbuffer)
205 {
206 // Disable P-buffer and try again
207 m_pShell->m_pShellData->bNeedPbuffer = false;
208 }
209 else if(m_pShell->m_pShellData->bNeedStencilBuffer)
210 {
211 // Disable Stencil Buffer and try again
212 m_pShell->m_pShellData->bNeedStencilBuffer = false;
213 }
214 else if(m_pShell->m_pShellData->nAASamples > 0)
215 {
216 // Still failing, reduce the AA samples and try again
217 --m_pShell->m_pShellData->nAASamples;
218 }
219 else
220 {
221 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to create a context\n");
222 return false;
223 }
224 }
225 } while(m_EGLContext == EGL_NO_CONTEXT);
226
227 #if defined(__QNXNTO__)
228 int format = SCREEN_FORMAT_RGBX8888;
229 if(screen_set_window_property_iv((_screen_window*) m_NWT, SCREEN_PROPERTY_FORMAT, &format))
230 {
231 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to set window property SCREEN_PROPERTY_FORMAT\n");
232 return false;
233 }
234
235 #if defined(BUILD_OGLES2)
236 int usage = SCREEN_USAGE_OPENGL_ES2;
237 #else
238 #if defined(BUILD_OGLES)
239 int usage = SCREEN_USAGE_OPENGL_ES1;
240 #endif
241 #endif
242 if(screen_set_window_property_iv((_screen_window*) m_NWT, SCREEN_PROPERTY_USAGE, &usage))
243 {
244 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to set window property SCREEN_PROPERTY_USAGE\n");
245 return false;
246 }
247
248 if(screen_create_window_buffers((_screen_window*) m_NWT, 2))
249 {
250 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to create window buffers\n");
251 return false;
252 }
253 #endif
254 EGLint attrib_list[16];
255 int i = 0;
256 #if defined(EGL_VERSION_1_2)
257 if(m_pShell->m_pShellData->bNeedAlphaFormatPre) // The default is EGL_ALPHA_FORMAT_NONPRE
258 {
259 attrib_list[i++] = EGL_ALPHA_FORMAT;
260 attrib_list[i++] = EGL_ALPHA_FORMAT_PRE;
261 }
262 #endif
263 // Terminate the attribute list with EGL_NONE
264 attrib_list[i] = EGL_NONE;
265
266 if(m_pShell->m_pShellData->bNeedPixmap)
267 {
268 m_pShell->PVRShellOutputDebug("InitAPI() Using pixmaps, about to create egl surface\n");
269 m_EGLWindow = eglCreatePixmapSurface(m_EGLDisplay, m_EGLConfig, m_NPT, attrib_list);
270 }
271 else
272 {
273 #if defined(ANDROID)
274 EGLint visualID;
275 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_NATIVE_VISUAL_ID, &visualID);
276
277 // Change the format of our window to match our config
278 ANativeWindow_setBuffersGeometry(m_NWT, 0, 0, visualID);
279 #endif
280 m_EGLWindow = eglCreateWindowSurface(m_EGLDisplay, m_EGLConfig, m_NWT, attrib_list);
281
282 // If we have failed to create a surface then try using Null
283 if(m_EGLWindow == EGL_NO_SURFACE)
284 {
285 m_EGLWindow = eglCreateWindowSurface(m_EGLDisplay, m_EGLConfig, NULL, attrib_list);
286 }
287 }
288
289 if (m_EGLWindow == EGL_NO_SURFACE)
290 {
291 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to create surface\n");
292 return false;
293 }
294
295 if (!eglMakeCurrent(m_EGLDisplay, m_EGLWindow, m_EGLWindow, m_EGLContext))
296 {
297 #ifdef EGL_VERSION_1_3
298 if((eglGetError() == EGL_CONTEXT_LOST))
299 #else
300 if((eglGetError() == EGL_CONTEXT_LOST_IMG) && m_bPowerManagementSupported)
301 #endif
302 {
303 bDone = false;
304 }
305 else
306 {
307 m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to make context current\n");
308 return false;
309 }
310 }
311 } while(!bDone);
312
313 /*
314 Get correct screen width and height and
315 save them into
316 m_pShell->m_pShellData->nShellDimX and
317 m_pShell->m_pShellData->nShellDimY
318 */
319 eglQuerySurface(m_EGLDisplay, m_EGLWindow,
320 EGL_WIDTH, (EGLint*)&m_pShell->m_pShellData->nShellDimX
321 );
322 eglQuerySurface(m_EGLDisplay, m_EGLWindow,
323 EGL_HEIGHT, (EGLint*)&m_pShell->m_pShellData->nShellDimY
324 );
325
326 #if defined(ANDROID)
327 glViewport(0, 0, m_pShell->m_pShellData->nShellDimX, m_pShell->m_pShellData->nShellDimY);
328 #endif
329 /*
330 Done - activate requested features
331 */
332
333 #if defined(BUILD_OGLES) || defined(BUILD_OGLES2)
334 //Get the discardframebufferEXT function.
335 {
336 //Get the gl extension string
337 const char* strExtensions = (const char*)glGetString(GL_EXTENSIONS);
338
339 //Get the length of the string we're searching for
340 const size_t strLength = strlen("GL_EXT_discard_framebuffer");
341
342 //Get the string position
343 const char* position = strstr(strExtensions,"GL_EXT_discard_framebuffer");
344
345 //Loop through until we find the actual extension, avoiding substrings.
346 while (position!=NULL && position[strLength]!='\0' && position[strLength]!=' ')
347 {
348 position = strstr(position+strLength,"GL_EXT_discard_framebuffer");
349 }
350
351 //Initialise the extension if it's found.
352 if (position != NULL)
353 {
354 glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT");
355 }
356 else
357 {
358 glDiscardFramebufferEXT = NULL;
359 }
360 }
361 #endif
362 ApiActivatePreferences();
363 return true;
364 }
365
366 /*!***********************************************************************
367 @Function OutputAPIInfo
368 @description When prefOutputInfo is set to true this function outputs
369 various pieces of API dependent information via
370 PVRShellOutputDebug.
371 *************************************************************************/
OutputAPIInfo()372 void PVRShellInit::OutputAPIInfo()
373 {
374 // Output API dependent information
375 if(m_pShell->PVRShellGet(prefOutputInfo))
376 {
377 EGLint i32Values[5];
378
379 m_pShell->PVRShellOutputDebug("\n");
380
381 m_pShell->PVRShellOutputDebug("GL:\n");
382 m_pShell->PVRShellOutputDebug(" Vendor: %s\n", (char*) glGetString(GL_VENDOR));
383 m_pShell->PVRShellOutputDebug(" Renderer: %s\n", (char*) glGetString(GL_RENDERER));
384 m_pShell->PVRShellOutputDebug(" Version: %s\n", (char*) glGetString(GL_VERSION));
385 m_pShell->PVRShellOutputDebug(" Extensions: ");
386
387 #if defined(BUILD_OGL)
388 //Get the glGetString process.
389 typedef const GLubyte* (KHRONOS_APIENTRY * PFNGLGETSTRINGIPROC)(GLenum name, GLuint index);
390 PFNGLGETSTRINGIPROC glGetStringi = (PFNGLGETSTRINGIPROC)eglGetProcAddress("glGetStringi");
391
392 //If we've successfully got the new way to query the string, then go ahead and use this.
393 if (glGetStringi)
394 {
395 #ifndef GL_NUM_EXTENSIONS
396 #define GL_NUM_EXTENSIONS 0x821D
397 #endif
398 GLint numExtensions;
399 glGetIntegerv(GL_NUM_EXTENSIONS,&numExtensions);
400
401 for (GLint i=0; i<numExtensions; ++i)
402 {
403 m_pShell->PVRShellOutputDebug((const char*)glGetStringi(GL_EXTENSIONS,i));
404 m_pShell->PVRShellOutputDebug(" ");
405 }
406 }
407 #else
408 m_pShell->PVRShellOutputDebug("%s\n", (char*) glGetString(GL_EXTENSIONS));
409 #endif
410
411 m_pShell->PVRShellOutputDebug("\n");
412
413 m_pShell->PVRShellOutputDebug("\n");
414 m_pShell->PVRShellOutputDebug("EGL:\n");
415 m_pShell->PVRShellOutputDebug(" Vendor: %s\n" , (char*) eglQueryString(m_EGLDisplay, EGL_VENDOR));
416 m_pShell->PVRShellOutputDebug(" Version: %s\n" , (char*) eglQueryString(m_EGLDisplay, EGL_VERSION));
417 m_pShell->PVRShellOutputDebug(" Extensions: %s\n" , (char*) eglQueryString(m_EGLDisplay, EGL_EXTENSIONS));
418
419 if(eglQueryContext(m_EGLDisplay, m_EGLContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &i32Values[0]))
420 {
421 switch(i32Values[0])
422 {
423 case EGL_CONTEXT_PRIORITY_HIGH_IMG: m_pShell->PVRShellOutputDebug(" Context priority: High\n"); break;
424 case EGL_CONTEXT_PRIORITY_MEDIUM_IMG: m_pShell->PVRShellOutputDebug(" Context priority: Medium\n");break;
425 case EGL_CONTEXT_PRIORITY_LOW_IMG: m_pShell->PVRShellOutputDebug(" Context priority: Low\n"); break;
426 default: m_pShell->PVRShellOutputDebug(" Context priority: Unrecognised.\n"); break;
427 }
428 }
429 else
430 {
431 eglGetError(); // Clear error
432 m_pShell->PVRShellOutputDebug(" Context priority: Unsupported\n");
433 }
434
435 #ifdef EGL_VERSION_1_2
436 m_pShell->PVRShellOutputDebug(" Client APIs: %s\n" , (char*) eglQueryString(m_EGLDisplay, EGL_CLIENT_APIS));
437 #endif
438
439 m_pShell->PVRShellOutputDebug("\n");
440 m_pShell->PVRShellOutputDebug("Window Width: %i\n" , m_pShell->PVRShellGet(prefWidth));
441 m_pShell->PVRShellOutputDebug("Window Height: %i\n" , m_pShell->PVRShellGet(prefHeight));
442 m_pShell->PVRShellOutputDebug("Is Rotated: %s\n", m_pShell->PVRShellGet(prefIsRotated) ? "Yes" : "No");
443 m_pShell->PVRShellOutputDebug("\n");
444
445 // EGLSurface details
446 m_pShell->PVRShellOutputDebug("EGL Surface:\n");
447 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_CONFIG_ID , &i32Values[0]);
448 m_pShell->PVRShellOutputDebug(" Config ID: %i\n", i32Values[0]);
449
450 // Colour buffer
451 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_BUFFER_SIZE , &i32Values[0]);
452 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_RED_SIZE , &i32Values[1]);
453 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_GREEN_SIZE , &i32Values[2]);
454 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_BLUE_SIZE , &i32Values[3]);
455 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_ALPHA_SIZE , &i32Values[4]);
456 m_pShell->PVRShellOutputDebug(" Colour Buffer: %i bits (R%i G%i B%i A%i)\n", i32Values[0],i32Values[1],i32Values[2],i32Values[3],i32Values[4]);
457
458 // Depth buffer
459 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_DEPTH_SIZE , &i32Values[0]);
460 m_pShell->PVRShellOutputDebug(" Depth Buffer: %i bits\n", i32Values[0]);
461
462 // Stencil Buffer
463 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_STENCIL_SIZE , &i32Values[0]);
464 m_pShell->PVRShellOutputDebug(" Stencil Buffer: %i bits\n", i32Values[0]);
465
466 // EGL surface bits support
467 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_SURFACE_TYPE , &i32Values[0]);
468 m_pShell->PVRShellOutputDebug(" Surface type: %s%s%s\n", i32Values[0] & EGL_WINDOW_BIT ? "WINDOW " : "",
469 i32Values[1] & EGL_PBUFFER_BIT ? "PBUFFER " : "",
470 i32Values[2] & EGL_PIXMAP_BIT ? "PIXMAP " : "");
471 // EGL renderable type
472 #ifdef EGL_VERSION_1_2
473 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_RENDERABLE_TYPE , &i32Values[0]);
474 m_pShell->PVRShellOutputDebug(" Renderable type: %s%s%s%s\n", i32Values[0] & EGL_OPENVG_BIT ? "OPENVG " : "",
475 i32Values[0] & EGL_OPENGL_ES_BIT ? "OPENGL_ES " : "",
476 #ifdef EGL_OPENGL_BIT
477 i32Values[0] & EGL_OPENGL_BIT ? "OPENGL " :
478 #endif
479 "",
480 i32Values[0] & EGL_OPENGL_ES2_BIT ? "OPENGL_ES2 " : "");
481 #endif
482
483 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_SAMPLE_BUFFERS , &i32Values[0]);
484 eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_SAMPLES , &i32Values[1]);
485 m_pShell->PVRShellOutputDebug(" Sample buffer No.: %i\n", i32Values[0]);
486 m_pShell->PVRShellOutputDebug(" Samples per pixel: %i\n", i32Values[1]);
487 }
488 }
489
490 /*!***********************************************************************
491 @Function ApiReleaseAPI
492 @description Releases all resources allocated by the API.
493 *************************************************************************/
ApiReleaseAPI()494 void PVRShellInit::ApiReleaseAPI()
495 {
496 eglSwapBuffers(m_EGLDisplay, m_EGLWindow);
497 eglMakeCurrent(m_EGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
498 eglDestroyContext(m_EGLDisplay, m_EGLContext);
499 eglDestroySurface(m_EGLDisplay, m_EGLWindow);
500 eglTerminate(m_EGLDisplay);
501 }
502
503 /*******************************************************************************
504 * Function Name : SelectEGLConfiguration
505 * Inputs : pData
506 * Returns : EGLConfig
507 * Description : Find the config to use for EGL initialisation
508 *******************************************************************************/
SelectEGLConfiguration(const PVRShellData * const pData)509 EGLConfig PVRShellInitAPI::SelectEGLConfiguration(const PVRShellData * const pData)
510 {
511 EGLint num_config;
512 EGLint conflist[32];
513 EGLConfig conf = (EGLConfig) 0;
514 int i = 0;
515
516 // Specific config ID requested?
517 if (m_iRequestedConfig > 0)
518 {
519 conflist[i++] = EGL_CONFIG_ID;
520 conflist[i++] = m_iRequestedConfig;
521 conflist[i++] = EGL_NONE;
522 if(!eglChooseConfig(m_EGLDisplay, conflist, &conf, 1, &num_config) || num_config != 1)
523 {
524 return 0;
525 }
526 return conf;
527 }
528
529 // Select default configuration
530 #if defined(ANDROID)
531 if(pData->nColorBPP == 32)
532 {
533 conflist[i++] = EGL_RED_SIZE;
534 conflist[i++] = 8;
535 conflist[i++] = EGL_GREEN_SIZE;
536 conflist[i++] = 8;
537 conflist[i++] = EGL_BLUE_SIZE;
538 conflist[i++] = 8;
539 conflist[i++] = EGL_ALPHA_SIZE;
540 conflist[i++] = 8;
541 }
542 else
543 {
544 conflist[i++] = EGL_RED_SIZE;
545 conflist[i++] = 5;
546 conflist[i++] = EGL_GREEN_SIZE;
547 conflist[i++] = 6;
548 conflist[i++] = EGL_BLUE_SIZE;
549 conflist[i++] = 5;
550 conflist[i++] = EGL_ALPHA_SIZE;
551 conflist[i++] = 0;
552 }
553 #else
554 conflist[i++] = EGL_BUFFER_SIZE;
555 conflist[i++] = pData->nColorBPP;
556 #endif
557
558 if(pData->bNeedZbuffer || pData->nDepthBPP > 0)
559 {
560 conflist[i++] = EGL_DEPTH_SIZE;
561 conflist[i++] = (pData->nDepthBPP > 0) ? pData->nDepthBPP : 16;
562 }
563
564 if(pData->bNeedStencilBuffer)
565 {
566 conflist[i++] = EGL_STENCIL_SIZE;
567 conflist[i++] = 8;
568 }
569
570 conflist[i++] = EGL_SURFACE_TYPE;
571 conflist[i] = EGL_WINDOW_BIT;
572
573 if(pData->bNeedPbuffer)
574 {
575 conflist[i] |= EGL_PBUFFER_BIT;
576 }
577
578 if(pData->bNeedPixmap)
579 {
580 conflist[i] |= EGL_PIXMAP_BIT;
581 }
582
583 ++i;
584
585 #if defined(BUILD_OGL)
586 conflist[i++] = EGL_RENDERABLE_TYPE;
587 conflist[i++] = EGL_OPENGL_BIT;
588 #elif defined(EGL_VERSION_1_3) && defined(GL_ES_VERSION_2_0)
589 conflist[i++] = EGL_RENDERABLE_TYPE;
590 conflist[i++] = EGL_OPENGL_ES2_BIT;
591 #endif
592
593 // Append number of number of samples depending on AA samples value set
594 if(pData->nAASamples > 0)
595 {
596 conflist[i++] = EGL_SAMPLE_BUFFERS;
597 conflist[i++] = 1;
598 conflist[i++] = EGL_SAMPLES;
599 conflist[i++] = pData->nAASamples;
600 }
601 else
602 {
603 conflist[i++] = EGL_SAMPLE_BUFFERS;
604 conflist[i++] = 0;
605 }
606
607 #if defined(EWS) || defined(__QNXNTO__)
608 if(m_NWT != NULL)
609 {
610 EGLint r,g,b,a, value;
611 EGLint i32Total_num_configs, j;
612 EGLConfig *pConfigs;
613
614 // Some platforms require an egl config to have the same pixel format as the native window because
615 // pixel format conversion is prohibited.
616 #if defined(EWS)
617 int format = EWS_PIXEL_FORMAT_RGB_565;
618 r = 5; g = 6; b = 5; a = 0;
619 #else
620 r = g = b = a = 8;
621 #endif
622
623 conflist[i++] = EGL_RED_SIZE;
624 conflist[i++] = r;
625
626 conflist[i++] = EGL_GREEN_SIZE;
627 conflist[i++] = g;
628
629 conflist[i++] = EGL_BLUE_SIZE;
630 conflist[i++] = b;
631
632 conflist[i++] = EGL_ALPHA_SIZE;
633 conflist[i++] = a;
634
635 // Terminate the list with EGL_NONE
636 conflist[i++] = EGL_NONE;
637
638 // Find out how many configs there are in total that match our criteria
639 if(!eglChooseConfig(m_EGLDisplay, conflist, NULL, 0, &i32Total_num_configs) || i32Total_num_configs == 0)
640 return 0;
641
642 // Allocate an array large enough to store all the possible configs that may be returned
643 pConfigs = new EGLConfig[i32Total_num_configs];
644
645 if(!pConfigs)
646 return 0;
647
648 // Get all the configs that match our criteria
649 if(!eglChooseConfig(m_EGLDisplay, conflist, pConfigs, i32Total_num_configs, &num_config))
650 {
651 delete[] pConfigs;
652 return 0;
653 }
654
655 // Go through the returned configs and try and find a suitable match
656 for(j = 0; j < num_config; ++j)
657 {
658 #if defined(__QNXNTO__)
659 if((eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_RED_SIZE, &value) && value == r)
660 && (eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_GREEN_SIZE, &value) && value == g)
661 && (eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_BLUE_SIZE, &value) && value == b)
662 && (eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_ALPHA_SIZE, &value) && value == a))
663 {
664 conf = pConfigs[j];
665 break;
666 }
667 #else
668 #if defined (EWS)
669 eglGetConfigAttrib(m_EGLDisplay, pConfigs[j], EGL_NATIVE_VISUAL_ID, &value);
670 if (value == format)
671 {
672 conf = pConfigs[j];
673 break;
674 }
675 #endif
676 #endif
677 }
678
679 // Tidy up
680 delete[] pConfigs;
681 }
682 else
683 #endif
684 {
685 // Terminate the list with EGL_NONE
686 conflist[i++] = EGL_NONE;
687
688 // Return null config if config is not found
689 if(!eglChooseConfig(m_EGLDisplay, conflist, &conf, 1, &num_config) || num_config != 1)
690 {
691 return 0;
692 }
693 }
694
695 // Return config index
696 return conf;
697 }
698
699 /*******************************************************************************
700 * Function Name : StringFrom_eglGetError
701 * Returns : A string
702 * Description : Returns a string representation of an egl error
703 *******************************************************************************/
StringFrom_eglGetError() const704 const char *PVRShellInitAPI::StringFrom_eglGetError() const
705 {
706 EGLint nErr = eglGetError();
707
708 switch(nErr)
709 {
710 case EGL_SUCCESS:
711 return "EGL_SUCCESS";
712 case EGL_BAD_DISPLAY:
713 return "EGL_BAD_DISPLAY";
714 case EGL_NOT_INITIALIZED:
715 return "EGL_NOT_INITIALIZED";
716 case EGL_BAD_ACCESS:
717 return "EGL_BAD_ACCESS";
718 case EGL_BAD_ALLOC:
719 return "EGL_BAD_ALLOC";
720 case EGL_BAD_ATTRIBUTE:
721 return "EGL_BAD_ATTRIBUTE";
722 case EGL_BAD_CONFIG:
723 return "EGL_BAD_CONFIG";
724 case EGL_BAD_CONTEXT:
725 return "EGL_BAD_CONTEXT";
726 case EGL_BAD_CURRENT_SURFACE:
727 return "EGL_BAD_CURRENT_SURFACE";
728 case EGL_BAD_MATCH:
729 return "EGL_BAD_MATCH";
730 case EGL_BAD_NATIVE_PIXMAP:
731 return "EGL_BAD_NATIVE_PIXMAP";
732 case EGL_BAD_NATIVE_WINDOW:
733 return "EGL_BAD_NATIVE_WINDOW";
734 case EGL_BAD_PARAMETER:
735 return "EGL_BAD_PARAMETER";
736 case EGL_BAD_SURFACE:
737 return "EGL_BAD_SURFACE";
738 default:
739 return "unknown";
740 }
741 }
742
743 /*!***********************************************************************
744 @Function ApiScreenCaptureBuffer
745 @Input Width Width of the region to capture
746 @Input Height Height of the region to capture
747 @Input pBuf A buffer to put the screen capture into
748 @description API-specific function to store the current content of the
749 FrameBuffer into the memory allocated by the user.
750 *************************************************************************/
ApiScreenCaptureBuffer(int Width,int Height,unsigned char * pBuf)751 bool PVRShellInit::ApiScreenCaptureBuffer(int Width,int Height,unsigned char *pBuf)
752 {
753 unsigned char *pLines2;
754 int i, j;
755 bool bRet = true;
756
757 /* Allocate memory for line */
758 pLines2 = (unsigned char *)calloc(4 * Width * Height, sizeof(unsigned char));
759 if (!pLines2) return false;
760
761 while (glGetError());
762 /* Read line from frame buffer */
763 glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, pLines2);
764
765 if(glGetError())
766 {
767 bRet = false;
768 }
769 else
770 {
771 /* Convert RGB to BGR in line */
772 for (j = 0, i = 0; j < 4 * Width * Height; j += 4, i += 3)
773 {
774 pBuf[i] = pLines2[j+2];
775 pBuf[i+1] = pLines2[j+1];
776 pBuf[i+2] = pLines2[j];
777 }
778 }
779
780 free(pLines2);
781 return bRet;
782 }
783
784 /*!***********************************************************************
785 @Function ApiRenderComplete
786 @description Perform API operations required after a frame has finished (e.g., flipping).
787 *************************************************************************/
ApiRenderComplete()788 void PVRShellInit::ApiRenderComplete()
789 {
790
791 #if defined(BUILD_OGLES) || defined(BUILD_OGLES2) || defined(BUILD_OGLES3)
792 //Discard the framebuffer if set.
793 #if !defined(BUILD_OGLES3)
794 if (glDiscardFramebufferEXT)
795 #endif
796 {
797 const GLint numAttachments=3;
798 GLenum attachments[numAttachments];
799 GLint currentAttachment=0;
800 if (m_pShell->PVRShellGet(prefDiscardColor))
801 {
802 attachments[currentAttachment] = GL_COLOR_EXT;
803 currentAttachment++;
804 }
805 if (m_pShell->PVRShellGet(prefDiscardDepth))
806 {
807 attachments[currentAttachment] = GL_DEPTH_EXT;
808 currentAttachment++;
809 }
810 if (m_pShell->PVRShellGet(prefDiscardStencil))
811 {
812 attachments[currentAttachment] = GL_STENCIL_EXT;
813 currentAttachment++;
814 }
815 //Assuming some attachments have been chosen, discard/invalidate them.
816 if (currentAttachment!=0)
817 {
818 #if defined(BUILD_OGLES)
819 glDiscardFramebufferEXT(GL_FRAMEBUFFER_OES, currentAttachment, attachments);
820 #elif defined(BUILD_OGLES2)
821 glDiscardFramebufferEXT(GL_FRAMEBUFFER, currentAttachment, attachments);
822 #elif defined(BUILD_OGLES3)
823 glInvalidateFramebuffer(GL_FRAMEBUFFER, currentAttachment, attachments);
824 #endif
825 }
826 }
827 #endif
828
829 bool bRes;
830
831 if(m_pShell->m_pShellData->bNeedPixmap)
832 {
833 /*
834 "Clients rendering to single buffered surfaces (e.g. pixmap surfaces)
835 should call eglWaitGL before accessing the native pixmap from the client."
836 */
837 eglWaitGL();
838
839 // Pixmap support: Copy the rendered pixmap to the display
840 if(m_pShell->m_pShellData->bNeedPixmapDisableCopy)
841 {
842 bRes = true;
843 }
844 else
845 {
846 bRes = OsPixmapCopy();
847 }
848 }
849 else
850 {
851 if(m_pShell->m_pShellData->bNoShellSwapBuffer)
852 return;
853
854 bRes = (eglSwapBuffers (m_EGLDisplay, m_EGLWindow) == EGL_TRUE);
855 }
856
857 if(!bRes)
858 {
859 // check for context loss
860 #ifdef EGL_VERSION_1_3
861 if(eglGetError() == EGL_CONTEXT_LOST)
862 #else
863 if((eglGetError() == EGL_CONTEXT_LOST_IMG) && m_bPowerManagementSupported)
864 #endif
865 {
866 m_pShell->ReleaseView();
867
868 OsDoReleaseAPI();
869 if(ApiInitAPI())
870 {
871 m_pShell->InitView();
872 }
873 }
874 else
875 {
876 if(m_pShell->m_pShellData->bNeedPixmap)
877 m_pShell->PVRShellOutputDebug("failed to copy pixmap\n");
878 else
879 m_pShell->PVRShellOutputDebug("eglSwapBuffers failed\n");
880 }
881 }
882 }
883
884 /*!***********************************************************************
885 @Function ApiSet
886 @Input prefName Name of value to set
887 @Modified i32Value Value to set it to
888 @description Set parameters which are specific to the API.
889 *************************************************************************/
ApiSet(const prefNameIntEnum prefName,const int i32Value)890 bool PVRShellInit::ApiSet(const prefNameIntEnum prefName, const int i32Value)
891 {
892 switch(prefName)
893 {
894 #ifdef EGL_VERSION_1_1
895 case prefSwapInterval:
896 m_pShell->m_pShellData->nSwapInterval = i32Value;
897 return true;
898 #endif
899 #if defined(BUILD_OGLES) || defined(BUILD_OGLES2) || defined(BUILD_OGLES3)
900 case prefPriority:
901 m_pShell->m_pShellData->nPriority = i32Value;
902 return true;
903 #endif
904 case prefRequestedConfig:
905 m_iRequestedConfig = (EGLint) i32Value;
906 return true;
907
908 default:
909 return false;
910 }
911 }
912
913 /*!***********************************************************************
914 @Function ApiGet
915 @Input prefName Name of value to get
916 @Modified pn A pointer set to the value asked for
917 @description Get parameters which are specific to the API.
918 *************************************************************************/
ApiGet(const prefNameIntEnum prefName,int * pn)919 bool PVRShellInit::ApiGet(const prefNameIntEnum prefName, int *pn)
920 {
921 switch(prefName)
922 {
923 case prefEGLMajorVersion:
924 *pn = (int) m_MajorVersion;
925 return true;
926
927 case prefEGLMinorVersion:
928 *pn = (int) m_MinorVersion;
929 return true;
930
931 case prefRequestedConfig:
932 *pn = (int) m_iRequestedConfig;
933 return true;
934
935 case prefConfig:
936 *pn = (int) m_iConfig;
937 return true;
938
939 default:
940 return false;
941 }
942 }
943
944 /*!***********************************************************************
945 @Function ApiGet
946 @Input prefName Name of value to get
947 @Modified pp A pointer set to the value asked for
948 @description Get parameters which are specific to the API.
949 *************************************************************************/
ApiGet(const prefNamePtrEnum prefName,void ** pp)950 bool PVRShellInit::ApiGet(const prefNamePtrEnum prefName, void **pp)
951 {
952 switch(prefName)
953 {
954 case prefEGLDisplay:
955 *pp = (void*)m_EGLDisplay;
956 return true;
957 case prefEGLSurface:
958 *pp = (void*)m_EGLWindow;
959 return true;
960 default:
961 return false;
962 }
963 }
964
965 /****************************************************************************
966 ** Local code
967 ****************************************************************************/
968
969 // The recommended technique for querying OpenGL extensions;
970 // adapted from http://opengl.org/resources/features/OGLextensions/
PVRShellIsExtensionSupported(EGLDisplay dpy,const char * extension)971 static bool PVRShellIsExtensionSupported(EGLDisplay dpy, const char *extension)
972 {
973 // The recommended technique for querying EGL extensions matches OpenGLES;
974 // from http://opengl.org/resources/features/OGLextensions/
975 const char *extensions = NULL;
976 const char *start;
977 char *terminator;
978
979 /* Extension names should not have spaces. */
980 char* where = (char *) strchr(extension, ' ');
981 if (where || *extension == '\0')
982 return 0;
983
984 extensions = eglQueryString(dpy, EGL_EXTENSIONS);
985 if(!extensions)
986 return false;
987
988 /* It takes a bit of care to be fool-proof about parsing the
989 OpenGL extensions string. Don't be fooled by sub-strings, etc. */
990 start = extensions;
991 for (;;) {
992 where = (char *) strstr((const char *) start, extension);
993 if (!where)
994 break;
995 terminator = where + strlen(extension);
996 if (where == start || *(where - 1) == ' ')
997 if (*terminator == ' ' || *terminator == '\0')
998 return true;
999 start = terminator;
1000 }
1001 return false;
1002 }
1003
1004 /// @endcond
1005
1006 /*****************************************************************************
1007 End of file (PVRShellAPI.cpp)
1008 *****************************************************************************/
1009
1010