Ejemplo n.º 1
0
//------------------------------------------------------------------------------
// eglCreateContext
//------------------------------------------------------------------------------
EGLAPI EGLContext EGLAPIENTRY
eglCreateContext(
	EGLDisplay display,
	EGLConfig config,
	EGLContext egl_share_context,
	const EGLint *egl_attrib_list
)
{
	if(!eglplus_egl_valid_display(display))
	{
		eglplus_egl_SetErrorCode(EGL_BAD_DISPLAY);
		return EGL_NO_CONTEXT;
	}

	if(!display->initialized())
	{
		eglplus_egl_SetErrorCode(EGL_NOT_INITIALIZED);
		return EGL_NO_CONTEXT;
	}

	if(!config._glx_fb_config)
	{
		eglplus_egl_SetErrorCode(EGL_BAD_CONFIG);
		return EGL_NO_CONTEXT;
	}

	if(eglplus_egl_CurrentAPI != EGL_OPENGL_API)
	{
		eglplus_egl_SetErrorCode(EGL_BAD_MATCH);
		return EGL_NO_CONTEXT;
	}

	if(eglplus_egl_glXCreateContextAttribsARB == nullptr)
	{
		eglplus_egl_glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
		glXGetProcAddressARB((const unsigned char*)"glXCreateContextAttribsARB");
	}

	if(eglplus_egl_glXCreateContextAttribsARB == nullptr)
	{
		eglplus_egl_SetErrorCode(EGL_BAD_DISPLAY);
		return EGL_NO_CONTEXT;
	}

	::GLXContext glx_share_context = ::GLXContext(0);

	if(egl_share_context != EGL_NO_CONTEXT)
	{
		if(eglplus_egl_valid_context(egl_share_context))
		{
			glx_share_context = egl_share_context->_glx_context;
		}
		else
		{
			eglplus_egl_SetErrorCode(EGL_BAD_CONFIG);
			return EGL_NO_CONTEXT;
		}
	}

	EGLint empty_list = EGL_NONE;
	if(!egl_attrib_list)
	{
		egl_attrib_list = &empty_list;
	}

	int glx_attrib_count = 0;

	if(*egl_attrib_list != EGL_NONE)
	{
		const EGLint* tmp_attrib_list = egl_attrib_list;
		while(*tmp_attrib_list != EGL_NONE)
		{
			bool bad_attrib = false;

			switch(*tmp_attrib_list++)
			{
				case 0x3098: //EGL_CONTEXT_MAJOR_VERSION_KHR
				case 0x30FB: //EGL_CONTEXT_MINOR_VERSION_KHR
					break;
				case 0x30FC: //EGL_CONTEXT_FLAGS_KHR
				{
					if((*tmp_attrib_list & ~0x07) != 0)
					{
						bad_attrib = true;
					}
					break;
				}
				case 0x31BD: //EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
				{
					switch(*tmp_attrib_list)
					{
						case 0x31BE:
						case 0x31BF:
							break;
						default: bad_attrib = true;
					}
					break;
				}
				case 0x30FD: //EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR
				{
					if((*tmp_attrib_list & ~0x03) != 0)
					{
						bad_attrib = true;
					}
					break;
				}
				default: bad_attrib = true;
			}

			if(bad_attrib)
			{
				eglplus_egl_SetErrorCode(EGL_BAD_ATTRIBUTE);
				return EGL_NO_CONTEXT;
			}
			++tmp_attrib_list;
			glx_attrib_count += 2;
		}
	}

	std::vector<int> glx_attrib_list(glx_attrib_count+1);
	glx_attrib_count = 0;

	if(*egl_attrib_list != EGL_NONE)
	{
		const EGLint* tmp_attrib_list = egl_attrib_list;
		while(*tmp_attrib_list != EGL_NONE)
		{
			switch(*tmp_attrib_list++)
			{
				case 0x3098: //EGL_CONTEXT_MAJOR_VERSION_KHR
				{
					glx_attrib_list[glx_attrib_count++] =
						//GLX_CONTEXT_MAJOR_VERSION_ARB
						0x2091;
					glx_attrib_list[glx_attrib_count++] =
						int(*tmp_attrib_list++);
					break;
				}
				case 0x30FB: //EGL_CONTEXT_MINOR_VERSION_KHR
				{
					glx_attrib_list[glx_attrib_count++] =
						//GLX_CONTEXT_MINOR_VERSION_ARB
						0x2092;
					glx_attrib_list[glx_attrib_count++] =
						int(*tmp_attrib_list++);
					break;
				}
				case 0x30FC: //EGL_CONTEXT_FLAGS_KHR
				{
					glx_attrib_list[glx_attrib_count++] =
						//GLX_CONTEXT_FLAGS_ARB
						0x2094;
					EGLint egl_flags = *tmp_attrib_list++;
					int glx_flags = 0;

					// EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
					if((egl_flags & 0x00000001) == 0x00000001)
						glx_flags |= 0x0001;
					// EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
					if((egl_flags & 0x00000002) == 0x00000002)
						glx_flags |= 0x0002;
					// EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR
					// TODO: currently ignored

					glx_attrib_list[glx_attrib_count++] =
						glx_flags;
					break;
				}
				case 0x31BD: //EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
				{
					// TODO: currently ignored
					break;
				}
				case 0x30FD: //EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR
				{
					glx_attrib_list[glx_attrib_count++] =
						//GLX_CONTEXT_PROFILE_MASK_ARB
						0x9126;
					EGLint egl_flags = *tmp_attrib_list++;
					int glx_flags = 0;

					// EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
					if((egl_flags & 0x00000001) == 0x00000001)
						glx_flags |= 0x0001;
					// EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR
					if((egl_flags & 0x00000002) == 0x00000002)
						glx_flags |= 0x0002;

					glx_attrib_list[glx_attrib_count++] =
						glx_flags;
					break;
				}
				default:;
			}
		}
	}
	glx_attrib_list[glx_attrib_count] = None;

	::GLXContext context = eglplus_egl_glXCreateContextAttribsARB(
		display->_x_open_display,
		static_cast< ::GLXFBConfig>(config._glx_fb_config),
		glx_share_context,
		True, // direct rendering
		glx_attrib_list.data()
	);

	if(context == ::GLXContext(0))
	{
		eglplus_egl_SetErrorCode(EGL_BAD_ALLOC);
		return EGL_NO_CONTEXT;
	}

	::XSync(display->_x_open_display, False);

	int empty_surf_attr[] = {
		GLX_PBUFFER_WIDTH, 0,
		GLX_PBUFFER_HEIGHT, 0,
		GLX_PRESERVED_CONTENTS, False,
		None
	};
	::GLXPbuffer empty_surf = ::glXCreatePbuffer(
		display->_x_open_display,
		static_cast< ::GLXFBConfig>(config._glx_fb_config),
		empty_surf_attr
	);

	try { return new eglplus_egl_glx_ContextImpl(context, empty_surf); }
	catch(...)
	{
		eglplus_egl_SetErrorCode(EGL_BAD_ALLOC);
		return EGL_NO_CONTEXT;
	}
}
Ejemplo n.º 2
0
//------------------------------------------------------------------------------
// eglChooseConfig
//------------------------------------------------------------------------------
EGLAPI EGLBoolean EGLAPIENTRY
eglChooseConfig(
	EGLDisplay display,
	const EGLint *egl_attrib_list,
	EGLConfig *configs,
	EGLint config_size,
	EGLint *num_configs
)
{
	if(!eglplus_egl_valid_display(display))
	{
		eglplus_egl_SetErrorCode(EGL_BAD_DISPLAY);
		return EGL_FALSE;
	}

	if(!display->initialized())
	{
		eglplus_egl_SetErrorCode(EGL_NOT_INITIALIZED);
		return EGL_FALSE;
	}

	EGLint empty_list = EGL_NONE;
	if(!egl_attrib_list)
	{
		egl_attrib_list = &empty_list;
	}

	std::vector<int> glx_attrib_list(1);
	bool unsupported_config = false;

	if(*egl_attrib_list != EGL_NONE)
	{
		unsigned attr_count = 0;
		const EGLint *egl_attrib = egl_attrib_list;
		while(*egl_attrib != EGL_NONE)
		{
			switch(*(++egl_attrib))
			{
				case EGL_NONE:
				{
					eglplus_egl_SetErrorCode(EGL_BAD_ATTRIBUTE);
					return EGL_FALSE;
				}
				case EGL_SURFACE_TYPE:
				case EGL_COLOR_BUFFER_TYPE:
				{
					attr_count += 2;
					break;
				}
				default: ++attr_count;
			}
			++egl_attrib;
		}
		glx_attrib_list.resize(2*attr_count+1);

		attr_count = 0;
		egl_attrib = egl_attrib_list;
		while(*egl_attrib != EGL_NONE)
		{
			EGLint egl_attrib_name = *(egl_attrib++);
			EGLint egl_attrib_value= *(egl_attrib++);
			int glx_attrib_name, glx_attrib_value;

			bool special_attrib = true;
			bool unsupported_attrib = false;
			switch(egl_attrib_name)
			{
				case EGL_MIN_SWAP_INTERVAL:
				case EGL_MAX_SWAP_INTERVAL:
				{
					// just skip this
					break;
				}
				case EGL_SAMPLES:
				case EGL_SAMPLE_BUFFERS:
				case EGL_ALPHA_MASK_SIZE:
				case EGL_LUMINANCE_SIZE:
				{
					// must be zero (or don't care)
					if(egl_attrib_value != 0)
						unsupported_attrib = true;
					break;
				}
				case EGL_RENDERABLE_TYPE:
				{
					if(egl_attrib_value != EGL_OPENGL_BIT)
						unsupported_attrib = true;
					break;
				}
				case EGL_SURFACE_TYPE:
				{
					bool doublebuffer =
						(egl_attrib_value & EGL_WINDOW_BIT)||
						(egl_attrib_value & EGL_PBUFFER_BIT);

					glx_attrib_list[attr_count++] =
						GLX_DOUBLEBUFFER;
					glx_attrib_list[attr_count++] =
						doublebuffer?True:False;
					break;
				}
				case EGL_COLOR_BUFFER_TYPE:
				{
					if(egl_attrib_value == EGL_RGB_BUFFER)
					{
						glx_attrib_list[attr_count++] =
							GLX_RENDER_TYPE;
						glx_attrib_list[attr_count++] =
							GLX_RGBA_BIT;
						glx_attrib_list[attr_count++] =
							GLX_X_VISUAL_TYPE;
						glx_attrib_list[attr_count++] =
							GLX_TRUE_COLOR;
					}
					else unsupported_attrib = true;
					break;
				}
				default: special_attrib = false;
			}

			if(special_attrib)
			{
				if(unsupported_attrib)
				{
					if(egl_attrib_value != EGL_DONT_CARE)
					{
						unsupported_config = true;
						break;
					}
				}
			}
			else if(eglplus_egl_glx_TranslateAttrib(
				egl_attrib_name,
				egl_attrib_value,
				glx_attrib_name,
				glx_attrib_value
			))
			{
				glx_attrib_list[attr_count++] = glx_attrib_name;
				glx_attrib_list[attr_count++] = glx_attrib_value;
			}
			else
			{
				eglplus_egl_SetErrorCode(EGL_BAD_ATTRIBUTE);
				return EGL_FALSE;
			}
		}
		glx_attrib_list.resize(2*attr_count+1);
	}
	glx_attrib_list.back() = None;

	if(unsupported_config)
	{
		*num_configs = 0;
		return EGL_TRUE;
	}

	int num_glx_configs = 0;
	::GLXFBConfig * glx_configs = ::glXChooseFBConfig(
		display->_x_open_display,
		DefaultScreen(display->_x_open_display),
		glx_attrib_list.data(),
		&num_glx_configs
	);

	if(configs)
	{
		int n = (num_glx_configs < int(config_size))?
			num_glx_configs:
			int(config_size);

		for(int i=0; i<n; ++i)
		{
			configs[i]._glx_fb_config =
				static_cast<void*>(glx_configs[i]);
		}
		*num_configs = n>=0?n:0;
	}
	else *num_configs = EGLint(num_glx_configs);

	return EGL_TRUE;
}