mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-10 02:20:25 +01:00
Add preliminary damage tracking
This is initially based around the requirements for handling internal fallbacks to the image compositor and reducing the number of pixels required to be transferred. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
c7d8ec72e6
commit
8bea52bb0b
10 changed files with 379 additions and 3 deletions
|
|
@ -66,6 +66,7 @@ cairo_private = \
|
|||
cairo-compositor-private.h \
|
||||
cairo-contour-private.h \
|
||||
cairo-composite-rectangles-private.h \
|
||||
cairo-damage-private.h \
|
||||
cairo-default-context-private.h \
|
||||
cairo-device-private.h \
|
||||
cairo-error-private.h \
|
||||
|
|
@ -142,6 +143,7 @@ cairo_sources = \
|
|||
cairo-composite-rectangles.c \
|
||||
cairo-compositor.c \
|
||||
cairo-contour.c \
|
||||
cairo-damage.c \
|
||||
cairo-debug.c \
|
||||
cairo-default-context.c \
|
||||
cairo-device.c \
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-damage-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
cairo_int_status_t
|
||||
|
|
@ -65,6 +66,10 @@ _cairo_compositor_paint (const cairo_compositor_t *compositor,
|
|||
compositor = compositor->delegate;
|
||||
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage)
|
||||
surface->damage = _cairo_damage_add_rectangle (surface->damage,
|
||||
&extents.unbounded);
|
||||
|
||||
_cairo_composite_rectangles_fini (&extents);
|
||||
|
||||
return status;
|
||||
|
|
@ -96,6 +101,10 @@ _cairo_compositor_mask (const cairo_compositor_t *compositor,
|
|||
compositor = compositor->delegate;
|
||||
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage)
|
||||
surface->damage = _cairo_damage_add_rectangle (surface->damage,
|
||||
&extents.unbounded);
|
||||
|
||||
_cairo_composite_rectangles_fini (&extents);
|
||||
|
||||
return status;
|
||||
|
|
@ -135,6 +144,10 @@ _cairo_compositor_stroke (const cairo_compositor_t *compositor,
|
|||
compositor = compositor->delegate;
|
||||
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage)
|
||||
surface->damage = _cairo_damage_add_rectangle (surface->damage,
|
||||
&extents.unbounded);
|
||||
|
||||
_cairo_composite_rectangles_fini (&extents);
|
||||
|
||||
return status;
|
||||
|
|
@ -170,6 +183,10 @@ _cairo_compositor_fill (const cairo_compositor_t *compositor,
|
|||
compositor = compositor->delegate;
|
||||
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage)
|
||||
surface->damage = _cairo_damage_add_rectangle (surface->damage,
|
||||
&extents.unbounded);
|
||||
|
||||
_cairo_composite_rectangles_fini (&extents);
|
||||
|
||||
return status;
|
||||
|
|
@ -207,6 +224,10 @@ _cairo_compositor_glyphs (const cairo_compositor_t *compositor,
|
|||
compositor = compositor->delegate;
|
||||
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage)
|
||||
surface->damage = _cairo_damage_add_rectangle (surface->damage,
|
||||
&extents.unbounded);
|
||||
|
||||
_cairo_composite_rectangles_fini (&extents);
|
||||
|
||||
return status;
|
||||
|
|
|
|||
82
src/cairo-damage-private.h
Normal file
82
src/cairo-damage-private.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2012 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., 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 Chris Wilson
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_DAMAGE_PRIVATE_H
|
||||
#define CAIRO_DAMAGE_PRIVATE_H
|
||||
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
#include <pixman.h>
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
struct _cairo_damage {
|
||||
cairo_status_t status;
|
||||
cairo_region_t *region;
|
||||
|
||||
int dirty, remain;
|
||||
struct _cairo_damage_chunk {
|
||||
struct _cairo_damage_chunk *next;
|
||||
cairo_box_t *base;
|
||||
int count;
|
||||
int size;
|
||||
} chunks, *tail;
|
||||
cairo_box_t boxes[32];
|
||||
};
|
||||
|
||||
cairo_private cairo_damage_t *
|
||||
_cairo_damage_create (void);
|
||||
|
||||
cairo_private cairo_damage_t *
|
||||
_cairo_damage_add_box (cairo_damage_t *damage,
|
||||
const cairo_box_t *box);
|
||||
|
||||
cairo_private cairo_damage_t *
|
||||
_cairo_damage_add_rectangle (cairo_damage_t *damage,
|
||||
const cairo_rectangle_int_t *rect);
|
||||
|
||||
cairo_private cairo_damage_t *
|
||||
_cairo_damage_add_region (cairo_damage_t *damage,
|
||||
const cairo_region_t *region);
|
||||
|
||||
cairo_private cairo_damage_t *
|
||||
_cairo_damage_reduce (cairo_damage_t *damage);
|
||||
|
||||
cairo_private void
|
||||
_cairo_damage_destroy (cairo_damage_t *damage);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_DAMAGE_PRIVATE_H */
|
||||
214
src/cairo-damage.c
Normal file
214
src/cairo-damage.c
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Copyright © 2012 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.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 Chris Wilson
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-damage-private.h"
|
||||
#include "cairo-region-private.h"
|
||||
|
||||
static const cairo_damage_t __cairo_damage__nil = { CAIRO_STATUS_NO_MEMORY };
|
||||
|
||||
cairo_damage_t *
|
||||
_cairo_damage_create (void)
|
||||
{
|
||||
cairo_damage_t *damage;
|
||||
|
||||
damage = malloc (sizeof (*damage));
|
||||
if (unlikely (damage == NULL)) {
|
||||
_cairo_error_throw(CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_damage_t *) &__cairo_damage__nil;
|
||||
}
|
||||
|
||||
damage->status = CAIRO_STATUS_SUCCESS;
|
||||
damage->region = NULL;
|
||||
damage->dirty = 0;
|
||||
damage->tail = &damage->chunks;
|
||||
damage->chunks.base = damage->boxes;
|
||||
damage->chunks.size = ARRAY_LENGTH(damage->boxes);
|
||||
damage->chunks.count = 0;
|
||||
damage->chunks.next = NULL;
|
||||
|
||||
damage->remain = damage->chunks.size;
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_damage_destroy (cairo_damage_t *damage)
|
||||
{
|
||||
struct _cairo_damage_chunk *chunk, *next;
|
||||
|
||||
for (chunk = damage->chunks.next; chunk != NULL; chunk = next) {
|
||||
next = chunk->next;
|
||||
free (chunk);
|
||||
}
|
||||
cairo_region_destroy (damage->region);
|
||||
free (damage);
|
||||
}
|
||||
|
||||
static cairo_damage_t *
|
||||
_cairo_damage_add_boxes(cairo_damage_t *damage,
|
||||
const cairo_box_t *boxes,
|
||||
int count)
|
||||
{
|
||||
struct _cairo_damage_chunk *chunk;
|
||||
int n, size;
|
||||
|
||||
if (damage == NULL)
|
||||
damage = _cairo_damage_create ();
|
||||
|
||||
damage->dirty += count;
|
||||
|
||||
n = count;
|
||||
if (n > damage->remain)
|
||||
n = damage->remain;
|
||||
|
||||
memcpy (damage->tail->base + damage->tail->count, boxes, n);
|
||||
|
||||
count -= n;
|
||||
damage->tail->count += n;
|
||||
damage->remain -= n;
|
||||
|
||||
if (count == 0)
|
||||
return damage;
|
||||
|
||||
size = 2 * damage->tail->size;
|
||||
if (size < count)
|
||||
size = (count + 64) & ~63;
|
||||
|
||||
chunk = malloc (sizeof (*chunk) + sizeof (cairo_box_t) * size);
|
||||
if (unlikely (chunk == NULL)) {
|
||||
_cairo_damage_destroy (damage);
|
||||
return (cairo_damage_t *) &__cairo_damage__nil;
|
||||
}
|
||||
|
||||
chunk->next = NULL;
|
||||
chunk->base = (cairo_box_t *) (chunk + 1);
|
||||
chunk->size = size;
|
||||
chunk->count = count;
|
||||
|
||||
damage->tail->next = chunk;
|
||||
damage->remain = size - count;
|
||||
|
||||
memcpy (damage->tail->base, boxes + n, count);
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
cairo_damage_t *
|
||||
_cairo_damage_add_box(cairo_damage_t *damage,
|
||||
const cairo_box_t *box)
|
||||
{
|
||||
return _cairo_damage_add_boxes(damage, box, 1);
|
||||
}
|
||||
|
||||
cairo_damage_t *
|
||||
_cairo_damage_add_rectangle(cairo_damage_t *damage,
|
||||
const cairo_rectangle_int_t *r)
|
||||
{
|
||||
cairo_box_t box;
|
||||
|
||||
box.p1.x = r->x;
|
||||
box.p1.y = r->y;
|
||||
box.p2.x = r->x + r->width;
|
||||
box.p2.y = r->y + r->height;
|
||||
|
||||
return _cairo_damage_add_boxes(damage, &box, 1);
|
||||
}
|
||||
|
||||
cairo_damage_t *
|
||||
_cairo_damage_add_region (cairo_damage_t *damage,
|
||||
const cairo_region_t *region)
|
||||
{
|
||||
cairo_box_t *boxes;
|
||||
int nbox;
|
||||
|
||||
boxes = _cairo_region_get_boxes (region, &nbox);
|
||||
return _cairo_damage_add_boxes(damage, boxes, nbox);
|
||||
}
|
||||
|
||||
cairo_damage_t *
|
||||
_cairo_damage_reduce (cairo_damage_t *damage)
|
||||
{
|
||||
cairo_box_t *free_boxes = NULL;
|
||||
cairo_box_t *boxes, *b;
|
||||
struct _cairo_damage_chunk *chunk, *last;
|
||||
|
||||
if (damage == NULL || !damage->dirty)
|
||||
return damage;
|
||||
|
||||
if (damage->region) {
|
||||
cairo_region_t *region;
|
||||
|
||||
region = damage->region;
|
||||
damage->region = NULL;
|
||||
|
||||
damage = _cairo_damage_add_region (damage, region);
|
||||
cairo_region_destroy (region);
|
||||
|
||||
if (unlikely (damage->status))
|
||||
return damage;
|
||||
}
|
||||
|
||||
boxes = damage->tail->base;
|
||||
if (damage->dirty > damage->tail->size) {
|
||||
boxes = free_boxes = malloc (damage->dirty * sizeof (cairo_box_t));
|
||||
if (unlikely (boxes == NULL)) {
|
||||
_cairo_damage_destroy (damage);
|
||||
return (cairo_damage_t *) &__cairo_damage__nil;
|
||||
}
|
||||
|
||||
b = boxes;
|
||||
last = NULL;
|
||||
} else {
|
||||
b = boxes + damage->tail->count;
|
||||
last = damage->tail;
|
||||
}
|
||||
|
||||
for (chunk = &damage->chunks; chunk != last; chunk = chunk->next) {
|
||||
memcpy (b, chunk->base, chunk->count * sizeof (cairo_box_t));
|
||||
b += chunk->count;
|
||||
}
|
||||
|
||||
damage->region = _cairo_region_create_from_boxes (boxes, damage->dirty);
|
||||
free (free_boxes);
|
||||
|
||||
if (unlikely (damage->region->status)) {
|
||||
_cairo_damage_destroy (damage);
|
||||
return (cairo_damage_t *) &__cairo_damage__nil;
|
||||
}
|
||||
|
||||
damage->dirty = 0;
|
||||
return damage;
|
||||
}
|
||||
|
|
@ -544,7 +544,7 @@ slim_hidden_def (cairo_image_surface_create_for_data);
|
|||
*
|
||||
* Since: 1.2
|
||||
**/
|
||||
unsigned char *
|
||||
unsigned char *
|
||||
cairo_image_surface_get_data (cairo_surface_t *surface)
|
||||
{
|
||||
cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
|
||||
|
|
@ -970,10 +970,10 @@ const cairo_surface_backend_t _cairo_image_surface_backend = {
|
|||
NULL, /* show_page */
|
||||
|
||||
_cairo_image_surface_get_extents,
|
||||
_cairo_image_surface_get_font_options,
|
||||
NULL,
|
||||
|
||||
NULL, /* flush */
|
||||
NULL, /* mark dirty */
|
||||
NULL,
|
||||
|
||||
_cairo_image_surface_paint,
|
||||
_cairo_image_surface_mask,
|
||||
|
|
|
|||
|
|
@ -66,6 +66,12 @@ _cairo_region_init_rectangle (cairo_region_t *region,
|
|||
cairo_private void
|
||||
_cairo_region_fini (cairo_region_t *region);
|
||||
|
||||
cairo_private cairo_region_t *
|
||||
_cairo_region_create_from_boxes (const cairo_box_t *boxes, int count);
|
||||
|
||||
cairo_private cairo_box_t *
|
||||
_cairo_region_get_boxes (const cairo_region_t *region, int *nbox);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_REGION_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -276,6 +276,38 @@ cairo_region_create_rectangles (const cairo_rectangle_int_t *rects,
|
|||
}
|
||||
slim_hidden_def (cairo_region_create_rectangles);
|
||||
|
||||
cairo_region_t *
|
||||
_cairo_region_create_from_boxes (const cairo_box_t *boxes, int count)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
|
||||
region = _cairo_malloc (sizeof (cairo_region_t));
|
||||
if (unlikely (region == NULL))
|
||||
return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1);
|
||||
region->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (! pixman_region32_init_rects (®ion->rgn,
|
||||
(pixman_box32_t *)boxes, count)) {
|
||||
free (region);
|
||||
return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
cairo_box_t *
|
||||
_cairo_region_get_boxes (const cairo_region_t *region, int *nbox)
|
||||
{
|
||||
if (region->status) {
|
||||
nbox = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (cairo_box_t *) pixman_region32_rectangles (CONST_CAST ®ion->rgn, nbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_region_create_rectangle:
|
||||
* @rectangle: a #cairo_rectangle_int_t
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ struct _cairo_surface {
|
|||
cairo_status_t status;
|
||||
unsigned int unique_id;
|
||||
unsigned int serial;
|
||||
cairo_damage_t *damage;
|
||||
|
||||
unsigned finished : 1;
|
||||
unsigned is_clear : 1;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
#include "cairo-array-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
#include "cairo-damage-private.h"
|
||||
#include "cairo-device-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-image-surface-private.h"
|
||||
|
|
@ -104,6 +105,7 @@ const cairo_surface_t name = { \
|
|||
status, /* status */ \
|
||||
0, /* unique id */ \
|
||||
0, /* serial */ \
|
||||
NULL, /* damage */ \
|
||||
FALSE, /* finished */ \
|
||||
TRUE, /* is_clear */ \
|
||||
FALSE, /* has_font_options */ \
|
||||
|
|
@ -410,6 +412,7 @@ _cairo_surface_init (cairo_surface_t *surface,
|
|||
surface->finished = FALSE;
|
||||
surface->is_clear = FALSE;
|
||||
surface->serial = 0;
|
||||
surface->damage = NULL;
|
||||
surface->owns_device = (device != NULL);
|
||||
|
||||
_cairo_user_data_array_init (&surface->user_data);
|
||||
|
|
@ -845,6 +848,9 @@ cairo_surface_destroy (cairo_surface_t *surface)
|
|||
/* paranoid check that nobody took a reference whilst finishing */
|
||||
assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count));
|
||||
|
||||
if (surface->damage)
|
||||
_cairo_damage_destroy (surface->damage);
|
||||
|
||||
_cairo_user_data_array_fini (&surface->user_data);
|
||||
_cairo_user_data_array_fini (&surface->mime_data);
|
||||
|
||||
|
|
@ -1424,6 +1430,17 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
|
|||
surface->is_clear = FALSE;
|
||||
surface->serial++;
|
||||
|
||||
if (surface->damage) {
|
||||
cairo_box_t box;
|
||||
|
||||
box.p1.x = x;
|
||||
box.p1.y = y;
|
||||
box.p2.x = x + width;
|
||||
box.p2.y = y + height;
|
||||
|
||||
surface->damage = _cairo_damage_add_box (surface->damage, &box);
|
||||
}
|
||||
|
||||
if (surface->backend->mark_dirty_rectangle != NULL) {
|
||||
/* XXX: FRAGILE: We're ignoring the scaling component of
|
||||
* device_transform here. I don't know what the right thing to
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ typedef struct _cairo_color_stop cairo_color_stop_t;
|
|||
typedef struct _cairo_contour cairo_contour_t;
|
||||
typedef struct _cairo_contour_chain cairo_contour_chain_t;
|
||||
typedef struct _cairo_contour_iter cairo_contour_iter_t;
|
||||
typedef struct _cairo_damage cairo_damage_t;
|
||||
typedef struct _cairo_device_backend cairo_device_backend_t;
|
||||
typedef struct _cairo_font_face_backend cairo_font_face_backend_t;
|
||||
typedef struct _cairo_gstate cairo_gstate_t;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue