static cairo_surface_t* create_source_surface(int width, int height) { 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 ctx; struct closure *arg; cairo_device_t *device; cairo_surface_t *surface; Display *dpy; dpy = XOpenDisplay(NULL); if (dpy == NULL) return NULL; visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs); if (visinfo == NULL) { XCloseDisplay (dpy); return NULL; } ctx = glXCreateContext (dpy, visinfo, NULL, True); XFree (visinfo); if (ctx == NULL) { XCloseDisplay (dpy); return NULL; } arg = (struct closure*)(malloc (sizeof (struct closure))); arg->dpy = dpy; arg->ctx = ctx; device = cairo_glx_device_create (dpy, ctx); if (cairo_device_set_user_data (device, (cairo_user_data_key_t *) cleanup, arg, cleanup)) { cleanup (arg); return NULL; } surface = cairo_gl_surface_create (device, CAIRO_CONTENT_COLOR_ALPHA, width, height); cairo_device_destroy (device); return surface; }
static cairo_surface_t * _cairo_boilerplate_egl_create_surface (const char *name, cairo_content_t content, double width, double height, double max_width, double max_height, cairo_boilerplate_mode_t mode, int id, void **closure) { egl_target_closure_t *gltc; cairo_surface_t *surface; int major, minor; EGLConfig *configs; EGLint numConfigs; gltc = xcalloc (1, sizeof (egl_target_closure_t)); *closure = gltc; gltc->dpy = eglGetDisplay (EGL_DEFAULT_DISPLAY); if (! eglInitialize (gltc->dpy, &major, &minor)) { free (gltc); return NULL; } eglGetConfigs (gltc->dpy, NULL, 0, &numConfigs); if (numConfigs == 0) { free (gltc); return NULL; } configs = xmalloc(sizeof(*configs) *numConfigs); eglGetConfigs (gltc->dpy, configs, numConfigs, &numConfigs); eglBindAPI (EGL_OPENGL_API); gltc->ctx = eglCreateContext (gltc->dpy, configs[0], EGL_NO_CONTEXT, NULL); if (gltc->ctx == EGL_NO_CONTEXT) { eglTerminate (gltc->dpy); free (gltc); return NULL; } gltc->device = cairo_egl_device_create (gltc->dpy, gltc->ctx); gltc->surface = surface = cairo_gl_surface_create (gltc->device, content, ceil (width), ceil (height)); if (cairo_surface_status (surface)) _cairo_boilerplate_egl_cleanup (gltc); return surface; }
static cairo_int_status_t render_glyphs_via_mask (cairo_gl_surface_t *dst, int dst_x, int dst_y, cairo_operator_t op, cairo_surface_t *source, cairo_composite_glyphs_info_t *info) { cairo_surface_t *mask; cairo_status_t status; cairo_bool_t has_component_alpha; TRACE ((stderr, "%s\n", __FUNCTION__)); /* XXX: For non-CA, this should be CAIRO_CONTENT_ALPHA to save memory */ mask = cairo_gl_surface_create (dst->base.device, CAIRO_CONTENT_COLOR_ALPHA, info->extents.width, info->extents.height); if (unlikely (mask->status)) return mask->status; status = render_glyphs ((cairo_gl_surface_t *) mask, info->extents.x, info->extents.y, CAIRO_OPERATOR_ADD, NULL, info, &has_component_alpha); if (likely (status == CAIRO_STATUS_SUCCESS)) { cairo_surface_pattern_t mask_pattern; cairo_surface_pattern_t source_pattern; mask->is_clear = FALSE; _cairo_pattern_init_for_surface (&mask_pattern, mask); mask_pattern.base.has_component_alpha = has_component_alpha; mask_pattern.base.filter = CAIRO_FILTER_NEAREST; mask_pattern.base.extend = CAIRO_EXTEND_NONE; cairo_matrix_init_translate (&mask_pattern.base.matrix, dst_x-info->extents.x, dst_y-info->extents.y); _cairo_pattern_init_for_surface (&source_pattern, source); cairo_matrix_init_translate (&source_pattern.base.matrix, dst_x-info->extents.x, dst_y-info->extents.y); status = _cairo_surface_mask (&dst->base, op, &source_pattern.base, &mask_pattern.base, NULL); _cairo_pattern_fini (&mask_pattern.base); _cairo_pattern_fini (&source_pattern.base); } cairo_surface_destroy (mask); return status; }
static cairo_int_status_t _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst, cairo_operator_t op, const cairo_pattern_t *source, cairo_glyph_t *glyphs, int num_glyphs, const cairo_rectangle_int_t *glyph_extents, cairo_scaled_font_t *scaled_font, cairo_clip_t *clip, int *remaining_glyphs) { cairo_surface_t *mask; cairo_status_t status; cairo_solid_pattern_t solid; int i; mask = cairo_gl_surface_create (dst->ctx, CAIRO_CONTENT_ALPHA, glyph_extents->width, glyph_extents->height); if (unlikely (mask->status)) return mask->status; for (i = 0; i < num_glyphs; i++) { glyphs[i].x -= glyph_extents->x; glyphs[i].y -= glyph_extents->y; } _cairo_pattern_init_solid (&solid, CAIRO_COLOR_WHITE, CAIRO_CONTENT_ALPHA); status = _render_glyphs ((cairo_gl_surface_t *) mask, 0, 0, CAIRO_OPERATOR_ADD, &solid.base, glyphs, num_glyphs, glyph_extents, scaled_font, NULL, remaining_glyphs); if (likely (status == CAIRO_STATUS_SUCCESS)) { cairo_surface_pattern_t mask_pattern; _cairo_pattern_init_for_surface (&mask_pattern, mask); cairo_matrix_init_translate (&mask_pattern.base.matrix, -glyph_extents->x, -glyph_extents->y); status = _cairo_surface_mask (&dst->base, op, source, &mask_pattern.base, clip); _cairo_pattern_fini (&mask_pattern.base); } else { for (i = 0; i < num_glyphs; i++) { glyphs[i].x += glyph_extents->x; glyphs[i].y += glyph_extents->y; } *remaining_glyphs = num_glyphs; } cairo_surface_destroy (mask); return status; }
static cairo_surface_t * _glx_surface_create (void *closure, cairo_content_t content, double width, double height, long uid) { if (width == 0) width = 1; if (height == 0) height = 1; return cairo_gl_surface_create (_glx_get_context (content), content, width, height); }
static cairo_surface_t* _prepare_unbounded_surface (cairo_gl_surface_t *dst) { cairo_surface_t* surface = cairo_gl_surface_create (dst->base.device, dst->base.content, dst->width, dst->height); if (surface == NULL) return NULL; if (unlikely (surface->status)) { cairo_surface_destroy (surface); return NULL; } return surface; }
static cairo_status_t cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx, cairo_format_t format, cairo_gl_glyph_cache_t **cache_out) { cairo_gl_glyph_cache_t *cache; cairo_content_t content; switch (format) { case CAIRO_FORMAT_RGB30: case CAIRO_FORMAT_RGB16_565: case CAIRO_FORMAT_ARGB32: case CAIRO_FORMAT_RGB24: cache = &ctx->glyph_cache[0]; content = CAIRO_CONTENT_COLOR_ALPHA; break; case CAIRO_FORMAT_A8: case CAIRO_FORMAT_A1: cache = &ctx->glyph_cache[1]; content = CAIRO_CONTENT_ALPHA; break; default: case CAIRO_FORMAT_INVALID: ASSERT_NOT_REACHED; return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); } if (unlikely (cache->surface == NULL)) { cairo_surface_t *surface; surface = cairo_gl_surface_create (&ctx->base, content, GLYPH_CACHE_WIDTH, GLYPH_CACHE_HEIGHT); if (unlikely (surface->status)) return surface->status; _cairo_surface_release_device_reference (surface); cache->surface = (cairo_gl_surface_t *)surface; cache->surface->operand.texture.attributes.has_component_alpha = content == CAIRO_CONTENT_COLOR_ALPHA; } *cache_out = cache; return CAIRO_STATUS_SUCCESS; }
int main(int argc, char *argv[]) { /* Use the MSAA compositor if it's available. */ setenv("CAIRO_GL_COMPOSITOR", "msaa", 1); Window window; cairo_device_t* device; cairo_surface_t* windowSurface; createAndShowWindow(gTileWidth * 2, gTileHeight * 2, &window, &device, &windowSurface); cairo_surface_t* textureSurface = cairo_gl_surface_create(device, CAIRO_CONTENT_COLOR_ALPHA, gTileWidth * 2, gTileHeight); while (1) { cairo_t* windowCr = cairo_create(windowSurface); cairo_translate(windowCr, 0, gTileHeight); render(windowCr, CAIRO_ANTIALIAS_NONE); cairo_translate(windowCr, gTileWidth, 0); render(windowCr, CAIRO_ANTIALIAS_GOOD); cairo_t* textureCr = cairo_create(textureSurface); render(textureCr, CAIRO_ANTIALIAS_NONE); cairo_translate(textureCr, gTileWidth, 0); render(textureCr, CAIRO_ANTIALIAS_GOOD); cairo_destroy(textureCr); cairo_translate(windowCr, -gTileWidth, -gTileHeight); cairo_set_source_surface(windowCr, textureSurface, 0, 0); cairo_rectangle(windowCr, 0, 0, gTileWidth * 2, gTileHeight); cairo_fill(windowCr); cairo_destroy(windowCr); cairo_gl_surface_swapbuffers(windowSurface); sleep(1); } cairo_surface_destroy(textureSurface); exit(EXIT_SUCCESS); }
static cairo_surface_t * _cairo_boilerplate_gl_create_surface (const char *name, cairo_content_t content, double width, double height, double max_width, double max_height, cairo_boilerplate_mode_t mode, void **closure) { int rgba_attribs[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_ALPHA_SIZE, 1, GLX_DOUBLEBUFFER, None }; int rgb_attribs[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None }; XVisualInfo *visinfo; GLXContext ctx; gl_target_closure_t *gltc; cairo_surface_t *surface; Display *dpy; gltc = calloc (1, sizeof (gl_target_closure_t)); *closure = gltc; if (width == 0) width = 1; if (height == 0) height = 1; dpy = XOpenDisplay (NULL); gltc->dpy = dpy; if (!gltc->dpy) { fprintf (stderr, "Failed to open display: %s\n", XDisplayName(0)); free (gltc); return NULL; } if (mode == CAIRO_BOILERPLATE_MODE_TEST) XSynchronize (gltc->dpy, 1); if (content == CAIRO_CONTENT_COLOR) visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgb_attribs); else visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs); if (visinfo == NULL) { fprintf (stderr, "Failed to create RGB, double-buffered visual\n"); XCloseDisplay (dpy); free (gltc); return NULL; } ctx = glXCreateContext (dpy, visinfo, NULL, True); XFree (visinfo); gltc->ctx = ctx; gltc->device = cairo_glx_device_create (dpy, ctx); gltc->surface = surface = cairo_gl_surface_create (gltc->device, content, ceil (width), ceil (height)); if (cairo_surface_status (surface)) _cairo_boilerplate_gl_cleanup (gltc); return surface; }