[gl] Add interface for creating surfaces from window backbuffers.

This commit is contained in:
Eric Anholt 2009-02-09 15:30:21 -08:00
parent 6cc3d8dcc0
commit fb6937565b
2 changed files with 85 additions and 9 deletions

View file

@ -54,6 +54,7 @@ typedef struct _cairo_gl_surface {
cairo_content_t content;
int width, height;
Window win; /* window if not rendering to FBO */
GLuint tex; /* GL texture object containing our data. */
GLuint fb; /* GL framebuffer object wrapping our data. */
} cairo_gl_surface_t;
@ -75,6 +76,11 @@ const cairo_gl_context_t _nil_context = {
CAIRO_STATUS_NO_MEMORY
};
static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface)
{
return surface->backend == &_cairo_gl_surface_backend;
}
static cairo_gl_context_t *
_cairo_gl_context_create_in_error (cairo_status_t status)
{
@ -155,15 +161,26 @@ _cairo_gl_context_release (cairo_gl_context_t *ctx)
static void
_cairo_gl_set_destination (cairo_gl_surface_t *surface)
{
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, surface->fb);
glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
if (surface->fb) {
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, surface->fb);
glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
} else {
/* Set the window as the target of our context. */
glXMakeCurrent (surface->ctx->dpy, surface->win, surface->ctx->gl_ctx);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
glDrawBuffer (GL_BACK_LEFT);
glReadBuffer (GL_BACK_LEFT);
}
glViewport (0, 0, surface->width, surface->height);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho(0, surface->width, 0, surface->height, -1.0, 1.0);
if (surface->fb)
glOrtho(0, surface->width, 0, surface->height, -1.0, 1.0);
else
glOrtho(0, surface->width, surface->height, 0, -1.0, 1.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
@ -328,6 +345,66 @@ cairo_gl_surface_create (cairo_gl_context_t *ctx,
return &surface->base;
}
cairo_surface_t *
cairo_gl_surface_create_for_window (cairo_gl_context_t *ctx,
Window win,
int width,
int height)
{
cairo_gl_surface_t *surface;
cairo_content_t content = CAIRO_CONTENT_COLOR_ALPHA;
surface = calloc (1, sizeof (cairo_gl_surface_t));
if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_surface_init (&surface->base,
&_cairo_gl_surface_backend,
content);
surface->ctx = cairo_gl_context_reference (ctx);
surface->content = content;
surface->width = width;
surface->height = height;
surface->win = win;
return &surface->base;
}
void
cairo_gl_surface_set_size (cairo_surface_t *abstract_surface,
int width,
int height)
{
cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
cairo_status_t status;
if (! _cairo_surface_is_gl (abstract_surface) || surface->fb) {
status = _cairo_surface_set_error (abstract_surface,
CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return;
}
surface->width = width;
surface->height = height;
}
void
cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface)
{
cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
cairo_status_t status;
if (! _cairo_surface_is_gl (abstract_surface) || surface->fb) {
status = _cairo_surface_set_error (abstract_surface,
CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return;
}
glXSwapBuffers(surface->ctx->dpy, surface->win);
}
static cairo_surface_t *
_cairo_gl_surface_create_similar (void *abstract_surface,
cairo_content_t content,

View file

@ -64,17 +64,16 @@ cairo_gl_surface_create (cairo_gl_context_t *ctx,
cairo_public cairo_surface_t *
cairo_gl_surface_create_for_window (cairo_gl_context_t *ctx,
Window win,
cairo_content_t content,
int width, int height);
cairo_public cairo_gl_context_t *
cairo_gl_surface_get_context (cairo_surface_t *abstract_surface);
cairo_public int
cairo_gl_surface_get_width (cairo_surface_t *surface);
cairo_public void
cairo_gl_surface_set_size (cairo_surface_t *surface, int width, int height);
cairo_public int
cairo_gl_surface_get_height (cairo_surface_t *surface);
cairo_public void
cairo_gl_surface_swapbuffers (cairo_surface_t *surface);
cairo_public cairo_status_t
cairo_gl_surface_glfinish (cairo_surface_t *surface);