summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2014-10-27 21:15:37 +0100
committerAlexander Larsson <alexl@redhat.com>2014-10-27 21:17:08 +0100
commitf7b1ba09430f07a02c5c29b0eba59516bf92aa9a (patch)
tree06737ea5a8c910deecca74cbd95572aa53f29f52
parent08d44648ea9378d62f0fa95995bbcc33d4cc338e (diff)
downloadgtk+-f7b1ba09430f07a02c5c29b0eba59516bf92aa9a.tar.gz
opengl: Use GL_TEXTURE_2D rather than GL_TEXTURE_RECTANGLE_ARB when possible
This is more standard, and most driver support non-power-of-2 TEXTURE_2D these days. We fall back for ancient drivers.
-rw-r--r--gdk/gdkgl.c73
-rw-r--r--gdk/x11/gdkglcontext-x11.c105
2 files changed, 132 insertions, 46 deletions
diff --git a/gdk/gdkgl.c b/gdk/gdkgl.c
index 09ee79ebba..a4b290a8f5 100644
--- a/gdk/gdkgl.c
+++ b/gdk/gdkgl.c
@@ -113,20 +113,15 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, source);
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_RENDERBUFFER_EXT, source);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
+ glBindFramebufferEXT (GL_DRAW_FRAMEBUFFER_EXT, 0);
}
else if (source_type == GL_TEXTURE)
{
+ glBindTexture (GL_TEXTURE_2D, source);
+
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size);
- glBindTexture (GL_TEXTURE_2D, source);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_2D, source, 0);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
+ glBindFramebufferEXT (GL_DRAW_FRAMEBUFFER_EXT, 0);
}
else
{
@@ -234,9 +229,6 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
/* Translate to impl coords */
cairo_region_translate (clip_region, dx, dy);
- glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texture_width);
- glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texture_height);
-
if (alpha_size != 0)
{
cairo_region_t *opaque_region, *blend_region;
@@ -260,6 +252,19 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
cairo_region_destroy (opaque_region);
cairo_region_destroy (blend_region);
}
+
+ 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);
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_TEXTURE_2D, source, 0);
+
glEnable (GL_SCISSOR_TEST);
glEnable (GL_TEXTURE_2D);
@@ -389,6 +394,9 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
unsigned int texture_id;
int window_scale;
double sx, sy;
+ float umax, vmax;
+ gboolean use_texture_rectangle;
+ guint target;
current = gdk_gl_context_get_current ();
if (current &&
@@ -398,7 +406,9 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
/* Software fallback */
- window = gdk_gl_context_get_window (gdk_gl_context_get_current ());
+ use_texture_rectangle = gdk_gl_context_use_texture_rectangle (current);
+
+ window = gdk_gl_context_get_window (current);
window_scale = gdk_window_get_scale_factor (window);
window_height = gdk_window_get_height (window);
@@ -411,8 +421,18 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
&device_x_offset, &device_y_offset);
glGenTextures (1, &texture_id);
- glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture_id);
- glEnable (GL_TEXTURE_RECTANGLE_ARB);
+ if (use_texture_rectangle)
+ target = GL_TEXTURE_RECTANGLE_ARB;
+ else
+ target = GL_TEXTURE_2D;
+
+ glBindTexture (target, texture_id);
+ glEnable (target);
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
n_rects = cairo_region_num_rectangles (region);
for (i = 0; i < n_rects; i++)
@@ -433,7 +453,7 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
glPixelStorei (GL_UNPACK_ROW_LENGTH, cairo_image_surface_get_stride (image)/4);
- glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 4, e.width, e.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+ glTexImage2D (target, 0, 4, e.width, e.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
cairo_image_surface_get_data (image));
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
@@ -441,21 +461,32 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
#define FLIP_Y(_y) (window_height - (_y))
+ if (use_texture_rectangle)
+ {
+ umax = rect.width * sx;
+ vmax = rect.height * sy;
+ }
+ else
+ {
+ umax = 1.0;
+ vmax = 1.0;
+ }
+
glBegin (GL_QUADS);
- glTexCoord2f (0.0f * sx, rect.height * sy);
+ glTexCoord2f (0, vmax);
glVertex2f (rect.x * window_scale, FLIP_Y(rect.y + rect.height) * window_scale);
- glTexCoord2f (rect.width * sx, rect.height * sy);
+ glTexCoord2f (umax, vmax);
glVertex2f ((rect.x + rect.width) * window_scale, FLIP_Y(rect.y + rect.height) * window_scale);
- glTexCoord2f (rect.width * sx, 0.0f * sy);
+ glTexCoord2f (umax, 0);
glVertex2f ((rect.x + rect.width) * window_scale, FLIP_Y(rect.y) * window_scale);
- glTexCoord2f (0.0f * sx, 0.0f * sy);
+ glTexCoord2f (0, 0);
glVertex2f (rect.x * window_scale, FLIP_Y(rect.y) * window_scale);
glEnd();
}
- glDisable (GL_TEXTURE_RECTANGLE_ARB);
+ glDisable (target);
glDeleteTextures (1, &texture_id);
}
diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c
index 6162b1048c..accc8a5c99 100644
--- a/gdk/x11/gdkglcontext-x11.c
+++ b/gdk/x11/gdkglcontext-x11.c
@@ -288,41 +288,64 @@ glx_pixmap_get (cairo_surface_t *surface)
XVisualInfo *visinfo;
int i, value;
gboolean y_inverted;
- const int pixmap_attributes[] = {
- GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
- GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
+ gboolean with_alpha;
+ guint target = 0;
+ guint format = 0;
+ int pixmap_attributes[] = {
+ GLX_TEXTURE_TARGET_EXT, 0,
+ GLX_TEXTURE_FORMAT_EXT, 0,
None
};
+ with_alpha = cairo_surface_get_content (surface) == CAIRO_CONTENT_COLOR_ALPHA;
+
y_inverted = FALSE;
fbconfigs = glXGetFBConfigs (display, XScreenNumberOfScreen (screen), &nfbconfigs);
for (i = 0; i < nfbconfigs; i++)
{
visinfo = glXGetVisualFromFBConfig (display, fbconfigs[i]);
if (!visinfo || visinfo->visualid != XVisualIDFromVisual (visual))
- continue;
+ continue;
glXGetFBConfigAttrib (display, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
if (!(value & GLX_PIXMAP_BIT))
- continue;
-
- glXGetFBConfigAttrib (display, fbconfigs[i],
- GLX_BIND_TO_TEXTURE_TARGETS_EXT,
- &value);
- if ((value & GLX_TEXTURE_RECTANGLE_BIT_EXT))
- continue;
+ continue;
glXGetFBConfigAttrib (display, fbconfigs[i],
- GLX_BIND_TO_TEXTURE_RGBA_EXT,
- &value);
- if (value == FALSE)
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+ &value);
+ if ((value & (GLX_TEXTURE_RECTANGLE_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT)) == 0)
continue;
+ if ((value & GLX_TEXTURE_2D_BIT_EXT))
+ target = GLX_TEXTURE_2D_EXT;
+ else
+ target = GLX_TEXTURE_RECTANGLE_EXT;
+
+ if (!with_alpha)
+ {
+ glXGetFBConfigAttrib (display, fbconfigs[i],
+ GLX_BIND_TO_TEXTURE_RGB_EXT,
+ &value);
+ if (!value)
+ continue;
+
+ format = GLX_TEXTURE_FORMAT_RGB_EXT;
+ }
+ else
+ {
+ glXGetFBConfigAttrib (display, fbconfigs[i],
+ GLX_BIND_TO_TEXTURE_RGBA_EXT,
+ &value);
+ if (!value)
+ continue;
+ format = GLX_TEXTURE_FORMAT_RGBA_EXT;
+ }
glXGetFBConfigAttrib (display, fbconfigs[i],
- GLX_Y_INVERTED_EXT,
- &value);
+ GLX_Y_INVERTED_EXT,
+ &value);
if (value == TRUE)
- y_inverted = TRUE;
+ y_inverted = TRUE;
break;
}
@@ -330,6 +353,9 @@ glx_pixmap_get (cairo_surface_t *surface)
if (i == nfbconfigs)
return NULL;
+ pixmap_attributes[1] = target;
+ pixmap_attributes[3] = format;
+
glx_pixmap = g_slice_new0 (GdkGLXPixmap);
glx_pixmap->y_inverted = y_inverted;
glx_pixmap->display = display;
@@ -345,6 +371,7 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
cairo_surface_t *surface,
cairo_region_t *region)
{
+ GdkGLContext *current;
GdkGLXPixmap *glx_pixmap;
double device_x_offset, device_y_offset;
cairo_rectangle_int_t rect;
@@ -353,7 +380,10 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
int window_height;
int window_scale;
unsigned int texture_id;
+ gboolean use_texture_rectangle;
+ guint target;
double sx, sy;
+ float uscale, vscale;
if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_XLIB)
return FALSE;
@@ -362,7 +392,11 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
if (glx_pixmap == NULL)
return FALSE;
- window = gdk_gl_context_get_window (gdk_gl_context_get_current ())->impl_window;
+ current = gdk_gl_context_get_current ();
+
+ use_texture_rectangle = gdk_gl_context_use_texture_rectangle (current);
+
+ window = gdk_gl_context_get_window (current)->impl_window;
window_scale = gdk_window_get_scale_factor (window);
window_height = gdk_window_get_height (window);
@@ -377,9 +411,19 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
/* Ensure all the X stuff are synced before we read it back via texture-from-pixmap */
glXWaitX();
+ if (use_texture_rectangle)
+ target = GL_TEXTURE_RECTANGLE_ARB;
+ else
+ target = GL_TEXTURE_2D;
+
glGenTextures (1, &texture_id);
- glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture_id);
- glEnable (GL_TEXTURE_RECTANGLE_ARB);
+ glBindTexture (target, texture_id);
+ glEnable (target);
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glXBindTexImageEXT (glx_pixmap->display, glx_pixmap->drawable,
GLX_FRONT_LEFT_EXT, NULL);
@@ -401,17 +445,28 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
#define FLIP_Y(_y) (window_height - (_y))
+ if (use_texture_rectangle)
+ {
+ uscale = 1.0;
+ vscale = 1.0;
+ }
+ else
+ {
+ uscale = 1.0 / cairo_xlib_surface_get_width (surface);
+ vscale = 1.0 / cairo_xlib_surface_get_height (surface);
+ }
+
glBegin (GL_QUADS);
- glTexCoord2f (src_x, src_y + src_height);
+ glTexCoord2f (uscale * src_x, vscale * (src_y + src_height));
glVertex2f (rect.x * window_scale, FLIP_Y(rect.y + rect.height) * window_scale);
- glTexCoord2f (src_x + src_width, src_y + src_height);
+ glTexCoord2f (uscale * (src_x + src_width), vscale * (src_y + src_height));
glVertex2f ((rect.x + rect.width) * window_scale, FLIP_Y(rect.y + rect.height) * window_scale);
- glTexCoord2f (src_x + src_width, src_y);
+ glTexCoord2f (uscale * (src_x + src_width), vscale * src_y);
glVertex2f ((rect.x + rect.width) * window_scale, FLIP_Y(rect.y) * window_scale);
- glTexCoord2f (src_x, src_y);
+ glTexCoord2f (uscale * src_x, vscale * src_y);
glVertex2f (rect.x * window_scale, FLIP_Y(rect.y) * window_scale);
glEnd();
}
@@ -419,7 +474,7 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
glXReleaseTexImageEXT (glx_pixmap->display, glx_pixmap->drawable,
GLX_FRONT_LEFT_EXT);
- glDisable (GL_TEXTURE_RECTANGLE_ARB);
+ glDisable (target);
glDeleteTextures (1, &texture_id);
glx_pixmap_destroy(glx_pixmap);