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.
This commit is contained in:
Alexander Larsson 2014-10-27 21:15:37 +01:00
parent 08d44648ea
commit f7b1ba0943
2 changed files with 134 additions and 48 deletions

View File

@ -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);
}

View File

@ -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;
glXGetFBConfigAttrib (display, fbconfigs[i],
GLX_BIND_TO_TEXTURE_RGBA_EXT,
&value);
if (value == FALSE)
continue;
glXGetFBConfigAttrib (display, fbconfigs[i],
GLX_Y_INVERTED_EXT,
&value);
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);
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);