Example #1
0
//------------------------------------------------------------------------------
// eglDestroyContext
//------------------------------------------------------------------------------
EGLAPI EGLBoolean EGLAPIENTRY
eglDestroyContext(
	EGLDisplay display,
	EGLContext context
)
{
	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;
	}

	if(!eglplus_egl_valid_context(context))
	{
		eglplus_egl_SetErrorCode(EGL_BAD_CONTEXT);
		return EGL_FALSE;
	}

	context->_cleanup(display->_x_open_display);
	delete context;
}
Example #2
0
//------------------------------------------------------------------------------
// eglGetConfigs
//------------------------------------------------------------------------------
EGLAPI EGLBoolean EGLAPIENTRY
eglGetConfigs(
	EGLDisplay display,
	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;
	}

	if(!num_configs)
	{
		eglplus_egl_SetErrorCode(EGL_BAD_PARAMETER);
		return EGL_FALSE;
	}

	int num_glx_configs = 0;
	::GLXFBConfig * glx_configs = ::glXGetFBConfigs(
		display->_x_open_display,
		DefaultScreen(display->_x_open_display),
		&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;
}
Example #3
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;
	}
}
Example #4
0
//------------------------------------------------------------------------------
// eglQueryContext
//------------------------------------------------------------------------------
EGLAPI EGLBoolean EGLAPIENTRY
eglQueryContext(
	EGLDisplay display,
	EGLContext context,
	EGLint egl_attribute,
	EGLint *egl_attrib_value
)
{
	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;
	}

	if(!eglplus_egl_valid_context(context))
	{
		eglplus_egl_SetErrorCode(EGL_BAD_CONTEXT);
		return EGL_FALSE;
	}

	int glx_attribute = 0;

	switch(egl_attribute)
	{
		case EGL_CONTEXT_CLIENT_TYPE:
		{
			if(egl_attrib_value)
				*egl_attrib_value = EGL_OPENGL_BIT;
			return EGL_TRUE;
		}
		case EGL_CONTEXT_CLIENT_VERSION:
		{
			if(egl_attrib_value)
				*egl_attrib_value = 3;
			return EGL_TRUE;
		}
		case EGL_RENDER_BUFFER:
		{
			//TODO
			if(egl_attrib_value)
				*egl_attrib_value = EGL_BACK_BUFFER;
			return EGL_TRUE;
		}
		case EGL_CONFIG_ID:
		{
			glx_attribute = GLX_FBCONFIG_ID;
			break;
		}
		default:
		{
			eglplus_egl_SetErrorCode(EGL_BAD_ATTRIBUTE);
			return EGL_FALSE;
		}
	}

	int glx_attrib_value = 0;

	if(glXQueryContext(
		display->_x_open_display,
		context->_glx_context,
		glx_attribute,
		&glx_attrib_value
	) != 0)
	{
		return EGL_FALSE;
	}

	switch(egl_attribute)
	{
		default:
		{
			if(egl_attrib_value)
				*egl_attrib_value = glx_attrib_value;
		}
	}

	return EGL_TRUE;
}
Example #5
0
//------------------------------------------------------------------------------
// eglMakeCurrent
//------------------------------------------------------------------------------
EGLAPI EGLBoolean EGLAPIENTRY
eglMakeCurrent(
	EGLDisplay display,
	EGLSurface egl_draw,
	EGLSurface egl_read,
	EGLContext context
)
{
	if(!eglplus_egl_valid_display(display))
	{
		eglplus_egl_SetErrorCode(EGL_BAD_DISPLAY);
		return EGL_FALSE;
	}

	::GLXContext glx_context = ::GLXContext(0);
	::GLXDrawable glx_draw = ::GLXDrawable(0);
	::GLXDrawable glx_read = ::GLXDrawable(0);

	if(context != EGL_NO_CONTEXT)
	{
		if(!eglplus_egl_valid_context(context))
		{
			eglplus_egl_SetErrorCode(EGL_BAD_CONTEXT);
			return EGL_FALSE;
		}

		if((egl_draw == EGL_NO_SURFACE) != (egl_read == EGL_NO_SURFACE))
		{
			eglplus_egl_SetErrorCode(EGL_BAD_MATCH);
			return EGL_FALSE;
		}

		if(egl_draw != EGL_NO_SURFACE)
		{
			if(!eglplus_egl_valid_surface(egl_draw))
			{
				eglplus_egl_SetErrorCode(EGL_BAD_SURFACE);
				return EGL_FALSE;
			}
			glx_draw = egl_draw->_glx_drawable;
		}
		else if(context->_glx_empty_surf)
		{
			// KHR_surfaceless_context
			glx_draw = context->_glx_empty_surf;
		}
		else
		{
			eglplus_egl_SetErrorCode(EGL_BAD_SURFACE);
			return EGL_FALSE;
		}

		if(egl_read != EGL_NO_SURFACE)
		{
			if(!eglplus_egl_valid_surface(egl_read))
			{
				eglplus_egl_SetErrorCode(EGL_BAD_SURFACE);
				return EGL_FALSE;
			}
			glx_read = egl_read->_glx_drawable;
		}
		else if(context->_glx_empty_surf)
		{
			// KHR_surfaceless_context
			glx_read = context->_glx_empty_surf;
		}
		else
		{
			eglplus_egl_SetErrorCode(EGL_BAD_SURFACE);
			return EGL_FALSE;
		}

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

		glx_context = context->_glx_context;
	}
	else
	{
		if(egl_draw != EGL_NO_SURFACE)
		{
			eglplus_egl_SetErrorCode(EGL_BAD_MATCH);
			return EGL_FALSE;
		}

		if(egl_read != EGL_NO_SURFACE)
		{
			eglplus_egl_SetErrorCode(EGL_BAD_MATCH);
			return EGL_FALSE;
		}
	}

	if(::glXMakeContextCurrent(
		display->_x_open_display,
		glx_draw,
		glx_read,
		glx_context
	) != True)
	{
		return EGL_FALSE;
	}

	eglplus_egl_glx_Current& current = eglplus_egl_CurrentRef();

	current.display = display;
	current.draw_surface = egl_draw;
	current.read_surface = egl_read;
	current.context = context;

	return EGL_TRUE;
}
Example #6
0
//------------------------------------------------------------------------------
// eglGetConfigAttrib
//------------------------------------------------------------------------------
EGLAPI EGLBoolean EGLAPIENTRY
eglGetConfigAttrib(
	EGLDisplay display,
	EGLConfig config,
	EGLint egl_attrib_name,
	EGLint *egl_attrib_value
)
{
	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;
	}

	if(!egl_attrib_value)
	{
		eglplus_egl_SetErrorCode(EGL_BAD_PARAMETER);
		return EGL_FALSE;
	}

	int glx_attrib_name;

	switch(egl_attrib_name)
	{
		case EGL_COLOR_BUFFER_TYPE:
		{
			*egl_attrib_value = EGL_RGB_BUFFER;
			// TODO: are luminance buffers supported by GLX?
			return EGL_TRUE;
		}
		case EGL_RENDERABLE_TYPE:
		case EGL_CONFORMANT:
		{
			*egl_attrib_value = EGL_OPENGL_BIT;
			//TODO | EGL_OPENGL_ES3_BIT_KHR;
			return EGL_TRUE;
		}

		case EGL_SAMPLES:
		case EGL_SAMPLE_BUFFERS:
		case EGL_LUMINANCE_SIZE:
		case EGL_ALPHA_MASK_SIZE:
		case EGL_MIN_SWAP_INTERVAL:
		case EGL_MAX_SWAP_INTERVAL:
		{
			*egl_attrib_value = 0;
			return EGL_TRUE;
		}

		default:
		{
			if(!eglplus_egl_glx_TranslateAttribName(
				egl_attrib_name,
				glx_attrib_name
			))
			{
				eglplus_egl_SetErrorCode(EGL_BAD_ATTRIBUTE);
				return EGL_FALSE;
			}
		}
	}

	int glx_attrib_value = 0;

	int glx_result = ::glXGetFBConfigAttrib(
		display->_x_open_display,
		static_cast< ::GLXFBConfig>(config._glx_fb_config),
		glx_attrib_name,
		&glx_attrib_value
	);

	if(glx_result == Success)
	{
		eglplus_egl_glx_TranslateAttribBack(
			egl_attrib_name,
			*egl_attrib_value,
			glx_attrib_value
		);
		return EGL_TRUE;
	}
	else if(glx_result == GLX_BAD_ATTRIBUTE)
	{
		eglplus_egl_SetErrorCode(EGL_BAD_ATTRIBUTE);
	}
	else
	{
		eglplus_egl_SetErrorCode(EGL_BAD_DISPLAY);
	}

	return EGL_FALSE;
}
Example #7
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;
}