gl: Use a uniform to flip R and B colors on GLES

This allows us to decide when the R and B color channels should be
flipped with a much better granularity.

For instance, when using GLX_EXT_texture_from_pixmap to create a GL
texture from a surface we don't need to swap the R and B channels, as
the internal representation of the texture data will already have the
appropriate colors.

We also don't need to flip color channels when blitting from a texture.
This commit is contained in:
Emmanuele Bassi 2016-04-25 13:38:22 +01:00
parent 1379b4b175
commit f848450a70
5 changed files with 24 additions and 11 deletions

View File

@ -138,6 +138,7 @@ make_program (GdkGLContextProgram *program,
program->position_location = glGetAttribLocation (program->program, "position"); program->position_location = glGetAttribLocation (program->program, "position");
program->uv_location = glGetAttribLocation (program->program, "uv"); program->uv_location = glGetAttribLocation (program->program, "uv");
program->map_location = glGetUniformLocation (program->program, "map"); program->map_location = glGetUniformLocation (program->program, "map");
program->flip_location = glGetUniformLocation (program->program, "flipColors");
} }
static void static void
@ -212,7 +213,8 @@ void
gdk_gl_texture_quads (GdkGLContext *paint_context, gdk_gl_texture_quads (GdkGLContext *paint_context,
guint texture_target, guint texture_target,
int n_quads, int n_quads,
GdkTexturedQuad *quads) GdkTexturedQuad *quads,
gboolean flip_colors)
{ {
GdkGLContextPaintData *paint_data = gdk_gl_context_get_paint_data (paint_context); GdkGLContextPaintData *paint_data = gdk_gl_context_get_paint_data (paint_context);
GdkGLContextProgram *program; GdkGLContextProgram *program;
@ -240,8 +242,13 @@ gdk_gl_texture_quads (GdkGLContext *paint_context,
program = paint_data->current_program; program = paint_data->current_program;
/* Use texture unit 0 */
glActiveTexture (GL_TEXTURE0); glActiveTexture (GL_TEXTURE0);
glUniform1i(program->map_location, 0); /* Use texture unit 0 */ glUniform1i(program->map_location, 0);
/* Flip 'R' and 'B' colors on GLES, if necessary */
if (gdk_gl_context_get_use_es (paint_context))
glUniform1i (program->flip_location, flip_colors ? 1 : 0);
glEnableVertexAttribArray (program->position_location); glEnableVertexAttribArray (program->position_location);
glEnableVertexAttribArray (program->uv_location); glEnableVertexAttribArray (program->uv_location);
@ -619,7 +626,7 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
} }
if (n_quads > 0) if (n_quads > 0)
gdk_gl_texture_quads (paint_context, GL_TEXTURE_2D, n_quads, quads); gdk_gl_texture_quads (paint_context, GL_TEXTURE_2D, n_quads, quads, FALSE);
g_free (quads); g_free (quads);
@ -798,7 +805,7 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
/* We don't want to combine the quads here, because they have different textures. /* We don't want to combine the quads here, because they have different textures.
* And we don't want to upload the unused source areas to make it one texture. */ * And we don't want to upload the unused source areas to make it one texture. */
gdk_gl_texture_quads (paint_context, target, 1, &quad); gdk_gl_texture_quads (paint_context, target, 1, &quad, TRUE);
} }
} }

View File

@ -56,6 +56,7 @@ typedef struct {
guint position_location; guint position_location;
guint uv_location; guint uv_location;
guint map_location; guint map_location;
guint flip_location;
} GdkGLContextProgram; } GdkGLContextProgram;
typedef struct { typedef struct {

View File

@ -443,7 +443,8 @@ typedef struct {
void gdk_gl_texture_quads (GdkGLContext *paint_context, void gdk_gl_texture_quads (GdkGLContext *paint_context,
guint texture_target, guint texture_target,
int n_quads, int n_quads,
GdkTexturedQuad *quads); GdkTexturedQuad *quads,
gboolean flip_colors);
void gdk_cairo_surface_mark_as_direct (cairo_surface_t *surface, void gdk_cairo_surface_mark_as_direct (cairo_surface_t *surface,
GdkWindow *window); GdkWindow *window);

View File

@ -1,12 +1,16 @@
precision mediump float; precision mediump float;
uniform sampler2D map; uniform sampler2D map;
uniform int flipColors;
varying highp vec2 vUv; varying highp vec2 vUv;
void main() { void main() {
vec4 color = texture2D(map, vUv); vec4 color = texture2D(map, vUv);
/* Flip R and B around to match the Cairo convention */ /* Flip R and B around to match the Cairo convention, if required */
gl_FragColor = vec4(color.z, color.y, color.x, color.w); if (flipColors == 1)
gl_FragColor = vec4(color.z, color.y, color.x, color.w);
else
gl_FragColor = color;
} }

View File

@ -455,15 +455,15 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context,
if (glx_pixmap == NULL) if (glx_pixmap == NULL)
return FALSE; return FALSE;
GDK_NOTE (OPENGL, g_message ("Using GLX_EXT_texture_from_pixmap to draw surface"));
window = gdk_gl_context_get_window (paint_context)->impl_window; window = gdk_gl_context_get_window (paint_context)->impl_window;
window_scale = gdk_window_get_scale_factor (window); window_scale = gdk_window_get_scale_factor (window);
gdk_window_get_unscaled_size (window, NULL, &unscaled_window_height); gdk_window_get_unscaled_size (window, NULL, &unscaled_window_height);
sx = sy = 1; sx = sy = 1;
cairo_surface_get_device_scale (window->current_paint.surface, &sx, &sy); cairo_surface_get_device_scale (window->current_paint.surface, &sx, &sy);
cairo_surface_get_device_offset (surface, &device_x_offset, &device_y_offset);
cairo_surface_get_device_offset (surface,
&device_x_offset, &device_y_offset);
/* Ensure all the X stuff are synced before we read it back via texture-from-pixmap */ /* Ensure all the X stuff are synced before we read it back via texture-from-pixmap */
glXWaitX(); glXWaitX();
@ -526,7 +526,7 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context,
#undef FLIP_Y #undef FLIP_Y
gdk_gl_texture_quads (paint_context, target, n_rects, quads); gdk_gl_texture_quads (paint_context, target, n_rects, quads, FALSE);
g_free (quads); g_free (quads);
glDisable (GL_SCISSOR_TEST); glDisable (GL_SCISSOR_TEST);