summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boilerplate/cairo-boilerplate-cogl.c12
-rw-r--r--src/Makefile.sources2
-rw-r--r--src/cairo-cogl-context-private.h58
-rw-r--r--src/cairo-cogl-context.c1063
-rw-r--r--src/cairo-cogl-private.h17
-rw-r--r--src/cairo-cogl-surface.c1133
-rw-r--r--src/cairo-debug.c4
-rw-r--r--src/meson.build1
8 files changed, 498 insertions, 1792 deletions
diff --git a/boilerplate/cairo-boilerplate-cogl.c b/boilerplate/cairo-boilerplate-cogl.c
index c293b3932..2339dd883 100644
--- a/boilerplate/cairo-boilerplate-cogl.c
+++ b/boilerplate/cairo-boilerplate-cogl.c
@@ -119,12 +119,12 @@ _cairo_boilerplate_cogl_create_onscreen_color_surface (const char *name,
height = 1;
if (content & CAIRO_CONTENT_ALPHA) {
- /* A hackish way to ensure that we get a framebuffer with
- * an alpha component */
- CoglSwapChain *swap_chain;
- CoglOnscreenTemplate *onscreen_template;
- CoglRenderer *renderer;
- CoglDisplay *display;
+ /* A hackish way to ensure that we get a framebuffer with
+ * an alpha component */
+ CoglSwapChain *swap_chain;
+ CoglOnscreenTemplate *onscreen_template;
+ CoglRenderer *renderer;
+ CoglDisplay *display;
swap_chain = cogl_swap_chain_new ();
cogl_swap_chain_set_has_alpha (swap_chain, TRUE);
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 096a3bcfa..2b573c8e5 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -468,9 +468,7 @@ cairo_vg_sources = cairo-vg-surface.c
cairo_cogl_headers = cairo-cogl.h
cairo_cogl_private = cairo-cogl-private.h \
cairo-cogl-gradient-private.h \
- cairo-cogl-context-private.h \
cairo-cogl-utils-private.h
cairo_cogl_sources = cairo-cogl-surface.c \
cairo-cogl-gradient.c \
- cairo-cogl-context.c \
cairo-cogl-utils.c
diff --git a/src/cairo-cogl-context-private.h b/src/cairo-cogl-context-private.h
deleted file mode 100644
index a1b3152b1..000000000
--- a/src/cairo-cogl-context-private.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2011 Intel Corporation.
- *
- * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.og/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.
- *
- * Contributor(s):
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef CAIRO_COGL_CONTEXT_PRIVATE_H
-#define CAIRO_COGL_CONTEXT_PRIVATE_H
-
-#include "cairo-default-context-private.h"
-#include "cairo-cogl-private.h"
-
-typedef struct _cairo_cogl_context {
- cairo_default_context_t base;
-
- int path_ctm_age;
- cairo_path_fixed_t user_path;
-
- cairo_bool_t path_is_rectangle;
- double x, y, width, height;
-
- cairo_backend_t backend;
-
- /* We save a copy of all the original backend methods that we override so
- * we can chain up...
- */
- cairo_backend_t backend_parent;
-} cairo_cogl_context_t;
-
-cairo_t *
-_cairo_cogl_context_create (void *target);
-
-#endif /* CAIRO_COGL_CONTEXT_PRIVATE_H */
diff --git a/src/cairo-cogl-context.c b/src/cairo-cogl-context.c
deleted file mode 100644
index e0017dd9b..000000000
--- a/src/cairo-cogl-context.c
+++ /dev/null
@@ -1,1063 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2011 Intel Corporation.
- *
- * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.og/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.
- *
- * Contributor(s):
- * Robert Bragg <robert@linux.intel.com>
- */
-
-/* so long as we can verify that the ctm doesn't change multiple times
- * during the construction of a path we can build a shadow
- * #cairo_path_fixed_t in user coordinates that we can use to create a
- * hash value for caching tessellations of that path.
- *
- * We need to hook into all the points where the ctm can be changed
- * so we can bump a cr->path_ctm_age counter.
- *
- * We need to hook into all the points where the path can be modified
- * so we can catch the start of a path and reset the cr->path_ctm_age
- * counter at that point.
- *
- * When a draw operation is hit we can then check that the
- * path_ctm_age == 0 and if so we create a hash of the path.
- *
- * We use this hash to lookup a #cairo_cogl_path_meta_t struct which
- * may contain tessellated triangles for the path or may just contain
- * a count of how many times the path has been re-seen (we only cache
- * tessellated triangles if there is evidence that the path is being
- * used multiple times because there is a cost involved in allocating
- * a separate buffer for the triangles).
- */
-
-#include "cairoint.h"
-
-#include "cairo-cogl-context-private.h"
-#include "cairo-freed-pool-private.h"
-#include "cairo-arc-private.h"
-#include "cairo-path-fixed-private.h"
-#include "cairo-surface-subsurface-inline.h"
-
-#include <glib.h>
-
-static freed_pool_t context_pool;
-
-void
-_cairo_cogl_context_reset_static_data (void)
-{
- _freed_pool_reset (&context_pool);
-}
-
-static cairo_status_t
-_cairo_cogl_context_rectangle_real (cairo_cogl_context_t *cr,
- double x, double y,
- double width, double height)
-{
- cairo_status_t status;
- status = cr->backend_parent.rectangle (cr, x, y, width, height);
- if (unlikely (status))
- return status;
-
- return _cairo_cogl_path_fixed_rectangle (&cr->user_path,
- _cairo_fixed_from_double (x),
- _cairo_fixed_from_double (y),
- _cairo_fixed_from_double (width),
- _cairo_fixed_from_double (height));
-}
-
-/* The idea here is that we have a simplified way of tracking rectangle paths
- * because rectangles are perhaps the most common shape drawn with cairo.
- *
- * Basically we have a speculative store for a rectangle path that doesn't
- * need to use the #cairo_path_fixed_t api to describe a rectangle in terms of
- * (move_to,rel_line_to,rel_line_to,_rel_line_to,close) because if you profile
- * heavy rectangle drawing with Cairo that process can be overly expensive.
- *
- * If the user asks to add more than just a rectangle to their current path
- * then we "flush" any speculative rectangle stored into the current path
- * before continuing to append their operations.
- *
- * In addition to the speculative store cairo-cogl also has a fast-path
- * fill_rectangle drawing operation that further aims to minimize the cost
- * of drawing rectangles.
- */
-static cairo_status_t
-_flush_cr_rectangle (cairo_cogl_context_t *cr)
-{
- if (!cr->path_is_rectangle)
- return CAIRO_STATUS_SUCCESS;
-
- cr->path_is_rectangle = FALSE;
- return _cairo_cogl_context_rectangle_real (cr, cr->x, cr->y, cr->width, cr->height);
-}
-
-static cairo_status_t
-_cairo_cogl_context_restore (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- if (cr->path_is_rectangle) {
- cairo_status_t status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- cr->path_ctm_age++;
- return cr->backend_parent.restore (abstract_cr);
-}
-
-static cairo_status_t
-_cairo_cogl_context_translate (void *abstract_cr, double tx, double ty)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- if (cr->path_is_rectangle) {
- cairo_status_t status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- cr->path_ctm_age++;
- return cr->backend_parent.translate (abstract_cr, tx, ty);
-}
-
-static cairo_status_t
-_cairo_cogl_context_scale (void *abstract_cr, double sx, double sy)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- if (cr->path_is_rectangle) {
- cairo_status_t status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- cr->path_ctm_age++;
- return cr->backend_parent.scale (abstract_cr, sx, sy);
-}
-
-static cairo_status_t
-_cairo_cogl_context_rotate (void *abstract_cr, double theta)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- if (cr->path_is_rectangle) {
- cairo_status_t status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- cr->path_ctm_age++;
- return cr->backend_parent.rotate (abstract_cr, theta);
-}
-
-static cairo_status_t
-_cairo_cogl_context_transform (void *abstract_cr,
- const cairo_matrix_t *matrix)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- if (cr->path_is_rectangle) {
- cairo_status_t status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- cr->path_ctm_age++;
- return cr->backend_parent.transform (abstract_cr, matrix);
-}
-
-static cairo_status_t
-_cairo_cogl_context_set_matrix (void *abstract_cr,
- const cairo_matrix_t *matrix)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- if (cr->path_is_rectangle) {
- cairo_status_t status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- cr->path_ctm_age++;
- return cr->backend_parent.set_matrix (abstract_cr, matrix);
-}
-
-static cairo_status_t
-_cairo_cogl_context_set_identity_matrix (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- if (cr->path_is_rectangle) {
- cairo_status_t status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- cr->path_ctm_age++;
- return cr->backend_parent.set_identity_matrix (abstract_cr);
-}
-
-static cairo_status_t
-_cairo_cogl_context_new_path (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- status = cr->backend_parent.new_path (abstract_cr);
- if (unlikely (status))
- return status;
-
- _cairo_path_fixed_fini (&cr->user_path);
- _cairo_path_fixed_init (&cr->user_path);
- cr->path_is_rectangle = FALSE;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_cogl_context_new_sub_path (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- status = cr->backend_parent.new_sub_path (abstract_cr);
- if (unlikely (status))
- return status;
-
- _cairo_path_fixed_new_sub_path (&cr->user_path);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_cogl_context_move_to (void *abstract_cr, double x, double y)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
- cairo_fixed_t x_fixed, y_fixed;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- status = cr->backend_parent.move_to (abstract_cr, x, y);
- if (unlikely (status))
- return status;
-
- x_fixed = _cairo_fixed_from_double (x);
- y_fixed = _cairo_fixed_from_double (y);
-
- return _cairo_path_fixed_move_to (&cr->user_path, x_fixed, y_fixed);
-}
-
-static cairo_status_t
-_cairo_cogl_context_line_to (void *abstract_cr, double x, double y)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
- cairo_fixed_t x_fixed, y_fixed;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- status = cr->backend_parent.line_to (abstract_cr, x, y);
- if (unlikely (status))
- return status;
-
- x_fixed = _cairo_fixed_from_double (x);
- y_fixed = _cairo_fixed_from_double (y);
-
- if (cr->user_path.buf.base.num_ops == 0)
- cr->path_ctm_age = 0;
-
- return _cairo_path_fixed_line_to (&cr->user_path, x_fixed, y_fixed);
-}
-
-static cairo_status_t
-_cairo_cogl_context_curve_to (void *abstract_cr,
- double x1, double y1,
- double x2, double y2,
- double x3, double y3)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
- cairo_fixed_t x1_fixed, y1_fixed;
- cairo_fixed_t x2_fixed, y2_fixed;
- cairo_fixed_t x3_fixed, y3_fixed;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- status = cr->backend_parent.curve_to (abstract_cr, x1, y1, x2, y2, x3, y3);
- if (unlikely (status))
- return status;
-
- x1_fixed = _cairo_fixed_from_double (x1);
- y1_fixed = _cairo_fixed_from_double (y1);
-
- x2_fixed = _cairo_fixed_from_double (x2);
- y2_fixed = _cairo_fixed_from_double (y2);
-
- x3_fixed = _cairo_fixed_from_double (x3);
- y3_fixed = _cairo_fixed_from_double (y3);
-
- if (cr->user_path.buf.base.num_ops == 0)
- cr->path_ctm_age = 0;
-
- return _cairo_path_fixed_curve_to (&cr->user_path,
- x1_fixed, y1_fixed,
- x2_fixed, y2_fixed,
- x3_fixed, y3_fixed);
-}
-
-static cairo_status_t
-_cairo_cogl_context_arc (void *abstract_cr,
- double xc,
- double yc,
- double radius,
- double angle1,
- double angle2,
- cairo_bool_t forward)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- if (cr->user_path.buf.base.num_ops == 0)
- cr->path_ctm_age = 0;
-
- /* Do nothing, successfully, if radius is <= 0 */
- if (radius <= 0.0) {
- cairo_fixed_t x_fixed, y_fixed;
-
- x_fixed = _cairo_fixed_from_double (xc);
- y_fixed = _cairo_fixed_from_double (yc);
- status = _cairo_cogl_context_line_to (abstract_cr,
- x_fixed,
- y_fixed);
- if (unlikely (status))
- return status;
-
- status = _cairo_cogl_context_line_to (abstract_cr,
- x_fixed,
- y_fixed);
- if (unlikely (status))
- return status;
-
- return CAIRO_STATUS_SUCCESS;
- }
-
- status = _cairo_cogl_context_line_to (cr,
- xc + radius * cos (angle1),
- yc + radius * sin (angle1));
-
- if (unlikely (status))
- return status;
-
- /* These functions will be expressed in terms of the backend
- * functions for line_to and curve_to, which we already add the
- * appropriate segments to the user path in */
- if (forward)
- _cairo_arc_path (&cr->base.base,
- xc,
- yc,
- radius,
- angle1,
- angle2);
- else
- _cairo_arc_path_negative (&cr->base.base,
- xc,
- yc,
- radius,
- angle1,
- angle2);
-
- /* any error will have already been set on cr */
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_cogl_context_rel_move_to (void *abstract_cr, double dx, double dy)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
- cairo_fixed_t dx_fixed, dy_fixed;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- status = cr->backend_parent.rel_move_to (abstract_cr, dx, dy);
- if (unlikely (status))
- return status;
-
- dx_fixed = _cairo_fixed_from_double (dx);
- dy_fixed = _cairo_fixed_from_double (dy);
-
- return _cairo_path_fixed_rel_move_to (&cr->user_path, dx_fixed, dy_fixed);
-}
-
-static cairo_status_t
-_cairo_cogl_context_rel_line_to (void *abstract_cr, double dx, double dy)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
- cairo_fixed_t dx_fixed, dy_fixed;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- status = cr->backend_parent.rel_line_to (abstract_cr, dx, dy);
- if (unlikely (status))
- return status;
-
- dx_fixed = _cairo_fixed_from_double (dx);
- dy_fixed = _cairo_fixed_from_double (dy);
-
- if (cr->user_path.buf.base.num_ops == 0)
- cr->path_ctm_age = 0;
-
- return _cairo_path_fixed_rel_line_to (&cr->user_path, dx_fixed, dy_fixed);
-}
-
-
-static cairo_status_t
-_cairo_cogl_context_rel_curve_to (void *abstract_cr,
- double dx1, double dy1,
- double dx2, double dy2,
- double dx3, double dy3)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
- cairo_fixed_t dx1_fixed, dy1_fixed;
- cairo_fixed_t dx2_fixed, dy2_fixed;
- cairo_fixed_t dx3_fixed, dy3_fixed;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- status = cr->backend_parent.rel_curve_to (abstract_cr, dx1, dy1, dx2, dy2, dx3, dy3);
- if (unlikely (status))
- return status;
-
- dx1_fixed = _cairo_fixed_from_double (dx1);
- dy1_fixed = _cairo_fixed_from_double (dy1);
-
- dx2_fixed = _cairo_fixed_from_double (dx2);
- dy2_fixed = _cairo_fixed_from_double (dy2);
-
- dx3_fixed = _cairo_fixed_from_double (dx3);
- dy3_fixed = _cairo_fixed_from_double (dy3);
-
- if (cr->user_path.buf.base.num_ops == 0)
- cr->path_ctm_age = 0;
-
- return _cairo_path_fixed_rel_curve_to (&cr->user_path,
- dx1_fixed, dy1_fixed,
- dx2_fixed, dy2_fixed,
- dx3_fixed, dy3_fixed);
-}
-
-#if 0
-static cairo_status_t
-_cairo_cogl_context_arc_to (void *abstract_cr,
- double x1, double y1,
- double x2, double y2,
- double radius)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- status = cr->backend_parent.arc_to (abstract_cr, x1, y1, x2, y2, radius);
- if (unlikely (status))
- return status;
-#warning "FIXME"
-}
-
-static cairo_status_t
-_cairo_cogl_rel_arc_to (void *cr,
- double dx1, double dy1,
- double dx2, double dy2,
- double radius)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- status = cr->backend_parent.rel_arc_to (abstract_cr, dx1, dy2, dx2, dy2, radius);
- if (unlikely (status))
- return status;
-#warning "FIXME"
-}
-#endif
-
-static cairo_status_t
-_cairo_cogl_context_close_path (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- status = cr->backend_parent.close_path (abstract_cr);
- if (unlikely (status))
- return status;
-
- if (cr->user_path.buf.base.num_ops == 0)
- cr->path_ctm_age = 0;
-
- return _cairo_path_fixed_close_path (&cr->user_path);
-}
-
-static cairo_status_t
-_cairo_cogl_context_rectangle (void *abstract_cr,
- double x, double y,
- double width, double height)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- /* Do not take the single-rectangle shortcut if we already have a
- * path, whether conventional or rectangle */
- if (cr->user_path.buf.base.num_ops == 0 && !cr->path_is_rectangle) {
- cr->path_ctm_age = 0;
-
-#if 1
- /* XXX: Since drawing rectangles is so common we have a
- * fast-path for drawing a single rectangle. */
- cr->x = x;
- cr->y = y;
- cr->width = width;
- cr->height = height;
- cr->path_is_rectangle = TRUE;
- cr->base.path->fill_is_empty = FALSE;
- return CAIRO_STATUS_SUCCESS;
-#endif
- }
-
- if (cr->path_is_rectangle) {
- cairo_status_t status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- return _cairo_cogl_context_rectangle_real (cr, x, y, width, height);
-}
-
-static void
-_cairo_cogl_context_path_extents (void *abstract_cr,
- double *x1,
- double *y1,
- double *x2,
- double *y2)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- if (cr->path_is_rectangle)
- assert (_flush_cr_rectangle (cr) == CAIRO_STATUS_SUCCESS);
-
- cr->backend_parent.path_extents (abstract_cr, x1, y1, x2, y2);
-}
-
-static cairo_bool_t
-_cairo_cogl_context_has_current_point (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- if (cr->path_is_rectangle)
- assert (_flush_cr_rectangle (cr) == CAIRO_STATUS_SUCCESS);
-
- return cr->backend_parent.has_current_point (abstract_cr);
-}
-
-static cairo_bool_t
-_cairo_cogl_context_get_current_point (void *abstract_cr,
- double *x,
- double *y)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- if (cr->path_is_rectangle)
- assert (_flush_cr_rectangle (cr) == CAIRO_STATUS_SUCCESS);
-
- return cr->backend_parent.get_current_point (abstract_cr, x, y);
-}
-
-static cairo_path_t *
-_cairo_cogl_context_copy_path (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- if (cr->path_is_rectangle)
- assert (_flush_cr_rectangle (cr) == CAIRO_STATUS_SUCCESS);
-
- return cr->backend_parent.copy_path (abstract_cr);
-}
-
-static cairo_path_t *
-_cairo_cogl_context_copy_path_flat (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- if (cr->path_is_rectangle)
- assert (_flush_cr_rectangle (cr) == CAIRO_STATUS_SUCCESS);
-
- return cr->backend_parent.copy_path_flat (abstract_cr);
-}
-
-static cairo_status_t
-_cairo_cogl_context_append_path (void *abstract_cr,
- const cairo_path_t *path)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
-
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- return cr->backend_parent.append_path (abstract_cr, path);
-}
-
-/* Since the surface backend drawing operator functions don't get
- * passed the current #cairo_t context we don't have a good way
- * to get our user-coordinates path into our surface operator
- * functions.
- *
- * For now we use this function to set side band data on the surface
- * itself.
- */
-static void
-_cairo_cogl_surface_set_side_band_state (cairo_cogl_surface_t *surface,
- cairo_cogl_context_t *cr)
-{
- cairo_gstate_t *gstate = cr->base.gstate;
-
- if (cr->path_ctm_age == 0) {
- surface->user_path = &cr->user_path;
- cairo_matrix_multiply (&surface->ctm,
- &gstate->ctm,
- &gstate->target->device_transform);
- cairo_matrix_multiply (&surface->ctm_inverse,
- &gstate->target->device_transform_inverse,
- &gstate->ctm_inverse);
- surface->path_is_rectangle = cr->path_is_rectangle;
- if (surface->path_is_rectangle) {
- surface->path_rectangle_x = cr->x;
- surface->path_rectangle_y = cr->y;
- surface->path_rectangle_width = cr->width;
- surface->path_rectangle_height = cr->height;
- }
- } else {
- surface->user_path = NULL;
- surface->path_is_rectangle = FALSE;
- }
-}
-
-static cairo_cogl_surface_t *
-_cairo_cogl_get_cogl_surface (cairo_surface_t *target)
-{
- /* Subsurfaces are always 1-depth */
- if (_cairo_surface_is_subsurface (target))
- target = _cairo_surface_subsurface_get_target (target);
-
- if (target->type == CAIRO_SURFACE_TYPE_COGL)
- return (cairo_cogl_surface_t *)target;
- else
- /* return NULL if the target is not a cogl surface */
- return NULL;
-}
-
-static cairo_status_t
-_cairo_cogl_context_fill (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
- cairo_cogl_surface_t *surface =
- _cairo_cogl_get_cogl_surface (cr->base.gstate->target);
-
- if (cr->path_is_rectangle) {
- if (surface) {
- cairo_matrix_t ctm;
-
- status =
- _cairo_surface_begin_modification (cr->base.gstate->target);
- if (status)
- return status;
-
- ctm = cr->base.gstate->ctm;
- if (_cairo_surface_is_subsurface (cr->base.gstate->target))
- cairo_matrix_translate (&ctm,
- ((cairo_surface_subsurface_t *)cr->base.gstate->target)->extents.x,
- ((cairo_surface_subsurface_t *)cr->base.gstate->target)->extents.y);
-
- status = _cairo_cogl_surface_fill_rectangle ((cairo_surface_t *)surface,
- cr->base.gstate->op,
- cr->base.gstate->source,
- cr->x,
- cr->y,
- cr->width,
- cr->height,
- &ctm,
- cr->base.gstate->clip);
- if (status == CAIRO_STATUS_SUCCESS)
- goto DONE;
- }
-
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- if (surface)
- _cairo_cogl_surface_set_side_band_state (surface, cr);
-
- status = cr->backend_parent.fill (abstract_cr);
- if (unlikely (status))
- return status;
-
-DONE:
- _cairo_path_fixed_fini (&cr->user_path);
- _cairo_path_fixed_init (&cr->user_path);
- cr->path_is_rectangle = FALSE;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_cogl_context_fill_preserve (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
- cairo_cogl_surface_t *surface =
- _cairo_cogl_get_cogl_surface (cr->base.gstate->target);
-
- if (cr->path_is_rectangle) {
- if (surface) {
- cairo_matrix_t ctm;
-
- status =
- _cairo_surface_begin_modification (cr->base.gstate->target);
- if (status)
- return status;
-
- ctm = cr->base.gstate->ctm;
- if (_cairo_surface_is_subsurface (cr->base.gstate->target))
- cairo_matrix_translate (&ctm,
- ((cairo_surface_subsurface_t *)cr->base.gstate->target)->extents.x,
- ((cairo_surface_subsurface_t *)cr->base.gstate->target)->extents.y);
-
- status = _cairo_cogl_surface_fill_rectangle ((cairo_surface_t *)surface,
- cr->base.gstate->op,
- cr->base.gstate->source,
- cr->x,
- cr->y,
- cr->width,
- cr->height,
- &ctm,
- cr->base.gstate->clip);
- if (status == CAIRO_STATUS_SUCCESS)
- goto DONE;
- }
-
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- if (surface)
- _cairo_cogl_surface_set_side_band_state (surface, cr);
-
- status = cr->backend_parent.fill_preserve (abstract_cr);
- if (unlikely (status))
- return status;
-
-DONE:
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_cogl_context_stroke (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
- cairo_cogl_surface_t *surface =
- _cairo_cogl_get_cogl_surface (cr->base.gstate->target);
-
- /* This operator can't use an accelerated rectangle path yet */
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- if (surface)
- _cairo_cogl_surface_set_side_band_state (surface, cr);
-
- status = cr->backend_parent.stroke (abstract_cr);
- if (unlikely (status))
- return status;
-
- _cairo_path_fixed_fini (&cr->user_path);
- _cairo_path_fixed_init (&cr->user_path);
- cr->path_is_rectangle = FALSE;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_cogl_context_stroke_preserve (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
- cairo_cogl_surface_t *surface =
- _cairo_cogl_get_cogl_surface (cr->base.gstate->target);
-
- /* This operator can't use an accelerated rectangle path yet */
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- if (surface)
- _cairo_cogl_surface_set_side_band_state (surface, cr);
-
- status = cr->backend_parent.stroke_preserve (abstract_cr);
- if (unlikely (status))
- return status;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_cogl_context_clip (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
- cairo_cogl_surface_t *surface =
- _cairo_cogl_get_cogl_surface (cr->base.gstate->target);
-
- /* This operator can't use an accelerated rectangle path yet */
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- if (surface)
- _cairo_cogl_surface_set_side_band_state (surface, cr);
-
- status = cr->backend_parent.clip (abstract_cr);
- if (unlikely (status))
- return status;
-
- _cairo_path_fixed_fini (&cr->user_path);
- _cairo_path_fixed_init (&cr->user_path);
- cr->path_is_rectangle = FALSE;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_cogl_context_clip_preserve (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
- cairo_status_t status;
- cairo_cogl_surface_t *surface =
- _cairo_cogl_get_cogl_surface (cr->base.gstate->target);
-
- /* This operator can't use an accelerated rectangle path yet */
- if (cr->path_is_rectangle) {
- status = _flush_cr_rectangle (cr);
- if (unlikely (status))
- return status;
- }
-
- if (surface)
- _cairo_cogl_surface_set_side_band_state (surface, cr);
-
- status = cr->backend_parent.clip_preserve (abstract_cr);
- if (unlikely (status))
- return status;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_cogl_context_destroy (void *abstract_cr)
-{
- cairo_cogl_context_t *cr = abstract_cr;
-
- _cairo_default_context_fini (&cr->base);
-
- _cairo_path_fixed_fini (&cr->user_path);
-
- /* mark the context as invalid to protect against misuse */
- cr->base.base.status = CAIRO_STATUS_NULL_POINTER;
- _freed_pool_put (&context_pool, cr);
-}
-
-void
-_cairo_cogl_context_set_custom_vtable_funcs (cairo_backend_t *backend);
-
-/* We want to hook into the frontend of the path construction APIs so
- * we can build up a path description in user coordinates instead of
- * backend coordinates so that we can recognize user coordinate
- * rectangles and so we can hash a user path independent of its
- * transform. (With some care to catch unusual cases where the ctm
- * changes mid-path) */
-cairo_t *
-_cairo_cogl_context_create (void *target)
-{
- cairo_cogl_context_t *cr;
- cairo_status_t status;
-
- cr = _freed_pool_get (&context_pool);
- if (unlikely (cr == NULL)) {
- cr = _cairo_malloc (sizeof (cairo_cogl_context_t));
- if (unlikely (cr == NULL))
- return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
- }
-
- status = _cairo_default_context_init (&cr->base, target);
- if (unlikely (status)) {
- _freed_pool_put (&context_pool, cr);
- return _cairo_create_in_error (status);
- }
-
- memcpy (&cr->backend, cr->base.base.backend, sizeof (cairo_backend_t));
- memcpy (&cr->backend_parent, cr->base.base.backend, sizeof (cairo_backend_t));
-
- _cairo_cogl_context_set_custom_vtable_funcs (&cr->backend);
-
- cr->base.base.backend = &cr->backend;
-
- _cairo_path_fixed_init (&cr->user_path);
- cr->path_is_rectangle = FALSE;
- cr->path_ctm_age = 0;
-
- return &cr->base.base;
-}
-
-void
-_cairo_cogl_context_set_custom_vtable_funcs (cairo_backend_t *backend)
-{
- backend->destroy = _cairo_cogl_context_destroy;
-
- backend->restore = _cairo_cogl_context_restore;
-
- backend->translate = _cairo_cogl_context_translate;
- backend->scale = _cairo_cogl_context_scale;
- backend->rotate = _cairo_cogl_context_rotate;
- backend->transform = _cairo_cogl_context_transform;
- backend->set_matrix = _cairo_cogl_context_set_matrix;
- backend->set_identity_matrix = _cairo_cogl_context_set_identity_matrix;
-
- backend->new_path = _cairo_cogl_context_new_path;
- backend->new_sub_path = _cairo_cogl_context_new_sub_path;
- backend->move_to = _cairo_cogl_context_move_to;
- backend->rel_move_to = _cairo_cogl_context_rel_move_to;
- backend->line_to = _cairo_cogl_context_line_to;
- backend->rel_line_to = _cairo_cogl_context_rel_line_to;
- backend->curve_to = _cairo_cogl_context_curve_to;
- backend->rel_curve_to = _cairo_cogl_context_rel_curve_to;
-#if 0
- backend->arc_to = _cairo_cogl_context_arc_to;
- backend->rel_arc_to = _cairo_cogl_context_rel_arc_to;
-#endif
- backend->close_path = _cairo_cogl_context_close_path;
- backend->arc = _cairo_cogl_context_arc;
- backend->rectangle = _cairo_cogl_context_rectangle;
- backend->path_extents = _cairo_cogl_context_path_extents;
- backend->has_current_point = _cairo_cogl_context_has_current_point;
- backend->get_current_point = _cairo_cogl_context_get_current_point;
- backend->copy_path = _cairo_cogl_context_copy_path;
- backend->copy_path_flat = _cairo_cogl_context_copy_path_flat;
- backend->append_path = _cairo_cogl_context_append_path;
-
- /* Try to automatically catch if any new path APIs are added that
- * mean we may need to overload more functions... */
- assert (((char *)&backend->clip
- - (char *)&backend->backend_to_user_distance)
- == (sizeof (void *) * 21));
-
- backend->fill = _cairo_cogl_context_fill;
- backend->fill_preserve = _cairo_cogl_context_fill_preserve;
- backend->stroke = _cairo_cogl_context_stroke;
- backend->stroke_preserve = _cairo_cogl_context_stroke_preserve;
- backend->clip = _cairo_cogl_context_clip;
- backend->clip_preserve = _cairo_cogl_context_clip_preserve;
-}
diff --git a/src/cairo-cogl-private.h b/src/cairo-cogl-private.h
index 3f7b3693e..b0be2661e 100644
--- a/src/cairo-cogl-private.h
+++ b/src/cairo-cogl-private.h
@@ -37,6 +37,7 @@
#include "cairo-backend-private.h"
#include "cairo-default-context-private.h"
#include "cairo-surface-private.h"
+#include "cairo-freelist-private.h"
#include <cogl/cogl2-experimental.h>
@@ -93,10 +94,11 @@ typedef struct _cairo_cogl_device {
/* Caches 1d linear gradient textures */
cairo_cache_t linear_cache;
- cairo_cache_t path_fill_staging_cache;
cairo_cache_t path_fill_prim_cache;
- cairo_cache_t path_stroke_staging_cache;
cairo_cache_t path_stroke_prim_cache;
+
+ cairo_freelist_t path_fill_meta_freelist;
+ cairo_freelist_t path_stroke_meta_freelist;
} cairo_cogl_device_t;
typedef struct _cairo_cogl_clip_primitives {
@@ -159,15 +161,4 @@ _cairo_cogl_path_fixed_rectangle (cairo_path_fixed_t *path,
cairo_fixed_t width,
cairo_fixed_t height);
-cairo_int_status_t
-_cairo_cogl_surface_fill_rectangle (void *abstract_surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- double x,
- double y,
- double width,
- double height,
- cairo_matrix_t *ctm,
- const cairo_clip_t *clip);
-
#endif /* CAIRO_COGL_PRIVATE_H */
diff --git a/src/cairo-cogl-surface.c b/src/cairo-cogl-surface.c
index f1f091bad..fce03db5d 100644
--- a/src/cairo-cogl-surface.c
+++ b/src/cairo-cogl-surface.c
@@ -43,7 +43,6 @@
#include "cairo-cogl-gradient-private.h"
#include "cairo-arc-private.h"
#include "cairo-traps-private.h"
-#include "cairo-cogl-context-private.h"
#include "cairo-cogl-utils-private.h"
#include "cairo-surface-subsurface-inline.h"
#include "cairo-surface-fallback-private.h"
@@ -57,15 +56,8 @@
#define CAIRO_COGL_DEBUG 0
//#define FILL_WITH_COGL_PATH
//#define USE_CAIRO_PATH_FLATTENER
-#define ENABLE_PATH_CACHE
//#define DISABLE_BATCHING
#define MAX_JOURNAL_SIZE 100
-#define ENABLE_RECTANGLES_FASTPATH
-//#define ENABLE_CLIP_CACHE // This hasn't been implemented yet
-
-#if defined (ENABLE_RECTANGLES_FASTPATH) || defined (ENABLE_PATH_CACHE)
-#define NEED_COGL_CONTEXT
-#endif
#if CAIRO_COGL_DEBUG && __GNUC__
#define UNSUPPORTED(reason) ({ \
@@ -139,7 +131,6 @@ typedef struct _cairo_cogl_journal_prim_entry {
cairo_cogl_pipeline_t *pipeline;
CoglPrimitive *primitive;
- cairo_bool_t has_transform;
cairo_matrix_t transform;
} cairo_cogl_journal_prim_entry_t;
@@ -151,49 +142,25 @@ typedef struct _cairo_cogl_journal_path_entry {
} cairo_cogl_journal_path_entry_t;
typedef struct _cairo_cogl_path_fill_meta {
- cairo_cache_entry_t cache_entry;
- cairo_reference_count_t ref_count;
- int counter;
- cairo_path_fixed_t *user_path;
- cairo_matrix_t ctm_inverse;
-
- /* TODO */
-#if 0
- /* A cached path tessellation should be re-usable with different rotations
- * and translations but not for different scales.
- *
- * one idea is to track the diagonal lengths of a unit rectangle
- * transformed through the original ctm use to tessellate the geometry
- * so we can check what the lengths are for any new ctm to know if
- * this geometry is compatible.
- */
-#endif
+ cairo_cache_entry_t base;
+ cairo_path_fixed_t path;
+ cairo_fill_rule_t fill_rule;
+ double tolerance;
CoglPrimitive *prim;
+
+ cairo_freelist_t *freelist;
} cairo_cogl_path_fill_meta_t;
typedef struct _cairo_cogl_path_stroke_meta {
- cairo_cache_entry_t cache_entry;
- cairo_reference_count_t ref_count;
- int counter;
- cairo_path_fixed_t *user_path;
- cairo_matrix_t ctm_inverse;
+ cairo_cache_entry_t base;
+ cairo_path_fixed_t path;
cairo_stroke_style_t style;
double tolerance;
- /* TODO */
-#if 0
- /* A cached path tessellation should be re-usable with different rotations
- * and translations but not for different scales.
- *
- * one idea is to track the diagonal lengths of a unit rectangle
- * transformed through the original ctm use to tessellate the geometry
- * so we can check what the lengths are for any new ctm to know if
- * this geometry is compatible.
- */
-#endif
-
CoglPrimitive *prim;
+
+ cairo_freelist_t *freelist;
} cairo_cogl_path_stroke_meta_t;
static cairo_surface_t *
@@ -449,12 +416,7 @@ _cairo_cogl_journal_log_primitive (cairo_cogl_surface_t *surface,
if (primitive)
cogl_object_ref (primitive);
- if (transform) {
- entry->transform = *transform;
- entry->has_transform = TRUE;
- } else {
- entry->has_transform = FALSE;
- }
+ entry->transform = *transform;
g_queue_push_tail (surface->journal, entry);
@@ -623,11 +585,11 @@ _cairo_cogl_traps_to_triangles_buffer (cairo_cogl_surface_t *surface,
p[2].x = _cairo_cogl_util_fixed_to_float (trap->right.p2.x);
p[2].y = _cairo_cogl_util_fixed_to_float (trap->right.p2.y);
- p[3].x = _cairo_cogl_util_fixed_to_float (trap->left.p1.x);
- p[3].y = _cairo_cogl_util_fixed_to_float (trap->left.p1.y);
+ p[3].x = p[0].x;
+ p[3].y = p[0].y;
- p[4].x = _cairo_cogl_util_fixed_to_float (trap->right.p2.x);
- p[4].y = _cairo_cogl_util_fixed_to_float (trap->right.p2.y);
+ p[4].x = p[2].x;
+ p[4].y = p[2].y;
p[5].x = _cairo_cogl_util_fixed_to_float (trap->right.p1.x);
p[5].y = _cairo_cogl_util_fixed_to_float (trap->right.p1.y);
@@ -699,6 +661,87 @@ _cairo_cogl_traps_to_composite_prim (cairo_cogl_surface_t *surface,
return prim;
}
+/* In order to facilitate path caching, we transform the input path
+ * into a form that will make all translations and rotations of a given
+ * path identical, thereby allowing them to be identified with
+ * conventional path hashing and equivalence functions. A
+ * transformation matrix is also output so that the path can be
+ * transformed back into its original form during rendering. */
+static cairo_int_status_t
+_cairo_cogl_get_untransformed_path (cairo_path_fixed_t *copy,
+ const cairo_path_fixed_t *orig,
+ cairo_matrix_t *transform_out)
+{
+ cairo_matrix_t transform;
+ cairo_int_status_t status;
+
+ if (orig->buf.base.num_points < 1)
+ return CAIRO_INT_STATUS_NOTHING_TO_DO;
+
+ status = _cairo_path_fixed_init_copy (copy, orig);
+ if (unlikely (status))
+ return status;
+
+ /* First the path is translated so that its first point lies on the
+ * origin. */
+ cairo_matrix_init_translate (&transform,
+ -_cairo_fixed_to_double(orig->buf.points[0].x),
+ -_cairo_fixed_to_double(orig->buf.points[0].y));
+
+ /* Then the path is rotated so that its second point lies on the
+ * x axis. */
+ if (orig->buf.base.num_points > 1) {
+ double x = _cairo_fixed_to_double(orig->buf.points[1].x) -
+ _cairo_fixed_to_double(orig->buf.points[0].x);
+ double y = _cairo_fixed_to_double(orig->buf.points[1].y) -
+ _cairo_fixed_to_double(orig->buf.points[0].y);
+ double hyp = sqrt (x * x + y * y);
+
+ transform.xx = x / hyp;
+ transform.yy = x / hyp;
+ transform.xy = -y / hyp;
+ transform.yx = y / hyp;
+ }
+
+ _cairo_path_fixed_transform (copy, &transform);
+
+ *transform_out = transform;
+ status = cairo_matrix_invert (transform_out);
+ if (unlikely (status)) {
+ _cairo_path_fixed_fini (copy);
+ return status;
+ }
+
+ return CAIRO_INT_STATUS_SUCCESS;
+}
+
+static void
+_cairo_cogl_path_fill_meta_destroy (cairo_cogl_path_fill_meta_t *meta)
+{
+ _cairo_path_fixed_fini (&meta->path);
+ cogl_object_unref (meta->prim);
+
+ _cairo_freelist_free (meta->freelist, meta);
+}
+
+static cairo_bool_t
+_cairo_cogl_path_fill_meta_equal (const void *key_a, const void *key_b)
+{
+ const cairo_cogl_path_fill_meta_t *meta0 = key_a;
+ const cairo_cogl_path_fill_meta_t *meta1 = key_b;
+
+ if (meta0->fill_rule != meta1->fill_rule)
+ return FALSE;
+
+ if (meta0->tolerance != meta1->tolerance)
+ return FALSE;
+
+ if (!_cairo_path_fixed_equal (&meta0->path, &meta1->path))
+ return FALSE;
+
+ return TRUE;
+}
+
static cairo_int_status_t
_cairo_cogl_fill_to_primitive (cairo_cogl_surface_t *surface,
const cairo_path_fixed_t *path,
@@ -706,13 +749,46 @@ _cairo_cogl_fill_to_primitive (cairo_cogl_surface_t *surface,
double tolerance,
cairo_bool_t one_shot,
CoglPrimitive **primitive,
- size_t *size)
+ cairo_matrix_t *transform)
{
cairo_traps_t traps;
cairo_int_status_t status;
+ cairo_cogl_path_fill_meta_t meta;
+ cairo_cogl_path_fill_meta_t *acquired_meta;
+ cairo_cogl_path_fill_meta_t *insert_meta = NULL;
+ cairo_cogl_device_t *dev = to_device (surface->base.device);
+ unsigned long hash;
+
+ *primitive = NULL;
+
+ status = _cairo_cogl_get_untransformed_path (&meta.path,
+ path,
+ transform);
+ if (unlikely (status))
+ return status;
+
+ hash = _cairo_path_fixed_hash (&meta.path);
+ hash = _cairo_hash_bytes (hash, &fill_rule, sizeof (fill_rule));
+ hash = _cairo_hash_bytes (hash, &tolerance, sizeof (tolerance));
+ meta.base.hash = hash;
+ meta.tolerance = tolerance;
+ meta.fill_rule = fill_rule;
+
+ acquired_meta = _cairo_cache_lookup (&dev->path_fill_prim_cache,
+ &meta.base);
+
+ if (acquired_meta) {
+ // g_print ("fill cache hit");
+ *primitive = cogl_object_ref (acquired_meta->prim);
+ _cairo_path_fixed_fini (&meta.path);
+ return CAIRO_STATUS_SUCCESS;
+ }
_cairo_traps_init (&traps);
- status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps);
+ status = _cairo_path_fixed_fill_to_traps (&meta.path,
+ fill_rule,
+ tolerance,
+ &traps);
if (unlikely (status))
goto BAIL;
@@ -721,16 +797,249 @@ _cairo_cogl_fill_to_primitive (cairo_cogl_surface_t *surface,
goto BAIL;
}
- *size = traps.num_traps * sizeof (CoglVertexP2) * 6;
+ *primitive = _cairo_cogl_traps_to_composite_prim (surface,
+ &traps,
+ one_shot);
+ if (unlikely (!*primitive)) {
+ status = CAIRO_INT_STATUS_NO_MEMORY;
+ goto BAIL;
+ }
+
+ insert_meta =
+ _cairo_freelist_alloc (&dev->path_fill_meta_freelist);
+ if (unlikely (!insert_meta)) {
+ status = CAIRO_INT_STATUS_NO_MEMORY;
+ goto BAIL;
+ }
+
+ insert_meta->base.hash = meta.base.hash;
+ insert_meta->base.size =
+ traps.num_traps * sizeof (CoglVertexP2) * 6;
+ insert_meta->tolerance = tolerance;
+ insert_meta->fill_rule = fill_rule;
+ insert_meta->prim = cogl_object_ref (*primitive);
+ insert_meta->freelist = &dev->path_fill_meta_freelist;
+
+ status = _cairo_path_fixed_init_copy (&insert_meta->path,
+ &meta.path);
+ if (unlikely (status))
+ goto BAIL;
+
+ if (unlikely (_cairo_cache_insert (&dev->path_fill_prim_cache,
+ &insert_meta->base)))
+ {
+ g_warning ("Fill primitive cache insertion unsuccessful");
+ goto BAIL;
+ }
+
+ _cairo_path_fixed_fini (&meta.path);
+ _cairo_traps_fini (&traps);
+
+ return status;
+
+BAIL:
+ if (*primitive) {
+ cogl_object_unref (*primitive);
+ *primitive = NULL;
+ }
+ if (insert_meta)
+ _cairo_cogl_path_fill_meta_destroy (insert_meta);
+ _cairo_path_fixed_fini (&meta.path);
+ _cairo_traps_fini (&traps);
+
+ return status;
+}
+
+static cairo_bool_t
+_cairo_cogl_stroke_style_equal (const cairo_stroke_style_t *a,
+ const cairo_stroke_style_t *b)
+{
+ if (a->line_width == b->line_width &&
+ a->line_cap == b->line_cap &&
+ a->line_join == b->line_join &&
+ a->miter_limit == b->miter_limit &&
+ a->num_dashes == b->num_dashes &&
+ a->dash_offset == b->dash_offset)
+ {
+ unsigned int i;
+ for (i = 0; i < a->num_dashes; i++) {
+ if (a->dash[i] != b->dash[i])
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static cairo_bool_t
+_cairo_cogl_path_stroke_meta_equal (const void *key_a,
+ const void *key_b)
+{
+ const cairo_cogl_path_stroke_meta_t *meta0 = key_a;
+ const cairo_cogl_path_stroke_meta_t *meta1 = key_b;
+
+ if (meta0->tolerance != meta1->tolerance)
+ return FALSE;
+
+ if (!_cairo_cogl_stroke_style_equal (&meta0->style, &meta1->style))
+ return FALSE;
+
+ if (!_cairo_path_fixed_equal (&meta0->path, &meta1->path))
+ return FALSE;
- *primitive = _cairo_cogl_traps_to_composite_prim (surface, &traps, one_shot);
+ return TRUE;
+}
+
+static void
+_cairo_cogl_path_stroke_meta_destroy (cairo_cogl_path_stroke_meta_t *meta)
+{
+ _cairo_stroke_style_fini (&meta->style);
+ _cairo_path_fixed_fini (&meta->path);
+ cogl_object_unref (meta->prim);
+
+ _cairo_freelist_free (meta->freelist, meta);
+}
+
+static unsigned long
+_cairo_cogl_stroke_style_hash (unsigned long hash,
+ const cairo_stroke_style_t *style)
+{
+ unsigned int i;
+ hash = _cairo_hash_bytes (hash, &style->line_width, sizeof (style->line_width));
+ hash = _cairo_hash_bytes (hash, &style->line_cap, sizeof (style->line_cap));
+ hash = _cairo_hash_bytes (hash, &style->line_join, sizeof (style->line_join));
+ hash = _cairo_hash_bytes (hash, &style->miter_limit, sizeof (style->miter_limit));
+ hash = _cairo_hash_bytes (hash, &style->num_dashes, sizeof (style->num_dashes));
+ hash = _cairo_hash_bytes (hash, &style->dash_offset, sizeof (style->dash_offset));
+ for (i = 0; i < style->num_dashes; i++)
+ hash = _cairo_hash_bytes (hash, &style->dash[i], sizeof (double));
+ return hash;
+}
+
+static cairo_int_status_t
+_cairo_cogl_stroke_to_primitive (cairo_cogl_surface_t *surface,
+ const cairo_path_fixed_t *path,
+ const cairo_stroke_style_t *style,
+ double tolerance,
+ cairo_bool_t one_shot,
+ CoglPrimitive **primitive,
+ cairo_matrix_t *transform)
+{
+ cairo_traps_t traps;
+ cairo_int_status_t status;
+ cairo_cogl_path_stroke_meta_t meta;
+ cairo_cogl_path_stroke_meta_t *acquired_meta;
+ cairo_cogl_path_stroke_meta_t *insert_meta = NULL;
+ cairo_matrix_t identity;
+ cairo_cogl_device_t *dev = to_device (surface->base.device);
+ unsigned long hash;
+
+ *primitive = NULL;
+
+ status = _cairo_cogl_get_untransformed_path (&meta.path,
+ path,
+ transform);
+ if (unlikely (status))
+ return status;
+
+ hash = _cairo_path_fixed_hash (&meta.path);
+ hash = _cairo_cogl_stroke_style_hash (hash, style);
+ hash = _cairo_hash_bytes (hash, &tolerance, sizeof (tolerance));
+ meta.base.hash = hash;
+ meta.tolerance = tolerance;
+
+ status = _cairo_stroke_style_init_copy (&meta.style, style);
+ if (unlikely (status)) {
+ _cairo_path_fixed_fini (&meta.path);
+ return status;
+ }
+
+ acquired_meta = _cairo_cache_lookup (&dev->path_stroke_prim_cache,
+ &meta.base);
+
+ if (acquired_meta) {
+ // g_print ("stroke cache hit");
+ *primitive = cogl_object_ref (acquired_meta->prim);
+ _cairo_path_fixed_fini (&meta.path);
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ _cairo_traps_init (&traps);
+
+ cairo_matrix_init_identity (&identity);
+ status = _cairo_path_fixed_stroke_polygon_to_traps (&meta.path,
+ style,
+ &identity,
+ &identity,
+ tolerance,
+ &traps);
+ if (unlikely (status))
+ goto BAIL;
+
+ if (traps.num_traps == 0) {
+ status = CAIRO_INT_STATUS_NOTHING_TO_DO;
+ goto BAIL;
+ }
+
+ *primitive = _cairo_cogl_traps_to_composite_prim (surface,
+ &traps,
+ one_shot);
if (unlikely (!*primitive)) {
status = CAIRO_INT_STATUS_NO_MEMORY;
goto BAIL;
}
+ insert_meta =
+ _cairo_freelist_alloc (&dev->path_stroke_meta_freelist);
+ if (unlikely (!insert_meta)) {
+ status = CAIRO_INT_STATUS_NO_MEMORY;
+ goto BAIL;
+ }
+
+ insert_meta->base.hash = meta.base.hash;
+ insert_meta->base.size =
+ traps.num_traps * sizeof (CoglVertexP2) * 6;
+ insert_meta->tolerance = tolerance;
+ insert_meta->prim = cogl_object_ref (*primitive);
+ insert_meta->freelist = &dev->path_stroke_meta_freelist;
+
+ status = _cairo_stroke_style_init_copy (&insert_meta->style,
+ style);
+ if (unlikely (status)) {
+ _cairo_stroke_style_fini (&insert_meta->style);
+ free (insert_meta);
+ insert_meta = NULL;
+ goto BAIL;
+ }
+
+ status = _cairo_path_fixed_init_copy (&insert_meta->path,
+ &meta.path);
+ if (unlikely (status))
+ goto BAIL;
+
+ if (unlikely (_cairo_cache_insert (&dev->path_stroke_prim_cache,
+ &insert_meta->base)))
+ {
+ g_warning ("Stroke primitive cache insertion unsuccessful");
+ goto BAIL;
+ }
+
+ _cairo_path_fixed_fini (&meta.path);
+ _cairo_stroke_style_fini (&meta.style);
+ _cairo_traps_fini (&traps);
+
+ return status;
+
BAIL:
+ if (*primitive) {
+ cogl_object_unref (*primitive);
+ *primitive = NULL;
+ }
+ if (insert_meta)
+ _cairo_cogl_path_stroke_meta_destroy (insert_meta);
+ _cairo_path_fixed_fini (&meta.path);
+ _cairo_stroke_style_fini (&meta.style);
_cairo_traps_fini (&traps);
+
return status;
}
@@ -744,20 +1053,9 @@ _cairo_cogl_set_path_prim_clip (cairo_cogl_surface_t *surface,
cairo_rectangle_int_t extents;
cairo_int_status_t status;
CoglPrimitive *prim;
- size_t prim_size;
-
- _cairo_path_fixed_approximate_clip_extents (path, &extents);
-
- /* TODO - maintain a fifo of the last 10 used clips with cached
- * primitives to see if we can avoid tessellating the path and
- * uploading the vertices...
- */
-#ifdef ENABLE_CLIP_CACHE
- prim = NULL;
- prim = find_clip_path_primitive (path);
- if (prim)
- // then bypass filling
-#endif
+ cairo_matrix_t transform;
+ CoglMatrix matrix;
+ double x1, y1, x2, y2;
status = _cairo_cogl_fill_to_primitive (surface,
path,
@@ -765,7 +1063,7 @@ _cairo_cogl_set_path_prim_clip (cairo_cogl_surface_t *surface,
tolerance,
FALSE,
&prim,
- &prim_size);
+ &transform);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
/* If the clip is of zero fill area, set all clipped */
cogl_framebuffer_push_scissor_clip (surface->framebuffer,
@@ -773,16 +1071,50 @@ _cairo_cogl_set_path_prim_clip (cairo_cogl_surface_t *surface,
(*clip_stack_depth)++;
return;
} else if (unlikely (status)) {
- g_warning ("Failed to get primitive for clip path while flushing journal");
+ g_warning ("Failed to get primitive for clip path while "
+ "flushing journal");
goto BAIL;
}
+ float transformfv[16] = {
+ transform.xx, transform.yx, 0, 0,
+ transform.xy, transform.yy, 0, 0,
+ 0, 0, 1, 0,
+ transform.x0, transform.y0, 0, 1
+ };
+
+ cogl_matrix_init_from_array (&matrix, transformfv);
+
+ cogl_framebuffer_push_matrix (surface->framebuffer);
+ cogl_framebuffer_transform (surface->framebuffer, &matrix);
+
+ _cairo_path_fixed_approximate_clip_extents (path, &extents);
+
+ /* The extents need to be transformed by the inverse of the
+ * modelview matrix because they are in terms of un-transformed
+ * device coordinates and the bounds coordinates will be
+ * transformed by the modelview matrix */
+ status = cairo_matrix_invert (&transform);
+ if (unlikely (status)) {
+ g_warning ("Could not apply clip due to invalid matrix from "
+ "path transformation");
+ goto BAIL;
+ }
+
+ x1 = extents.x;
+ y1 = extents.y;
+ x2 = extents.x + extents.width;
+ y2 = extents.y + extents.height;
+ _cairo_matrix_transform_bounding_box (&transform,
+ &x1, &y1, &x2, &y2,
+ NULL);
+
cogl_framebuffer_push_primitive_clip (surface->framebuffer, prim,
- extents.x, extents.y,
- extents.x + extents.width,
- extents.y + extents.height);
+ x1, y1, x2, y2);
(*clip_stack_depth)++;
+ cogl_framebuffer_pop_matrix (surface->framebuffer);
+
BAIL:
if (prim)
cogl_object_unref (prim);
@@ -1158,20 +1490,15 @@ _cairo_cogl_journal_flush (cairo_cogl_surface_t *surface)
prim_entry->pipeline);
cogl_framebuffer_push_matrix (surface->framebuffer);
- if (prim_entry->has_transform) {
- cairo_matrix_t *ctm = &prim_entry->transform;
- float ctmfv[16] = {
- ctm->xx, ctm->yx, 0, 0,
- ctm->xy, ctm->yy, 0, 0,
- 0, 0, 1, 0,
- ctm->x0, ctm->y0, 0, 1
- };
- cogl_matrix_init_from_array (&transform, ctmfv);
- cogl_framebuffer_transform (surface->framebuffer, &transform);
- } else {
- cogl_matrix_init_identity (&transform);
- cogl_framebuffer_set_modelview_matrix (surface->framebuffer, &transform);
- }
+ cairo_matrix_t *ctm = &prim_entry->transform;
+ float ctmfv[16] = {
+ ctm->xx, ctm->yx, 0, 0,
+ ctm->xy, ctm->yy, 0, 0,
+ 0, 0, 1, 0,
+ ctm->x0, ctm->y0, 0, 1
+ };
+ cogl_matrix_init_from_array (&transform, ctmfv);
+ cogl_framebuffer_transform (surface->framebuffer, &transform);
/* If the primitive is NULL, it means we just draw the
* unbounded rectangle */
@@ -2702,8 +3029,11 @@ static void
set_layer_texture_with_attributes (CoglPipeline *pipeline,
int layer_index,
CoglTexture *texture,
- cairo_cogl_texture_attributes_t *attributes)
+ cairo_cogl_texture_attributes_t *attributes,
+ cairo_matrix_t *path_transform)
{
+ cairo_matrix_t m;
+
cogl_pipeline_set_layer_texture (pipeline, layer_index, texture);
cogl_pipeline_set_layer_filters (pipeline,
@@ -2711,13 +3041,20 @@ set_layer_texture_with_attributes (CoglPipeline *pipeline,
attributes->filter,
attributes->filter);
- if (!_cairo_matrix_is_identity (&attributes->matrix)) {
- cairo_matrix_t *m = &attributes->matrix;
+ /* We multiply in the path transform here so that we read texture
+ * values from coordinates that are consistent with the coordinates
+ * of the path after it is transformed by the modelview matrix */
+ if (path_transform)
+ cairo_matrix_multiply (&m, path_transform, &attributes->matrix);
+ else
+ m = attributes->matrix;
+
+ if (!_cairo_matrix_is_identity (&m)) {
float texture_matrixfv[16] = {
- m->xx, m->yx, 0, 0,
- m->xy, m->yy, 0, 0,
- 0, 0, 1, 0,
- m->x0, m->y0, 0, 1
+ m.xx, m.yx, 0, 0,
+ m.xy, m.yy, 0, 0,
+ 0, 0, 1, 0,
+ m.x0, m.y0, 0, 1
};
CoglMatrix texture_matrix;
cogl_matrix_init_from_array (&texture_matrix, texture_matrixfv);
@@ -2741,7 +3078,8 @@ get_source_mask_operator_destination_pipelines (cairo_cogl_pipeline_t **pi
const cairo_pattern_t *source,
cairo_operator_t op,
cairo_cogl_surface_t *destination,
- cairo_composite_rectangles_t *extents)
+ cairo_composite_rectangles_t *extents,
+ cairo_matrix_t *path_transform)
{
cairo_cogl_template_type template_type;
cairo_cogl_device_t *dev = to_device(destination->base.device);
@@ -2899,7 +3237,8 @@ get_source_mask_operator_destination_pipelines (cairo_cogl_pipeline_t **pi
set_layer_texture_with_attributes (pipelines[1]->pipeline,
pipelines[1]->n_layers++,
texture,
- &attributes);
+ &attributes,
+ path_transform);
cogl_object_unref (texture);
if (pipelines[1]->src_tex_clip.buf.base.num_ops > 0)
@@ -2953,7 +3292,8 @@ get_source_mask_operator_destination_pipelines (cairo_cogl_pipeline_t **pi
set_layer_texture_with_attributes (pipelines[1]->pipeline,
pipelines[1]->n_layers++,
texture,
- &attributes);
+ &attributes,
+ path_transform);
}
if (pipelines[0]) {
if (mask_tex_clip.buf.base.num_ops > 0) {
@@ -2965,7 +3305,8 @@ get_source_mask_operator_destination_pipelines (cairo_cogl_pipeline_t **pi
set_layer_texture_with_attributes (pipelines[0]->pipeline,
pipelines[0]->n_layers++,
texture,
- &attributes);
+ &attributes,
+ path_transform);
}
_cairo_path_fixed_fini (&mask_tex_clip);
@@ -3147,8 +3488,9 @@ _cairo_cogl_surface_paint (void *abstract_surface,
source,
op,
surface,
- &extents);
- if (!pipelines[0] && !pipelines[1]) {
+ &extents,
+ NULL);
+ if (unlikely (pipelines[0] == NULL && pipelines[1] == NULL)) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto BAIL;
}
@@ -3210,8 +3552,9 @@ _cairo_cogl_surface_mask (void *abstract_surface,
source,
op,
surface,
- &extents);
- if (!pipelines[0] && !pipelines[1]) {
+ &extents,
+ NULL);
+ if (unlikely (pipelines[0] == NULL && pipelines[1] == NULL)) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto BAIL;
}
@@ -3242,230 +3585,6 @@ BAIL:
return status;
}
-static cairo_bool_t
-_cairo_cogl_path_fill_meta_equal (const void *key_a, const void *key_b)
-{
- const cairo_cogl_path_fill_meta_t *meta0 = key_a;
- const cairo_cogl_path_fill_meta_t *meta1 = key_b;
-
- return _cairo_path_fixed_equal (meta0->user_path, meta1->user_path);
-}
-
-static cairo_bool_t
-_cairo_cogl_stroke_style_equal (const cairo_stroke_style_t *a,
- const cairo_stroke_style_t *b)
-{
- if (a->line_width == b->line_width &&
- a->line_cap == b->line_cap &&
- a->line_join == b->line_join &&
- a->miter_limit == b->miter_limit &&
- a->num_dashes == b->num_dashes &&
- a->dash_offset == b->dash_offset)
- {
- unsigned int i;
- for (i = 0; i < a->num_dashes; i++) {
- if (a->dash[i] != b->dash[i])
- return FALSE;
- }
- }
- return TRUE;
-}
-
-static cairo_bool_t
-_cairo_cogl_path_stroke_meta_equal (const void *key_a,
- const void *key_b)
-{
- const cairo_cogl_path_stroke_meta_t *meta0 = key_a;
- const cairo_cogl_path_stroke_meta_t *meta1 = key_b;
-
- return _cairo_cogl_stroke_style_equal (&meta0->style, &meta1->style) &&
- _cairo_path_fixed_equal (meta0->user_path, meta1->user_path);
-}
-
-static cairo_cogl_path_stroke_meta_t *
-_cairo_cogl_path_stroke_meta_reference (cairo_cogl_path_stroke_meta_t *meta)
-{
- assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&meta->ref_count));
-
- _cairo_reference_count_inc (&meta->ref_count);
-
- return meta;
-}
-
-static void
-_cairo_cogl_path_stroke_meta_destroy (cairo_cogl_path_stroke_meta_t *meta)
-{
- assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&meta->ref_count));
-
- if (! _cairo_reference_count_dec_and_test (&meta->ref_count))
- return;
-
- _cairo_path_fixed_fini (meta->user_path);
- free (meta->user_path);
-
- _cairo_stroke_style_fini (&meta->style);
-
- if (meta->prim)
- cogl_object_unref (meta->prim);
-
- free (meta);
-}
-
-static cairo_cogl_path_stroke_meta_t *
-_cairo_cogl_path_stroke_meta_lookup (cairo_cogl_device_t *ctx,
- unsigned long hash,
- cairo_path_fixed_t *user_path,
- const cairo_stroke_style_t *style,
- double tolerance)
-{
- cairo_cogl_path_stroke_meta_t *ret;
- cairo_cogl_path_stroke_meta_t lookup;
-
- lookup.cache_entry.hash = hash;
- lookup.user_path = user_path;
- lookup.style = *style;
- lookup.tolerance = tolerance;
-
- ret = _cairo_cache_lookup (&ctx->path_stroke_staging_cache, &lookup.cache_entry);
- if (!ret)
- ret = _cairo_cache_lookup (&ctx->path_stroke_prim_cache, &lookup.cache_entry);
- return ret;
-}
-
-static void
-_cairo_cogl_path_stroke_meta_set_prim_size (cairo_cogl_surface_t *surface,
- cairo_cogl_path_stroke_meta_t *meta,
- size_t size)
-{
- /* now that we know the meta structure is associated with a primitive
- * we promote it from the staging cache into the primitive cache.
- */
-
- /* XXX: _cairo_cache borks if you try and remove an entry that's already
- * been evicted so we explicitly look it up first... */
- if (_cairo_cache_lookup (&to_device(surface->base.device)->path_stroke_staging_cache, &meta->cache_entry)) {
- _cairo_cogl_path_stroke_meta_reference (meta);
- _cairo_cache_remove (&to_device(surface->base.device)->path_stroke_staging_cache, &meta->cache_entry);
- }
-
- meta->cache_entry.size = size;
- if (_cairo_cache_insert (&to_device(surface->base.device)->path_stroke_prim_cache, &meta->cache_entry) !=
- CAIRO_STATUS_SUCCESS)
- _cairo_cogl_path_stroke_meta_destroy (meta);
-}
-
-static unsigned int
-_cairo_cogl_stroke_style_hash (unsigned int hash,
- const cairo_stroke_style_t *style)
-{
- unsigned int i;
- hash = _cairo_hash_bytes (hash, &style->line_width, sizeof (style->line_width));
- hash = _cairo_hash_bytes (hash, &style->line_cap, sizeof (style->line_cap));
- hash = _cairo_hash_bytes (hash, &style->line_join, sizeof (style->line_join));
- hash = _cairo_hash_bytes (hash, &style->miter_limit, sizeof (style->miter_limit));
- hash = _cairo_hash_bytes (hash, &style->num_dashes, sizeof (style->num_dashes));
- hash = _cairo_hash_bytes (hash, &style->dash_offset, sizeof (style->dash_offset));
- for (i = 0; i < style->num_dashes; i++)
- hash = _cairo_hash_bytes (hash, &style->dash[i], sizeof (double));
- return hash;
-}
-
-static cairo_cogl_path_stroke_meta_t *
-_cairo_cogl_get_path_stroke_meta (cairo_cogl_surface_t *surface,
- const cairo_stroke_style_t *style,
- double tolerance)
-{
- unsigned long hash;
- cairo_cogl_path_stroke_meta_t *meta = NULL;
- cairo_path_fixed_t *meta_path = NULL;
- cairo_status_t status;
-
- if (!surface->user_path)
- return NULL;
-
- hash = _cairo_path_fixed_hash (surface->user_path);
- hash = _cairo_cogl_stroke_style_hash (hash, style);
- hash = _cairo_hash_bytes (hash, &tolerance, sizeof (tolerance));
-
- meta = _cairo_cogl_path_stroke_meta_lookup (to_device(surface->base.device), hash,
- surface->user_path, style, tolerance);
- if (meta)
- return meta;
-
- meta = calloc (1, sizeof (cairo_cogl_path_stroke_meta_t));
- if (unlikely (!meta))
- goto BAIL;
- CAIRO_REFERENCE_COUNT_INIT (&meta->ref_count, 1);
- meta->cache_entry.hash = hash;
- meta->counter = 0;
- meta_path = _cairo_malloc (sizeof (cairo_path_fixed_t));
- if (unlikely (!meta_path))
- goto BAIL;
- /* FIXME: we should add a ref-counted wrapper for our user_paths
- * so we don't have to keep copying them here! */
- status = _cairo_path_fixed_init_copy (meta_path, surface->user_path);
- if (unlikely (status))
- goto BAIL;
- meta->user_path = meta_path;
- meta->ctm_inverse = surface->ctm_inverse;
-
- status = _cairo_stroke_style_init_copy (&meta->style, style);
- if (unlikely (status)) {
- _cairo_path_fixed_fini (meta_path);
- goto BAIL;
- }
- meta->tolerance = tolerance;
-
- return meta;
-
-BAIL:
- free (meta_path);
- free (meta);
- return NULL;
-}
-
-static cairo_int_status_t
-_cairo_cogl_stroke_to_primitive (cairo_cogl_surface_t *surface,
- const cairo_path_fixed_t *path,
- const cairo_stroke_style_t *style,
- const cairo_matrix_t *ctm,
- const cairo_matrix_t *ctm_inverse,
- double tolerance,
- cairo_bool_t one_shot,
- CoglPrimitive **primitive,
- size_t *size)
-{
- cairo_traps_t traps;
- cairo_int_status_t status;
-
- _cairo_traps_init (&traps);
-
- status = _cairo_path_fixed_stroke_polygon_to_traps (path, style,
- ctm, ctm_inverse,
- tolerance,
- &traps);
- if (unlikely (status))
- goto BAIL;
-
- if (traps.num_traps == 0) {
- status = CAIRO_INT_STATUS_NOTHING_TO_DO;
- goto BAIL;
- }
-
- *size = traps.num_traps * sizeof (CoglVertexP2) * 6;
-
- //g_print ("new stroke prim\n");
- *primitive = _cairo_cogl_traps_to_composite_prim (surface, &traps, one_shot);
- if (unlikely (!*primitive)) {
- status = CAIRO_INT_STATUS_NO_MEMORY;
- goto BAIL;
- }
-
-BAIL:
- _cairo_traps_fini (&traps);
- return status;
-}
-
static cairo_int_status_t
_cairo_cogl_surface_stroke (void *abstract_surface,
cairo_operator_t op,
@@ -3482,14 +3601,8 @@ _cairo_cogl_surface_stroke (void *abstract_surface,
cairo_composite_rectangles_t extents;
cairo_cogl_pipeline_t *pipelines[2];
cairo_int_status_t status;
-#ifdef ENABLE_PATH_CACHE
- cairo_cogl_path_stroke_meta_t *meta = NULL;
- cairo_matrix_t transform_matrix;
-#endif
- cairo_matrix_t *transform = NULL;
- cairo_bool_t one_shot = TRUE;
+ cairo_matrix_t transform;
CoglPrimitive *prim = NULL;
- cairo_bool_t new_prim = FALSE;
if (! is_operator_supported (op))
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -3503,44 +3616,15 @@ _cairo_cogl_surface_stroke (void *abstract_surface,
if (unlikely (status))
return status;
-#ifdef ENABLE_PATH_CACHE
- /* FIXME: we are currently leaking the meta state if we don't reach
- * the cache_insert at the end. */
- meta = _cairo_cogl_get_path_stroke_meta (surface, style, tolerance);
- if (meta) {
- prim = meta->prim;
- if (prim) {
- cairo_matrix_multiply (&transform_matrix,
- &meta->ctm_inverse,
- &surface->ctm);
- transform = &transform_matrix;
- } else if (meta->counter++ > 10) {
- one_shot = FALSE;
- }
- }
-#endif
-
- if (!prim) {
- size_t prim_size;
- status = _cairo_cogl_stroke_to_primitive (surface, path, style,
- ctm, ctm_inverse, tolerance,
- one_shot, &prim,
- &prim_size);
- if (status == CAIRO_INT_STATUS_NOTHING_TO_DO
- && _cairo_operator_bounded_by_mask (op) == FALSE) {
- /* Just render the unbounded rectangle */
- prim = NULL;
- } else if (unlikely (status)) {
- goto BAIL;
- } else {
- new_prim = TRUE;
- }
-#if defined (ENABLE_PATH_CACHE)
- if (meta && prim) {
- meta->prim = cogl_object_ref (prim);
- _cairo_cogl_path_stroke_meta_set_prim_size (surface, meta, prim_size);
- }
-#endif
+ status = _cairo_cogl_stroke_to_primitive (surface, path, style,
+ tolerance, TRUE, &prim,
+ &transform);
+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO
+ && _cairo_operator_bounded_by_mask (op) == FALSE) {
+ /* Just render the unbounded rectangle */
+ prim = NULL;
+ } else if (unlikely (status)) {
+ goto BAIL;
}
get_source_mask_operator_destination_pipelines (pipelines,
@@ -3548,8 +3632,9 @@ _cairo_cogl_surface_stroke (void *abstract_surface,
source,
op,
surface,
- &extents);
- if (!pipelines[0] && !pipelines[1]) {
+ &extents,
+ &transform);
+ if (unlikely (pipelines[0] == NULL && pipelines[1] == NULL)) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto BAIL;
}
@@ -3560,16 +3645,16 @@ _cairo_cogl_surface_stroke (void *abstract_surface,
_cairo_cogl_journal_log_primitive (surface,
pipelines[0],
prim,
- transform);
+ &transform);
if (pipelines[1])
_cairo_cogl_journal_log_primitive (surface,
pipelines[1],
prim,
- transform);
+ &transform);
BAIL:
/* The journal will take a reference on the primitive... */
- if (new_prim)
+ if (prim)
cogl_object_unref (prim);
_cairo_composite_rectangles_fini (&extents);
@@ -3577,123 +3662,6 @@ BAIL:
return status;
}
-static cairo_cogl_path_fill_meta_t *
-_cairo_cogl_path_fill_meta_reference (cairo_cogl_path_fill_meta_t *meta)
-{
- assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&meta->ref_count));
-
- _cairo_reference_count_inc (&meta->ref_count);
-
- return meta;
-}
-
-static void
-_cairo_cogl_path_fill_meta_destroy (cairo_cogl_path_fill_meta_t *meta)
-{
- assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&meta->ref_count));
-
- if (! _cairo_reference_count_dec_and_test (&meta->ref_count))
- return;
-
- _cairo_path_fixed_fini (meta->user_path);
- free (meta->user_path);
-
- if (meta->prim)
- cogl_object_unref (meta->prim);
-
- free (meta);
-}
-
-static cairo_cogl_path_fill_meta_t *
-_cairo_cogl_path_fill_meta_lookup (cairo_cogl_device_t *ctx,
- unsigned long hash,
- cairo_path_fixed_t *user_path)
-{
- cairo_cogl_path_fill_meta_t *ret;
- cairo_cogl_path_fill_meta_t lookup;
-
- lookup.cache_entry.hash = hash;
- lookup.user_path = user_path;
-
- ret = _cairo_cache_lookup (&ctx->path_fill_staging_cache, &lookup.cache_entry);
- if (!ret)
- ret = _cairo_cache_lookup (&ctx->path_fill_prim_cache, &lookup.cache_entry);
- return ret;
-}
-
-static void
-_cairo_cogl_path_fill_meta_set_prim_size (cairo_cogl_surface_t *surface,
- cairo_cogl_path_fill_meta_t *meta,
- size_t size)
-{
- /* now that we know the meta structure is associated with a primitive
- * we promote it from the staging cache into the primitive cache.
- */
-
- /* XXX: _cairo_cache borks if you try and remove an entry that's already
- * been evicted so we explicitly look it up first... */
- if (_cairo_cache_lookup (&to_device(surface->base.device)->path_fill_staging_cache, &meta->cache_entry)) {
- _cairo_cogl_path_fill_meta_reference (meta);
- _cairo_cache_remove (&to_device(surface->base.device)->path_fill_staging_cache, &meta->cache_entry);
- }
-
- meta->cache_entry.size = size;
- if (_cairo_cache_insert (&to_device(surface->base.device)->path_fill_prim_cache, &meta->cache_entry) !=
- CAIRO_STATUS_SUCCESS)
- _cairo_cogl_path_fill_meta_destroy (meta);
-}
-
-static cairo_cogl_path_fill_meta_t *
-_cairo_cogl_get_path_fill_meta (cairo_cogl_surface_t *surface)
-{
- unsigned long hash;
- cairo_cogl_path_fill_meta_t *meta = NULL;
- cairo_path_fixed_t *meta_path = NULL;
- cairo_status_t status;
-
- if (!surface->user_path)
- return NULL;
-
- hash = _cairo_path_fixed_hash (surface->user_path);
-
- meta = _cairo_cogl_path_fill_meta_lookup (to_device(surface->base.device),
- hash, surface->user_path);
- if (meta)
- return meta;
-
- meta = calloc (1, sizeof (cairo_cogl_path_fill_meta_t));
- if (unlikely (!meta))
- goto BAIL;
- meta->cache_entry.hash = hash;
- meta->counter = 0;
- CAIRO_REFERENCE_COUNT_INIT (&meta->ref_count, 1);
- meta_path = _cairo_malloc (sizeof (cairo_path_fixed_t));
- if (unlikely (!meta_path))
- goto BAIL;
- /* FIXME: we should add a ref-counted wrapper for our user_paths
- * so we don't have to keep copying them here! */
- status = _cairo_path_fixed_init_copy (meta_path, surface->user_path);
- if (unlikely (status))
- goto BAIL;
- meta->user_path = meta_path;
- meta->ctm_inverse = surface->ctm_inverse;
-
- /* To start with - until we associate a CoglPrimitive with the meta
- * structure - we keep the meta in a staging structure until we
- * see whether it actually gets re-used. */
- meta->cache_entry.size = 1;
- if (_cairo_cache_insert (&to_device(surface->base.device)->path_fill_staging_cache, &meta->cache_entry) !=
- CAIRO_STATUS_SUCCESS)
- _cairo_cogl_path_fill_meta_destroy (meta);
-
- return meta;
-
-BAIL:
- free (meta_path);
- free (meta);
- return NULL;
-}
-
static cairo_int_status_t
_cairo_cogl_surface_fill (void *abstract_surface,
cairo_operator_t op,
@@ -3707,14 +3675,8 @@ _cairo_cogl_surface_fill (void *abstract_surface,
cairo_cogl_surface_t *surface = abstract_surface;
cairo_composite_rectangles_t extents;
cairo_int_status_t status;
-#ifdef ENABLE_PATH_CACHE
- cairo_cogl_path_fill_meta_t *meta = NULL;
- cairo_matrix_t transform_matrix;
-#endif
- cairo_matrix_t *transform = NULL;
- cairo_bool_t one_shot = TRUE;
+ cairo_matrix_t transform;
CoglPrimitive *prim = NULL;
- cairo_bool_t new_prim = FALSE;
cairo_cogl_pipeline_t *pipelines[2];
if (! is_operator_supported (op))
@@ -3728,42 +3690,16 @@ _cairo_cogl_surface_fill (void *abstract_surface,
return status;
#ifndef FILL_WITH_COGL_PATH
-#ifdef ENABLE_PATH_CACHE
- meta = _cairo_cogl_get_path_fill_meta (surface);
- if (meta) {
- prim = meta->prim;
- if (prim) {
- cairo_matrix_multiply (&transform_matrix,
- &meta->ctm_inverse,
- &surface->ctm);
- transform = &transform_matrix;
- } else if (meta->counter++ > 10) {
- one_shot = FALSE;
- }
- }
-#endif /* ENABLE_PATH_CACHE */
-
- if (!prim) {
- size_t prim_size;
- status = _cairo_cogl_fill_to_primitive (surface, path, fill_rule, tolerance,
- one_shot, &prim, &prim_size);
- if (status == CAIRO_INT_STATUS_NOTHING_TO_DO
- && _cairo_operator_bounded_by_mask (op) == FALSE) {
- /* Just render the unbounded rectangle */
- prim = NULL;
- } else if (unlikely (status)) {
- goto BAIL;
- } else {
- new_prim = TRUE;
- }
-#ifdef ENABLE_PATH_CACHE
- if (meta && prim) {
- meta->prim = cogl_object_ref (prim);
- _cairo_cogl_path_fill_meta_set_prim_size (surface, meta, prim_size);
- }
-#endif /* ENABLE_PATH_CACHE */
+ status = _cairo_cogl_fill_to_primitive (surface, path, fill_rule,
+ tolerance, TRUE, &prim,
+ &transform);
+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO
+ && _cairo_operator_bounded_by_mask (op) == FALSE) {
+ /* Just render the unbounded rectangle */
+ prim = NULL;
+ } else if (unlikely (status)) {
+ goto BAIL;
}
-
#endif /* !FILL_WITH_COGL_PATH */
get_source_mask_operator_destination_pipelines (pipelines,
@@ -3771,8 +3707,9 @@ _cairo_cogl_surface_fill (void *abstract_surface,
source,
op,
surface,
- &extents);
- if (!pipelines[0] && !pipelines[1]) {
+ &extents,
+ &transform);
+ if (unlikely (pipelines[0] == NULL && pipelines[1] == NULL)) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto BAIL;
}
@@ -3784,12 +3721,12 @@ _cairo_cogl_surface_fill (void *abstract_surface,
_cairo_cogl_journal_log_primitive (surface,
pipelines[0],
prim,
- transform);
+ &transform);
if (pipelines[1])
_cairo_cogl_journal_log_primitive (surface,
pipelines[1],
prim,
- transform);
+ &transform);
#else
CoglPath * cogl_path = _cairo_cogl_util_path_from_cairo (path, fill_rule, tolerance);
@@ -3806,88 +3743,14 @@ _cairo_cogl_surface_fill (void *abstract_surface,
#endif
BAIL:
-#ifndef FILL_WITH_COGL_PATH
/* The journal will take a reference on the prim */
- if (new_prim)
+ if (prim)
cogl_object_unref (prim);
-#endif
-
_cairo_composite_rectangles_fini (&extents);
return status;
}
-cairo_int_status_t
-_cairo_cogl_surface_fill_rectangle (void *abstract_surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- double x,
- double y,
- double width,
- double height,
- cairo_matrix_t *ctm,
- const cairo_clip_t *clip)
-{
- cairo_cogl_surface_t *surface = abstract_surface;
- cairo_composite_rectangles_t extents;
- cairo_int_status_t status;
- cairo_cogl_pipeline_t *pipelines[2];
-
- if (! is_operator_supported (op))
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
- /* These extents will be larger than necessary, but in the absence
- * of a specialized function, they will do */
- status =
- _cairo_composite_rectangles_init_for_paint (&extents,
- &surface->base,
- op,
- source,
- clip);
- if (unlikely (status))
- return status;
-
- get_source_mask_operator_destination_pipelines (pipelines,
- NULL,
- source,
- op,
- surface,
- &extents);
- if (!pipelines[0] && !pipelines[1]) {
- status = CAIRO_INT_STATUS_UNSUPPORTED;
- goto BAIL;
- }
-
- _cairo_cogl_log_clip (surface, clip);
-
- if (pipelines[0])
- _cairo_cogl_journal_log_rectangle (surface,
- pipelines[0],
- x, y, width, height,
- ctm);
- if (pipelines[1])
- _cairo_cogl_journal_log_rectangle (surface,
- pipelines[1],
- x, y, width, height,
- ctm);
-
-BAIL:
- _cairo_composite_rectangles_fini (&extents);
-
- return status;
- } else {
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- /* TODO:
- * We need to acquire the textures here, look at the corresponding
- * attributes and see if this can be trivially handled by logging
- * a textured rectangle only needing simple scaling or translation
- * of texture coordinates.
- */
-}
-
/* Mostly taken from cairo_vg_surface.c */
/* TODO: implement actual font support, with either cogl-pango's glyph
* cache or our own */
@@ -3900,7 +3763,6 @@ _cairo_cogl_surface_show_glyphs (void *abstract_surface,
cairo_scaled_font_t *scaled_font,
const cairo_clip_t *clip)
{
- cairo_cogl_surface_t *surface = abstract_surface;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_path_fixed_t path;
int num_chunk_glyphs;
@@ -3925,15 +3787,6 @@ _cairo_cogl_surface_show_glyphs (void *abstract_surface,
if (unlikely (status))
goto BAIL;
-#ifdef NEED_COGL_CONTEXT
- /* XXX: in cairo-cogl-context.c we set some sideband data on the
- * surface before issuing a fill so we need to do that here too... */
- surface->user_path = &path;
- cairo_matrix_init_identity (&surface->ctm);
- surface->ctm_inverse = surface->ctm;
- surface->path_is_rectangle = FALSE;
-#endif
-
status = _cairo_cogl_surface_fill (abstract_surface,
op, source, &path,
CAIRO_FILL_RULE_WINDING,
@@ -3957,11 +3810,7 @@ BAIL:
const cairo_surface_backend_t _cairo_cogl_surface_backend = {
CAIRO_SURFACE_TYPE_COGL,
_cairo_cogl_surface_finish,
-#ifdef NEED_COGL_CONTEXT
- _cairo_cogl_context_create,
-#else
_cairo_default_context_create,
-#endif
_cairo_cogl_surface_create_similar,
NULL, /* create similar image */
@@ -4232,11 +4081,12 @@ _cairo_cogl_device_finish (void *device)
/* XXX: Drop references to external resources */
_cairo_cache_fini (&dev->linear_cache);
- _cairo_cache_fini (&dev->path_fill_staging_cache);
_cairo_cache_fini (&dev->path_fill_prim_cache);
- _cairo_cache_fini (&dev->path_stroke_staging_cache);
_cairo_cache_fini (&dev->path_stroke_prim_cache);
+ _cairo_freelist_fini (&dev->path_fill_meta_freelist);
+ _cairo_freelist_fini (&dev->path_stroke_meta_freelist);
+
if (dev->buffer_stack && dev->buffer_stack_offset) {
cogl_buffer_unmap (dev->buffer_stack);
cogl_object_unref (dev->buffer_stack);
@@ -4308,18 +4158,6 @@ cairo_cogl_device_create (CoglContext *cogl_context)
return _cairo_device_create_in_error (status);
}
- status = _cairo_cache_init (&dev->path_fill_staging_cache,
- _cairo_cogl_path_fill_meta_equal,
- NULL,
- (cairo_destroy_func_t) _cairo_cogl_path_fill_meta_destroy,
- 1000);
-
- status = _cairo_cache_init (&dev->path_stroke_staging_cache,
- _cairo_cogl_path_stroke_meta_equal,
- NULL,
- (cairo_destroy_func_t) _cairo_cogl_path_stroke_meta_destroy,
- 1000);
-
status = _cairo_cache_init (&dev->path_fill_prim_cache,
_cairo_cogl_path_fill_meta_equal,
NULL,
@@ -4332,6 +4170,11 @@ cairo_cogl_device_create (CoglContext *cogl_context)
(cairo_destroy_func_t) _cairo_cogl_path_stroke_meta_destroy,
CAIRO_COGL_PATH_META_CACHE_SIZE);
+ _cairo_freelist_init (&dev->path_fill_meta_freelist,
+ sizeof(cairo_cogl_path_fill_meta_t));
+ _cairo_freelist_init (&dev->path_stroke_meta_freelist,
+ sizeof(cairo_cogl_path_stroke_meta_t));
+
_cairo_device_init (&dev->base, &_cairo_cogl_device_backend);
return &dev->base;
}
diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index 760f092e3..6acdea9dd 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -94,10 +94,6 @@ cairo_debug_reset_static_data (void)
_cairo_default_context_reset_static_data ();
-#if CAIRO_HAS_COGL_SURFACE
- _cairo_cogl_context_reset_static_data ();
-#endif
-
CAIRO_MUTEX_FINALIZE ();
}
diff --git a/src/meson.build b/src/meson.build
index 5a3fb92e5..160e6657c 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -217,7 +217,6 @@ cairo_feature_sources = {
'cairo-cogl': [
'cairo-cogl-surface.c',
'cairo-cogl-gradient.c',
- 'cairo-cogl-context.c',
'cairo-cogl-utils.c',
],
'cairo-directfb': [