diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2010-06-17 18:19:39 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2010-07-07 18:11:36 -0400 |
commit | 9e6c151af810886e94372ac8e4878915059c6c14 (patch) | |
tree | 00b95bb156b165df0ad4a2a8ca9331726c6ba0a4 /src/cairo-gl-surface.c | |
parent | 4c91bb9a221bc8e3d65a96365bbd1157b3f4e612 (diff) |
gl: Add new cairo-gl surface constructor to create surface for texture
Diffstat (limited to 'src/cairo-gl-surface.c')
-rw-r--r-- | src/cairo-gl-surface.c | 111 |
1 files changed, 99 insertions, 12 deletions
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c index cfc1f449..5b311710 100644 --- a/src/cairo-gl-surface.c +++ b/src/cairo-gl-surface.c @@ -217,13 +217,13 @@ _cairo_gl_surface_init (cairo_device_t *device, } static cairo_surface_t * -_cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height) +_cairo_gl_surface_create_scratch_for_texture (cairo_gl_context_t *ctx, + cairo_content_t content, + GLuint tex, + int width, + int height) { cairo_gl_surface_t *surface; - GLenum format; assert (width <= ctx->max_framebuffer_size && height <= ctx->max_framebuffer_size); @@ -232,6 +232,35 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_gl_surface_init (&ctx->base, surface, content, width, height); + surface->tex = tex; + + /* Create the texture used to store the surface's data. */ + _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); + 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); + + return &surface->base; +} + +static cairo_surface_t * +_cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, + cairo_content_t content, + int width, + int height) +{ + cairo_gl_surface_t *surface; + GLenum format; + GLuint tex; + + glGenTextures (1, &tex); + surface = (cairo_gl_surface_t *) + _cairo_gl_surface_create_scratch_for_texture (ctx, content, + tex, width, height); + if (unlikely (surface->base.status)) + return &surface->base; + + surface->owns_tex = TRUE; /* adjust the texture size after setting our real extents */ if (width < 1) @@ -262,12 +291,6 @@ _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, break; } - /* Create the texture used to store the surface's data. */ - _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); - glGenTextures (1, &surface->tex); - 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); @@ -356,6 +379,69 @@ cairo_gl_surface_create (cairo_device_t *abstract_device, } slim_hidden_def (cairo_gl_surface_create); + +/** + * cairo_gl_surface_create_for_texture: + * @content: type of content in the surface + * @tex: name of texture to use for storage of surface pixels + * @width: width of the surface, in pixels + * @height: height of the surface, in pixels + * + * Creates a GL surface for the specified texture with the specified + * content and dimensions. The texture must be kept around until the + * #cairo_surface_t is destroyed or cairo_surface_finish() is called + * on the surface. The initial contents of @tex will be used as the + * initial image contents; you must explicitly clear the buffer, + * using, for example, cairo_rectangle() and cairo_fill() if you want + * it cleared. The format of @tex should be compatible with @content, + * in the sense that it must have the color components required by + * @content. + * + * Return value: a pointer to the newly created surface. The caller + * owns the surface and should call cairo_surface_destroy() when done + * with it. + * + * This function always returns a valid pointer, but it will return a + * pointer to a "nil" surface if an error such as out of memory + * occurs. You can use cairo_surface_status() to check for this. + **/ +cairo_surface_t * +cairo_gl_surface_create_for_texture (cairo_device_t *abstract_device, + cairo_content_t content, + GLuint tex, + int width, + int height) +{ + cairo_gl_context_t *ctx; + cairo_gl_surface_t *surface; + cairo_status_t status; + + if (! CAIRO_CONTENT_VALID (content)) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); + + if (abstract_device == NULL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER)); + + if (abstract_device->status) + return _cairo_surface_create_in_error (abstract_device->status); + + if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); + + status = _cairo_gl_context_acquire (abstract_device, &ctx); + if (unlikely (status)) + return _cairo_surface_create_in_error (status); + + surface = (cairo_gl_surface_t *) + _cairo_gl_surface_create_scratch_for_texture (ctx, content, + tex, width, height); + _cairo_gl_context_release (ctx); + + return &surface->base; +} +slim_hidden_def (cairo_gl_surface_create_for_texture); + + void cairo_gl_surface_set_size (cairo_surface_t *abstract_surface, int width, @@ -702,7 +788,8 @@ _cairo_gl_surface_finish (void *abstract_surface) glDeleteFramebuffersEXT (1, &surface->depth); if (surface->fb) glDeleteFramebuffersEXT (1, &surface->fb); - glDeleteTextures (1, &surface->tex); + if (surface->owns_tex) + glDeleteTextures (1, &surface->tex); return _cairo_gl_context_release (ctx, status); } |