gl: Add more OpenGL ES checks

Check for the appropriate extensions depending on which type of API
we're using.
This commit is contained in:
Emmanuele Bassi 2016-04-22 17:27:04 +01:00
parent 8bb4eb5544
commit 1620b7bda7
3 changed files with 124 additions and 26 deletions

View File

@ -370,7 +370,10 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
{
glBindTexture (GL_TEXTURE_2D, source);
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size);
if (gdk_gl_context_get_use_es (paint_context))
alpha_size = 1;
else
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size);
}
else
{
@ -419,7 +422,22 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
glEnable (GL_SCISSOR_TEST);
gdk_window_get_unscaled_size (impl_window, NULL, &unscaled_window_height);
glDrawBuffer (GL_BACK);
if (!gdk_gl_context_get_use_es (paint_context))
glDrawBuffer (GL_BACK);
else
{
int maj, min;
gdk_gl_context_get_version (paint_context, &maj, &min);
if ((maj * 100 + min) >= 300)
{
static const GLenum buffers[] = { GL_BACK };
glDrawBuffers (G_N_ELEMENTS (buffers), buffers);
}
}
#define FLIP_Y(_y) (unscaled_window_height - (_y))
@ -518,8 +536,16 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
glBindTexture (GL_TEXTURE_2D, source);
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texture_width);
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texture_height);
if (gdk_gl_context_get_use_es (paint_context))
{
texture_width = width;
texture_height = height;
}
else
{
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texture_width);
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texture_height);
}
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

View File

@ -100,6 +100,7 @@ typedef struct {
guint use_texture_rectangle : 1;
guint has_gl_framebuffer_blit : 1;
guint has_frame_terminator : 1;
guint has_unpack_subimage : 1;
guint extensions_checked : 1;
guint debug_enabled : 1;
guint forward_compatible : 1;
@ -240,13 +241,23 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
int height,
guint texture_target)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
glPixelStorei (GL_UNPACK_ROW_LENGTH, cairo_image_surface_get_stride (image_surface)/4);
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
cairo_image_surface_get_data (image_surface));
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
/* GL_UNPACK_ROW_LENGTH is available on desktop GL, OpenGL ES >= 3.0, or if
* the GL_EXT_unpack_subimage extension for OpenGL ES 2.0 is available
*/
if (epoxy_is_desktop_gl () || priv->gl_version >= 30 || priv->has_unpack_subimage)
{
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
glPixelStorei (GL_UNPACK_ROW_LENGTH, cairo_image_surface_get_stride (image_surface) / 4);
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
cairo_image_surface_get_data (image_surface));
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
}
else
g_critical ("Unable to upload the contents of the image surface");
}
static void
@ -379,6 +390,14 @@ gdk_gl_context_has_frame_terminator (GdkGLContext *context)
return priv->has_frame_terminator;
}
gboolean
gdk_gl_context_has_unpack_subimage (GdkGLContext *context)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
return priv->has_unpack_subimage;
}
/**
* gdk_gl_context_set_debug_enabled:
* @context: a #GdkGLContext
@ -515,10 +534,10 @@ gdk_gl_context_set_required_version (GdkGLContext *context,
/* Enforce a minimum context version number of 3.2 */
version = (major * 100) + minor;
if (!priv->use_es)
min_ver = 302;
else
if (priv->use_es || (_gdk_gl_flags & GDK_GL_GLES) != 0)
min_ver = 200;
else
min_ver = 302;
if (version < min_ver)
{
@ -551,16 +570,16 @@ gdk_gl_context_get_required_version (GdkGLContext *context,
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
if (!priv->use_es)
{
default_major = 3;
default_minor = 2;
}
else
if (priv->use_es || (_gdk_gl_flags & GDK_GL_GLES) != 0)
{
default_major = 2;
default_minor = 0;
}
else
{
default_major = 3;
default_minor = 2;
}
if (priv->major > 0)
maj = priv->major;
@ -623,20 +642,50 @@ gdk_gl_context_set_is_legacy (GdkGLContext *context,
priv->is_legacy = !!is_legacy;
}
/**
* gdk_gl_context_set_use_es:
* @context: a #GdkGLContext:
* @use_es: whether the context should use OpenGL ES instead of OpenGL
*
* Requests that GDK create a OpenGL ES context instead of an OpenGL one.
*
* The @context must not have been realized.
*
* You should check the return value of gdk_gl_context_get_use_es() to
* decide whether to use the OpenGL or OpenGL ES API, extensions, or
* shaders.
*
* Since: 3.22
*/
void
gdk_gl_context_set_use_es (GdkGLContext *context,
gboolean use_es)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
g_return_if_fail (!priv->realized);
priv->use_es = !!use_es;
}
/**
* gdk_gl_context_get_use_es:
* @context: a #GdkGLContext
*
* Checks whether the @context is using an OpenGL or OpenGL ES profile.
*
* Returns: %TRUE if the #GdkGLContext is using an OpenGL ES profile
*
* Since: 3.22
*/
gboolean
gdk_gl_context_get_use_es (GdkGLContext *context)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), FALSE);
return priv->use_es;
}
@ -681,15 +730,36 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
if (priv->extensions_checked)
return;
priv->use_es = !epoxy_is_desktop_gl ();
priv->gl_version = epoxy_gl_version ();
has_npot = epoxy_has_gl_extension ("GL_ARB_texture_non_power_of_two");
has_texture_rectangle = epoxy_has_gl_extension ("GL_ARB_texture_rectangle");
if (priv->use_es)
{
has_npot = priv->gl_version >= 20;
has_texture_rectangle = FALSE;
priv->has_gl_framebuffer_blit = epoxy_has_gl_extension ("GL_EXT_framebuffer_blit");
priv->has_frame_terminator = epoxy_has_gl_extension ("GL_GREMEDY_frame_terminator");
/* This should check for GL_NV_framebuffer_blit - see extension at:
*
* https://www.khronos.org/registry/gles/extensions/NV/NV_framebuffer_blit.txt
*/
priv->has_gl_framebuffer_blit = FALSE;
if (G_UNLIKELY (_gdk_gl_flags & GDK_GL_TEXTURE_RECTANGLE))
/* No OES version */
priv->has_frame_terminator = FALSE;
priv->has_unpack_subimage = epoxy_has_gl_extension ("GL_EXT_unpack_subimage");
}
else
{
has_npot = epoxy_has_gl_extension ("GL_ARB_texture_non_power_of_two");
has_texture_rectangle = epoxy_has_gl_extension ("GL_ARB_texture_rectangle");
priv->has_gl_framebuffer_blit = epoxy_has_gl_extension ("GL_EXT_framebuffer_blit");
priv->has_frame_terminator = epoxy_has_gl_extension ("GL_GREMEDY_frame_terminator");
priv->has_unpack_subimage = TRUE;
}
if (!priv->use_es && G_UNLIKELY (_gdk_gl_flags & GDK_GL_TEXTURE_RECTANGLE))
priv->use_texture_rectangle = TRUE;
else if (has_npot)
priv->use_texture_rectangle = FALSE;
@ -699,13 +769,14 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
g_warning ("GL implementation doesn't support any form of non-power-of-two textures");
GDK_NOTE (OPENGL,
g_message ("OpenGL version: %d.%d\n"
"Extensions checked:\n"
g_message ("%s version: %d.%d\n"
"* Extensions checked:\n"
" - GL_ARB_texture_non_power_of_two: %s\n"
" - GL_ARB_texture_rectangle: %s\n"
" - GL_EXT_framebuffer_blit: %s\n"
" - GL_GREMEDY_frame_terminator: %s\n"
"Using texture rectangle: %s",
"* Using texture rectangle: %s",
priv->use_es ? "OpenGL ES" : "OpenGL",
priv->gl_version / 10, priv->gl_version % 10,
has_npot ? "yes" : "no",
has_texture_rectangle ? "yes" : "no",

View File

@ -84,6 +84,7 @@ GdkGLContextPaintData * gdk_gl_context_get_paint_data (GdkGLContext
gboolean gdk_gl_context_use_texture_rectangle (GdkGLContext *context);
gboolean gdk_gl_context_has_framebuffer_blit (GdkGLContext *context);
gboolean gdk_gl_context_has_frame_terminator (GdkGLContext *context);
gboolean gdk_gl_context_has_unpack_subimage (GdkGLContext *context);
void gdk_gl_context_end_frame (GdkGLContext *context,
cairo_region_t *painted,
cairo_region_t *damage);