git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6186 dfc29bdd-3216-0410-991c-e03cc46cb475
		
			
				
	
	
		
			663 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			663 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| // Copyright (C) 2013 Patryk Nadrowski
 | |
| // This file is part of the "Irrlicht Engine".
 | |
| // For conditions of distribution and use, see copyright notice in Irrlicht.h
 | |
| 
 | |
| #include "CEGLManager.h"
 | |
| 
 | |
| #ifdef _IRR_COMPILE_WITH_EGL_MANAGER_
 | |
| 
 | |
| #include "irrString.h"
 | |
| #include "irrArray.h"
 | |
| #include "os.h"
 | |
| 
 | |
| #if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
 | |
| #include <android/native_activity.h>
 | |
| #endif
 | |
| 
 | |
| namespace irr
 | |
| {
 | |
| namespace video
 | |
| {
 | |
| 
 | |
| CEGLManager::CEGLManager() : IContextManager(), EglWindow(0), EglDisplay(EGL_NO_DISPLAY),
 | |
|     EglSurface(EGL_NO_SURFACE), EglContext(EGL_NO_CONTEXT), EglConfig(0), MajorVersion(0), MinorVersion(0)
 | |
| {
 | |
| 	#ifdef _DEBUG
 | |
| 	setDebugName("CEGLManager");
 | |
| 	#endif
 | |
| }
 | |
| 
 | |
| CEGLManager::~CEGLManager()
 | |
| {
 | |
|     destroyContext();
 | |
|     destroySurface();
 | |
|     terminate();
 | |
| }
 | |
| 
 | |
| bool CEGLManager::initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data)
 | |
| {
 | |
| 	// store new data
 | |
| 	Params=params;
 | |
| 	Data=data;
 | |
| 
 | |
| 	if (EglWindow != 0 && EglDisplay != EGL_NO_DISPLAY)
 | |
|         return true;
 | |
| 
 | |
| 	// Window is depend on platform.
 | |
| #if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
 | |
| 	EglWindow = (NativeWindowType)Data.OpenGLWin32.HWnd;
 | |
| 	Data.OpenGLWin32.HDc = GetDC((HWND)EglWindow);
 | |
| 	EglDisplay = eglGetDisplay((NativeDisplayType)Data.OpenGLWin32.HDc);
 | |
| #elif defined(_IRR_EMSCRIPTEN_PLATFORM_)
 | |
| 	EglWindow = 0;
 | |
| 	EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | |
| #elif defined(_IRR_COMPILE_WITH_X11_DEVICE_)
 | |
| 	EglWindow = (NativeWindowType)Data.OpenGLLinux.X11Window;
 | |
| 	EglDisplay = eglGetDisplay((NativeDisplayType)Data.OpenGLLinux.X11Display);
 | |
| #elif defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
 | |
| 	EglWindow =	(ANativeWindow*)Data.OGLESAndroid.Window;
 | |
| 	EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | |
| #elif defined(_IRR_COMPILE_WITH_FB_DEVICE_)
 | |
| 	EglWindow = (NativeWindowType)Data.OpenGLFB.Window;
 | |
| 	EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
 | |
| #endif
 | |
| 
 | |
| 	// We must check if EGL display is valid.
 | |
| 	if (EglDisplay == EGL_NO_DISPLAY)
 | |
|     {
 | |
| 		os::Printer::log("Could not get EGL display.");
 | |
| 		terminate();
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
| 	// Initialize EGL here.
 | |
| 	if (!eglInitialize(EglDisplay, &MajorVersion, &MinorVersion))
 | |
|     {
 | |
| 		os::Printer::log("Could not initialize EGL display.");
 | |
| 
 | |
|         EglDisplay = EGL_NO_DISPLAY;
 | |
| 		terminate();
 | |
|         return false;
 | |
|     }
 | |
| 	else
 | |
| 		os::Printer::log("EGL version", core::stringc(MajorVersion+(MinorVersion*0.1f)).c_str());
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| void CEGLManager::terminate()
 | |
| {
 | |
| 	if (EglWindow == 0 && EglDisplay == EGL_NO_DISPLAY)
 | |
| 		return;
 | |
| 
 | |
| 	if (EglDisplay != EGL_NO_DISPLAY)
 | |
| 	{
 | |
| 		// We should unbind current EGL context before terminate EGL.
 | |
| 		eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 | |
| 
 | |
| 		eglTerminate(EglDisplay);
 | |
| 		EglDisplay = EGL_NO_DISPLAY;
 | |
| 	}
 | |
| 
 | |
| #if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
 | |
| 	if (Data.OpenGLWin32.HDc)
 | |
|     {
 | |
| 		ReleaseDC((HWND)EglWindow, (HDC)Data.OpenGLWin32.HDc);
 | |
|         Data.OpenGLWin32.HDc = 0;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     MajorVersion = 0;
 | |
|     MinorVersion = 0;
 | |
| }
 | |
| 
 | |
| bool CEGLManager::generateSurface()
 | |
| {
 | |
|     if (EglDisplay == EGL_NO_DISPLAY)
 | |
|         return false;
 | |
| 
 | |
|     if (EglSurface != EGL_NO_SURFACE)
 | |
|         return true;
 | |
| 
 | |
| 	// We should assign new WindowID on platforms, where WindowID may change at runtime,
 | |
| 	// at this time only Android support this feature.
 | |
| 	// this needs an update method instead!
 | |
| 
 | |
| #if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
 | |
| 	EglWindow = (ANativeWindow*)Data.OGLESAndroid.Window;
 | |
| #endif
 | |
| 
 | |
| #if defined(_IRR_EMSCRIPTEN_PLATFORM_)
 | |
| 	// eglChooseConfig is currently only implemented as stub in emscripten (version 1.37.22 at point of writing)
 | |
| 	// But the other solution would also be fine as it also only generates a single context so there is not much to choose from.
 | |
| 	EglConfig = chooseConfig(ECS_IRR_CHOOSE);
 | |
| #else
 | |
| 	EglConfig = chooseConfig(ECS_EGL_CHOOSE_FIRST_LOWER_EXPECTATIONS);
 | |
| #endif
 | |
| 
 | |
| 	if ( EglConfig == 0 )
 | |
| 	{
 | |
| 		os::Printer::log("Could not get config for EGL display.");
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| #if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
 | |
|     EGLint Format = 0;
 | |
|     eglGetConfigAttrib(EglDisplay, EglConfig, EGL_NATIVE_VISUAL_ID, &Format);
 | |
| 
 | |
|     ANativeWindow_setBuffersGeometry(EglWindow, 0, 0, Format);
 | |
| #endif
 | |
| 
 | |
| 	// Now we are able to create EGL surface.
 | |
| 	EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, EglWindow, 0);
 | |
| 
 | |
| 	if (EGL_NO_SURFACE == EglSurface)
 | |
| 		EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, 0, 0);
 | |
| 
 | |
| 	if (EGL_NO_SURFACE == EglSurface)
 | |
| 		os::Printer::log("Could not create EGL surface.");
 | |
| 
 | |
| #ifdef EGL_VERSION_1_2
 | |
| 	if (MinorVersion > 1)
 | |
| 		eglBindAPI(EGL_OPENGL_ES_API);
 | |
| #endif
 | |
| 
 | |
|     if (Params.Vsync)
 | |
| 		eglSwapInterval(EglDisplay, 1);
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| EGLConfig CEGLManager::chooseConfig(EConfigStyle confStyle)
 | |
| {
 | |
| 	EGLConfig configResult = 0;
 | |
| 
 | |
| 	// Find proper OpenGL BIT.
 | |
| 	EGLint eglOpenGLBIT = 0;
 | |
| 	switch (Params.DriverType)
 | |
| 	{
 | |
| 	case EDT_OGLES1:
 | |
| 		eglOpenGLBIT = EGL_OPENGL_ES_BIT;
 | |
| 		break;
 | |
| 	case EDT_OGLES2:
 | |
| 	case EDT_WEBGL1:
 | |
| 		eglOpenGLBIT = EGL_OPENGL_ES2_BIT;
 | |
| 		break;
 | |
| 	default:
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	if ( confStyle == ECS_EGL_CHOOSE_FIRST_LOWER_EXPECTATIONS )
 | |
| 	{
 | |
| 		EGLint Attribs[] =
 | |
| 		{
 | |
| 			EGL_RED_SIZE, 8,
 | |
| 			EGL_GREEN_SIZE, 8,
 | |
| 			EGL_BLUE_SIZE, 8,
 | |
| 			EGL_ALPHA_SIZE, Params.WithAlphaChannel ? 1:0,
 | |
| 			EGL_BUFFER_SIZE, Params.Bits,
 | |
| 			EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
 | |
| 			EGL_DEPTH_SIZE, Params.ZBufferBits,
 | |
| 			EGL_STENCIL_SIZE, Params.Stencilbuffer,
 | |
| 			EGL_SAMPLE_BUFFERS, Params.AntiAlias ? 1:0,
 | |
| 			EGL_SAMPLES, Params.AntiAlias,
 | |
| 	#ifdef EGL_VERSION_1_3
 | |
| 			EGL_RENDERABLE_TYPE, eglOpenGLBIT,
 | |
| 	#endif
 | |
| 			EGL_NONE, 0
 | |
| 		};
 | |
| 
 | |
| 		EGLint numConfigs = 0;
 | |
| 		u32 steps = 5;
 | |
| 
 | |
| 		// Choose the best EGL config.
 | |
| 			// TODO: We should also have a confStyle ECS_EGL_CHOOSE_CLOSEST
 | |
| 			//       which doesn't take first result of eglChooseConfigs,
 | |
| 			//       but the closest to requested parameters. eglChooseConfigs
 | |
| 			//       can return more than 1 result and first one might have
 | |
| 			//       "better" values than requested (more bits per pixel etc).
 | |
| 			//       So this returns the config which can do most, not the
 | |
| 			//       config which is closest to the requested parameters.
 | |
| 		//
 | |
| 		while (!eglChooseConfig(EglDisplay, Attribs, &configResult, 1, &numConfigs) || !numConfigs)
 | |
| 		{
 | |
| 			switch (steps)
 | |
| 			{
 | |
| 			case 5: // samples
 | |
| 				if (Attribs[19] > 2)	// Params.AntiAlias
 | |
| 					--Attribs[19];
 | |
| 				else
 | |
| 				{
 | |
| 					Attribs[17] = 0;	// Params.Stencilbuffer
 | |
| 					Attribs[19] = 0;	// Params.AntiAlias
 | |
| 					--steps;
 | |
| 				}
 | |
| 				break;
 | |
| 			case 4: // alpha
 | |
| 				if (Attribs[7])	// Params.WithAlphaChannel
 | |
| 				{
 | |
| 					Attribs[7] = 0;
 | |
| 
 | |
| 					if (Params.AntiAlias)
 | |
| 					{
 | |
| 						Attribs[17] = 1;
 | |
| 						Attribs[19] = Params.AntiAlias;
 | |
| 						steps = 5;
 | |
| 					}
 | |
| 				}
 | |
| 				else
 | |
| 					--steps;
 | |
| 				break;
 | |
| 			case 3: // stencil
 | |
| 				if (Attribs[15])	// Params.Stencilbuffer
 | |
| 				{
 | |
| 					Attribs[15] = 0;
 | |
| 
 | |
| 					if (Params.AntiAlias)
 | |
| 					{
 | |
| 						Attribs[17] = 1;
 | |
| 						Attribs[19] = Params.AntiAlias;
 | |
| 						steps = 5;
 | |
| 					}
 | |
| 				}
 | |
| 				else
 | |
| 					--steps;
 | |
| 				break;
 | |
| 			case 2: // depth size
 | |
| 				if (Attribs[13] > 16)	// Params.ZBufferBits
 | |
| 				{
 | |
| 					Attribs[13] -= 8;
 | |
| 				}
 | |
| 				else
 | |
| 					--steps;
 | |
| 				break;
 | |
| 			case 1: // buffer size
 | |
| 				if (Attribs[9] > 16)	// Params.Bits
 | |
| 				{
 | |
| 					Attribs[9] -= 8;
 | |
| 				}
 | |
| 				else
 | |
| 					--steps;
 | |
| 				break;
 | |
| 			default:
 | |
| 				return 0;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if (Params.AntiAlias && !Attribs[17])
 | |
| 			os::Printer::log("No multisampling.");
 | |
| 
 | |
| 		if (Params.WithAlphaChannel && !Attribs[7])
 | |
| 			os::Printer::log("No alpha.");
 | |
| 
 | |
| 		if (Params.Stencilbuffer && !Attribs[15])
 | |
| 			os::Printer::log("No stencil buffer.");
 | |
| 
 | |
| 		if (Params.ZBufferBits > Attribs[13])
 | |
| 			os::Printer::log("No full depth buffer.");
 | |
| 
 | |
| 		if (Params.Bits > Attribs[9])
 | |
| 			os::Printer::log("No full color buffer.");
 | |
| 	}
 | |
| 	else if ( confStyle == ECS_IRR_CHOOSE )
 | |
| 	{
 | |
| 		// find number of available configs
 | |
| 		EGLint numConfigs;
 | |
| 		if ( eglGetConfigs( EglDisplay, NULL, 0, &numConfigs) == EGL_FALSE )
 | |
| 		{
 | |
| 			testEGLError();
 | |
| 			return 0;
 | |
| 		}
 | |
| 
 | |
| 		if ( numConfigs <= 0 )
 | |
| 			return 0;
 | |
| 
 | |
| 		// Get all available configs.
 | |
| 		EGLConfig * configs = new EGLConfig[numConfigs];
 | |
| 		if ( eglGetConfigs( EglDisplay, configs, numConfigs, &numConfigs) == EGL_FALSE )
 | |
| 		{
 | |
| 			testEGLError();
 | |
| 			return 0;
 | |
| 		}
 | |
| 
 | |
| 		// Find the best one.
 | |
| 		core::array<SConfigRating> ratings((u32)numConfigs);
 | |
| 		for ( u32 i=0; i < (u32)numConfigs; ++i )
 | |
| 		{
 | |
| 			SConfigRating r;
 | |
| 			r.config = configs[i];
 | |
| 			r.rating = rateConfig(r.config, eglOpenGLBIT);
 | |
| 
 | |
| 			if ( r.rating >= 0 )
 | |
| 				ratings.push_back(r);
 | |
| 		}
 | |
| 
 | |
| 		if ( ratings.size() > 0 )
 | |
| 		{
 | |
| 			ratings.sort();
 | |
| 			configResult = ratings[0].config;
 | |
| 
 | |
| 			if ( ratings[0].rating != 0 )
 | |
| 			{
 | |
| 				// This is just to print some log info (it also rates again while doing that, but rating is cheap enough, so that doesn't matter here).
 | |
| 				rateConfig(ratings[0].config, eglOpenGLBIT, true);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		delete[] configs;
 | |
| 	}
 | |
| 
 | |
| 	return configResult;
 | |
| }
 | |
| 
 | |
| irr::s32 CEGLManager::rateConfig(EGLConfig config, EGLint eglOpenGLBIT, bool log)
 | |
| {
 | |
| 	// some values must be there or we ignore the config
 | |
| #ifdef EGL_VERSION_1_3
 | |
| 	EGLint attribRenderableType = 0;
 | |
| 	eglGetConfigAttrib( EglDisplay, config, EGL_RENDERABLE_TYPE, &attribRenderableType);
 | |
| 	if  ( attribRenderableType != eglOpenGLBIT )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 			os::Printer::log("EGL_RENDERABLE_TYPE != eglOpenGLBIT");
 | |
| 		return -1;
 | |
| 	}
 | |
| #endif
 | |
| 	EGLint attribSurfaceType = 0;
 | |
| 	eglGetConfigAttrib( EglDisplay, config, EGL_SURFACE_TYPE, &attribSurfaceType);
 | |
| 	if ( attribSurfaceType != EGL_WINDOW_BIT )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 			os::Printer::log("EGL_SURFACE_TYPE!= EGL_WINDOW_BIT");
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	// Generally we give a really bad rating if attributes are worse than requested
 | |
| 	// We give a slight worse rating if attributes are not exact as requested
 | |
| 	// And we use some priorities which might make sense (but not really fine-tuned,
 | |
| 	// so if you think other priorities would be better don't worry about changing the values.
 | |
| 	int rating = 0;
 | |
| 
 | |
| 	EGLint attribBufferSize = 0;
 | |
| 	eglGetConfigAttrib( EglDisplay, config, EGL_BUFFER_SIZE, &attribBufferSize);
 | |
| 	if ( attribBufferSize < Params.Bits )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 			os::Printer::log("No full color buffer.");
 | |
| 		rating += 100;
 | |
| 	}
 | |
| 	if ( attribBufferSize > Params.Bits )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 			os::Printer::log("Larger color buffer.", ELL_DEBUG);
 | |
| 		++rating;
 | |
| 	}
 | |
| 
 | |
| 	EGLint attribRedSize = 0;
 | |
| 	eglGetConfigAttrib( EglDisplay, config, EGL_RED_SIZE, &attribRedSize);
 | |
| 	if ( attribRedSize < 5 && Params.Bits >= 4 )
 | |
| 		rating += 100;
 | |
| 	else if ( attribRedSize < 8 && Params.Bits >= 24)
 | |
| 		rating += 10;
 | |
| 	else if ( attribRedSize >= 8 && Params.Bits < 24 )
 | |
| 		rating ++;
 | |
| 	EGLint attribGreenSize = 0;
 | |
| 	eglGetConfigAttrib( EglDisplay, config, EGL_GREEN_SIZE, &attribGreenSize);
 | |
| 	if ( attribGreenSize < 5 && Params.Bits >= 4 )
 | |
| 		rating += 100;
 | |
| 	else if ( attribGreenSize < 8 && Params.Bits >= 24)
 | |
| 		rating += 10;
 | |
| 	else if ( attribGreenSize >= 8 && Params.Bits < 24 )
 | |
| 		rating ++;
 | |
| 	EGLint attribBlueSize = 0;
 | |
| 	eglGetConfigAttrib( EglDisplay, config, EGL_BLUE_SIZE, &attribBlueSize);
 | |
| 	if ( attribBlueSize < 5 && Params.Bits >= 4 )
 | |
| 		rating += 100;
 | |
| 	else if ( attribBlueSize < 8 && Params.Bits >= 24)
 | |
| 		rating += 10;
 | |
| 	else if ( attribBlueSize >= 8 && Params.Bits < 24 )
 | |
| 		rating ++;
 | |
| 
 | |
| 	EGLint attribAlphaSize = 0;
 | |
| 	eglGetConfigAttrib( EglDisplay, config, EGL_ALPHA_SIZE, &attribAlphaSize);
 | |
| 	if ( Params.WithAlphaChannel && attribAlphaSize == 0 )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 			os::Printer::log("No alpha.");
 | |
| 		rating += 10;
 | |
| 	}
 | |
| 	else if ( !Params.WithAlphaChannel && attribAlphaSize > 0 )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 			os::Printer::log("Got alpha (unrequested).", ELL_DEBUG);
 | |
| 		rating ++;
 | |
| 	}
 | |
| 
 | |
| 	EGLint attribStencilSize = 0;
 | |
| 	eglGetConfigAttrib( EglDisplay, config, EGL_STENCIL_SIZE, &attribStencilSize);
 | |
| 	if ( Params.Stencilbuffer && attribStencilSize == 0 )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 			os::Printer::log("No stencil buffer.");
 | |
| 		rating += 10;
 | |
| 	}
 | |
| 	else if ( !Params.Stencilbuffer && attribStencilSize > 0 )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 			os::Printer::log("Got a stencil buffer (unrequested).", ELL_DEBUG);
 | |
| 		rating ++;
 | |
| 	}
 | |
| 
 | |
| 	EGLint attribDepthSize = 0;
 | |
| 	eglGetConfigAttrib( EglDisplay, config, EGL_DEPTH_SIZE, &attribDepthSize);
 | |
| 	if ( attribDepthSize < Params.ZBufferBits )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 		{
 | |
| 			if (attribDepthSize > 0)
 | |
| 				os::Printer::log("No full depth buffer.");
 | |
| 			else
 | |
| 				os::Printer::log("No depth buffer.");
 | |
| 		}
 | |
| 		rating += 50;
 | |
| 	}
 | |
| 	else if ( attribDepthSize != Params.ZBufferBits )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 		{
 | |
| 			if ( Params.ZBufferBits == 0 )
 | |
| 				os::Printer::log("Got a depth buffer (unrequested).", ELL_DEBUG);
 | |
| 			else
 | |
| 				os::Printer::log("Got a larger depth buffer.", ELL_DEBUG);
 | |
| 		}
 | |
| 		rating ++;
 | |
| 	}
 | |
| 
 | |
| 	EGLint attribSampleBuffers=0, attribSamples = 0;
 | |
| 	eglGetConfigAttrib( EglDisplay, config, EGL_SAMPLE_BUFFERS, &attribSampleBuffers);
 | |
| 	eglGetConfigAttrib( EglDisplay, config, EGL_SAMPLES, &attribSamples);
 | |
| 	if ( Params.AntiAlias && attribSampleBuffers == 0 )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 			os::Printer::log("No multisampling.");
 | |
| 		rating += 20;
 | |
| 	}
 | |
| 	else if ( Params.AntiAlias && attribSampleBuffers && attribSamples < Params.AntiAlias )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 			os::Printer::log("Multisampling with less samples than requested.", ELL_DEBUG);
 | |
| 		rating += 10;
 | |
| 	}
 | |
| 	else if ( Params.AntiAlias && attribSampleBuffers && attribSamples > Params.AntiAlias )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 			os::Printer::log("Multisampling with more samples than requested.", ELL_DEBUG);
 | |
| 		rating += 5;
 | |
| 	}
 | |
| 	else if ( !Params.AntiAlias && attribSampleBuffers > 0 )
 | |
| 	{
 | |
| 		if ( log )
 | |
| 			os::Printer::log("Got multisampling (unrequested).", ELL_DEBUG);
 | |
| 		rating += 3;
 | |
| 	}
 | |
| 
 | |
| 	return rating;
 | |
| }
 | |
| 
 | |
| void CEGLManager::destroySurface()
 | |
| {
 | |
| 	if (EglSurface == EGL_NO_SURFACE)
 | |
| 		return;
 | |
| 
 | |
| 	// We should unbind current EGL context before destroy EGL surface.
 | |
| 	eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 | |
| 
 | |
|     eglDestroySurface(EglDisplay, EglSurface);
 | |
|     EglSurface = EGL_NO_SURFACE;
 | |
| }
 | |
| 
 | |
| bool CEGLManager::generateContext()
 | |
| {
 | |
| 	if (EglDisplay == EGL_NO_DISPLAY || EglSurface == EGL_NO_SURFACE)
 | |
| 		return false;
 | |
| 
 | |
| 	if (EglContext != EGL_NO_CONTEXT)
 | |
| 		return true;
 | |
| 
 | |
| 	EGLint OpenGLESVersion = 0;
 | |
| 
 | |
| 	switch (Params.DriverType)
 | |
| 	{
 | |
| 	case EDT_OGLES1:
 | |
| 		OpenGLESVersion = 1;
 | |
| 		break;
 | |
| 	case EDT_OGLES2:
 | |
| 	case EDT_WEBGL1:
 | |
| 		OpenGLESVersion = 2;
 | |
| 		break;
 | |
| 	default:
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
|     EGLint ContextAttrib[] =
 | |
| 	{
 | |
| #ifdef EGL_VERSION_1_3
 | |
| 		EGL_CONTEXT_CLIENT_VERSION, OpenGLESVersion,
 | |
| #endif
 | |
| 		EGL_NONE, 0
 | |
| 	};
 | |
| 
 | |
| 	EglContext = eglCreateContext(EglDisplay, EglConfig, EGL_NO_CONTEXT, ContextAttrib);
 | |
| 
 | |
| 	if (testEGLError())
 | |
| 	{
 | |
| 		os::Printer::log("Could not create EGL context.", ELL_ERROR);
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	os::Printer::log("EGL context created with OpenGLESVersion: ", core::stringc((int)OpenGLESVersion), ELL_DEBUG);
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| void CEGLManager::destroyContext()
 | |
| {
 | |
| 	if (EglContext == EGL_NO_CONTEXT)
 | |
| 		return;
 | |
| 
 | |
| 	// We must unbind current EGL context before destroy it.
 | |
| 	eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 | |
| 	eglDestroyContext(EglDisplay, EglContext);
 | |
| 
 | |
|     EglContext = EGL_NO_CONTEXT;
 | |
| }
 | |
| 
 | |
| bool CEGLManager::activateContext(const SExposedVideoData& videoData, bool restorePrimaryOnZero)
 | |
| {
 | |
| 	eglMakeCurrent(EglDisplay, EglSurface, EglSurface, EglContext);
 | |
| 
 | |
| 	if (testEGLError())
 | |
| 	{
 | |
| 		os::Printer::log("Could not make EGL context current.");
 | |
| 		return false;
 | |
| 	}
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| const SExposedVideoData& CEGLManager::getContext() const
 | |
| {
 | |
| 	return Data;
 | |
| }
 | |
| 
 | |
| bool CEGLManager::swapBuffers()
 | |
| {
 | |
|     return (eglSwapBuffers(EglDisplay, EglSurface)==EGL_TRUE);
 | |
| }
 | |
| 
 | |
| bool CEGLManager::testEGLError()
 | |
| {
 | |
| #if defined(EGL_VERSION_1_0) && defined(_DEBUG)
 | |
| 	EGLint status = eglGetError();
 | |
| 
 | |
| 	switch (status)
 | |
| 	{
 | |
| 		case EGL_SUCCESS:
 | |
|             return false;
 | |
| 		case EGL_NOT_INITIALIZED :
 | |
| 			os::Printer::log("Not Initialized", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_BAD_ACCESS:
 | |
| 			os::Printer::log("Bad Access", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_BAD_ALLOC:
 | |
| 			os::Printer::log("Bad Alloc", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_BAD_ATTRIBUTE:
 | |
| 			os::Printer::log("Bad Attribute", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_BAD_CONTEXT:
 | |
| 			os::Printer::log("Bad Context", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_BAD_CONFIG:
 | |
| 			os::Printer::log("Bad Config", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_BAD_CURRENT_SURFACE:
 | |
| 			os::Printer::log("Bad Current Surface", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_BAD_DISPLAY:
 | |
| 			os::Printer::log("Bad Display", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_BAD_SURFACE:
 | |
| 			os::Printer::log("Bad Surface", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_BAD_MATCH:
 | |
| 			os::Printer::log("Bad Match", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_BAD_PARAMETER:
 | |
| 			os::Printer::log("Bad Parameter", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_BAD_NATIVE_PIXMAP:
 | |
| 			os::Printer::log("Bad Native Pixmap", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_BAD_NATIVE_WINDOW:
 | |
| 			os::Printer::log("Bad Native Window", ELL_ERROR);
 | |
|             break;
 | |
| 		case EGL_CONTEXT_LOST:
 | |
| 			os::Printer::log("Context Lost", ELL_ERROR);
 | |
|             break;
 | |
|         default:
 | |
|             break;
 | |
| 	};
 | |
| 
 | |
| 	return true;
 | |
| #else
 | |
| 	return false;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| }
 | |
| }
 | |
| 
 | |
| #endif
 |