• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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