diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c index 9e130d0a2..dbd24c534 100644 --- a/src/cairo-gl-glyphs.c +++ b/src/cairo-gl-glyphs.c @@ -50,7 +50,8 @@ typedef struct _cairo_gl_glyph_private { } cairo_gl_glyph_private_t; static cairo_status_t -_cairo_gl_glyph_cache_add_glyph (cairo_gl_glyph_cache_t *cache, +_cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx, + cairo_gl_glyph_cache_t *cache, cairo_scaled_glyph_t *scaled_glyph) { cairo_image_surface_t *glyph_surface = scaled_glyph->surface; @@ -110,7 +111,7 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_glyph_cache_t *cache, glPixelStorei (GL_UNPACK_ROW_LENGTH, glyph_surface->stride / (PIXMAN_FORMAT_BPP (glyph_surface->pixman_format) / 8)); - glTexSubImage2D (GL_TEXTURE_2D, 0, + glTexSubImage2D (ctx->tex_target, 0, node->x, node->y, glyph_surface->width, glyph_surface->height, format, type, @@ -181,10 +182,10 @@ cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx, } glGenTextures (1, &cache->tex); - glBindTexture (GL_TEXTURE_2D, cache->tex); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D (GL_TEXTURE_2D, 0, internal_format, + glBindTexture (ctx->tex_target, cache->tex); + glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D (ctx->tex_target, 0, internal_format, GLYPH_CACHE_WIDTH, GLYPH_CACHE_HEIGHT, 0, internal_format, GL_FLOAT, NULL); } @@ -271,7 +272,7 @@ _cairo_gl_glyphs_set_shader_fixed (cairo_gl_context_t *ctx, * the loop over glyphs below. */ glActiveTexture (GL_TEXTURE1); - glEnable (GL_TEXTURE_2D); + glEnable (ctx->tex_target); glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); @@ -555,7 +556,7 @@ _render_glyphs (cairo_gl_surface_t *dst, cache = cairo_gl_context_get_glyph_cache (ctx, scaled_glyph->surface->format); - glBindTexture (GL_TEXTURE_2D, cache->tex); + glBindTexture (ctx->tex_target, cache->tex); last_format = scaled_glyph->surface->format; /* If we're doing component alpha in this function, it should @@ -571,13 +572,13 @@ _render_glyphs (cairo_gl_surface_t *dst, } if (scaled_glyph->surface_private == NULL) { - status = _cairo_gl_glyph_cache_add_glyph (cache, scaled_glyph); + status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph); if (status == CAIRO_INT_STATUS_UNSUPPORTED) { /* Cache is full, so flush existing prims and try again. */ _cairo_gl_flush_glyphs (ctx, &setup); _cairo_gl_glyph_cache_unlock (cache); - status = _cairo_gl_glyph_cache_add_glyph (cache, scaled_glyph); + status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph); } if (unlikely (_cairo_status_is_error (status))) @@ -612,12 +613,12 @@ _render_glyphs (cairo_gl_surface_t *dst, glDisableClientState (GL_TEXTURE_COORD_ARRAY); glActiveTexture (GL_TEXTURE0); glDisable (GL_TEXTURE_1D); - glDisable (GL_TEXTURE_2D); + glDisable (ctx->tex_target); glClientActiveTexture (GL_TEXTURE1); glDisableClientState (GL_TEXTURE_COORD_ARRAY); glActiveTexture (GL_TEXTURE1); - glDisable (GL_TEXTURE_2D); + glDisable (ctx->tex_target); _cairo_gl_use_program (NULL); glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0); diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h index 6cd3ec815..6faaffa12 100644 --- a/src/cairo-gl-private.h +++ b/src/cairo-gl-private.h @@ -122,6 +122,7 @@ typedef struct _cairo_gl_context { GLuint vbo; GLint max_framebuffer_size; GLint max_texture_size; + GLenum tex_target; cairo_bool_t using_glsl; cairo_bool_t using_shaders; diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c index 919c6cfb5..6470f69b6 100644 --- a/src/cairo-gl-surface.c +++ b/src/cairo-gl-surface.c @@ -100,7 +100,6 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx) if (! GLEW_EXT_framebuffer_object || ! GLEW_ARB_texture_env_combine || - ! GLEW_ARB_texture_non_power_of_two || ! GLEW_EXT_bgra) { fprintf (stderr, @@ -109,8 +108,6 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx) fprintf (stderr, " GL_EXT_framebuffer_object\n"); if (! GLEW_ARB_texture_env_combine) fprintf (stderr, " GL_ARB_texture_env_combine\n"); - if (! GLEW_ARB_texture_non_power_of_two) - fprintf (stderr, " GL_ARB_texture_non_power_of_two\n"); /* EXT_bgra is used in two places: * - draw_image to upload common pixman formats without hand-swizzling. * - get_image to download common pixman formats without hand-swizzling. @@ -121,6 +118,19 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx) return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); /* XXX */ } + if (! GLEW_ARB_texture_non_power_of_two && + ! GLEW_EXT_texture_rectangle ) { + fprintf (stderr, + "Required GL extensions not available:\n"); + fprintf (stderr, " GL_ARB_texture_non_power_of_two, GL_EXT_texture_rectangle\n"); + } + + if (!GLEW_ARB_texture_non_power_of_two) + ctx->tex_target = GL_TEXTURE_RECTANGLE_EXT; + else + ctx->tex_target = GL_TEXTURE_2D; + + if (GLEW_VERSION_2_0 || (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && @@ -133,8 +143,8 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx) /* Set up the dummy texture for tex_env_combine with constant color. */ glGenTextures (1, &ctx->dummy_tex); - glBindTexture (GL_TEXTURE_2D, ctx->dummy_tex); - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, + glBindTexture (ctx->tex_target, ctx->dummy_tex); + glTexImage2D (ctx->tex_target, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); /* PBO for any sort of texture upload */ @@ -367,45 +377,53 @@ _cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op, static void _cairo_gl_set_texture_surface (int tex_unit, GLuint tex, - cairo_surface_attributes_t *attributes) + cairo_surface_attributes_t *attributes, + GLint tex_target) { + + if (tex_target == GL_TEXTURE_RECTANGLE_EXT) { + if (attributes->extend == CAIRO_EXTEND_REPEAT || + attributes->extend == CAIRO_EXTEND_REFLECT) + fprintf(stderr,"cannot use rect texture for repeat/reflect\n"); + } + glActiveTexture (GL_TEXTURE0 + tex_unit); - glBindTexture (GL_TEXTURE_2D, tex); + glBindTexture (tex_target, tex); switch (attributes->extend) { case CAIRO_EXTEND_NONE: - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); break; case CAIRO_EXTEND_PAD: - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); break; case CAIRO_EXTEND_REPEAT: - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_REPEAT); break; case CAIRO_EXTEND_REFLECT: - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); break; } switch (attributes->filter) { case CAIRO_FILTER_FAST: case CAIRO_FILTER_NEAREST: - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); break; case CAIRO_FILTER_GOOD: case CAIRO_FILTER_BEST: case CAIRO_FILTER_BILINEAR: - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); break; default: case CAIRO_FILTER_GAUSSIAN: ASSERT_NOT_REACHED; } - glEnable (GL_TEXTURE_2D); + glEnable (tex_target); } void @@ -472,10 +490,10 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, /* Create the texture used to store the surface's data. */ glGenTextures (1, &surface->tex); - glBindTexture (GL_TEXTURE_2D, surface->tex); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D (GL_TEXTURE_2D, 0, format, width, height, 0, + glBindTexture (ctx->tex_target, surface->tex); + glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D (ctx->tex_target, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, NULL); /* Create a framebuffer object wrapping the texture so that we can render @@ -485,7 +503,7 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, surface->fb); glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_2D, + ctx->tex_target, surface->tex, 0); ctx->current_target = NULL; @@ -664,6 +682,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, GLenum internal_format, format, type; cairo_bool_t has_alpha; cairo_image_surface_t *clone = NULL; + cairo_gl_context_t *ctx = (cairo_gl_context_t *) dst->base.device; int cpp; if (! _cairo_gl_get_image_format_and_type (src->pixman_format, @@ -691,12 +710,12 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, cpp = PIXMAN_FORMAT_BPP (src->pixman_format) / 8; - glBindTexture (GL_TEXTURE_2D, dst->tex); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glBindTexture (ctx->tex_target, dst->tex); + glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp); - glTexSubImage2D (GL_TEXTURE_2D, 0, + glTexSubImage2D (ctx->tex_target, 0, dst_x, dst_y, width, height, format, GL_UNSIGNED_BYTE, src->data + src_y * src->stride + src_x * cpp); @@ -1143,7 +1162,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_composite_operand_t *operand, cairo_matrix_t m; cairo_gl_surface_t *surface; cairo_surface_attributes_t *attributes; - + cairo_gl_context_t *ctx = (cairo_gl_context_t *) dst->base.device; attributes = &operand->operand.texture.attributes; status = _cairo_pattern_acquire_surface (src, &dst->base, @@ -1183,9 +1202,15 @@ _cairo_gl_pattern_texture_setup (cairo_gl_composite_operand_t *operand, * (unnormalized src -> unnormalized src) to * (unnormalized dst -> normalized src) */ - cairo_matrix_init_scale (&m, - 1.0 / surface->width, - 1.0 / surface->height); + if (ctx->tex_target == GL_TEXTURE_RECTANGLE_EXT) { + cairo_matrix_init_scale (&m, + 1.0, + 1.0); + } else { + cairo_matrix_init_scale (&m, + 1.0 / surface->width, + 1.0 / surface->height); + } cairo_matrix_multiply (&attributes->matrix, &attributes->matrix, &m); @@ -1415,8 +1440,8 @@ _cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx, /* Fall back to fixed function */ glActiveTexture (GL_TEXTURE0 + tex_unit); /* Have to have a dummy texture bound in order to use the combiner unit. */ - glBindTexture (GL_TEXTURE_2D, ctx->dummy_tex); - glEnable (GL_TEXTURE_2D); + glBindTexture (ctx->tex_target, ctx->dummy_tex); + glEnable (ctx->tex_target); glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color); glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); @@ -1460,7 +1485,7 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx, break; case OPERAND_TEXTURE: _cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex, - src_attributes); + src_attributes, ctx->tex_target); if (!setup->shader) { /* Set up the constant color we use to set color to 0 if needed. */ glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color); @@ -1573,7 +1598,7 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx, break; case OPERAND_TEXTURE: _cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex, - src_attributes); + src_attributes, ctx->tex_target); if (!setup->shader) { /* Set up the combiner to just set color to the sampled texture. */ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); @@ -1699,9 +1724,9 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx, setup->src.operand.constant.color[2], setup->src.operand.constant.color[3]); } else { - glBindTexture (GL_TEXTURE_2D, ctx->dummy_tex); + glBindTexture (ctx->tex_target, ctx->dummy_tex); glActiveTexture (GL_TEXTURE1); - glEnable (GL_TEXTURE_2D); + glEnable (ctx->tex_target); glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, setup->mask.operand.constant.color); @@ -1714,7 +1739,7 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx, break; case OPERAND_TEXTURE: _cairo_gl_set_texture_surface (1, setup->mask.operand.texture.tex, - mask_attributes); + mask_attributes, ctx->tex_target); if (!setup->shader) { /* Set up the constant color we use to set color to 0 if needed. */ glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color); @@ -1980,13 +2005,13 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op, glDisableClientState (GL_TEXTURE_COORD_ARRAY); glActiveTexture (GL_TEXTURE0); glDisable (GL_TEXTURE_1D); - glDisable (GL_TEXTURE_2D); + glDisable (ctx->tex_target); glClientActiveTexture (GL_TEXTURE1); glDisableClientState (GL_TEXTURE_COORD_ARRAY); glActiveTexture (GL_TEXTURE1); glDisable (GL_TEXTURE_1D); - glDisable (GL_TEXTURE_2D); + glDisable (ctx->tex_target); while ((err = glGetError ())) fprintf (stderr, "GL error 0x%08x\n", (int) err); @@ -2107,7 +2132,7 @@ _cairo_gl_surface_composite (cairo_operator_t op, case OPERAND_TEXTURE: _cairo_gl_set_texture_surface (1, setup.mask.operand.texture.tex, - mask_attributes); + mask_attributes, ctx->tex_target); if (!setup.shader) { glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); @@ -2227,13 +2252,13 @@ _cairo_gl_surface_composite (cairo_operator_t op, glDisableClientState (GL_TEXTURE_COORD_ARRAY); glActiveTexture (GL_TEXTURE0); glDisable (GL_TEXTURE_1D); - glDisable (GL_TEXTURE_2D); + glDisable (ctx->tex_target); glClientActiveTexture (GL_TEXTURE1); glDisableClientState (GL_TEXTURE_COORD_ARRAY); glActiveTexture (GL_TEXTURE1); glDisable (GL_TEXTURE_1D); - glDisable (GL_TEXTURE_2D); + glDisable (ctx->tex_target); while ((err = glGetError ())) fprintf (stderr, "GL error 0x%08x\n", (int) err); @@ -2750,11 +2775,11 @@ _cairo_gl_surface_span_renderer_finish (void *abstract_renderer) glDisableClientState (GL_TEXTURE_COORD_ARRAY); glActiveTexture (GL_TEXTURE0); glDisable (GL_TEXTURE_1D); - glDisable (GL_TEXTURE_2D); + glDisable (renderer->ctx->tex_target); if (!renderer->setup.shader) { glActiveTexture (GL_TEXTURE1); - glDisable (GL_TEXTURE_2D); + glDisable (renderer->ctx->tex_target); } glDisable (GL_BLEND); @@ -2791,6 +2816,7 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op, cairo_region_t *clip_region) { cairo_gl_surface_t *dst = abstract_dst; + cairo_gl_context_t *ctx = (cairo_gl_context_t *) dst->base.device; cairo_gl_surface_span_renderer_t *renderer; cairo_status_t status; cairo_surface_attributes_t *src_attributes; @@ -2850,8 +2876,8 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op, /* Set up the mask to source from the incoming vertex color. */ glActiveTexture (GL_TEXTURE1); /* Have to have a dummy texture bound in order to use the combiner unit. */ - glBindTexture (GL_TEXTURE_2D, renderer->ctx->dummy_tex); - glEnable (GL_TEXTURE_2D); + glBindTexture (ctx->tex_target, renderer->ctx->dummy_tex); + glEnable (ctx->tex_target); glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);