mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-07 21:28:02 +02:00
Merge branch 'gl' into gl-span-renderer
Conflicts: src/cairo-gl-surface.c
This commit is contained in:
commit
7ee0fee900
22 changed files with 1732 additions and 134 deletions
|
|
@ -149,6 +149,26 @@ enabled_cairo_boilerplate_private += $(cairo_boilerplate_gl_private)
|
|||
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_gl_sources)
|
||||
endif
|
||||
|
||||
supported_cairo_boilerplate_headers += $(cairo_boilerplate_gl_glx_headers)
|
||||
all_cairo_boilerplate_headers += $(cairo_boilerplate_gl_glx_headers)
|
||||
all_cairo_boilerplate_private += $(cairo_boilerplate_gl_glx_private)
|
||||
all_cairo_boilerplate_sources += $(cairo_boilerplate_gl_glx_sources)
|
||||
ifeq ($(CAIRO_HAS_GL_GLX_SURFACE),1)
|
||||
enabled_cairo_boilerplate_headers += $(cairo_boilerplate_gl_glx_headers)
|
||||
enabled_cairo_boilerplate_private += $(cairo_boilerplate_gl_glx_private)
|
||||
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_gl_glx_sources)
|
||||
endif
|
||||
|
||||
supported_cairo_boilerplate_headers += $(cairo_boilerplate_gl_egl_headers)
|
||||
all_cairo_boilerplate_headers += $(cairo_boilerplate_gl_egl_headers)
|
||||
all_cairo_boilerplate_private += $(cairo_boilerplate_gl_egl_private)
|
||||
all_cairo_boilerplate_sources += $(cairo_boilerplate_gl_egl_sources)
|
||||
ifeq ($(CAIRO_HAS_GL_EGL_SURFACE),1)
|
||||
enabled_cairo_boilerplate_headers += $(cairo_boilerplate_gl_egl_headers)
|
||||
enabled_cairo_boilerplate_private += $(cairo_boilerplate_gl_egl_private)
|
||||
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_gl_egl_sources)
|
||||
endif
|
||||
|
||||
unsupported_cairo_boilerplate_headers += $(cairo_boilerplate_glitz_headers)
|
||||
all_cairo_boilerplate_headers += $(cairo_boilerplate_glitz_headers)
|
||||
all_cairo_boilerplate_private += $(cairo_boilerplate_glitz_private)
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ _cairo_boilerplate_gl_create_surface (const char *name,
|
|||
XFree (visinfo);
|
||||
|
||||
gltc->gl_ctx = gl_ctx;
|
||||
gltc->ctx = cairo_gl_glx_context_create (dpy, gl_ctx);
|
||||
gltc->ctx = cairo_glx_context_create (dpy, gl_ctx);
|
||||
|
||||
gltc->surface = cairo_gl_surface_create (gltc->ctx, content,
|
||||
width, height);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ CAIRO_HAS_BEOS_SURFACE=0
|
|||
CAIRO_HAS_SDL_SURFACE=0
|
||||
CAIRO_HAS_PNG_FUNCTIONS=1
|
||||
CAIRO_HAS_GL_SURFACE=0
|
||||
CAIRO_HAS_GL_GLX_SURFACE=0
|
||||
CAIRO_HAS_GL_EGL_SURFACE=0
|
||||
CAIRO_HAS_GLITZ_SURFACE=0
|
||||
CAIRO_HAS_DIRECTFB_SURFACE=0
|
||||
CAIRO_HAS_SCRIPT_SURFACE=0
|
||||
|
|
|
|||
|
|
@ -44,6 +44,12 @@ endif
|
|||
ifeq ($(CAIRO_HAS_GL_SURFACE),1)
|
||||
@echo "#define CAIRO_HAS_GL_SURFACE 1" >> src/cairo-features.h
|
||||
endif
|
||||
ifeq ($(CAIRO_HAS_GL_GLX_SURFACE),1)
|
||||
@echo "#define CAIRO_HAS_GL_GLX_SURFACE 1" >> src/cairo-features.h
|
||||
endif
|
||||
ifeq ($(CAIRO_HAS_GL_EGL_SURFACE),1)
|
||||
@echo "#define CAIRO_HAS_GL_EGL_SURFACE 1" >> src/cairo-features.h
|
||||
endif
|
||||
ifeq ($(CAIRO_HAS_GLITZ_SURFACE),1)
|
||||
@echo "#define CAIRO_HAS_GLITZ_SURFACE 1" >> src/cairo-features.h
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -377,6 +377,9 @@ AC_DEFUN([CAIRO_REPORT],
|
|||
echo " BeOS: $use_beos"
|
||||
echo " DirectFB: $use_directfb"
|
||||
echo " SDL: $use_sdl"
|
||||
echo " GL: $use_gl"
|
||||
echo " GL/GLX: $use_gl_glx"
|
||||
echo " GL/EGL: $use_gl_egl"
|
||||
echo ""
|
||||
echo "The following font backends:"
|
||||
echo " User: yes (always builtin)"
|
||||
|
|
|
|||
30
configure.ac
30
configure.ac
|
|
@ -199,14 +199,40 @@ CAIRO_ENABLE_SURFACE_BACKEND(gl, gl, no, [
|
|||
|
||||
AC_CHECK_LIB(GLEW, glewInit, [
|
||||
AC_CHECK_HEADER(GL/glew.h, [], [
|
||||
have_gl="no (requires glew http://glew.sourceforge.net/)"
|
||||
use_gl="no (requires glew http://glew.sourceforge.net/)"
|
||||
])
|
||||
], [
|
||||
have_gl="no (requires glew http://glew.sourceforge.net/)"
|
||||
use_gl="no (requires glew http://glew.sourceforge.net/)"
|
||||
])
|
||||
gl_NONPKGCONFIG_LIBS="-lGLEW"
|
||||
])
|
||||
|
||||
CAIRO_ENABLE_SURFACE_BACKEND(gl_glx, GLX, auto, [
|
||||
if test "x$use_gl" != "xyes"; then
|
||||
use_gl_glx="no (requires --enable-gl)"
|
||||
else
|
||||
gl_glx_BASE=cairo-gl
|
||||
old_CPPFLAGS=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS $gl_CFLAGS $gl_NONPKGCONFIG_CFLAGS"
|
||||
AC_CHECK_HEADER(GL/glx.h,
|
||||
[],
|
||||
[use_gl_glx="no (requires GLX)"])
|
||||
CPPFLAGS=$old_CPPFLAGS
|
||||
fi
|
||||
])
|
||||
|
||||
CAIRO_ENABLE_SURFACE_BACKEND(gl_egl, eagle, auto, [
|
||||
if test "x$use_gl" != "xyes"; then
|
||||
use_gl_egl="no (requires --enable-gl)"
|
||||
else
|
||||
gl_egl_BASE=cairo-gl
|
||||
gl_egl_REQUIRES="eagle"
|
||||
PKG_CHECK_MODULES(gl_egl, $gl_egl_REQUIRES, ,
|
||||
[AC_MSG_RESULT(no)
|
||||
use_gl_egl="no (requires eagle)"])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl ===========================================================================
|
||||
|
||||
GLITZ_MIN_VERSION=0.5.1
|
||||
|
|
|
|||
|
|
@ -245,8 +245,10 @@ cairo_beos_headers = cairo-beos.h
|
|||
#cairo_beos_sources = cairo-beos-surface.cpp
|
||||
|
||||
cairo_gl_headers = cairo-gl.h
|
||||
cairo_gl_private =
|
||||
cairo_gl_private = cairo-gl-private.h
|
||||
cairo_gl_sources = cairo-gl-surface.c
|
||||
cairo_gl_glx_sources = cairo-glx-context.c
|
||||
cairo_gl_egl_sources = cairo-egl-context.c
|
||||
|
||||
cairo_glitz_headers = cairo-glitz.h
|
||||
cairo_glitz_private = cairo-glitz-private.h
|
||||
|
|
|
|||
|
|
@ -203,6 +203,34 @@ ifeq ($(CAIRO_HAS_GL_SURFACE),1)
|
|||
enabled_cairo_pkgconf += cairo-gl.pc
|
||||
endif
|
||||
|
||||
supported_cairo_headers += $(cairo_gl_glx_headers)
|
||||
all_cairo_headers += $(cairo_gl_glx_headers)
|
||||
all_cairo_private += $(cairo_gl_glx_private)
|
||||
all_cairo_sources += $(cairo_gl_glx_sources)
|
||||
ifeq ($(CAIRO_HAS_GL_GLX_SURFACE),1)
|
||||
enabled_cairo_headers += $(cairo_gl_glx_headers)
|
||||
enabled_cairo_private += $(cairo_gl_glx_private)
|
||||
enabled_cairo_sources += $(cairo_gl_glx_sources)
|
||||
endif
|
||||
all_cairo_pkgconf += cairo-gl-glx.pc
|
||||
ifeq ($(CAIRO_HAS_GL_GLX_SURFACE),1)
|
||||
enabled_cairo_pkgconf += cairo-gl-glx.pc
|
||||
endif
|
||||
|
||||
supported_cairo_headers += $(cairo_gl_egl_headers)
|
||||
all_cairo_headers += $(cairo_gl_egl_headers)
|
||||
all_cairo_private += $(cairo_gl_egl_private)
|
||||
all_cairo_sources += $(cairo_gl_egl_sources)
|
||||
ifeq ($(CAIRO_HAS_GL_EGL_SURFACE),1)
|
||||
enabled_cairo_headers += $(cairo_gl_egl_headers)
|
||||
enabled_cairo_private += $(cairo_gl_egl_private)
|
||||
enabled_cairo_sources += $(cairo_gl_egl_sources)
|
||||
endif
|
||||
all_cairo_pkgconf += cairo-gl-egl.pc
|
||||
ifeq ($(CAIRO_HAS_GL_EGL_SURFACE),1)
|
||||
enabled_cairo_pkgconf += cairo-gl-egl.pc
|
||||
endif
|
||||
|
||||
unsupported_cairo_headers += $(cairo_glitz_headers)
|
||||
all_cairo_headers += $(cairo_glitz_headers)
|
||||
all_cairo_private += $(cairo_glitz_private)
|
||||
|
|
|
|||
181
src/cairo-egl-context.c
Normal file
181
src/cairo-egl-context.c
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Eric Anholt
|
||||
* Copyright © 2009 Chris Wilson
|
||||
* Copyright © 2005 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-gl-private.h"
|
||||
|
||||
#include <i915_drm.h> /* XXX dummy surface for glewInit() */
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
typedef struct _cairo_egl_context {
|
||||
cairo_gl_context_t base;
|
||||
|
||||
EGLDisplay display;
|
||||
EGLContext context;
|
||||
} cairo_egl_context_t;
|
||||
|
||||
typedef struct _cairo_egl_surface {
|
||||
cairo_gl_surface_t base;
|
||||
|
||||
EGLSurface egl;
|
||||
} cairo_egl_surface_t;
|
||||
|
||||
static void
|
||||
_egl_make_current (void *abstract_ctx,
|
||||
cairo_gl_surface_t *abstract_surface)
|
||||
{
|
||||
cairo_egl_context_t *ctx = abstract_ctx;
|
||||
cairo_egl_surface_t *surface = (cairo_egl_surface_t *) abstract_surface;
|
||||
|
||||
eglMakeCurrent (ctx->display, surface->egl, surface->egl, ctx->context);
|
||||
}
|
||||
|
||||
static void
|
||||
_egl_swap_buffers (void *abstract_ctx,
|
||||
cairo_gl_surface_t *abstract_surface)
|
||||
{
|
||||
cairo_egl_context_t *ctx = abstract_ctx;
|
||||
cairo_egl_surface_t *surface = (cairo_egl_surface_t *) abstract_surface;
|
||||
|
||||
eglSwapBuffers (ctx->display, surface->egl);
|
||||
}
|
||||
|
||||
static void
|
||||
_egl_destroy (void *abstract_ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_egl_init (EGLDisplay display, EGLContext context)
|
||||
{
|
||||
const EGLint config_attribs[] = {
|
||||
EGL_CONFIG_CAVEAT, EGL_NONE,
|
||||
EGL_NONE
|
||||
};
|
||||
const EGLint surface_attribs[] = {
|
||||
EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLConfig config;
|
||||
EGLSurface dummy;
|
||||
struct drm_i915_gem_create create;
|
||||
struct drm_gem_flink flink;
|
||||
int fd;
|
||||
GLenum err;
|
||||
|
||||
if (! eglChooseConfig (display, config_attribs, &config, 1, NULL)) {
|
||||
fprintf (stderr, "Unable to choose config\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* XXX */
|
||||
fd = eglGetDisplayFD (display);
|
||||
|
||||
create.size = 4096;
|
||||
if (ioctl (fd, DRM_IOCTL_I915_GEM_CREATE, &create) != 0) {
|
||||
fprintf (stderr, "gem create failed: %m\n");
|
||||
return FALSE;
|
||||
}
|
||||
flink.handle = create.handle;
|
||||
if (ioctl (fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) {
|
||||
fprintf (stderr, "gem flink failed: %m\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dummy = eglCreateSurfaceForName (display, config, flink.name,
|
||||
1, 1, 4, surface_attribs);
|
||||
if (dummy == NULL) {
|
||||
fprintf (stderr, "Failed to create dummy surface\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
eglMakeCurrent (display, dummy, dummy, context);
|
||||
}
|
||||
|
||||
cairo_gl_context_t *
|
||||
cairo_egl_context_create (EGLDisplay display, EGLContext context)
|
||||
{
|
||||
cairo_egl_context_t *ctx;
|
||||
cairo_status_t status;
|
||||
|
||||
if (! _egl_init (display, context)) {
|
||||
return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
ctx = calloc (1, sizeof (cairo_egl_context_t));
|
||||
if (ctx == NULL)
|
||||
return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
ctx->display = display;
|
||||
ctx->context = context;
|
||||
|
||||
ctx->base.make_current = _egl_make_current;
|
||||
ctx->base.swap_buffers = _egl_swap_buffers;
|
||||
ctx->base.destroy = _egl_destroy;
|
||||
|
||||
status = _cairo_gl_context_init (&ctx->base);
|
||||
if (status) {
|
||||
free (ctx);
|
||||
return _cairo_gl_context_create_in_error (status);
|
||||
}
|
||||
|
||||
return &ctx->base;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_gl_surface_create_for_eagle (cairo_gl_context_t *ctx,
|
||||
EGLSurface egl,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_egl_surface_t *surface;
|
||||
|
||||
if (ctx->status)
|
||||
return _cairo_surface_create_in_error (ctx->status);
|
||||
|
||||
surface = calloc (1, sizeof (cairo_egl_surface_t));
|
||||
if (unlikely (surface == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
_cairo_gl_surface_init (ctx, &surface->base,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, width, height);
|
||||
surface->egl = egl;
|
||||
|
||||
return &surface->base.base;
|
||||
}
|
||||
88
src/cairo-gl-private.h
Normal file
88
src/cairo-gl-private.h
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Eric Anholt
|
||||
* Copyright © 2009 Chris Wilson
|
||||
* Copyright © 2005 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_GL_PRIVATE_H
|
||||
#define CAIRO_GL_PRIVATE_H
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "cairo-gl.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/glext.h>
|
||||
|
||||
typedef struct _cairo_gl_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
cairo_gl_context_t *ctx;
|
||||
int width, height;
|
||||
|
||||
GLuint tex; /* GL texture object containing our data. */
|
||||
GLuint fb; /* GL framebuffer object wrapping our data. */
|
||||
} cairo_gl_surface_t;
|
||||
|
||||
struct _cairo_gl_context {
|
||||
cairo_reference_count_t ref_count;
|
||||
cairo_status_t status;
|
||||
|
||||
cairo_mutex_t mutex; /* needed? */
|
||||
GLuint dummy_tex;
|
||||
|
||||
cairo_gl_surface_t *current_target;
|
||||
|
||||
void (*make_current)(void *ctx, cairo_gl_surface_t *surface);
|
||||
void (*swap_buffers)(void *ctx, cairo_gl_surface_t *surface);
|
||||
void (*destroy) (void *ctx);
|
||||
};
|
||||
|
||||
cairo_private cairo_gl_context_t *
|
||||
_cairo_gl_context_create_in_error (cairo_status_t status);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gl_context_init (cairo_gl_context_t *ctx);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_surface_init (cairo_gl_context_t *ctx,
|
||||
cairo_gl_surface_t *surface,
|
||||
cairo_content_t content,
|
||||
int width, int height);
|
||||
|
||||
#endif /* CAIRO_GL_PRIVATE_H */
|
||||
|
|
@ -35,17 +35,13 @@
|
|||
* Carl Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <GL/glew.h>
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/glx.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-gl.h"
|
||||
#include "cairo-gl-private.h"
|
||||
|
||||
slim_hidden_proto (cairo_gl_context_reference);
|
||||
slim_hidden_proto (cairo_gl_context_destroy);
|
||||
slim_hidden_proto (cairo_gl_surface_create);
|
||||
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
|
|
@ -61,29 +57,6 @@ int_as_float(uint32_t val)
|
|||
return fi.f;
|
||||
}
|
||||
|
||||
typedef struct _cairo_gl_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
cairo_gl_context_t *ctx;
|
||||
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;
|
||||
|
||||
struct _cairo_gl_context {
|
||||
cairo_reference_count_t ref_count;
|
||||
cairo_status_t status;
|
||||
|
||||
Display *dpy;
|
||||
GLXContext gl_ctx;
|
||||
cairo_mutex_t mutex; /* needed? */
|
||||
cairo_gl_surface_t *current_target;
|
||||
GLuint dummy_tex;
|
||||
};
|
||||
|
||||
enum cairo_gl_composite_operand_type {
|
||||
OPERAND_CONSTANT,
|
||||
OPERAND_TEXTURE,
|
||||
|
|
@ -116,7 +89,7 @@ typedef struct _cairo_gl_composite_setup {
|
|||
|
||||
static const cairo_surface_backend_t _cairo_gl_surface_backend;
|
||||
|
||||
const cairo_gl_context_t _nil_context = {
|
||||
static const cairo_gl_context_t _nil_context = {
|
||||
CAIRO_REFERENCE_COUNT_INVALID,
|
||||
CAIRO_STATUS_NO_MEMORY
|
||||
};
|
||||
|
|
@ -126,7 +99,7 @@ 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_t *
|
||||
_cairo_gl_context_create_in_error (cairo_status_t status)
|
||||
{
|
||||
if (status == CAIRO_STATUS_NO_MEMORY)
|
||||
|
|
@ -136,37 +109,31 @@ _cairo_gl_context_create_in_error (cairo_status_t status)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
cairo_gl_context_t *
|
||||
cairo_gl_glx_context_create (Display *dpy, GLXContext gl_ctx)
|
||||
cairo_status_t
|
||||
_cairo_gl_context_init (cairo_gl_context_t *ctx)
|
||||
{
|
||||
cairo_gl_context_t *ctx;
|
||||
GLenum err;
|
||||
|
||||
ctx = calloc (1, sizeof(cairo_gl_context_t));
|
||||
if (ctx == NULL)
|
||||
return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
ctx->status = CAIRO_STATUS_SUCCESS;
|
||||
CAIRO_REFERENCE_COUNT_INIT (&ctx->ref_count, 1);
|
||||
ctx->dpy = dpy;
|
||||
ctx->gl_ctx = gl_ctx;
|
||||
CAIRO_MUTEX_INIT (ctx->mutex);
|
||||
|
||||
/* Make our GL context active. While we'll be setting the destination
|
||||
* drawable with each rendering operation, in order to set the context
|
||||
* we have to choose a drawable. The root window happens to be convenient
|
||||
* for this.
|
||||
*/
|
||||
glXMakeCurrent(dpy, RootWindow (dpy, DefaultScreen (dpy)), gl_ctx);
|
||||
|
||||
err = glewInit();
|
||||
if (err != GLEW_OK) {
|
||||
free(ctx);
|
||||
return NULL;
|
||||
if (glewInit () != GLEW_OK) {
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); /* XXX */
|
||||
}
|
||||
|
||||
if (!GLEW_EXT_framebuffer_object || !GLEW_ARB_texture_env_combine ||
|
||||
!GLEW_ARB_texture_non_power_of_two) {
|
||||
free(ctx);
|
||||
return NULL;
|
||||
if (! GLEW_EXT_framebuffer_object ||
|
||||
! GLEW_ARB_texture_env_combine ||
|
||||
! GLEW_ARB_texture_non_power_of_two)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Required GL extensions not available:\n");
|
||||
if (! GLEW_EXT_framebuffer_object)
|
||||
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");
|
||||
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); /* XXX */
|
||||
}
|
||||
|
||||
/* Set up the dummy texture for tex_env_combine with constant color. */
|
||||
|
|
@ -175,7 +142,7 @@ cairo_gl_glx_context_create (Display *dpy, GLXContext gl_ctx)
|
|||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
return ctx;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_gl_context_t *
|
||||
|
|
@ -192,6 +159,7 @@ cairo_gl_context_reference (cairo_gl_context_t *context)
|
|||
|
||||
return context;
|
||||
}
|
||||
slim_hidden_def (cairo_gl_context_reference);
|
||||
|
||||
void
|
||||
cairo_gl_context_destroy (cairo_gl_context_t *context)
|
||||
|
|
@ -208,8 +176,11 @@ cairo_gl_context_destroy (cairo_gl_context_t *context)
|
|||
|
||||
glDeleteTextures (1, &context->dummy_tex);
|
||||
|
||||
context->destroy (context);
|
||||
|
||||
free (context);
|
||||
}
|
||||
slim_hidden_def (cairo_gl_context_destroy);
|
||||
|
||||
static cairo_gl_context_t *
|
||||
_cairo_gl_context_acquire (cairo_gl_context_t *ctx)
|
||||
|
|
@ -237,8 +208,7 @@ _cairo_gl_set_destination (cairo_gl_surface_t *surface)
|
|||
glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
|
||||
glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
|
||||
} else {
|
||||
/* Set the window as the target of our context. */
|
||||
glXMakeCurrent (ctx->dpy, surface->win, ctx->gl_ctx);
|
||||
ctx->make_current (ctx, surface);
|
||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
|
||||
glDrawBuffer (GL_BACK_LEFT);
|
||||
glReadBuffer (GL_BACK_LEFT);
|
||||
|
|
@ -292,7 +262,7 @@ _cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op)
|
|||
/* We may have a visual with alpha bits despite the user requesting
|
||||
* CAIRO_CONTENT_COLOR. So clear out those bits in that case.
|
||||
*/
|
||||
if (dst->content == CAIRO_CONTENT_COLOR) {
|
||||
if (dst->base.content == CAIRO_CONTENT_COLOR) {
|
||||
if (src_factor == GL_ONE_MINUS_DST_ALPHA)
|
||||
src_factor = GL_ZERO;
|
||||
if (src_factor == GL_DST_ALPHA)
|
||||
|
|
@ -347,6 +317,21 @@ _cairo_gl_set_texture_surface (int tex_unit, GLuint tex,
|
|||
glEnable (GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gl_surface_init (cairo_gl_context_t *ctx,
|
||||
cairo_gl_surface_t *surface,
|
||||
cairo_content_t content,
|
||||
int width, int height)
|
||||
{
|
||||
_cairo_surface_init (&surface->base,
|
||||
&_cairo_gl_surface_backend,
|
||||
content);
|
||||
|
||||
surface->ctx = cairo_gl_context_reference (ctx);
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_gl_surface_create (cairo_gl_context_t *ctx,
|
||||
cairo_content_t content,
|
||||
|
|
@ -371,12 +356,7 @@ cairo_gl_surface_create (cairo_gl_context_t *ctx,
|
|||
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;
|
||||
_cairo_gl_surface_init (ctx, surface, content, width, height);
|
||||
|
||||
switch (content) {
|
||||
default:
|
||||
|
|
@ -419,9 +399,6 @@ cairo_gl_surface_create (cairo_gl_context_t *ctx,
|
|||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
fprintf(stderr, "destination is framebuffer incomplete\n");
|
||||
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
|
||||
/* Cairo surfaces start out initialized to transparent (black) */
|
||||
ctx = _cairo_gl_context_acquire (surface->ctx);
|
||||
_cairo_gl_set_destination (surface);
|
||||
|
|
@ -431,33 +408,7 @@ 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;
|
||||
}
|
||||
slim_hidden_def (cairo_gl_surface_create);
|
||||
|
||||
void
|
||||
cairo_gl_surface_set_size (cairo_surface_t *abstract_surface,
|
||||
|
|
@ -477,19 +428,43 @@ cairo_gl_surface_set_size (cairo_surface_t *abstract_surface,
|
|||
surface->height = height;
|
||||
}
|
||||
|
||||
int
|
||||
cairo_gl_surface_get_width (cairo_surface_t *abstract_surface)
|
||||
{
|
||||
cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
|
||||
|
||||
if (! _cairo_surface_is_gl (abstract_surface))
|
||||
return 0;
|
||||
|
||||
return surface->width;
|
||||
}
|
||||
|
||||
int
|
||||
cairo_gl_surface_get_height (cairo_surface_t *abstract_surface)
|
||||
{
|
||||
cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
|
||||
|
||||
if (! _cairo_surface_is_gl (abstract_surface))
|
||||
return 0;
|
||||
|
||||
return surface->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) {
|
||||
if (! _cairo_surface_is_gl (abstract_surface)) {
|
||||
status = _cairo_surface_set_error (abstract_surface,
|
||||
CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
||||
return;
|
||||
}
|
||||
|
||||
glXSwapBuffers(surface->ctx->dpy, surface->win);
|
||||
if (! surface->fb)
|
||||
surface->ctx->swap_buffers (surface->ctx, surface);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
@ -540,8 +515,8 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
|
|||
type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
cpp = 4;
|
||||
} else if (src->pixman_format == PIXMAN_x8r8g8b8) {
|
||||
assert(dst->content != CAIRO_CONTENT_COLOR_ALPHA);
|
||||
assert(dst->content != CAIRO_CONTENT_ALPHA);
|
||||
assert(dst->base.content != CAIRO_CONTENT_COLOR_ALPHA);
|
||||
assert(dst->base.content != CAIRO_CONTENT_ALPHA);
|
||||
format = GL_BGRA;
|
||||
type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
cpp = 4;
|
||||
|
|
@ -559,7 +534,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
|
|||
*/
|
||||
temp_data = malloc (width * height * cpp);
|
||||
if (temp_data == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
src_data_start = (char *)src->data + (src_y * src->stride) + (src_x * cpp);
|
||||
for (y = 0; y < height; y++) {
|
||||
|
|
@ -609,23 +584,23 @@ _cairo_gl_surface_get_image (cairo_gl_surface_t *surface,
|
|||
*rect_out = extents;
|
||||
|
||||
/* Want to use a switch statement here but the compiler gets whiny. */
|
||||
if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) {
|
||||
if (surface->base.content == CAIRO_CONTENT_COLOR_ALPHA) {
|
||||
format = GL_BGRA;
|
||||
cairo_format = CAIRO_FORMAT_ARGB32;
|
||||
type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
cpp = 4;
|
||||
} else if (surface->content == CAIRO_CONTENT_COLOR) {
|
||||
} else if (surface->base.content == CAIRO_CONTENT_COLOR) {
|
||||
format = GL_BGRA;
|
||||
cairo_format = CAIRO_FORMAT_RGB24;
|
||||
type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
cpp = 4;
|
||||
} else if (surface->content == CAIRO_CONTENT_ALPHA) {
|
||||
} else if (surface->base.content == CAIRO_CONTENT_ALPHA) {
|
||||
format = GL_ALPHA;
|
||||
cairo_format = CAIRO_FORMAT_A8;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
cpp = 1;
|
||||
} else {
|
||||
fprintf(stderr, "get_image fallback: %d\n", surface->content);
|
||||
fprintf(stderr, "get_image fallback: %d\n", surface->base.content);
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
|
@ -646,7 +621,7 @@ _cairo_gl_surface_get_image (cairo_gl_surface_t *surface,
|
|||
*/
|
||||
temp_data = malloc (extents.width * extents.height * cpp);
|
||||
if (temp_data == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glReadPixels(extents.x, extents.y,
|
||||
|
|
@ -765,7 +740,8 @@ _cairo_gl_surface_clone_similar (void *abstract_surface,
|
|||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
clone = (cairo_gl_surface_t *)
|
||||
_cairo_gl_surface_create_similar (&surface->base, src->content,
|
||||
_cairo_gl_surface_create_similar (&surface->base,
|
||||
src->content,
|
||||
width, height);
|
||||
if (clone == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
|
@ -1024,7 +1000,7 @@ _cairo_gl_pattern_image_texture_setup (cairo_gl_composite_operand_t *operand,
|
|||
}
|
||||
|
||||
/**
|
||||
* Like cairo_pattern_acquire_surface, but returns a matrix that transforms
|
||||
* Like cairo_pattern_acquire_surface(), but returns a matrix that transforms
|
||||
* from dest to src coords.
|
||||
*/
|
||||
static cairo_status_t
|
||||
|
|
@ -1472,7 +1448,7 @@ _cairo_gl_surface_fill_rectangles (void *abstract_surface,
|
|||
_cairo_gl_context_release(ctx);
|
||||
free(vertices);
|
||||
free(colors);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* This should be loaded in as either a blend constant and an operator
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@
|
|||
#ifndef CAIRO_GL_H
|
||||
#define CAIRO_GL_H
|
||||
|
||||
#include <GL/glx.h>
|
||||
|
||||
#include "cairo.h"
|
||||
|
||||
#if CAIRO_HAS_GL_SURFACE
|
||||
|
|
@ -44,15 +42,9 @@ CAIRO_BEGIN_DECLS
|
|||
|
||||
typedef struct _cairo_gl_context cairo_gl_context_t;
|
||||
|
||||
cairo_public cairo_gl_context_t *
|
||||
cairo_gl_glx_context_create (Display *dpy, GLXContext gl_ctx);
|
||||
|
||||
cairo_public cairo_gl_context_t *
|
||||
cairo_gl_context_reference (cairo_gl_context_t *context);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_gl_context_status (cairo_gl_context_t *context);
|
||||
|
||||
cairo_public void
|
||||
cairo_gl_context_destroy (cairo_gl_context_t *context);
|
||||
|
||||
|
|
@ -61,23 +53,45 @@ cairo_gl_surface_create (cairo_gl_context_t *ctx,
|
|||
cairo_content_t content,
|
||||
int width, int height);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_gl_surface_create_for_window (cairo_gl_context_t *ctx,
|
||||
Window win,
|
||||
int width, int height);
|
||||
|
||||
cairo_public cairo_gl_context_t *
|
||||
cairo_gl_surface_get_context (cairo_surface_t *abstract_surface);
|
||||
|
||||
cairo_public void
|
||||
cairo_gl_surface_set_size (cairo_surface_t *surface, int width, int height);
|
||||
|
||||
cairo_public int
|
||||
cairo_gl_surface_get_width (cairo_surface_t *abstract_surface);
|
||||
|
||||
cairo_public int
|
||||
cairo_gl_surface_get_height (cairo_surface_t *abstract_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);
|
||||
|
||||
#if CAIRO_HAS_GL_GLX_SURFACE
|
||||
#include <GL/glx.h>
|
||||
|
||||
cairo_public cairo_gl_context_t *
|
||||
cairo_glx_context_create (Display *dpy, GLXContext gl_ctx);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_gl_surface_create_for_window (cairo_gl_context_t *ctx,
|
||||
Window win,
|
||||
int width, int height);
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_GL_EGL_SURFACE
|
||||
#include <eagle.h>
|
||||
|
||||
cairo_public cairo_gl_context_t *
|
||||
cairo_egl_context_create (EGLDisplay display, EGLContext context);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_gl_surface_create_for_eagle (cairo_gl_context_t *ctx,
|
||||
EGLSurface surface,
|
||||
int width, int height);
|
||||
#endif
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#else /* CAIRO_HAS_GL_SURFACE */
|
||||
|
|
@ -85,4 +99,3 @@ CAIRO_END_DECLS
|
|||
#endif /* CAIRO_HAS_GL_SURFACE */
|
||||
|
||||
#endif /* CAIRO_GL_H */
|
||||
|
||||
|
|
|
|||
136
src/cairo-glx-context.c
Normal file
136
src/cairo-glx-context.c
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Eric Anholt
|
||||
* Copyright © 2009 Chris Wilson
|
||||
* Copyright © 2005 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-gl-private.h"
|
||||
|
||||
typedef struct _cairo_glx_context {
|
||||
cairo_gl_context_t base;
|
||||
|
||||
Display *display;
|
||||
GLXContext context;
|
||||
} cairo_glx_context_t;
|
||||
|
||||
typedef struct _cairo_glx_surface {
|
||||
cairo_gl_surface_t base;
|
||||
|
||||
Window win;
|
||||
} cairo_glx_surface_t;
|
||||
|
||||
static void
|
||||
_glx_make_current (void *abstract_ctx,
|
||||
cairo_gl_surface_t *abstract_surface)
|
||||
{
|
||||
cairo_glx_context_t *ctx = abstract_ctx;
|
||||
cairo_glx_surface_t *surface = (cairo_glx_surface_t *) abstract_surface;
|
||||
|
||||
/* Set the window as the target of our context. */
|
||||
glXMakeCurrent (ctx->display, surface->win, ctx->context);
|
||||
}
|
||||
|
||||
static void
|
||||
_glx_swap_buffers (void *abstract_ctx,
|
||||
cairo_gl_surface_t *abstract_surface)
|
||||
{
|
||||
cairo_glx_context_t *ctx = abstract_ctx;
|
||||
cairo_glx_surface_t *surface = (cairo_glx_surface_t *) abstract_surface;
|
||||
|
||||
glXSwapBuffers (ctx->display, surface->win);
|
||||
}
|
||||
|
||||
static void
|
||||
_glx_destroy (void *abstract_ctx)
|
||||
{
|
||||
}
|
||||
|
||||
cairo_gl_context_t *
|
||||
cairo_glx_context_create (Display *dpy, GLXContext gl_ctx)
|
||||
{
|
||||
cairo_glx_context_t *ctx;
|
||||
cairo_status_t status;
|
||||
|
||||
/* Make our GL context active. While we'll be setting the destination
|
||||
* drawable with each rendering operation, in order to set the context
|
||||
* we have to choose a drawable. The root window happens to be convenient
|
||||
* for this.
|
||||
*/
|
||||
if (! glXMakeCurrent (dpy, RootWindow (dpy, DefaultScreen (dpy)), gl_ctx))
|
||||
return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
ctx = calloc (1, sizeof (cairo_glx_context_t));
|
||||
if (ctx == NULL)
|
||||
return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
ctx->display = dpy;
|
||||
ctx->context = gl_ctx;
|
||||
|
||||
ctx->base.make_current = _glx_make_current;
|
||||
ctx->base.swap_buffers = _glx_swap_buffers;
|
||||
ctx->base.destroy = _glx_destroy;
|
||||
|
||||
status = _cairo_gl_context_init (&ctx->base);
|
||||
if (status) {
|
||||
free (ctx);
|
||||
return _cairo_gl_context_create_in_error (status);
|
||||
}
|
||||
|
||||
return &ctx->base;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_gl_surface_create_for_window (cairo_gl_context_t *ctx,
|
||||
Window win,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_glx_surface_t *surface;
|
||||
|
||||
if (ctx->status)
|
||||
return _cairo_surface_create_in_error (ctx->status);
|
||||
|
||||
surface = calloc (1, sizeof (cairo_glx_surface_t));
|
||||
if (unlikely (surface == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
_cairo_gl_surface_init (ctx, &surface->base,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, width, height);
|
||||
surface->win = win;
|
||||
|
||||
return &surface->base.base;
|
||||
}
|
||||
2
test/.gitignore
vendored
2
test/.gitignore
vendored
|
|
@ -13,6 +13,8 @@ any2ppm
|
|||
.any2ppm.errors
|
||||
cairo-test-constructors.c
|
||||
cairo-test-suite
|
||||
egl-flowers
|
||||
glx-flowers
|
||||
pdf2png
|
||||
ps2png
|
||||
svg2png
|
||||
|
|
|
|||
|
|
@ -227,6 +227,16 @@ if CAIRO_HAS_QUARTZ_SURFACE
|
|||
test_sources += quartz-surface-source.c
|
||||
endif
|
||||
|
||||
if CAIRO_HAS_GL_EGL_SURFACE
|
||||
EXTRA_PROGRAMS += egl-flowers$(EXEEXT)
|
||||
egl_flowers_LDADD = $(top_builddir)/src/libcairo.la $(CAIRO_LDADD)
|
||||
endif
|
||||
|
||||
if CAIRO_HAS_GL_GLX_SURFACE
|
||||
EXTRA_PROGRAMS += glx-flowers$(EXEEXT)
|
||||
glx_flowers_LDADD = $(top_builddir)/src/libcairo.la $(CAIRO_LDADD)
|
||||
endif
|
||||
|
||||
if CAIRO_HAS_GLITZ_SURFACE
|
||||
test_sources += glitz-surface-source.c
|
||||
endif
|
||||
|
|
|
|||
358
test/egl-flowers.c
Normal file
358
test/egl-flowers.c
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
* Copyright © 2007 Michael Dominic K.
|
||||
* Copyright © 2008, 2009 Kristian Høgsberg
|
||||
* Copyright © 2009 Chris Wilson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <cairo-gl.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <i915_drm.h>
|
||||
|
||||
#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
|
||||
#include <libudev.h>
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float scale;
|
||||
float rotation;
|
||||
float r1, g1, b1, a1;
|
||||
float r2, b2, g2, a2;
|
||||
} Flower;
|
||||
|
||||
#define N_FLOWERS 200
|
||||
#define FLOWER_SIZE 128
|
||||
static Flower flowers[N_FLOWERS];
|
||||
|
||||
static EGLDisplay
|
||||
_get_display (void)
|
||||
{
|
||||
EGLint major, minor;
|
||||
EGLDisplay display;
|
||||
struct udev *udev;
|
||||
struct udev_device *device;
|
||||
struct stat st;
|
||||
|
||||
if (stat ("/dev/dri/card0", &st) < 0) {
|
||||
fprintf(stderr, "no such device\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
udev = udev_new ();
|
||||
device = udev_device_new_from_devnum (udev, 'c', st.st_rdev);
|
||||
if (device == NULL) {
|
||||
fprintf (stderr, "failed to find device\n");
|
||||
return NULL;
|
||||
}
|
||||
display = eglCreateDisplayNative (device);
|
||||
udev_device_unref (device);
|
||||
udev_unref (udev);
|
||||
|
||||
if (display == NULL) {
|
||||
fprintf (stderr, "failed to open display\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (! eglInitialize (display, &major, &minor)) {
|
||||
fprintf (stderr, "failed to initialize display\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_get_fb (void)
|
||||
{
|
||||
const EGLint config_attribs[] = {
|
||||
EGL_DEPTH_SIZE, 24,
|
||||
EGL_STENCIL_SIZE, 8,
|
||||
EGL_CONFIG_CAVEAT, EGL_NONE,
|
||||
EGL_NONE
|
||||
};
|
||||
const EGLint surface_attribs[] = {
|
||||
EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLDisplay display;
|
||||
EGLContext context;
|
||||
EGLConfig config;
|
||||
EGLSurface s;
|
||||
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
drmModeConnector *connector;
|
||||
drmModeRes *resources;
|
||||
drmModeEncoder *encoder;
|
||||
drmModeModeInfo *mode;
|
||||
struct drm_i915_gem_create create;
|
||||
struct drm_gem_flink flink;
|
||||
int i, ret, fd;
|
||||
uint32_t fb_id;
|
||||
|
||||
display = _get_display ();
|
||||
if (display == NULL) {
|
||||
fprintf (stderr, "Unable to open display\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (! eglChooseConfig (display, config_attribs, &config, 1, NULL)) {
|
||||
fprintf (stderr, "Unable to choose config\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context = eglCreateContext (display, config, NULL, NULL);
|
||||
if (context == NULL) {
|
||||
fprintf (stderr, "failed to create context\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = eglGetDisplayFD (display);
|
||||
resources = drmModeGetResources (fd);
|
||||
if (resources == NULL) {
|
||||
fprintf (stderr, "drmModeGetResources failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < resources->count_connectors; i++) {
|
||||
connector = drmModeGetConnector (fd, resources->connectors[i]);
|
||||
if (connector == NULL)
|
||||
continue;
|
||||
|
||||
if (connector->connection == DRM_MODE_CONNECTED &&
|
||||
connector->count_modes > 0)
|
||||
break;
|
||||
|
||||
drmModeFreeConnector (connector);
|
||||
}
|
||||
|
||||
if (i == resources->count_connectors) {
|
||||
fprintf (stderr, "No currently active connector found.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mode = &connector->modes[0];
|
||||
|
||||
for (i = 0; i < resources->count_encoders; i++) {
|
||||
encoder = drmModeGetEncoder(fd, resources->encoders[i]);
|
||||
|
||||
if (encoder == NULL)
|
||||
continue;
|
||||
|
||||
if (encoder->encoder_id == connector->encoder_id)
|
||||
break;
|
||||
|
||||
drmModeFreeEncoder(encoder);
|
||||
}
|
||||
|
||||
/* Mode size at 32 bpp */
|
||||
create.size = mode->hdisplay * mode->vdisplay * 4;
|
||||
if (ioctl (fd, DRM_IOCTL_I915_GEM_CREATE, &create) != 0) {
|
||||
fprintf (stderr, "gem create failed: %m\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = drmModeAddFB (fd, mode->hdisplay, mode->vdisplay,
|
||||
32, 32, mode->hdisplay * 4, create.handle, &fb_id);
|
||||
if (ret) {
|
||||
fprintf (stderr, "failed to add fb: %m\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = drmModeSetCrtc (fd, encoder->crtc_id, fb_id, 0, 0,
|
||||
&connector->connector_id, 1, mode);
|
||||
if (ret) {
|
||||
fprintf (stderr, "failed to set mode: %m\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flink.handle = create.handle;
|
||||
if (ioctl (fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) {
|
||||
fprintf (stderr, "gem flink failed: %m\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s = eglCreateSurfaceForName (display, config,
|
||||
flink.name,
|
||||
mode->hdisplay, mode->vdisplay,
|
||||
mode->hdisplay * 4,
|
||||
surface_attribs);
|
||||
if (s == NULL) {
|
||||
fprintf (stderr, "failed to create surface\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx = cairo_egl_context_create (display, context);
|
||||
surface = cairo_gl_surface_create_for_eagle (ctx, s,
|
||||
mode->hdisplay,
|
||||
mode->vdisplay);
|
||||
cairo_gl_context_destroy (ctx);
|
||||
|
||||
if (cairo_surface_status (surface)) {
|
||||
fprintf (stderr, "failed to create cairo surface\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
|
||||
static unsigned int
|
||||
hars_petruska_f54_1_random (void)
|
||||
{
|
||||
#define rol(x,k) ((x << k) | (x >> (32-k)))
|
||||
static unsigned int x;
|
||||
return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
|
||||
#undef rol
|
||||
}
|
||||
|
||||
static void
|
||||
random_colour (float *r, float *g, float *b, float *a)
|
||||
{
|
||||
unsigned int x = hars_petruska_f54_1_random ();
|
||||
*r = (x & 255) / 255.; x >>= 8;
|
||||
*g = (x & 255) / 255.; x >>= 8;
|
||||
*b = (x & 255) / 255.; x >>= 8;
|
||||
*a = x / 255.;
|
||||
}
|
||||
|
||||
static void
|
||||
randomize_flower (Flower *flower, int width, int height)
|
||||
{
|
||||
flower->x = (hars_petruska_f54_1_random() & 8191) * width / 8191.;
|
||||
flower->y = (hars_petruska_f54_1_random() & 8191) * height / 8191.;
|
||||
flower->scale = 10 + (hars_petruska_f54_1_random() & 511) * 140 / 512.;
|
||||
flower->rotation = (hars_petruska_f54_1_random() & 511) * M_PI / 256;
|
||||
|
||||
random_colour (&flower->r1,
|
||||
&flower->g1,
|
||||
&flower->b1,
|
||||
&flower->a1);
|
||||
random_colour (&flower->r2,
|
||||
&flower->g2,
|
||||
&flower->b2,
|
||||
&flower->a2);
|
||||
}
|
||||
|
||||
static void
|
||||
randomize_flowers (int width, int height)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < N_FLOWERS; i++)
|
||||
randomize_flower (&flowers [i], width, height);
|
||||
}
|
||||
|
||||
static cairo_pattern_t *
|
||||
create_flower (cairo_surface_t *target, int size)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_pattern_t *mask;
|
||||
cairo_t *cr;
|
||||
|
||||
surface = cairo_surface_create_similar (target,
|
||||
CAIRO_CONTENT_ALPHA, size, size);
|
||||
cr = cairo_create (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
cairo_scale (cr, size/2, size/2);
|
||||
cairo_translate (cr, 1., 1.);
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_curve_to (cr, -0.9, 0, -0.9, -0.9, -0.9, -0.9);
|
||||
cairo_curve_to (cr, 0.0, -0.9, 0, 0, 0, 0);
|
||||
cairo_curve_to (cr, 0.9, 0.0, 0.9, -0.9, 0.9, -0.9);
|
||||
cairo_curve_to (cr, 0.0, -0.9, 0.0, 0.0, 0.0, 0.0);
|
||||
cairo_curve_to (cr, 0.9, 0.0, 0.9, 0.9, 0.9, 0.9);
|
||||
cairo_curve_to (cr, 0.0, 0.9, 0.0, 0.0, 0.0, 0.0);
|
||||
cairo_curve_to (cr, -0.9, 0.0, -0.9, 0.9, -0.9, 0.9);
|
||||
cairo_curve_to (cr, 0.0, 0.9, 0.0, 0.0, 0.0, 0.0);
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_fill (cr);
|
||||
|
||||
mask = cairo_pattern_create_for_surface (cairo_get_target (cr));
|
||||
cairo_destroy (cr);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void
|
||||
paint (cairo_surface_t *surface,
|
||||
cairo_pattern_t *mask,
|
||||
int mask_size)
|
||||
{
|
||||
cairo_t *cr;
|
||||
int i;
|
||||
|
||||
cr = cairo_create (surface);
|
||||
for (i = 0; i < N_FLOWERS; i++) {
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_matrix_t matrix;
|
||||
|
||||
cairo_matrix_init_identity (&matrix);
|
||||
cairo_matrix_translate (&matrix, flowers[i].x, flowers[i].y);
|
||||
cairo_matrix_scale (&matrix,
|
||||
flowers[i].scale/mask_size,
|
||||
flowers[i].scale/mask_size);
|
||||
cairo_matrix_rotate (&matrix, flowers[i].rotation);
|
||||
cairo_set_matrix (cr, &matrix);
|
||||
|
||||
pattern = cairo_pattern_create_linear (0, -mask_size, 0, mask_size);
|
||||
cairo_pattern_add_color_stop_rgba (pattern, 0,
|
||||
flowers[i].r1, flowers[i].g1, flowers[i].b1, flowers[i].a1);
|
||||
cairo_pattern_add_color_stop_rgba (pattern, 1,
|
||||
flowers[i].r2, flowers[i].g2, flowers[i].b2, flowers[i].a2);
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_pattern_destroy (pattern);
|
||||
|
||||
cairo_mask (cr, mask);
|
||||
}
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_pattern_t *flower;
|
||||
|
||||
surface = _get_fb ();
|
||||
if (surface == NULL) {
|
||||
fprintf (stderr, "Failed to create framebuffer\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
flower = create_flower (surface, FLOWER_SIZE);
|
||||
while (1) {
|
||||
randomize_flowers (cairo_gl_surface_get_width (surface),
|
||||
cairo_gl_surface_get_height (surface));
|
||||
paint (surface, flower, FLOWER_SIZE);
|
||||
cairo_gl_surface_swapbuffers (surface);
|
||||
}
|
||||
|
||||
cairo_pattern_destroy (flower);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
256
test/glx-flowers.c
Normal file
256
test/glx-flowers.c
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* Copyright © 2007 Michael Dominic K.
|
||||
* Copyright © 2009 Chris Wilson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <cairo-gl.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float scale;
|
||||
float rotation;
|
||||
float r1, g1, b1, a1;
|
||||
float r2, b2, g2, a2;
|
||||
} Flower;
|
||||
|
||||
#define N_FLOWERS 200
|
||||
#define FLOWER_SIZE 128
|
||||
static Flower flowers[N_FLOWERS];
|
||||
|
||||
#define WIDTH 640
|
||||
#define HEIGHT 480
|
||||
|
||||
static cairo_surface_t *
|
||||
_surface_create (void)
|
||||
{
|
||||
int rgb_attribs[] = { GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_DOUBLEBUFFER,
|
||||
None };
|
||||
XVisualInfo *vi;
|
||||
GLXContext ctx;
|
||||
Display *dpy;
|
||||
Colormap cmap;
|
||||
XSetWindowAttributes swa;
|
||||
Window win;
|
||||
|
||||
cairo_gl_context_t *context;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
dpy = XOpenDisplay (NULL);
|
||||
if (dpy == NULL) {
|
||||
fprintf (stderr, "Failed to open display\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vi = glXChooseVisual (dpy, DefaultScreen (dpy), rgb_attribs);
|
||||
if (vi == NULL) {
|
||||
fprintf (stderr, "Failed to create RGB, double-buffered visual\n");
|
||||
XCloseDisplay (dpy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx = glXCreateContext (dpy, vi, NULL, True);
|
||||
|
||||
cmap = XCreateColormap (dpy,
|
||||
RootWindow (dpy, vi->screen),
|
||||
vi->visual,
|
||||
AllocNone);
|
||||
swa.colormap = cmap;
|
||||
swa.border_pixel = 0;
|
||||
win = XCreateWindow (dpy, RootWindow (dpy, vi->screen),
|
||||
0, 0,
|
||||
640, 480,
|
||||
0,
|
||||
vi->depth,
|
||||
InputOutput,
|
||||
vi->visual,
|
||||
CWBorderPixel | CWColormap, &swa);
|
||||
XMapWindow (dpy, win);
|
||||
XFlush (dpy);
|
||||
XFree (vi);
|
||||
|
||||
context = cairo_glx_context_create (dpy, ctx);
|
||||
surface = cairo_gl_surface_create_for_window (context, win, WIDTH, HEIGHT);
|
||||
cairo_gl_context_destroy (context);
|
||||
|
||||
if (cairo_surface_status (surface)) {
|
||||
fprintf (stderr, "failed to create cairo surface\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
hars_petruska_f54_1_random (void)
|
||||
{
|
||||
#define rol(x,k) ((x << k) | (x >> (32-k)))
|
||||
static unsigned int x;
|
||||
return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
|
||||
#undef rol
|
||||
}
|
||||
|
||||
static void
|
||||
random_colour (float *r, float *g, float *b, float *a)
|
||||
{
|
||||
unsigned int x = hars_petruska_f54_1_random ();
|
||||
*r = (x & 255) / 255.; x >>= 8;
|
||||
*g = (x & 255) / 255.; x >>= 8;
|
||||
*b = (x & 255) / 255.; x >>= 8;
|
||||
*a = x / 255.;
|
||||
}
|
||||
|
||||
static void
|
||||
randomize_flower (Flower *flower, int width, int height)
|
||||
{
|
||||
flower->x = (hars_petruska_f54_1_random() & 8191) * width / 8191.;
|
||||
flower->y = (hars_petruska_f54_1_random() & 8191) * height / 8191.;
|
||||
flower->scale = 10 + (hars_petruska_f54_1_random() & 511) * 140 / 512.;
|
||||
flower->rotation = (hars_petruska_f54_1_random() & 511) * M_PI / 256;
|
||||
|
||||
random_colour (&flower->r1, &flower->g1, &flower->b1, &flower->a1);
|
||||
random_colour (&flower->r2, &flower->g2, &flower->b2, &flower->a2);
|
||||
}
|
||||
|
||||
static void
|
||||
randomize_flowers (int width, int height)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < N_FLOWERS; i++)
|
||||
randomize_flower (&flowers [i], width, height);
|
||||
}
|
||||
|
||||
static cairo_pattern_t *
|
||||
create_flower (cairo_surface_t *target, int size)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_pattern_t *mask;
|
||||
cairo_t *cr;
|
||||
|
||||
surface = cairo_surface_create_similar (target,
|
||||
CAIRO_CONTENT_ALPHA, size, size);
|
||||
cr = cairo_create (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
cairo_scale (cr, size/2, size/2);
|
||||
cairo_translate (cr, 1., 1.);
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_curve_to (cr, -0.9, 0, -0.9, -0.9, -0.9, -0.9);
|
||||
cairo_curve_to (cr, 0.0, -0.9, 0, 0, 0, 0);
|
||||
cairo_curve_to (cr, 0.9, 0.0, 0.9, -0.9, 0.9, -0.9);
|
||||
cairo_curve_to (cr, 0.0, -0.9, 0.0, 0.0, 0.0, 0.0);
|
||||
cairo_curve_to (cr, 0.9, 0.0, 0.9, 0.9, 0.9, 0.9);
|
||||
cairo_curve_to (cr, 0.0, 0.9, 0.0, 0.0, 0.0, 0.0);
|
||||
cairo_curve_to (cr, -0.9, 0.0, -0.9, 0.9, -0.9, 0.9);
|
||||
cairo_curve_to (cr, 0.0, 0.9, 0.0, 0.0, 0.0, 0.0);
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_fill (cr);
|
||||
|
||||
mask = cairo_pattern_create_for_surface (cairo_get_target (cr));
|
||||
cairo_destroy (cr);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void
|
||||
paint (cairo_surface_t *surface,
|
||||
cairo_pattern_t *mask,
|
||||
int mask_size)
|
||||
{
|
||||
cairo_t *cr;
|
||||
int i;
|
||||
|
||||
cr = cairo_create (surface);
|
||||
for (i = 0; i < N_FLOWERS; i++) {
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_matrix_t matrix;
|
||||
|
||||
cairo_matrix_init_identity (&matrix);
|
||||
cairo_matrix_translate (&matrix, flowers[i].x, flowers[i].y);
|
||||
cairo_matrix_scale (&matrix,
|
||||
flowers[i].scale/mask_size,
|
||||
flowers[i].scale/mask_size);
|
||||
cairo_matrix_rotate (&matrix, flowers[i].rotation);
|
||||
cairo_set_matrix (cr, &matrix);
|
||||
|
||||
pattern = cairo_pattern_create_linear (0, -mask_size, 0, mask_size);
|
||||
cairo_pattern_add_color_stop_rgba (pattern, 0,
|
||||
flowers[i].r1, flowers[i].g1, flowers[i].b1, flowers[i].a1);
|
||||
cairo_pattern_add_color_stop_rgba (pattern, 1,
|
||||
flowers[i].r2, flowers[i].g2, flowers[i].b2, flowers[i].a2);
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_pattern_destroy (pattern);
|
||||
|
||||
cairo_mask (cr, mask);
|
||||
}
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_pattern_t *flower;
|
||||
int frame, frame_target = 5;
|
||||
struct timeval start, stop;
|
||||
|
||||
surface = _surface_create ();
|
||||
if (surface == NULL) {
|
||||
fprintf (stderr, "Failed to create framebuffer\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
flower = create_flower (surface, FLOWER_SIZE);
|
||||
frame = 0;
|
||||
gettimeofday (&start, NULL);
|
||||
while (1) {
|
||||
randomize_flowers (cairo_gl_surface_get_width (surface),
|
||||
cairo_gl_surface_get_height (surface));
|
||||
paint (surface, flower, FLOWER_SIZE);
|
||||
cairo_gl_surface_swapbuffers (surface);
|
||||
|
||||
if (++frame == frame_target) {
|
||||
int ticks;
|
||||
|
||||
gettimeofday (&stop, NULL);
|
||||
|
||||
ticks = (stop.tv_sec - start.tv_sec) * 1000000;
|
||||
ticks += (stop.tv_usec - start.tv_usec);
|
||||
printf ("%.2f fps\n", frame * 1000000. / ticks);
|
||||
|
||||
/* rate-limit output to once every 5 seconds */
|
||||
frame_target = (frame_target + 5000000 * frame / ticks + 1) / 2;
|
||||
|
||||
frame = 0;
|
||||
start = stop;
|
||||
}
|
||||
}
|
||||
|
||||
cairo_pattern_destroy (flower);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
2
util/cairo-script/.gitignore
vendored
2
util/cairo-script/.gitignore
vendored
|
|
@ -1,2 +1,4 @@
|
|||
csi-replay
|
||||
csi-exec
|
||||
csi-egl
|
||||
csi-glx
|
||||
|
|
|
|||
|
|
@ -22,10 +22,25 @@ libcairo_script_interpreter_la_LDFLAGS = -version-info $(CAIRO_LIBTOOL_VERSION_I
|
|||
libcairo_script_interpreter_la_LIBADD = $(top_builddir)/src/libcairo.la $(CAIRO_LIBS)
|
||||
|
||||
csi_replay_SOURCES = csi-replay.c
|
||||
csi_replay_CFLAGS = $(CAIRO_CFLAGS)
|
||||
csi_replay_LDADD = libcairo-script-interpreter.la $(top_builddir)/src/libcairo.la $(CAIRO_LIBS)
|
||||
|
||||
csi_exec_SOURCES = csi-exec.c
|
||||
csi_exec_LDADD = libcairo-script-interpreter.la $(top_builddir)/src/libcairo.la $(CAIRO_LIBS)
|
||||
|
||||
if CAIRO_HAS_GL_EGL_SURFACE
|
||||
noinst_PROGRAMS += csi-egl
|
||||
csi_egl_SOURCES = csi-egl.c
|
||||
csi_egl_CFLAGS = $(CAIRO_CFLAGS)
|
||||
csi_egl_LDADD = libcairo-script-interpreter.la $(top_builddir)/src/libcairo.la $(CAIRO_LIBS)
|
||||
endif
|
||||
|
||||
if CAIRO_HAS_GL_GLX_SURFACE
|
||||
noinst_PROGRAMS += csi-glx
|
||||
csi_glx_SOURCES = csi-glx.c
|
||||
csi_glx_CFLAGS = $(CAIRO_CFLAGS)
|
||||
csi_glx_LDADD = libcairo-script-interpreter.la $(top_builddir)/src/libcairo.la $(CAIRO_LIBS)
|
||||
endif
|
||||
|
||||
EXTRA_DIST = \
|
||||
COPYING
|
||||
|
|
|
|||
263
util/cairo-script/csi-egl.c
Normal file
263
util/cairo-script/csi-egl.c
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
#include <cairo-gl.h>
|
||||
#include "cairo-script-interpreter.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <i915_drm.h>
|
||||
|
||||
#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
|
||||
#include <libudev.h>
|
||||
|
||||
static void
|
||||
die (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
vfprintf (stderr, fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static EGLDisplay
|
||||
_get_display (const char *card)
|
||||
{
|
||||
EGLint major, minor;
|
||||
EGLDisplay display;
|
||||
struct udev *udev;
|
||||
struct udev_device *device;
|
||||
struct stat st;
|
||||
|
||||
if (stat (card, &st) < 0) {
|
||||
die ("no such device\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
udev = udev_new ();
|
||||
device = udev_device_new_from_devnum (udev, 'c', st.st_rdev);
|
||||
if (device == NULL) {
|
||||
die ("failed to find device\n");
|
||||
return NULL;
|
||||
}
|
||||
display = eglCreateDisplayNative (device);
|
||||
udev_device_unref (device);
|
||||
udev_unref (udev);
|
||||
|
||||
if (display == NULL) {
|
||||
die ("failed to open display\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (! eglInitialize (display, &major, &minor)) {
|
||||
die ("failed to initialize display\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_get_fb (const char *card)
|
||||
{
|
||||
const EGLint config_attribs[] = {
|
||||
EGL_DEPTH_SIZE, 24,
|
||||
EGL_STENCIL_SIZE, 8,
|
||||
EGL_CONFIG_CAVEAT, EGL_NONE,
|
||||
EGL_NONE
|
||||
};
|
||||
const EGLint surface_attribs[] = {
|
||||
EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLDisplay display;
|
||||
EGLContext context;
|
||||
EGLConfig config;
|
||||
EGLSurface s;
|
||||
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
drmModeConnector *connector;
|
||||
drmModeRes *resources;
|
||||
drmModeEncoder *encoder;
|
||||
drmModeModeInfo *mode;
|
||||
struct drm_i915_gem_create create;
|
||||
struct drm_gem_flink flink;
|
||||
int i, ret, fd;
|
||||
uint32_t fb_id;
|
||||
|
||||
display = _get_display (card);
|
||||
if (display == NULL) {
|
||||
die ("Unable to open display\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (! eglChooseConfig (display, config_attribs, &config, 1, NULL)) {
|
||||
die ("Unable to choose config\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context = eglCreateContext (display, config, NULL, NULL);
|
||||
if (context == NULL) {
|
||||
die ("failed to create context\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = eglGetDisplayFD (display);
|
||||
resources = drmModeGetResources (fd);
|
||||
if (resources == NULL) {
|
||||
die ("drmModeGetResources failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < resources->count_connectors; i++) {
|
||||
connector = drmModeGetConnector (fd, resources->connectors[i]);
|
||||
if (connector == NULL)
|
||||
continue;
|
||||
|
||||
if (connector->connection == DRM_MODE_CONNECTED &&
|
||||
connector->count_modes > 0)
|
||||
break;
|
||||
|
||||
drmModeFreeConnector (connector);
|
||||
}
|
||||
|
||||
if (i == resources->count_connectors) {
|
||||
die ("No currently active connector found.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mode = &connector->modes[0];
|
||||
|
||||
for (i = 0; i < resources->count_encoders; i++) {
|
||||
encoder = drmModeGetEncoder(fd, resources->encoders[i]);
|
||||
|
||||
if (encoder == NULL)
|
||||
continue;
|
||||
|
||||
if (encoder->encoder_id == connector->encoder_id)
|
||||
break;
|
||||
|
||||
drmModeFreeEncoder(encoder);
|
||||
}
|
||||
|
||||
/* Mode size at 32 bpp */
|
||||
create.size = mode->hdisplay * mode->vdisplay * 4;
|
||||
if (ioctl (fd, DRM_IOCTL_I915_GEM_CREATE, &create) != 0) {
|
||||
die ("gem create failed: %m\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = drmModeAddFB (fd, mode->hdisplay, mode->vdisplay,
|
||||
32, 32, mode->hdisplay * 4, create.handle, &fb_id);
|
||||
if (ret) {
|
||||
die ("failed to add fb: %m\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = drmModeSetCrtc (fd, encoder->crtc_id, fb_id, 0, 0,
|
||||
&connector->connector_id, 1, mode);
|
||||
if (ret) {
|
||||
die ("failed to set mode: %m\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flink.handle = create.handle;
|
||||
if (ioctl (fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) {
|
||||
die ("gem flink failed: %m\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s = eglCreateSurfaceForName (display, config,
|
||||
flink.name,
|
||||
mode->hdisplay, mode->vdisplay,
|
||||
mode->hdisplay * 4,
|
||||
surface_attribs);
|
||||
if (s == NULL) {
|
||||
die ("failed to create surface\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx = cairo_egl_context_create (display, context);
|
||||
surface = cairo_gl_surface_create_for_eagle (ctx, s,
|
||||
mode->hdisplay,
|
||||
mode->vdisplay);
|
||||
cairo_gl_context_destroy (ctx);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_egl_surface_create (void *closure,
|
||||
cairo_content_t content,
|
||||
double width, double height)
|
||||
{
|
||||
return cairo_surface_create_similar (closure, content, width, height);
|
||||
}
|
||||
|
||||
static struct list {
|
||||
struct list *next;
|
||||
cairo_t *context;
|
||||
cairo_surface_t *surface;
|
||||
} *list;
|
||||
|
||||
static cairo_t *
|
||||
_egl_context_create (void *closure, cairo_surface_t *surface)
|
||||
{
|
||||
cairo_t *cr = cairo_create (surface);
|
||||
struct list *l = malloc (sizeof (*l));
|
||||
l->next = list;
|
||||
l->context = cr;
|
||||
l->surface = cairo_surface_reference (surface);
|
||||
list = l;
|
||||
return cr;
|
||||
}
|
||||
|
||||
static void
|
||||
_egl_context_destroy (void *closure, void *ptr)
|
||||
{
|
||||
struct list *l, **prev = &list;
|
||||
while ((l = *prev) != NULL) {
|
||||
if (l->context == ptr) {
|
||||
if (cairo_surface_status (l->surface) == CAIRO_STATUS_SUCCESS) {
|
||||
cairo_t *cr = cairo_create (closure);
|
||||
cairo_set_source_surface (cr, l->surface, 0, 0);
|
||||
cairo_paint (cr);
|
||||
cairo_destroy (cr);
|
||||
cairo_gl_surface_swapbuffers (closure);
|
||||
}
|
||||
|
||||
cairo_surface_destroy (l->surface);
|
||||
*prev = l->next;
|
||||
free (l);
|
||||
return;
|
||||
}
|
||||
prev = &l->next;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
const cairo_script_interpreter_hooks_t hooks = {
|
||||
.closure = _get_fb ("/dev/dri/card0"),
|
||||
.surface_create = _egl_surface_create,
|
||||
.context_create = _egl_context_create,
|
||||
.context_destroy = _egl_context_destroy
|
||||
};
|
||||
cairo_script_interpreter_t *csi;
|
||||
int i;
|
||||
|
||||
csi = cairo_script_interpreter_create ();
|
||||
cairo_script_interpreter_install_hooks (csi, &hooks);
|
||||
for (i = 1; i < argc; i++)
|
||||
cairo_script_interpreter_run (csi, argv[i]);
|
||||
return cairo_script_interpreter_destroy (csi);
|
||||
}
|
||||
150
util/cairo-script/csi-glx.c
Normal file
150
util/cairo-script/csi-glx.c
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
#include <cairo-gl.h>
|
||||
#include "cairo-script-interpreter.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
static void
|
||||
die (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
vfprintf (stderr, fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_get_fb (void)
|
||||
{
|
||||
int rgb_attribs[] = { GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_DOUBLEBUFFER,
|
||||
None };
|
||||
XVisualInfo *vi;
|
||||
GLXContext ctx;
|
||||
Display *dpy;
|
||||
Screen *screen;
|
||||
Colormap cmap;
|
||||
XSetWindowAttributes swa;
|
||||
Window win;
|
||||
|
||||
cairo_gl_context_t *context;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
dpy = XOpenDisplay (NULL);
|
||||
if (dpy == NULL)
|
||||
die ("Failed to open display\n");
|
||||
|
||||
vi = glXChooseVisual (dpy, DefaultScreen (dpy), rgb_attribs);
|
||||
if (vi == NULL)
|
||||
die ("Failed to create RGB, double-buffered visual\n");
|
||||
|
||||
ctx = glXCreateContext (dpy, vi, NULL, True);
|
||||
|
||||
screen = ScreenOfDisplay (dpy, vi->screen);
|
||||
|
||||
cmap = XCreateColormap (dpy,
|
||||
RootWindowOfScreen (screen),
|
||||
vi->visual,
|
||||
AllocNone);
|
||||
swa.colormap = cmap;
|
||||
swa.border_pixel = 0;
|
||||
swa.override_redirect = True;
|
||||
win = XCreateWindow (dpy, RootWindowOfScreen (screen),
|
||||
0, 0,
|
||||
WidthOfScreen (screen), HeightOfScreen (screen),
|
||||
0,
|
||||
vi->depth,
|
||||
InputOutput,
|
||||
vi->visual,
|
||||
CWBorderPixel | CWColormap | CWOverrideRedirect,
|
||||
&swa);
|
||||
XMapWindow (dpy, win);
|
||||
XFlush (dpy);
|
||||
XFree (vi);
|
||||
|
||||
context = cairo_glx_context_create (dpy, ctx);
|
||||
surface = cairo_gl_surface_create_for_window (context, win,
|
||||
WidthOfScreen (screen),
|
||||
HeightOfScreen (screen));
|
||||
cairo_gl_context_destroy (context);
|
||||
|
||||
if (cairo_surface_status (surface))
|
||||
die ("failed to create cairo surface\n");
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_glx_surface_create (void *closure,
|
||||
cairo_content_t content,
|
||||
double width, double height)
|
||||
{
|
||||
return cairo_surface_create_similar (closure, content, width, height);
|
||||
}
|
||||
|
||||
static struct list {
|
||||
struct list *next;
|
||||
cairo_t *context;
|
||||
cairo_surface_t *surface;
|
||||
} *list;
|
||||
|
||||
static cairo_t *
|
||||
_glx_context_create (void *closure, cairo_surface_t *surface)
|
||||
{
|
||||
cairo_t *cr = cairo_create (surface);
|
||||
struct list *l = malloc (sizeof (*l));
|
||||
l->next = list;
|
||||
l->context = cr;
|
||||
l->surface = cairo_surface_reference (surface);
|
||||
list = l;
|
||||
return cr;
|
||||
}
|
||||
|
||||
static void
|
||||
_glx_context_destroy (void *closure, void *ptr)
|
||||
{
|
||||
struct list *l, **prev = &list;
|
||||
while ((l = *prev) != NULL) {
|
||||
if (l->context == ptr) {
|
||||
if (cairo_surface_status (l->surface) == CAIRO_STATUS_SUCCESS) {
|
||||
cairo_t *cr = cairo_create (closure);
|
||||
cairo_set_source_surface (cr, l->surface, 0, 0);
|
||||
cairo_paint (cr);
|
||||
cairo_destroy (cr);
|
||||
cairo_gl_surface_swapbuffers (closure);
|
||||
}
|
||||
|
||||
cairo_surface_destroy (l->surface);
|
||||
*prev = l->next;
|
||||
free (l);
|
||||
return;
|
||||
}
|
||||
prev = &l->next;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
const cairo_script_interpreter_hooks_t hooks = {
|
||||
.closure = _get_fb (),
|
||||
.surface_create = _glx_surface_create,
|
||||
.context_create = _glx_context_create,
|
||||
.context_destroy = _glx_context_destroy
|
||||
};
|
||||
cairo_script_interpreter_t *csi;
|
||||
int i;
|
||||
|
||||
csi = cairo_script_interpreter_create ();
|
||||
cairo_script_interpreter_install_hooks (csi, &hooks);
|
||||
for (i = 1; i < argc; i++)
|
||||
cairo_script_interpreter_run (csi, argv[i]);
|
||||
return cairo_script_interpreter_destroy (csi);
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static const cairo_user_data_key_t _key;
|
||||
|
||||
|
|
@ -107,6 +108,63 @@ _xrender_surface_create (void *closure,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_GL_GLX_SURFACE
|
||||
#include <cairo-gl.h>
|
||||
static cairo_gl_context_t *
|
||||
_glx_get_context (cairo_content_t content)
|
||||
{
|
||||
static cairo_gl_context_t *context;
|
||||
|
||||
if (context == NULL) {
|
||||
int rgba_attribs[] = {
|
||||
GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_ALPHA_SIZE, 1,
|
||||
GLX_DOUBLEBUFFER,
|
||||
None
|
||||
};
|
||||
XVisualInfo *visinfo;
|
||||
GLXContext gl_ctx;
|
||||
Display *dpy;
|
||||
|
||||
dpy = XOpenDisplay (NULL);
|
||||
if (dpy == NULL) {
|
||||
fprintf (stderr, "Failed to open display.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs);
|
||||
if (visinfo == NULL) {
|
||||
fprintf (stderr, "Failed to create RGBA, double-buffered visual\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
gl_ctx = glXCreateContext (dpy, visinfo, NULL, True);
|
||||
XFree (visinfo);
|
||||
|
||||
context = cairo_glx_context_create (dpy, gl_ctx);
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_glx_surface_create (void *closure,
|
||||
cairo_content_t content,
|
||||
double width, double height)
|
||||
{
|
||||
if (width == 0)
|
||||
width = 1;
|
||||
if (height == 0)
|
||||
height = 1;
|
||||
|
||||
return cairo_gl_surface_create (_glx_get_context (content),
|
||||
content, width, height);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_PDF_SURFACE
|
||||
#include <cairo-pdf.h>
|
||||
static cairo_surface_t *
|
||||
|
|
@ -174,6 +232,9 @@ main (int argc, char **argv)
|
|||
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
||||
{ "--xrender", _xrender_surface_create },
|
||||
#endif
|
||||
#if CAIRO_HAS_GL_GLX_SURFACE
|
||||
{ "--glx", _glx_surface_create },
|
||||
#endif
|
||||
#if CAIRO_HAS_PDF_SURFACE
|
||||
{ "--pdf", _pdf_surface_create },
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue