mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-05 20:50:24 +01:00
xlib: Implement SHM fallbacks and fast upload paths
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
140fafed89
commit
0bfd2acd35
41 changed files with 2517 additions and 238 deletions
|
|
@ -63,7 +63,7 @@ AM_CONDITIONAL(CAIRO_HAS_DLSYM, test "x$have_dlsym" = "xyes")
|
|||
dnl ===========================================================================
|
||||
|
||||
CAIRO_ENABLE_SURFACE_BACKEND(xlib, Xlib, auto, [
|
||||
xlib_REQUIRES="x11"
|
||||
xlib_REQUIRES="x11 xext"
|
||||
PKG_CHECK_MODULES(xlib, $xlib_REQUIRES, ,
|
||||
[AC_MSG_RESULT(no)
|
||||
xlib_REQUIRES=""
|
||||
|
|
@ -71,7 +71,7 @@ CAIRO_ENABLE_SURFACE_BACKEND(xlib, Xlib, auto, [
|
|||
if test "x$no_x" = xyes; then
|
||||
use_xlib="no (requires X development libraries)"
|
||||
else
|
||||
xlib_NONPKGCONFIG_LIBS="$X_PRE_LIBS $X_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
xlib_NONPKGCONFIG_LIBS="$X_PRE_LIBS $X_LIBS -lX11 -lXext $X_EXTRA_LIBS"
|
||||
xlib_NONPKGCONFIG_CFLAGS=$X_CFLAGS
|
||||
fi])
|
||||
])
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ cairo_private = \
|
|||
cairo-list-inline.h \
|
||||
cairo-list-private.h \
|
||||
cairo-malloc-private.h \
|
||||
cairo-mempool-private.h \
|
||||
cairo-mutex-impl-private.h \
|
||||
cairo-mutex-list-private.h \
|
||||
cairo-mutex-private.h \
|
||||
|
|
@ -178,6 +179,7 @@ cairo_sources = \
|
|||
cairo-matrix.c \
|
||||
cairo-mask-compositor.c \
|
||||
cairo-mesh-pattern-rasterizer.c \
|
||||
cairo-mempool.c \
|
||||
cairo-misc.c \
|
||||
cairo-mono-scan-converter.c \
|
||||
cairo-mutex.c \
|
||||
|
|
@ -311,6 +313,7 @@ cairo_xlib_sources = \
|
|||
cairo-xlib-screen.c \
|
||||
cairo-xlib-source.c \
|
||||
cairo-xlib-surface.c \
|
||||
cairo-xlib-surface-shm.c \
|
||||
cairo-xlib-visual.c \
|
||||
cairo-xlib-xcb-surface.c \
|
||||
$(NULL)
|
||||
|
|
|
|||
|
|
@ -929,10 +929,14 @@ _cairo_cogl_journal_flush (cairo_cogl_surface_t *surface)
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_cogl_surface_flush (void *abstract_surface)
|
||||
_cairo_cogl_surface_flush (void *abstract_surface,
|
||||
unsigned flags)
|
||||
{
|
||||
cairo_cogl_surface_t *surface = (cairo_cogl_surface_t *)abstract_surface;
|
||||
|
||||
if (flags)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_cogl_journal_flush (surface);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -1331,7 +1335,7 @@ _cairo_cogl_acquire_surface_texture (cairo_cogl_surface_t *reference_surface,
|
|||
|
||||
if (abstract_surface->device == reference_surface->base.device) {
|
||||
cairo_cogl_surface_t *surface = (cairo_cogl_surface_t *)abstract_surface;
|
||||
_cairo_cogl_surface_flush (surface);
|
||||
_cairo_cogl_surface_flush (surface, 0);
|
||||
return surface->texture ? cogl_object_ref (surface->texture) : NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@ _cairo_damage_add_boxes(cairo_damage_t *damage,
|
|||
if (damage->status)
|
||||
return damage;
|
||||
|
||||
|
||||
damage->dirty += count;
|
||||
|
||||
n = count;
|
||||
|
|
|
|||
|
|
@ -209,10 +209,14 @@ _cairo_dfb_surface_unmap_image (void *abstract_surface,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_dfb_surface_flush (void *abstract_surface)
|
||||
_cairo_dfb_surface_flush (void *abstract_surface,
|
||||
unsigned flags)
|
||||
{
|
||||
cairo_dfb_surface_t *surface = abstract_surface;
|
||||
|
||||
if (flags)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (surface->image.pixman_image) {
|
||||
surface->dfb_surface->Unlock (surface->dfb_surface);
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
static const cairo_surface_backend_t _cairo_gl_surface_backend;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_surface_flush (void *abstract_surface);
|
||||
_cairo_gl_surface_flush (void *abstract_surface, unsigned flags);
|
||||
|
||||
static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface)
|
||||
{
|
||||
|
|
@ -834,7 +834,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
|
|||
|
||||
cpp = PIXMAN_FORMAT_BPP (src->pixman_format) / 8;
|
||||
|
||||
status = _cairo_gl_surface_flush (&dst->base);
|
||||
status = _cairo_gl_surface_flush (&dst->base, 0);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
|
|
@ -1200,12 +1200,15 @@ _cairo_gl_surface_get_extents (void *abstract_surface,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_surface_flush (void *abstract_surface)
|
||||
_cairo_gl_surface_flush (void *abstract_surface, unsigned flags)
|
||||
{
|
||||
cairo_gl_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
cairo_gl_context_t *ctx;
|
||||
|
||||
if (flags)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_gl_context_acquire (surface->base.device, &ctx);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -750,6 +750,16 @@ composite_tristrip (void *_dst,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
check_composite_glyphs (const cairo_composite_rectangles_t *extents,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int *num_glyphs)
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#if HAS_PIXMAN_GLYPHS
|
||||
static pixman_glyph_cache_t *global_glyph_cache;
|
||||
|
||||
static inline pixman_glyph_cache_t *
|
||||
|
|
@ -776,16 +786,6 @@ _cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
|
|||
CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
check_composite_glyphs (const cairo_composite_rectangles_t *extents,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int *num_glyphs)
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#if HAS_PIXMAN_GLYPHS
|
||||
static cairo_int_status_t
|
||||
composite_glyphs (void *_dst,
|
||||
cairo_operator_t op,
|
||||
|
|
@ -896,6 +896,12 @@ out_unlock:
|
|||
return status;
|
||||
}
|
||||
#else
|
||||
void
|
||||
_cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph)
|
||||
{
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
composite_one_glyph (void *_dst,
|
||||
cairo_operator_t op,
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ _cairo_image_surface_is_clone (cairo_image_surface_t *image)
|
|||
static inline cairo_bool_t
|
||||
_cairo_surface_is_image (const cairo_surface_t *surface)
|
||||
{
|
||||
return surface->backend == &_cairo_image_surface_backend;
|
||||
return surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -151,6 +151,12 @@ _cairo_image_surface_init (cairo_image_surface_t *surface,
|
|||
pixman_image_t *pixman_image,
|
||||
pixman_format_code_t pixman_format);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_image_surface_create_similar (void *abstract_other,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_private cairo_image_surface_t *
|
||||
_cairo_image_surface_map_to_image (void *abstract_other,
|
||||
const cairo_rectangle_int_t *extents);
|
||||
|
|
|
|||
|
|
@ -723,7 +723,7 @@ _cairo_format_bits_per_pixel (cairo_format_t format)
|
|||
}
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
cairo_surface_t *
|
||||
_cairo_image_surface_create_similar (void *abstract_other,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
|
|
|
|||
83
src/cairo-mempool-private.h
Normal file
83
src/cairo-mempool-private.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/* Cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2007 Chris Wilson
|
||||
* Copyright © 2009 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 Red Hat, Inc.
|
||||
*
|
||||
* Contributors(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_MEMPOOL_PRIVATE_H
|
||||
#define CAIRO_MEMPOOL_PRIVATE_H
|
||||
|
||||
#include "cairo-compiler-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
typedef struct _cairo_mempool cairo_mempool_t;
|
||||
|
||||
struct _cairo_mempool {
|
||||
char *base;
|
||||
struct _cairo_memblock {
|
||||
int bits;
|
||||
cairo_list_t link;
|
||||
} *blocks;
|
||||
cairo_list_t free[32];
|
||||
unsigned char *map;
|
||||
|
||||
unsigned int num_blocks;
|
||||
int min_bits; /* Minimum block size is 1 << min_bits */
|
||||
int num_sizes;
|
||||
int max_free_bits;
|
||||
|
||||
size_t free_bytes;
|
||||
size_t max_bytes;
|
||||
};
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_mempool_init (cairo_mempool_t *pool,
|
||||
void *base,
|
||||
size_t bytes,
|
||||
int min_bits,
|
||||
int num_sizes);
|
||||
|
||||
cairo_private void *
|
||||
_cairo_mempool_alloc (cairo_mempool_t *pi, size_t bytes);
|
||||
|
||||
cairo_private void
|
||||
_cairo_mempool_free (cairo_mempool_t *pi, void *storage);
|
||||
|
||||
cairo_private void
|
||||
_cairo_mempool_fini (cairo_mempool_t *pool);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_MEMPOOL_PRIVATE_H */
|
||||
359
src/cairo-mempool.c
Normal file
359
src/cairo-mempool.c
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
/* Cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2007 Chris Wilson
|
||||
* Copyright © 2009 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 recipoolent 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 Red Hat, Inc.
|
||||
*
|
||||
* Contributors(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-mempool-private.h"
|
||||
#include "cairo-list-inline.h"
|
||||
|
||||
/* a simple buddy allocator for memory pools
|
||||
* XXX fragmentation? use Doug Lea's malloc?
|
||||
*/
|
||||
|
||||
#define BITTEST(p, n) ((p)->map[(n) >> 3] & (128 >> ((n) & 7)))
|
||||
#define BITSET(p, n) ((p)->map[(n) >> 3] |= (128 >> ((n) & 7)))
|
||||
#define BITCLEAR(p, n) ((p)->map[(n) >> 3] &= ~(128 >> ((n) & 7)))
|
||||
|
||||
static void
|
||||
clear_bits (cairo_mempool_t *pool, size_t first, size_t last)
|
||||
{
|
||||
size_t i, n = last;
|
||||
size_t first_full = (first + 7) & ~7;
|
||||
size_t past_full = last & ~7;
|
||||
size_t bytes;
|
||||
|
||||
if (n > first_full)
|
||||
n = first_full;
|
||||
for (i = first; i < n; i++)
|
||||
BITCLEAR (pool, i);
|
||||
|
||||
if (past_full > first_full) {
|
||||
bytes = past_full - first_full;
|
||||
bytes = bytes >> 3;
|
||||
memset (pool->map + (first_full >> 3), 0, bytes);
|
||||
}
|
||||
|
||||
if (past_full < n)
|
||||
past_full = n;
|
||||
for (i = past_full; i < last; i++)
|
||||
BITCLEAR (pool, i);
|
||||
}
|
||||
|
||||
static void
|
||||
free_bits (cairo_mempool_t *pool, size_t start, int bits, cairo_bool_t clear)
|
||||
{
|
||||
struct _cairo_memblock *block;
|
||||
|
||||
if (clear)
|
||||
clear_bits (pool, start, start + (1 << bits));
|
||||
|
||||
block = pool->blocks + start;
|
||||
block->bits = bits;
|
||||
|
||||
cairo_list_add (&block->link, &pool->free[bits]);
|
||||
|
||||
pool->free_bytes += 1 << (bits + pool->min_bits);
|
||||
if (bits > pool->max_free_bits)
|
||||
pool->max_free_bits = bits;
|
||||
}
|
||||
|
||||
/* Add a chunk to the free list */
|
||||
static void
|
||||
free_blocks (cairo_mempool_t *pool,
|
||||
size_t first,
|
||||
size_t last,
|
||||
cairo_bool_t clear)
|
||||
{
|
||||
size_t i, len;
|
||||
int bits = 0;
|
||||
|
||||
for (i = first, len = 1; i < last; i += len) {
|
||||
/* To avoid cost quadratic in the number of different
|
||||
* blocks produced from this chunk of store, we have to
|
||||
* use the size of the previous block produced from this
|
||||
* chunk as the starting point to work out the size of the
|
||||
* next block we can produce. If you look at the binary
|
||||
* representation of the starting points of the blocks
|
||||
* produced, you can see that you first of all increase the
|
||||
* size of the blocks produced up to some maximum as the
|
||||
* address dealt with gets offsets added on which zap out
|
||||
* low order bits, then decrease as the low order bits of the
|
||||
* final block produced get added in. E.g. as you go from
|
||||
* 001 to 0111 you generate blocks
|
||||
* of size 001 at 001 taking you to 010
|
||||
* of size 010 at 010 taking you to 100
|
||||
* of size 010 at 100 taking you to 110
|
||||
* of size 001 at 110 taking you to 111
|
||||
* So the maximum total cost of the loops below this comment
|
||||
* is one trip from the lowest blocksize to the highest and
|
||||
* back again.
|
||||
*/
|
||||
while (bits < pool->num_sizes - 1) {
|
||||
size_t next_bits = bits + 1;
|
||||
size_t next_len = len << 1;
|
||||
|
||||
if (i + next_bits > last) {
|
||||
/* off end of chunk to be freed */
|
||||
break;
|
||||
}
|
||||
|
||||
if (i & (next_len - 1)) /* block would not be on boundary */
|
||||
break;
|
||||
|
||||
bits = next_bits;
|
||||
len = next_len;
|
||||
}
|
||||
|
||||
do {
|
||||
if (i + len <= last && /* off end of chunk to be freed */
|
||||
(i & (len - 1)) == 0) /* block would not be on boundary */
|
||||
break;
|
||||
|
||||
bits--; len >>=1;
|
||||
} while (len);
|
||||
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
free_bits (pool, i, bits, clear);
|
||||
}
|
||||
}
|
||||
|
||||
static struct _cairo_memblock *
|
||||
get_buddy (cairo_mempool_t *pool, size_t offset, int bits)
|
||||
{
|
||||
struct _cairo_memblock *block;
|
||||
|
||||
assert (offset + (1 << bits) <= pool->num_blocks);
|
||||
|
||||
if (BITTEST (pool, offset + (1 << bits) - 1))
|
||||
return NULL; /* buddy is allocated */
|
||||
|
||||
block = pool->blocks + offset;
|
||||
if (block->bits != bits)
|
||||
return NULL; /* buddy is partially allocated */
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static void
|
||||
merge_buddies (cairo_mempool_t *pool,
|
||||
struct _cairo_memblock *block,
|
||||
int max_bits)
|
||||
{
|
||||
size_t block_offset = block - pool->blocks;
|
||||
int bits = block->bits;
|
||||
|
||||
while (bits < max_bits - 1) {
|
||||
/* while you can, merge two blocks and get a legal block size */
|
||||
size_t buddy_offset = block_offset ^ (1 << bits);
|
||||
|
||||
block = get_buddy (pool, buddy_offset, bits);
|
||||
if (block == NULL)
|
||||
break;
|
||||
|
||||
cairo_list_del (&block->link);
|
||||
|
||||
/* Merged block starts at buddy */
|
||||
if (buddy_offset < block_offset)
|
||||
block_offset = buddy_offset;
|
||||
|
||||
bits++;
|
||||
}
|
||||
|
||||
block = pool->blocks + block_offset;
|
||||
block->bits = bits;
|
||||
cairo_list_add (&block->link, &pool->free[bits]);
|
||||
|
||||
if (bits > pool->max_free_bits)
|
||||
pool->max_free_bits = bits;
|
||||
}
|
||||
|
||||
/* attempt to merge all available buddies up to a particular size */
|
||||
static int
|
||||
merge_bits (cairo_mempool_t *pool, int max_bits)
|
||||
{
|
||||
struct _cairo_memblock *block, *buddy, *next;
|
||||
int bits;
|
||||
|
||||
for (bits = 0; bits < max_bits - 1; bits++) {
|
||||
cairo_list_foreach_entry_safe (block, next,
|
||||
struct _cairo_memblock,
|
||||
&pool->free[bits],
|
||||
link)
|
||||
{
|
||||
size_t buddy_offset = (block - pool->blocks) ^ (1 << bits);
|
||||
|
||||
buddy = get_buddy (pool, buddy_offset, bits);
|
||||
if (buddy == NULL)
|
||||
continue;
|
||||
|
||||
if (buddy == next) {
|
||||
next = cairo_container_of (buddy->link.next,
|
||||
struct _cairo_memblock,
|
||||
link);
|
||||
}
|
||||
|
||||
cairo_list_del (&block->link);
|
||||
merge_buddies (pool, block, max_bits);
|
||||
}
|
||||
}
|
||||
|
||||
return pool->max_free_bits;
|
||||
}
|
||||
|
||||
/* find store for 1 << bits blocks */
|
||||
static void *
|
||||
buddy_malloc (cairo_mempool_t *pool, int bits)
|
||||
{
|
||||
size_t past, offset;
|
||||
struct _cairo_memblock *block;
|
||||
int b;
|
||||
|
||||
if (bits > pool->max_free_bits && bits > merge_bits (pool, bits))
|
||||
return NULL;
|
||||
|
||||
/* Find a list with blocks big enough on it */
|
||||
block = NULL;
|
||||
for (b = bits; b <= pool->max_free_bits; b++) {
|
||||
if (! cairo_list_is_empty (&pool->free[b])) {
|
||||
block = cairo_list_first_entry (&pool->free[b],
|
||||
struct _cairo_memblock,
|
||||
link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert (block != NULL);
|
||||
|
||||
cairo_list_del (&block->link);
|
||||
|
||||
while (cairo_list_is_empty (&pool->free[pool->max_free_bits])) {
|
||||
if (--pool->max_free_bits == -1)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Mark end of allocated area */
|
||||
offset = block - pool->blocks;
|
||||
past = offset + (1 << bits);
|
||||
BITSET (pool, past - 1);
|
||||
block->bits = bits;
|
||||
|
||||
/* If we used a larger free block than we needed, free the rest */
|
||||
pool->free_bytes -= 1 << (b + pool->min_bits);
|
||||
free_blocks (pool, past, offset + (1 << b), 0);
|
||||
|
||||
return pool->base + ((block - pool->blocks) << pool->min_bits);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_mempool_init (cairo_mempool_t *pool,
|
||||
void *base, size_t bytes,
|
||||
int min_bits, int num_sizes)
|
||||
{
|
||||
int num_blocks;
|
||||
int i;
|
||||
|
||||
assert ((((unsigned long) base) & ((1 << min_bits) - 1)) == 0);
|
||||
assert (num_sizes < ARRAY_LENGTH (pool->free));
|
||||
|
||||
pool->base = base;
|
||||
pool->free_bytes = 0;
|
||||
pool->max_bytes = bytes;
|
||||
pool->max_free_bits = -1;
|
||||
|
||||
num_blocks = bytes >> min_bits;
|
||||
pool->blocks = calloc (num_blocks, sizeof (struct _cairo_memblock));
|
||||
if (pool->blocks == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
pool->num_blocks = num_blocks;
|
||||
pool->min_bits = min_bits;
|
||||
pool->num_sizes = num_sizes;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH (pool->free); i++)
|
||||
cairo_list_init (&pool->free[i]);
|
||||
|
||||
pool->map = malloc ((num_blocks + 7) >> 3);
|
||||
if (pool->map == NULL) {
|
||||
free (pool->blocks);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
memset (pool->map, -1, (num_blocks + 7) >> 3);
|
||||
clear_bits (pool, 0, num_blocks);
|
||||
|
||||
/* Now add all blocks to the free list */
|
||||
free_blocks (pool, 0, num_blocks, 1);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void *
|
||||
_cairo_mempool_alloc (cairo_mempool_t *pool, size_t bytes)
|
||||
{
|
||||
size_t size;
|
||||
int bits;
|
||||
|
||||
size = 1 << pool->min_bits;
|
||||
for (bits = 0; size < bytes; bits++)
|
||||
size <<= 1;
|
||||
if (bits >= pool->num_sizes)
|
||||
return NULL;
|
||||
|
||||
return buddy_malloc (pool, bits);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_mempool_free (cairo_mempool_t *pool, void *storage)
|
||||
{
|
||||
size_t block_offset;
|
||||
struct _cairo_memblock *block;
|
||||
|
||||
block_offset = ((char *)storage - pool->base) >> pool->min_bits;
|
||||
block = pool->blocks + block_offset;
|
||||
|
||||
BITCLEAR (pool, block_offset + ((1 << block->bits) - 1));
|
||||
pool->free_bytes += 1 << (block->bits + pool->min_bits);
|
||||
|
||||
merge_buddies (pool, block, pool->num_sizes);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_mempool_fini (cairo_mempool_t *pool)
|
||||
{
|
||||
free (pool->map);
|
||||
free (pool->blocks);
|
||||
}
|
||||
|
|
@ -141,12 +141,16 @@ _cairo_quartz_image_surface_get_extents (void *asurface,
|
|||
*/
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_quartz_image_surface_flush (void *asurface)
|
||||
_cairo_quartz_image_surface_flush (void *asurface,
|
||||
unsigned flags)
|
||||
{
|
||||
cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
|
||||
CGImageRef oldImage = surface->image;
|
||||
CGImageRef newImage = NULL;
|
||||
|
||||
if (flags)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* XXX only flush if the image has been modified. */
|
||||
|
||||
/* To be released by the ReleaseCallback */
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ _cairo_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
|
|||
}
|
||||
|
||||
_cairo_image_scaled_glyph_fini (scaled_font, scaled_glyph);
|
||||
|
||||
|
||||
if (scaled_glyph->surface != NULL)
|
||||
cairo_surface_destroy (&scaled_glyph->surface->base);
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,8 @@ struct _cairo_surface_backend {
|
|||
cairo_font_options_t *options);
|
||||
|
||||
cairo_warn cairo_status_t
|
||||
(*flush) (void *surface);
|
||||
(*flush) (void *surface,
|
||||
unsigned flags);
|
||||
|
||||
cairo_warn cairo_status_t
|
||||
(*mark_dirty_rectangle) (void *surface,
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@
|
|||
#include "cairo-surface-private.h"
|
||||
|
||||
static inline cairo_status_t
|
||||
_cairo_surface_flush (cairo_surface_t *surface)
|
||||
__cairo_surface_flush (cairo_surface_t *surface, unsigned flags)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
if (surface->backend->flush)
|
||||
status = surface->backend->flush (surface);
|
||||
status = surface->backend->flush (surface, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1202,14 +1202,12 @@ _cairo_surface_observer_glyphs (void *abstract_surface,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_surface_observer_flush (void *abstract_surface)
|
||||
_cairo_surface_observer_flush (void *abstract_surface, unsigned flags)
|
||||
{
|
||||
cairo_surface_observer_t *surface = abstract_surface;
|
||||
|
||||
do_callbacks (surface, &surface->flush_callbacks);
|
||||
|
||||
cairo_surface_flush (surface->target);
|
||||
return surface->target->status;
|
||||
return _cairo_surface_flush (surface->target, flags);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
|
|||
|
|
@ -115,4 +115,7 @@ cairo_private cairo_surface_t *
|
|||
_cairo_surface_get_source (cairo_surface_t *surface,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_flush (cairo_surface_t *surface, unsigned flags);
|
||||
|
||||
#endif /* CAIRO_SURFACE_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -64,15 +64,14 @@ _cairo_surface_snapshot_finish (void *abstract_surface)
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_surface_snapshot_flush (void *abstract_surface)
|
||||
_cairo_surface_snapshot_flush (void *abstract_surface, unsigned flags)
|
||||
{
|
||||
cairo_surface_snapshot_t *surface = abstract_surface;
|
||||
cairo_surface_t *target;
|
||||
cairo_status_t status;
|
||||
|
||||
target = _cairo_surface_snapshot_get_target (&surface->base);
|
||||
cairo_surface_flush (target);
|
||||
status = target->status;
|
||||
status = _cairo_surface_flush (target, flags);
|
||||
cairo_surface_destroy (target);
|
||||
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -222,12 +222,10 @@ _cairo_surface_subsurface_glyphs (void *abstract_surface,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_surface_subsurface_flush (void *abstract_surface)
|
||||
_cairo_surface_subsurface_flush (void *abstract_surface, unsigned flags)
|
||||
{
|
||||
cairo_surface_subsurface_t *surface = abstract_surface;
|
||||
|
||||
cairo_surface_flush (surface->target);
|
||||
return surface->target->status;
|
||||
return _cairo_surface_flush (surface->target, flags);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "cairo-image-surface-inline.h"
|
||||
#include "cairo-recording-surface-private.h"
|
||||
#include "cairo-region-private.h"
|
||||
#include "cairo-surface-inline.h"
|
||||
#include "cairo-tee-surface-private.h"
|
||||
|
||||
/**
|
||||
|
|
@ -386,17 +387,13 @@ _cairo_surface_has_snapshot (cairo_surface_t *surface,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
cairo_status_t
|
||||
_cairo_surface_begin_modification (cairo_surface_t *surface)
|
||||
{
|
||||
assert (surface->status == CAIRO_STATUS_SUCCESS);
|
||||
assert (! surface->finished);
|
||||
|
||||
_cairo_surface_detach_snapshots (surface);
|
||||
if (surface->snapshot_of != NULL)
|
||||
_cairo_surface_detach_snapshot (surface);
|
||||
|
||||
_cairo_surface_detach_mime_data (surface);
|
||||
return _cairo_surface_flush (surface, 1);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -416,6 +413,7 @@ _cairo_surface_init (cairo_surface_t *surface,
|
|||
surface->status = CAIRO_STATUS_SUCCESS;
|
||||
surface->unique_id = _cairo_surface_allocate_unique_id ();
|
||||
surface->finished = FALSE;
|
||||
surface->_finishing = FALSE;
|
||||
surface->is_clear = FALSE;
|
||||
surface->serial = 0;
|
||||
surface->damage = NULL;
|
||||
|
|
@ -989,14 +987,12 @@ cairo_surface_get_reference_count (cairo_surface_t *surface)
|
|||
static void
|
||||
_cairo_surface_finish_snapshots (cairo_surface_t *surface)
|
||||
{
|
||||
cairo_surface_flush (surface);
|
||||
cairo_status_t status;
|
||||
|
||||
/* update the snapshots *before* we declare the surface as finished */
|
||||
surface->_finishing = TRUE;
|
||||
|
||||
_cairo_surface_detach_snapshots (surface);
|
||||
if (surface->snapshot_of != NULL)
|
||||
_cairo_surface_detach_snapshot (surface);
|
||||
status = _cairo_surface_flush (surface, 0);
|
||||
(void) status;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1459,6 +1455,18 @@ cairo_surface_get_font_options (cairo_surface_t *surface,
|
|||
}
|
||||
slim_hidden_def (cairo_surface_get_font_options);
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_flush (cairo_surface_t *surface, unsigned flags)
|
||||
{
|
||||
/* update the current snapshots *before* the user updates the surface */
|
||||
_cairo_surface_detach_snapshots (surface);
|
||||
if (surface->snapshot_of != NULL)
|
||||
_cairo_surface_detach_snapshot (surface);
|
||||
_cairo_surface_detach_mime_data (surface);
|
||||
|
||||
return __cairo_surface_flush (surface, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_surface_flush:
|
||||
* @surface: a #cairo_surface_t
|
||||
|
|
@ -1483,15 +1491,9 @@ cairo_surface_flush (cairo_surface_t *surface)
|
|||
if (surface->finished)
|
||||
return;
|
||||
|
||||
/* update the current snapshots *before* the user updates the surface */
|
||||
_cairo_surface_detach_snapshots (surface);
|
||||
_cairo_surface_detach_mime_data (surface);
|
||||
|
||||
if (surface->backend->flush) {
|
||||
status = surface->backend->flush (surface);
|
||||
if (unlikely (status))
|
||||
_cairo_surface_set_error (surface, status);
|
||||
}
|
||||
status = _cairo_surface_flush (surface, 0);
|
||||
if (unlikely (status))
|
||||
_cairo_surface_set_error (surface, status);
|
||||
}
|
||||
slim_hidden_def (cairo_surface_flush);
|
||||
|
||||
|
|
@ -1508,7 +1510,12 @@ slim_hidden_def (cairo_surface_flush);
|
|||
void
|
||||
cairo_surface_mark_dirty (cairo_surface_t *surface)
|
||||
{
|
||||
cairo_surface_mark_dirty_rectangle (surface, 0, 0, -1, -1);
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
_cairo_surface_get_extents (surface, &extents);
|
||||
cairo_surface_mark_dirty_rectangle (surface,
|
||||
extents.x, extents.y,
|
||||
extents.width, extents.height);
|
||||
}
|
||||
slim_hidden_def (cairo_surface_mark_dirty);
|
||||
|
||||
|
|
@ -1620,7 +1627,11 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
|
|||
return;
|
||||
}
|
||||
|
||||
_cairo_surface_begin_modification (surface);
|
||||
status = _cairo_surface_begin_modification (surface);
|
||||
if (unlikely (status)) {
|
||||
_cairo_surface_set_error (surface, status);
|
||||
return;
|
||||
}
|
||||
|
||||
surface->device_transform.xx = sx;
|
||||
surface->device_transform.yy = sy;
|
||||
|
|
@ -1672,7 +1683,11 @@ cairo_surface_set_device_offset (cairo_surface_t *surface,
|
|||
return;
|
||||
}
|
||||
|
||||
_cairo_surface_begin_modification (surface);
|
||||
status = _cairo_surface_begin_modification (surface);
|
||||
if (unlikely (status)) {
|
||||
_cairo_surface_set_error (surface, status);
|
||||
return;
|
||||
}
|
||||
|
||||
surface->device_transform.x0 = x_offset;
|
||||
surface->device_transform.y0 = y_offset;
|
||||
|
|
@ -1747,6 +1762,8 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface,
|
|||
double x_pixels_per_inch,
|
||||
double y_pixels_per_inch)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (unlikely (surface->status))
|
||||
return;
|
||||
|
||||
|
|
@ -1765,7 +1782,11 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface,
|
|||
return;
|
||||
}
|
||||
|
||||
_cairo_surface_begin_modification (surface);
|
||||
status = _cairo_surface_begin_modification (surface);
|
||||
if (unlikely (status)) {
|
||||
_cairo_surface_set_error (surface, status);
|
||||
return;
|
||||
}
|
||||
|
||||
surface->x_fallback_resolution = x_pixels_per_inch;
|
||||
surface->y_fallback_resolution = y_pixels_per_inch;
|
||||
|
|
@ -1971,7 +1992,9 @@ _cairo_surface_paint (cairo_surface_t *surface,
|
|||
if (nothing_to_do (surface, op, source))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_surface_begin_modification (surface);
|
||||
status = _cairo_surface_begin_modification (surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = surface->backend->paint (surface, op, source, clip);
|
||||
if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
|
||||
|
|
@ -2016,7 +2039,9 @@ _cairo_surface_mask (cairo_surface_t *surface,
|
|||
if (nothing_to_do (surface, op, source))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_surface_begin_modification (surface);
|
||||
status = _cairo_surface_begin_modification (surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = surface->backend->mask (surface, op, source, mask, clip);
|
||||
if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
|
||||
|
|
@ -2068,7 +2093,9 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface,
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_surface_begin_modification (surface);
|
||||
status = _cairo_surface_begin_modification (surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (surface->backend->fill_stroke) {
|
||||
cairo_matrix_t dev_ctm = *stroke_ctm;
|
||||
|
|
@ -2138,7 +2165,9 @@ _cairo_surface_stroke (cairo_surface_t *surface,
|
|||
if (nothing_to_do (surface, op, source))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_surface_begin_modification (surface);
|
||||
status = _cairo_surface_begin_modification (surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = surface->backend->stroke (surface, op, source,
|
||||
path, stroke_style,
|
||||
|
|
@ -2179,7 +2208,9 @@ _cairo_surface_fill (cairo_surface_t *surface,
|
|||
if (nothing_to_do (surface, op, source))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_surface_begin_modification (surface);
|
||||
status = _cairo_surface_begin_modification (surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = surface->backend->fill (surface, op, source,
|
||||
path, fill_rule,
|
||||
|
|
@ -2243,6 +2274,8 @@ slim_hidden_def (cairo_surface_copy_page);
|
|||
void
|
||||
cairo_surface_show_page (cairo_surface_t *surface)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (unlikely (surface->status))
|
||||
return;
|
||||
|
||||
|
|
@ -2251,7 +2284,11 @@ cairo_surface_show_page (cairo_surface_t *surface)
|
|||
return;
|
||||
}
|
||||
|
||||
_cairo_surface_begin_modification (surface);
|
||||
status = _cairo_surface_begin_modification (surface);
|
||||
if (unlikely (status)) {
|
||||
_cairo_surface_set_error (surface, status);
|
||||
return;
|
||||
}
|
||||
|
||||
/* It's fine if some backends don't implement show_page */
|
||||
if (surface->backend->show_page == NULL)
|
||||
|
|
@ -2389,7 +2426,9 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
|
|||
if (nothing_to_do (surface, op, source))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_surface_begin_modification (surface);
|
||||
status = _cairo_surface_begin_modification (surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (_cairo_surface_has_device_transform (surface) &&
|
||||
! _cairo_matrix_is_integer_translation (&surface->device_transform, NULL, NULL))
|
||||
|
|
|
|||
|
|
@ -714,11 +714,15 @@ _put_image_boxes (cairo_xcb_surface_t *surface,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xcb_surface_flush (void *abstract_surface)
|
||||
_cairo_xcb_surface_flush (void *abstract_surface,
|
||||
unsigned flags)
|
||||
{
|
||||
cairo_xcb_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
if (flags)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (likely (surface->fallback == NULL)) {
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
if (! surface->base.finished && surface->deferred_clear)
|
||||
|
|
|
|||
|
|
@ -95,6 +95,8 @@ _cairo_xlib_display_destroy (void *abstract_display)
|
|||
{
|
||||
cairo_xlib_display_t *display = abstract_display;
|
||||
|
||||
_cairo_xlib_display_fini_shm (display);
|
||||
|
||||
free (display);
|
||||
}
|
||||
|
||||
|
|
@ -147,15 +149,18 @@ static const cairo_device_backend_t _cairo_xlib_device_backend = {
|
|||
_cairo_xlib_display_destroy,
|
||||
};
|
||||
|
||||
|
||||
static void _cairo_xlib_display_select_compositor (cairo_xlib_display_t *display)
|
||||
{
|
||||
#if 1
|
||||
if (display->render_major > 0 || display->render_minor >= 4)
|
||||
display->compositor = _cairo_xlib_traps_compositor_get ();
|
||||
else if (display->render_major > 0 || display->render_minor >= 0)
|
||||
display->compositor = _cairo_xlib_mask_compositor_get ();
|
||||
else
|
||||
display->compositor = _cairo_xlib_core_compositor_get ();
|
||||
#else
|
||||
display->compositor = _cairo_xlib_fallback_compositor_get ();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -263,6 +268,8 @@ _cairo_xlib_device_create (Display *dpy)
|
|||
|
||||
display->force_precision = -1;
|
||||
|
||||
_cairo_xlib_display_init_shm (display);
|
||||
|
||||
/* Prior to Render 0.10, there is no protocol support for gradients and
|
||||
* we call function stubs instead, which would silently consume the drawing.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -47,12 +47,198 @@
|
|||
#include "cairo-xlib-private.h"
|
||||
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-image-surface-private.h"
|
||||
#include "cairo-surface-offset-private.h"
|
||||
|
||||
static const cairo_compositor_t *
|
||||
_get_compositor (cairo_surface_t *surface)
|
||||
{
|
||||
return ((cairo_image_surface_t *)surface)->compositor;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
unclipped (cairo_xlib_surface_t *xlib, cairo_clip_t *clip)
|
||||
{
|
||||
cairo_rectangle_int_t r;
|
||||
|
||||
r.x = r.y = 0;
|
||||
r.width = xlib->width;
|
||||
r.height = xlib->height;
|
||||
return _cairo_clip_contains_rectangle (clip, &r);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_shm_compositor_paint (const cairo_compositor_t *_compositor,
|
||||
cairo_composite_rectangles_t *extents)
|
||||
{
|
||||
cairo_xlib_surface_t *xlib = (cairo_xlib_surface_t *)extents->surface;
|
||||
cairo_int_status_t status;
|
||||
cairo_surface_t *shm;
|
||||
|
||||
TRACE ((stderr, "%s\n", __FUNCTION__));
|
||||
|
||||
shm = _cairo_xlib_surface_get_shm (xlib);
|
||||
if (shm == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_compositor_paint (_get_compositor (shm), shm,
|
||||
extents->op,
|
||||
&extents->source_pattern.base,
|
||||
extents->clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
xlib->base.is_clear =
|
||||
extents->op == CAIRO_OPERATOR_CLEAR && unclipped (xlib, extents->clip);
|
||||
xlib->base.serial++;
|
||||
xlib->fallback++;
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_shm_compositor_mask (const cairo_compositor_t *_compositor,
|
||||
cairo_composite_rectangles_t *extents)
|
||||
{
|
||||
cairo_xlib_surface_t *xlib = (cairo_xlib_surface_t *)extents->surface;
|
||||
cairo_int_status_t status;
|
||||
cairo_surface_t *shm;
|
||||
|
||||
TRACE ((stderr, "%s\n", __FUNCTION__));
|
||||
|
||||
shm = _cairo_xlib_surface_get_shm (xlib);
|
||||
if (shm == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_compositor_mask (_get_compositor (shm), shm,
|
||||
extents->op,
|
||||
&extents->source_pattern.base,
|
||||
&extents->mask_pattern.base,
|
||||
extents->clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
xlib->base.is_clear = FALSE;
|
||||
xlib->base.serial++;
|
||||
xlib->fallback++;
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_shm_compositor_stroke (const cairo_compositor_t *_compositor,
|
||||
cairo_composite_rectangles_t *extents,
|
||||
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_antialias_t antialias)
|
||||
{
|
||||
cairo_xlib_surface_t *xlib = (cairo_xlib_surface_t *)extents->surface;
|
||||
cairo_int_status_t status;
|
||||
cairo_surface_t *shm;
|
||||
|
||||
TRACE ((stderr, "%s\n", __FUNCTION__));
|
||||
|
||||
shm = _cairo_xlib_surface_get_shm (xlib);
|
||||
if (shm == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_compositor_stroke (_get_compositor (shm), shm,
|
||||
extents->op,
|
||||
&extents->source_pattern.base,
|
||||
path, style,
|
||||
ctm, ctm_inverse,
|
||||
tolerance,
|
||||
antialias,
|
||||
extents->clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
xlib->base.is_clear = FALSE;
|
||||
xlib->base.serial++;
|
||||
xlib->fallback++;
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_shm_compositor_fill (const cairo_compositor_t *_compositor,
|
||||
cairo_composite_rectangles_t *extents,
|
||||
const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_xlib_surface_t *xlib = (cairo_xlib_surface_t *)extents->surface;
|
||||
cairo_int_status_t status;
|
||||
cairo_surface_t *shm;
|
||||
|
||||
TRACE ((stderr, "%s\n", __FUNCTION__));
|
||||
|
||||
shm = _cairo_xlib_surface_get_shm (xlib);
|
||||
if (shm == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_compositor_fill (_get_compositor (shm), shm,
|
||||
extents->op,
|
||||
&extents->source_pattern.base,
|
||||
path,
|
||||
fill_rule, tolerance, antialias,
|
||||
extents->clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
xlib->base.is_clear = FALSE;
|
||||
xlib->base.serial++;
|
||||
xlib->fallback++;
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_shm_compositor_glyphs (const cairo_compositor_t *_compositor,
|
||||
cairo_composite_rectangles_t *extents,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_bool_t overlap)
|
||||
{
|
||||
cairo_xlib_surface_t *xlib = (cairo_xlib_surface_t *)extents->surface;
|
||||
cairo_int_status_t status;
|
||||
cairo_surface_t *shm;
|
||||
|
||||
TRACE ((stderr, "%s\n", __FUNCTION__));
|
||||
|
||||
shm = _cairo_xlib_surface_get_shm (xlib);
|
||||
if (shm == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_compositor_glyphs (_get_compositor (shm), shm,
|
||||
extents->op,
|
||||
&extents->source_pattern.base,
|
||||
glyphs, num_glyphs, scaled_font,
|
||||
extents->clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
xlib->base.is_clear = FALSE;
|
||||
xlib->base.serial++;
|
||||
xlib->fallback++;
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
static const cairo_compositor_t _cairo_xlib_shm_compositor = {
|
||||
&_cairo_fallback_compositor,
|
||||
|
||||
_cairo_xlib_shm_compositor_paint,
|
||||
_cairo_xlib_shm_compositor_mask,
|
||||
_cairo_xlib_shm_compositor_stroke,
|
||||
_cairo_xlib_shm_compositor_fill,
|
||||
_cairo_xlib_shm_compositor_glyphs,
|
||||
};
|
||||
|
||||
const cairo_compositor_t *
|
||||
_cairo_xlib_fallback_compositor_get (void)
|
||||
{
|
||||
/* XXX Do something interesting here to mitigate fallbacks ala xcb */
|
||||
return &_cairo_fallback_compositor;
|
||||
return &_cairo_xlib_shm_compositor;
|
||||
}
|
||||
|
||||
#endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */
|
||||
|
|
|
|||
|
|
@ -52,8 +52,10 @@
|
|||
#include <pixman.h>
|
||||
|
||||
typedef struct _cairo_xlib_display cairo_xlib_display_t;
|
||||
typedef struct _cairo_xlib_shm_display cairo_xlib_shm_display_t;
|
||||
typedef struct _cairo_xlib_screen cairo_xlib_screen_t;
|
||||
typedef struct _cairo_xlib_source cairo_xlib_source_t;
|
||||
typedef struct _cairo_xlib_proxy cairo_xlib_proxy_t;
|
||||
typedef struct _cairo_xlib_surface cairo_xlib_surface_t;
|
||||
|
||||
/* size of color cube */
|
||||
|
|
@ -72,6 +74,8 @@ struct _cairo_xlib_display {
|
|||
cairo_list_t screens;
|
||||
cairo_list_t fonts;
|
||||
|
||||
cairo_xlib_shm_display_t *shm;
|
||||
|
||||
const cairo_compositor_t *compositor;
|
||||
|
||||
int render_major;
|
||||
|
|
@ -168,6 +172,8 @@ struct _cairo_xlib_surface {
|
|||
Picture picture;
|
||||
|
||||
const cairo_compositor_t *compositor;
|
||||
cairo_surface_t *shm;
|
||||
int fallback;
|
||||
|
||||
cairo_xlib_display_t *display;
|
||||
cairo_xlib_screen_t *screen;
|
||||
|
|
@ -205,6 +211,11 @@ struct _cairo_xlib_surface {
|
|||
} embedded_source;
|
||||
};
|
||||
|
||||
struct _cairo_xlib_proxy {
|
||||
struct _cairo_xlib_source source;
|
||||
cairo_surface_t *owner;
|
||||
};
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_xlib_surface_get_gc (cairo_xlib_display_t *display,
|
||||
cairo_xlib_surface_t *surface,
|
||||
|
|
@ -213,6 +224,12 @@ _cairo_xlib_surface_get_gc (cairo_xlib_display_t *display,
|
|||
cairo_private cairo_device_t *
|
||||
_cairo_xlib_device_create (Display *display);
|
||||
|
||||
cairo_private void
|
||||
_cairo_xlib_display_init_shm (cairo_xlib_display_t *display);
|
||||
|
||||
cairo_private void
|
||||
_cairo_xlib_display_fini_shm (cairo_xlib_display_t *display);
|
||||
|
||||
cairo_private cairo_xlib_screen_t *
|
||||
_cairo_xlib_display_get_screen (cairo_xlib_display_t *display,
|
||||
Screen *screen);
|
||||
|
|
@ -381,4 +398,46 @@ _cairo_xlib_surface_put_gc (cairo_xlib_display_t *display,
|
|||
gc);
|
||||
}
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_xlib_surface_create_similar_shm (void *surface,
|
||||
cairo_format_t format,
|
||||
int width, int height);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_xlib_surface_get_shm (cairo_xlib_surface_t *surface);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_xlib_surface_put_shm (cairo_xlib_surface_t *surface);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_xlib_surface_create_shm_image (cairo_xlib_surface_t *surface,
|
||||
pixman_format_code_t format,
|
||||
int width, int height);
|
||||
|
||||
cairo_private void
|
||||
_cairo_xlib_shm_surface_get_ximage (cairo_surface_t *surface,
|
||||
XImage *ximage);
|
||||
|
||||
cairo_private void *
|
||||
_cairo_xlib_shm_surface_get_obdata (cairo_surface_t *surface);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_xlib_shm_surface_is_active (cairo_surface_t *surface);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_xlib_shm_surface_is_idle (cairo_surface_t *surface);
|
||||
|
||||
cairo_private Pixmap
|
||||
_cairo_xlib_shm_surface_get_pixmap (cairo_surface_t *surface);
|
||||
|
||||
cairo_private void
|
||||
_cairo_xlib_shm_surface_mark_active (cairo_surface_t *surface);
|
||||
|
||||
cairo_private XRenderPictFormat *
|
||||
_cairo_xlib_shm_surface_get_xrender_format (cairo_surface_t *surface);
|
||||
|
||||
cairo_private pixman_format_code_t
|
||||
_pixman_format_for_xlib_surface (cairo_xlib_surface_t *surface);
|
||||
|
||||
|
||||
#endif /* CAIRO_XLIB_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "cairo-xlib-private.h"
|
||||
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-damage-private.h"
|
||||
#include "cairo-image-surface-private.h"
|
||||
#include "cairo-list-inline.h"
|
||||
#include "cairo-pattern-private.h"
|
||||
|
|
@ -124,15 +125,141 @@ set_clip_region (void *_surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
copy_image_boxes (void *_dst,
|
||||
cairo_image_surface_t *image,
|
||||
cairo_boxes_t *boxes,
|
||||
int dx, int dy)
|
||||
{
|
||||
cairo_xlib_surface_t *dst = _dst;
|
||||
struct _cairo_boxes_chunk *chunk;
|
||||
cairo_int_status_t status;
|
||||
Pixmap src;
|
||||
GC gc;
|
||||
int i, j;
|
||||
|
||||
status = acquire (dst);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_xlib_surface_get_gc (dst->display, dst, &gc);
|
||||
if (unlikely (status)) {
|
||||
release (dst);
|
||||
return status;
|
||||
}
|
||||
|
||||
src = _cairo_xlib_shm_surface_get_pixmap (&image->base);
|
||||
if (boxes->num_boxes == 1) {
|
||||
int x1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.x);
|
||||
int y1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.y);
|
||||
int x2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.x);
|
||||
int y2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.y);
|
||||
|
||||
XCopyArea (dst->dpy, src, dst->drawable, gc,
|
||||
x1 + dx, y1 + dy,
|
||||
x2 - x1, y2 - y1,
|
||||
x1, y1);
|
||||
} else {
|
||||
XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)];
|
||||
XRectangle *rects = stack_rects;
|
||||
|
||||
if (boxes->num_boxes > ARRAY_LENGTH (stack_rects)) {
|
||||
rects = _cairo_malloc_ab (boxes->num_boxes, sizeof (XRectangle));
|
||||
if (unlikely (rects == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
j = 0;
|
||||
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
|
||||
for (i = 0; i < chunk->count; i++) {
|
||||
int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
|
||||
int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
|
||||
int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
|
||||
int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
|
||||
|
||||
rects[j].x = x1;
|
||||
rects[j].y = y1;
|
||||
rects[j].width = x2 - x1;
|
||||
rects[j].height = y2 - y1;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
assert (j == boxes->num_boxes);
|
||||
|
||||
XSetClipRectangles (dst->dpy, gc, 0, 0, rects, j, Unsorted);
|
||||
|
||||
XCopyArea (dst->dpy, src, dst->drawable, gc,
|
||||
dx, dy,
|
||||
image->width, image->height,
|
||||
0, 0);
|
||||
|
||||
XSetClipMask (dst->dpy, gc, None);
|
||||
|
||||
if (rects != stack_rects)
|
||||
free (rects);
|
||||
}
|
||||
|
||||
_cairo_xlib_shm_surface_mark_active (&image->base);
|
||||
_cairo_xlib_surface_put_gc (dst->display, dst, gc);
|
||||
release (dst);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
draw_image_boxes (void *_dst,
|
||||
cairo_image_surface_t *image,
|
||||
cairo_boxes_t *boxes,
|
||||
int dx, int dy)
|
||||
{
|
||||
cairo_xlib_surface_t *dst = _dst;
|
||||
struct _cairo_boxes_chunk *chunk;
|
||||
cairo_image_surface_t *shm;
|
||||
int i;
|
||||
|
||||
if (image->base.device == dst->base.device &&
|
||||
_cairo_xlib_shm_surface_get_pixmap (&image->base))
|
||||
return copy_image_boxes (dst, image, boxes, dx, dy);
|
||||
|
||||
shm = (cairo_image_surface_t *) _cairo_xlib_surface_get_shm (dst);
|
||||
if (shm) {
|
||||
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
|
||||
for (i = 0; i < chunk->count; i++) {
|
||||
cairo_box_t *b = &chunk->base[i];
|
||||
cairo_rectangle_int_t r;
|
||||
|
||||
r.x = _cairo_fixed_integer_part (b->p1.x);
|
||||
r.y = _cairo_fixed_integer_part (b->p1.y);
|
||||
r.width = _cairo_fixed_integer_part (b->p2.x) - r.x;
|
||||
r.height = _cairo_fixed_integer_part (b->p2.y) - r.y;
|
||||
|
||||
if (shm->pixman_format != image->pixman_format ||
|
||||
! pixman_blt ((uint32_t *)image->data, (uint32_t *)shm->data,
|
||||
image->stride / sizeof (uint32_t),
|
||||
shm->stride / sizeof (uint32_t),
|
||||
PIXMAN_FORMAT_BPP (image->pixman_format),
|
||||
PIXMAN_FORMAT_BPP (shm->pixman_format),
|
||||
r.x + dx, r.y + dy,
|
||||
r.x, r.y,
|
||||
r.width, r.height))
|
||||
{
|
||||
pixman_image_composite32 (PIXMAN_OP_SRC,
|
||||
image->pixman_image, NULL, shm->pixman_image,
|
||||
r.x + dx, r.y + dy,
|
||||
0, 0,
|
||||
r.x, r.y,
|
||||
r.width, r.height);
|
||||
}
|
||||
|
||||
shm->base.damage =
|
||||
_cairo_damage_add_rectangle (shm->base.damage, &r);
|
||||
}
|
||||
}
|
||||
dst->base.is_clear = FALSE;
|
||||
dst->fallback++;
|
||||
dst->base.serial++;
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
|
||||
for (i = 0; i < chunk->count; i++) {
|
||||
cairo_box_t *b = &chunk->base[i];
|
||||
|
|
@ -140,7 +267,7 @@ draw_image_boxes (void *_dst,
|
|||
int y1 = _cairo_fixed_integer_part (b->p1.y);
|
||||
int x2 = _cairo_fixed_integer_part (b->p2.x);
|
||||
int y2 = _cairo_fixed_integer_part (b->p2.y);
|
||||
if ( _cairo_xlib_surface_draw_image (_dst, image,
|
||||
if ( _cairo_xlib_surface_draw_image (dst, image,
|
||||
x1 + dx, y1 + dy,
|
||||
x2 - x1, y2 - y1,
|
||||
x1, y1))
|
||||
|
|
@ -163,6 +290,7 @@ copy_boxes (void *_dst,
|
|||
struct _cairo_boxes_chunk *chunk;
|
||||
cairo_int_status_t status;
|
||||
GC gc;
|
||||
Drawable d;
|
||||
int i, j;
|
||||
|
||||
if (! _cairo_xlib_surface_same_screen (dst, src))
|
||||
|
|
@ -181,11 +309,18 @@ copy_boxes (void *_dst,
|
|||
return status;
|
||||
}
|
||||
|
||||
if (! src->owns_pixmap) {
|
||||
XGCValues gcv;
|
||||
if (src->fallback && src->shm->damage->dirty) {
|
||||
assert (src != dst);
|
||||
d = _cairo_xlib_shm_surface_get_pixmap (src->shm);
|
||||
assert (d != 0);
|
||||
} else {
|
||||
if (! src->owns_pixmap) {
|
||||
XGCValues gcv;
|
||||
|
||||
gcv.subwindow_mode = IncludeInferiors;
|
||||
XChangeGC (dst->display->display, gc, GCSubwindowMode, &gcv);
|
||||
gcv.subwindow_mode = IncludeInferiors;
|
||||
XChangeGC (dst->display->display, gc, GCSubwindowMode, &gcv);
|
||||
}
|
||||
d = src->drawable;
|
||||
}
|
||||
|
||||
if (boxes->num_boxes == 1) {
|
||||
|
|
@ -194,7 +329,7 @@ copy_boxes (void *_dst,
|
|||
int x2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.x);
|
||||
int y2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.y);
|
||||
|
||||
XCopyArea (dst->dpy, src->drawable, dst->drawable, gc,
|
||||
XCopyArea (dst->dpy, d, dst->drawable, gc,
|
||||
x1 + dx, y1 + dy,
|
||||
x2 - x1, y2 - y1,
|
||||
x1, y1);
|
||||
|
|
@ -215,7 +350,7 @@ copy_boxes (void *_dst,
|
|||
int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
|
||||
int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
|
||||
int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
|
||||
XCopyArea (dst->dpy, src->drawable, dst->drawable, gc,
|
||||
XCopyArea (dst->dpy, d, dst->drawable, gc,
|
||||
x1 + dx, y1 + dy,
|
||||
x2 - x1, y2 - y1,
|
||||
x1, y1);
|
||||
|
|
@ -250,7 +385,7 @@ copy_boxes (void *_dst,
|
|||
|
||||
XSetClipRectangles (dst->dpy, gc, 0, 0, rects, j, Unsorted);
|
||||
|
||||
XCopyArea (dst->dpy, src->drawable, dst->drawable, gc,
|
||||
XCopyArea (dst->dpy, d, dst->drawable, gc,
|
||||
extents->x + dx, extents->y + dy,
|
||||
extents->width, extents->height,
|
||||
extents->x, extents->y);
|
||||
|
|
@ -262,7 +397,9 @@ copy_boxes (void *_dst,
|
|||
}
|
||||
}
|
||||
|
||||
if (! src->owns_pixmap) {
|
||||
if (src->fallback && src->shm->damage->dirty) {
|
||||
_cairo_xlib_shm_surface_mark_active (src->shm);
|
||||
} else if (! src->owns_pixmap) {
|
||||
XGCValues gcv;
|
||||
|
||||
gcv.subwindow_mode = ClipByChildren;
|
||||
|
|
|
|||
|
|
@ -75,11 +75,28 @@ _cairo_xlib_source_finish (void *abstract_surface)
|
|||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_xlib_source_backend = {
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_SURFACE_TYPE_XLIB,
|
||||
_cairo_xlib_source_finish,
|
||||
NULL, /* read-only wrapper */
|
||||
};
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_proxy_finish (void *abstract_surface)
|
||||
{
|
||||
cairo_xlib_proxy_t *proxy = abstract_surface;
|
||||
|
||||
XRenderFreePicture (proxy->source.dpy, proxy->source.picture);
|
||||
_cairo_xlib_shm_surface_mark_active (proxy->owner);
|
||||
cairo_surface_destroy (proxy->owner);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_xlib_proxy_backend = {
|
||||
CAIRO_SURFACE_TYPE_XLIB,
|
||||
_cairo_xlib_proxy_finish,
|
||||
NULL, /* read-only wrapper */
|
||||
};
|
||||
|
||||
static cairo_surface_t *
|
||||
source (cairo_xlib_surface_t *dst, Picture picture)
|
||||
{
|
||||
|
|
@ -286,6 +303,12 @@ render_pattern (cairo_xlib_surface_t *dst,
|
|||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
status = _cairo_xlib_surface_put_shm (src);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&src->base);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
src->picture = XRenderCreatePicture (dpy,
|
||||
src->drawable, src->xrender_format,
|
||||
0, NULL);
|
||||
|
|
@ -295,7 +318,6 @@ render_pattern (cairo_xlib_surface_t *dst,
|
|||
return &src->base;
|
||||
}
|
||||
|
||||
|
||||
static cairo_surface_t *
|
||||
gradient_source (cairo_xlib_surface_t *dst,
|
||||
const cairo_gradient_pattern_t *gradient,
|
||||
|
|
@ -538,24 +560,15 @@ solid_source (cairo_xlib_surface_t *dst,
|
|||
return transparent_source (dst, color);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
embedded_source (cairo_xlib_surface_t *dst,
|
||||
const cairo_surface_pattern_t *pattern,
|
||||
cairo_xlib_surface_t *src,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
int *src_x, int *src_y)
|
||||
static cairo_xlib_source_t *init_source (cairo_xlib_surface_t *dst,
|
||||
cairo_xlib_surface_t *src)
|
||||
{
|
||||
cairo_xlib_source_t *source;
|
||||
Display *dpy = dst->display->display;
|
||||
cairo_int_status_t status;
|
||||
XTransform xtransform;
|
||||
XRenderPictureAttributes pa;
|
||||
unsigned mask = 0;
|
||||
cairo_xlib_source_t *source = &src->embedded_source;
|
||||
|
||||
/* As these are frequent and meant to be fast, we track pictures for
|
||||
* native surface and minimise update requests.
|
||||
*/
|
||||
source = &src->embedded_source;
|
||||
if (source->picture == None) {
|
||||
XRenderPictureAttributes pa;
|
||||
|
||||
|
|
@ -576,6 +589,22 @@ embedded_source (cairo_xlib_surface_t *dst,
|
|||
source->extend = CAIRO_EXTEND_NONE;
|
||||
}
|
||||
|
||||
return (cairo_xlib_source_t *) cairo_surface_reference (&source->base);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
embedded_source (cairo_xlib_surface_t *dst,
|
||||
const cairo_surface_pattern_t *pattern,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
int *src_x, int *src_y,
|
||||
cairo_xlib_source_t *source)
|
||||
{
|
||||
Display *dpy = dst->display->display;
|
||||
cairo_int_status_t status;
|
||||
XTransform xtransform;
|
||||
XRenderPictureAttributes pa;
|
||||
unsigned mask = 0;
|
||||
|
||||
status = _cairo_matrix_to_pixman_matrix_offset (&pattern->base.matrix,
|
||||
pattern->base.filter,
|
||||
extents->x + extents->width / 2,
|
||||
|
|
@ -614,7 +643,7 @@ embedded_source (cairo_xlib_surface_t *dst,
|
|||
if (mask)
|
||||
XRenderChangePicture (dpy, source->picture, mask, &pa);
|
||||
|
||||
return cairo_surface_reference (&source->base);
|
||||
return &source->base;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
@ -642,6 +671,9 @@ subsurface_source (cairo_xlib_surface_t *dst,
|
|||
sample->y + sample->height <= sub->extents.height)
|
||||
{
|
||||
src = (cairo_xlib_surface_t *) sub->target;
|
||||
status = _cairo_surface_flush (&src->base, 0);
|
||||
if (unlikely (status))
|
||||
return _cairo_surface_create_in_error (status);
|
||||
|
||||
if (pattern->base.filter == CAIRO_FILTER_NEAREST &&
|
||||
_cairo_matrix_is_translation (&pattern->base.matrix))
|
||||
|
|
@ -658,8 +690,8 @@ subsurface_source (cairo_xlib_surface_t *dst,
|
|||
local_pattern.base.matrix.x0 += sub->extents.x;
|
||||
local_pattern.base.matrix.y0 += sub->extents.y;
|
||||
local_pattern.base.extend = CAIRO_EXTEND_NONE;
|
||||
return embedded_source (dst, &local_pattern, src, extents,
|
||||
src_x, src_y);
|
||||
return embedded_source (dst, &local_pattern, extents,
|
||||
src_x, src_y, init_source (dst, src));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -750,7 +782,8 @@ native_source (cairo_xlib_surface_t *dst,
|
|||
const cairo_rectangle_int_t *sample,
|
||||
int *src_x, int *src_y)
|
||||
{
|
||||
cairo_xlib_surface_t *src = (cairo_xlib_surface_t *) pattern->surface;
|
||||
cairo_xlib_surface_t *src;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (_cairo_surface_is_subsurface (pattern->surface))
|
||||
return subsurface_source (dst, pattern, is_mask,
|
||||
|
|
@ -758,6 +791,9 @@ native_source (cairo_xlib_surface_t *dst,
|
|||
src_x, src_y);
|
||||
|
||||
src = unwrap_source (pattern);
|
||||
status = _cairo_surface_flush (&src->base, 0);
|
||||
if (unlikely (status))
|
||||
return _cairo_surface_create_in_error (status);
|
||||
|
||||
if (pattern->base.filter == CAIRO_FILTER_NEAREST &&
|
||||
sample->x >= 0 && sample->y >= 0 &&
|
||||
|
|
@ -771,65 +807,10 @@ native_source (cairo_xlib_surface_t *dst,
|
|||
return cairo_surface_reference (&src->base);
|
||||
}
|
||||
|
||||
return embedded_source (dst, pattern, src, extents, src_x, src_y);
|
||||
return embedded_source (dst, pattern, extents, src_x, src_y,
|
||||
init_source (dst, src));
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* It is general quicker if we let the application choose which images
|
||||
* to cache for itself and only upload the fragments required for this
|
||||
* operation.
|
||||
*/
|
||||
static cairo_surface_t *
|
||||
image_source (cairo_xlib_surface_t *dst,
|
||||
const cairo_surface_pattern_t *pattern,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
int *src_x, int *src_y)
|
||||
{
|
||||
cairo_image_surface_t *src = (cairo_image_surface_t *) pattern->surface;
|
||||
cairo_xlib_surface_t *snapshot;
|
||||
cairo_surface_pattern_t local_pattern;
|
||||
cairo_status_t status;
|
||||
|
||||
snapshot = (cairo_xlib_surface_t *)
|
||||
_cairo_surface_has_snapshot (&src->base, dst->base.backend);
|
||||
if (snapshot == NULL || snapshot->screen != dst->screen) {
|
||||
if (snapshot)
|
||||
_cairo_surface_detach_snapshot (&snapshot->base);
|
||||
|
||||
snapshot = (cairo_xlib_surface_t *)
|
||||
_cairo_surface_create_similar_scratch (&dst->base,
|
||||
src->base.content,
|
||||
src->width,
|
||||
src->height);
|
||||
if (snapshot->base.type != CAIRO_SURFACE_TYPE_XLIB) {
|
||||
cairo_surface_destroy (&snapshot->base);
|
||||
return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
status = _cairo_xlib_surface_draw_image (snapshot, src,
|
||||
0, 0,
|
||||
src->width, src->height,
|
||||
0, 0);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&snapshot->base);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
_cairo_surface_attach_snapshot (&src->base,
|
||||
&snapshot->base,
|
||||
cairo_surface_finish);
|
||||
|
||||
/* reference remains held by the snapshot from image */
|
||||
cairo_surface_destroy (&snapshot->base);
|
||||
}
|
||||
|
||||
local_pattern = *pattern;
|
||||
local_pattern.surface = &snapshot->base;
|
||||
|
||||
return native_source (dst, &local_pattern, extents, src_x, src_y);
|
||||
}
|
||||
#endif
|
||||
|
||||
static cairo_surface_t *
|
||||
recording_pattern_get_surface (const cairo_pattern_t *pattern)
|
||||
{
|
||||
|
|
@ -912,13 +893,49 @@ surface_source (cairo_xlib_surface_t *dst,
|
|||
const cairo_rectangle_int_t *sample,
|
||||
int *src_x, int *src_y)
|
||||
{
|
||||
cairo_xlib_surface_t *src;
|
||||
cairo_image_surface_t *image;
|
||||
cairo_surface_t *src;
|
||||
cairo_xlib_surface_t *xsrc;
|
||||
cairo_surface_pattern_t local_pattern;
|
||||
cairo_status_t status;
|
||||
cairo_rectangle_int_t upload, limit, map_extents;
|
||||
cairo_matrix_t m;
|
||||
|
||||
src = pattern->surface;
|
||||
if (src->type == CAIRO_SURFACE_TYPE_IMAGE &&
|
||||
src->device == dst->base.device &&
|
||||
_cairo_xlib_shm_surface_get_pixmap (src)) {
|
||||
cairo_xlib_proxy_t *proxy;
|
||||
|
||||
cairo_surface_reference (src);
|
||||
|
||||
prepare_shm_image:
|
||||
proxy = malloc (sizeof(*proxy));
|
||||
if (unlikely (proxy == NULL)) {
|
||||
cairo_surface_destroy (src);
|
||||
return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
_cairo_surface_init (&proxy->source.base,
|
||||
&cairo_xlib_proxy_backend,
|
||||
dst->base.device,
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
proxy->source.dpy = dst->display->display;
|
||||
proxy->source.picture = XRenderCreatePicture (proxy->source.dpy,
|
||||
_cairo_xlib_shm_surface_get_pixmap (src),
|
||||
_cairo_xlib_shm_surface_get_xrender_format (src),
|
||||
0, NULL);
|
||||
|
||||
proxy->source.has_component_alpha = 0;
|
||||
proxy->source.has_matrix = 0;
|
||||
proxy->source.filter = CAIRO_FILTER_NEAREST;
|
||||
proxy->source.extend = CAIRO_EXTEND_NONE;
|
||||
proxy->owner = src;
|
||||
|
||||
return embedded_source (dst, pattern, extents, src_x, src_y,
|
||||
&proxy->source);
|
||||
}
|
||||
|
||||
upload = *sample;
|
||||
if (_cairo_surface_get_extents (pattern->surface, &limit)) {
|
||||
if (pattern->base.extend == CAIRO_EXTEND_NONE) {
|
||||
|
|
@ -935,15 +952,10 @@ surface_source (cairo_xlib_surface_t *dst,
|
|||
}
|
||||
}
|
||||
|
||||
src = (cairo_xlib_surface_t *)
|
||||
_cairo_surface_create_similar_scratch (&dst->base,
|
||||
pattern->surface->content,
|
||||
upload.width,
|
||||
upload.height);
|
||||
if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
|
||||
cairo_surface_destroy (&src->base);
|
||||
return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
src = _cairo_xlib_surface_create_similar_shm (&dst->base,
|
||||
_cairo_format_from_content (pattern->surface->content),
|
||||
upload.width,
|
||||
upload.height);
|
||||
|
||||
_cairo_pattern_init_for_surface (&local_pattern, pattern->surface);
|
||||
cairo_matrix_init_translate (&local_pattern.base.matrix,
|
||||
|
|
@ -952,20 +964,18 @@ surface_source (cairo_xlib_surface_t *dst,
|
|||
map_extents = upload;
|
||||
map_extents.x = map_extents.y = 0;
|
||||
|
||||
image = _cairo_surface_map_to_image (&src->base, &map_extents);
|
||||
status = _cairo_surface_paint (&image->base,
|
||||
status = _cairo_surface_paint (src,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&local_pattern.base,
|
||||
NULL);
|
||||
status = _cairo_surface_unmap_image (&src->base, image);
|
||||
_cairo_pattern_fini (&local_pattern.base);
|
||||
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&src->base);
|
||||
cairo_surface_destroy (src);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
local_pattern.base.matrix = pattern->base.matrix;
|
||||
_cairo_pattern_init_static_copy (&local_pattern.base, &pattern->base);
|
||||
if (upload.x | upload.y) {
|
||||
cairo_matrix_init_translate (&m, -upload.x, -upload.y);
|
||||
cairo_matrix_multiply (&local_pattern.base.matrix,
|
||||
|
|
@ -974,21 +984,44 @@ surface_source (cairo_xlib_surface_t *dst,
|
|||
}
|
||||
|
||||
*src_x = *src_y = 0;
|
||||
_cairo_xlib_surface_ensure_picture (src);
|
||||
if (! picture_set_properties (src->display,
|
||||
src->picture,
|
||||
&pattern->base,
|
||||
if (src->device == dst->base.device &&
|
||||
_cairo_xlib_shm_surface_get_pixmap (src)) {
|
||||
pattern = &local_pattern;
|
||||
goto prepare_shm_image;
|
||||
}
|
||||
|
||||
xsrc = (cairo_xlib_surface_t *)
|
||||
_cairo_surface_create_similar_scratch (&dst->base,
|
||||
src->content,
|
||||
upload.width,
|
||||
upload.height);
|
||||
if (xsrc->base.type != CAIRO_SURFACE_TYPE_XLIB) {
|
||||
cairo_surface_destroy (src);
|
||||
cairo_surface_destroy (&xsrc->base);
|
||||
return None;
|
||||
}
|
||||
|
||||
status = _cairo_xlib_surface_draw_image (xsrc, (cairo_image_surface_t *)src,
|
||||
0, 0,
|
||||
upload.width, upload.height,
|
||||
0, 0);
|
||||
cairo_surface_destroy (src);
|
||||
|
||||
_cairo_xlib_surface_ensure_picture (xsrc);
|
||||
if (! picture_set_properties (xsrc->display,
|
||||
xsrc->picture,
|
||||
&local_pattern.base,
|
||||
&local_pattern.base.matrix,
|
||||
extents,
|
||||
src_x, src_y))
|
||||
{
|
||||
cairo_surface_destroy (&src->base);
|
||||
cairo_surface_destroy (&xsrc->base);
|
||||
return render_pattern (dst, &pattern->base,
|
||||
is_mask, extents,
|
||||
src_x, src_y);
|
||||
}
|
||||
|
||||
return &src->base;
|
||||
return &xsrc->base;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
|
|
@ -1052,10 +1085,6 @@ _cairo_xlib_source_create_for_pattern (cairo_surface_t *_dst,
|
|||
return record_source (dst, spattern, is_mask,
|
||||
extents, sample,
|
||||
src_x, src_y);
|
||||
#if 0
|
||||
if (spattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE)
|
||||
return image_source (dst, spattern, extents, src_x, src_y);
|
||||
#endif
|
||||
|
||||
return surface_source (dst, spattern, is_mask,
|
||||
extents, sample,
|
||||
|
|
|
|||
1119
src/cairo-xlib-surface-shm.c
Normal file
1119
src/cairo-xlib-surface-shm.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -54,6 +54,7 @@
|
|||
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
#include "cairo-damage-private.h"
|
||||
#include "cairo-default-context-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-image-surface-private.h"
|
||||
|
|
@ -66,6 +67,10 @@
|
|||
|
||||
#include <X11/Xutil.h> /* for XDestroyImage */
|
||||
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
|
||||
#define XLIB_COORD_MAX 32767
|
||||
|
||||
#define DEBUG 0
|
||||
|
|
@ -375,6 +380,8 @@ _cairo_xlib_surface_finish (void *abstract_surface)
|
|||
if (surface->owns_pixmap)
|
||||
XFreePixmap (display->display, surface->drawable);
|
||||
|
||||
cairo_surface_destroy (surface->shm);
|
||||
|
||||
cairo_device_release (&display->base);
|
||||
|
||||
return status;
|
||||
|
|
@ -678,15 +685,32 @@ static int bits_per_pixel(cairo_xlib_surface_t *surface)
|
|||
return 1;
|
||||
}
|
||||
|
||||
pixman_format_code_t
|
||||
_pixman_format_for_xlib_surface (cairo_xlib_surface_t *surface)
|
||||
{
|
||||
cairo_format_masks_t masks;
|
||||
pixman_format_code_t format;
|
||||
|
||||
masks.bpp = bits_per_pixel (surface);
|
||||
masks.alpha_mask = surface->a_mask;
|
||||
masks.red_mask = surface->r_mask;
|
||||
masks.green_mask = surface->g_mask;
|
||||
masks.blue_mask = surface->b_mask;
|
||||
if (! _pixman_format_from_masks (&masks, &format))
|
||||
return 0;
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_get_image_surface (cairo_xlib_surface_t *surface,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
const cairo_rectangle_int_t *extents,
|
||||
int try_shm)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
cairo_image_surface_t *image = NULL;
|
||||
XImage *ximage;
|
||||
pixman_format_code_t pixman_format;
|
||||
cairo_format_masks_t xlib_masks;
|
||||
cairo_xlib_display_t *display;
|
||||
|
||||
assert (extents->x >= 0);
|
||||
|
|
@ -697,13 +721,8 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
if (surface->base.is_clear ||
|
||||
(surface->base.serial == 0 && surface->owns_pixmap))
|
||||
{
|
||||
xlib_masks.bpp = bits_per_pixel (surface);
|
||||
xlib_masks.alpha_mask = surface->a_mask;
|
||||
xlib_masks.red_mask = surface->r_mask;
|
||||
xlib_masks.green_mask = surface->g_mask;
|
||||
xlib_masks.blue_mask = surface->b_mask;
|
||||
if (_pixman_format_from_masks (&xlib_masks, &pixman_format) &&
|
||||
_cairo_format_from_pixman_format (pixman_format) != CAIRO_FORMAT_INVALID)
|
||||
pixman_format = _pixman_format_for_xlib_surface (surface);
|
||||
if (pixman_format)
|
||||
{
|
||||
return _cairo_image_surface_create_with_pixman_format (NULL,
|
||||
pixman_format,
|
||||
|
|
@ -713,11 +732,59 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
}
|
||||
}
|
||||
|
||||
if (surface->shm) {
|
||||
cairo_image_surface_t *src = (cairo_image_surface_t *) surface->shm;
|
||||
cairo_surface_t *dst;
|
||||
cairo_surface_pattern_t pattern;
|
||||
|
||||
dst = cairo_image_surface_create (src->format,
|
||||
extents->width, extents->height);
|
||||
if (unlikely (dst->status))
|
||||
return dst;
|
||||
|
||||
_cairo_pattern_init_for_surface (&pattern, &src->base);
|
||||
cairo_matrix_init_translate (&pattern.base.matrix,
|
||||
extents->x, extents->y);
|
||||
status = _cairo_surface_paint (dst, CAIRO_OPERATOR_SOURCE, &pattern.base, NULL);
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (dst);
|
||||
dst = _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
status = _cairo_xlib_display_acquire (surface->base.device, &display);
|
||||
if (status)
|
||||
return _cairo_surface_create_in_error (status);
|
||||
|
||||
/* XXX: This should try to use the XShm extension if available */
|
||||
pixman_format = _pixman_format_for_xlib_surface (surface);
|
||||
if (try_shm && pixman_format) {
|
||||
image = (cairo_image_surface_t *)
|
||||
_cairo_xlib_surface_create_shm_image (surface, pixman_format,
|
||||
extents->width, extents->height);
|
||||
if (image && image->base.status == CAIRO_STATUS_SUCCESS) {
|
||||
cairo_xlib_error_func_t old_handler;
|
||||
XImage shm_image;
|
||||
Bool success;
|
||||
|
||||
_cairo_xlib_shm_surface_get_ximage (&image->base, &shm_image);
|
||||
|
||||
old_handler = XSetErrorHandler (_noop_error_handler);
|
||||
success = XShmGetImage (display->display,
|
||||
surface->drawable,
|
||||
&shm_image,
|
||||
extents->x, extents->y,
|
||||
AllPlanes);
|
||||
XSetErrorHandler (old_handler);
|
||||
|
||||
if (success)
|
||||
return &image->base;
|
||||
|
||||
cairo_surface_destroy (&image->base);
|
||||
}
|
||||
}
|
||||
|
||||
if (surface->use_pixmap == 0) {
|
||||
cairo_xlib_error_func_t old_handler;
|
||||
|
|
@ -793,19 +860,13 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
|
||||
_swap_ximage_to_native (ximage);
|
||||
|
||||
xlib_masks.bpp = ximage->bits_per_pixel;
|
||||
xlib_masks.alpha_mask = surface->a_mask;
|
||||
xlib_masks.red_mask = surface->r_mask;
|
||||
xlib_masks.green_mask = surface->g_mask;
|
||||
xlib_masks.blue_mask = surface->b_mask;
|
||||
|
||||
/* We can't use pixman to simply write to image if:
|
||||
* (a) the pixels are not appropriately aligned,
|
||||
* (b) pixman does not the pixel format, or
|
||||
* (c) if the image is palettized and we need to convert.
|
||||
*/
|
||||
if (ximage->bitmap_unit == 32 && ximage->bitmap_pad == 32 &&
|
||||
_pixman_format_from_masks (&xlib_masks, &pixman_format) &&
|
||||
if (pixman_format &&
|
||||
ximage->bitmap_unit == 32 && ximage->bitmap_pad == 32 &&
|
||||
(surface->visual == NULL || surface->visual->class == TrueColor))
|
||||
{
|
||||
image = (cairo_image_surface_t*)
|
||||
|
|
@ -1024,6 +1085,7 @@ _cairo_xlib_surface_draw_image (cairo_xlib_surface_t *surface,
|
|||
ximage.green_mask = surface->g_mask;
|
||||
ximage.blue_mask = surface->b_mask;
|
||||
ximage.xoffset = 0;
|
||||
ximage.obdata = NULL;
|
||||
|
||||
status = _cairo_xlib_display_acquire (surface->base.device, &display);
|
||||
if (unlikely (status))
|
||||
|
|
@ -1042,6 +1104,9 @@ _cairo_xlib_surface_draw_image (cairo_xlib_surface_t *surface,
|
|||
ximage.bits_per_pixel = image_masks.bpp;
|
||||
ximage.bytes_per_line = image->stride;
|
||||
ximage.data = (char *)image->data;
|
||||
ximage.obdata = NULL;
|
||||
if (image->base.device == surface->base.device)
|
||||
ximage.obdata = _cairo_xlib_shm_surface_get_obdata (&image->base);
|
||||
own_data = FALSE;
|
||||
|
||||
ret = XInitImage (&ximage);
|
||||
|
|
@ -1207,13 +1272,16 @@ _cairo_xlib_surface_draw_image (cairo_xlib_surface_t *surface,
|
|||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
XPutImage (display->display, surface->drawable, gc, &ximage,
|
||||
src_x, src_y, dst_x, dst_y, width, height);
|
||||
if (ximage.obdata)
|
||||
XShmPutImage (display->display, surface->drawable, gc, &ximage,
|
||||
src_x, src_y, dst_x, dst_y, width, height, TRUE);
|
||||
else
|
||||
XPutImage (display->display, surface->drawable, gc, &ximage,
|
||||
src_x, src_y, dst_x, dst_y, width, height);
|
||||
|
||||
_cairo_xlib_surface_put_gc (display, surface, gc);
|
||||
|
||||
BAIL:
|
||||
|
||||
cairo_device_release (&display->base);
|
||||
|
||||
if (own_data)
|
||||
|
|
@ -1247,12 +1315,18 @@ _cairo_xlib_surface_acquire_source_image (void *abstract_surf
|
|||
cairo_xlib_surface_t *surface = abstract_surface;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
*image_extra = NULL;
|
||||
*image_out = (cairo_image_surface_t *)
|
||||
_cairo_xlib_surface_get_shm (abstract_surface);
|
||||
if (*image_out)
|
||||
return (*image_out)->base.status;
|
||||
|
||||
extents.x = extents.y = 0;
|
||||
extents.width = surface->width;
|
||||
extents.height = surface->height;
|
||||
|
||||
*image_extra = NULL;
|
||||
*image_out = (cairo_image_surface_t*)_get_image_surface (surface, &extents);
|
||||
*image_out = (cairo_image_surface_t*)
|
||||
_get_image_surface (surface, &extents, TRUE);
|
||||
return (*image_out)->base.status;
|
||||
}
|
||||
|
||||
|
|
@ -1266,8 +1340,7 @@ _cairo_xlib_surface_snapshot (void *abstract_surface)
|
|||
extents.width = surface->width;
|
||||
extents.height = surface->height;
|
||||
|
||||
/* XXX notice the duplication with acquire source */
|
||||
return _get_image_surface (surface, &extents);
|
||||
return _get_image_surface (surface, &extents, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1275,6 +1348,11 @@ _cairo_xlib_surface_release_source_image (void *abstract_surfa
|
|||
cairo_image_surface_t *image,
|
||||
void *image_extra)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = abstract_surface;
|
||||
|
||||
if (&image->base == surface->shm)
|
||||
return;
|
||||
|
||||
cairo_surface_destroy (&image->base);
|
||||
}
|
||||
|
||||
|
|
@ -1282,9 +1360,17 @@ static cairo_image_surface_t *
|
|||
_cairo_xlib_surface_map_to_image (void *abstract_surface,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = abstract_surface;
|
||||
cairo_surface_t *image;
|
||||
|
||||
image = _get_image_surface (abstract_surface, extents);
|
||||
image = _cairo_xlib_surface_get_shm (abstract_surface);
|
||||
if (image) {
|
||||
assert (surface->base.damage);
|
||||
surface->fallback++;
|
||||
return _cairo_image_surface_map_to_image (image, extents);
|
||||
}
|
||||
|
||||
image = _get_image_surface (abstract_surface, extents, TRUE);
|
||||
cairo_surface_set_device_offset (image, -extents->x, -extents->y);
|
||||
|
||||
return (cairo_image_surface_t *) image;
|
||||
|
|
@ -1294,8 +1380,28 @@ static cairo_int_status_t
|
|||
_cairo_xlib_surface_unmap_image (void *abstract_surface,
|
||||
cairo_image_surface_t *image)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (surface->shm) {
|
||||
cairo_rectangle_int_t r;
|
||||
|
||||
assert (surface->fallback);
|
||||
assert (surface->base.damage);
|
||||
|
||||
r.x = image->base.device_transform_inverse.x0;
|
||||
r.y = image->base.device_transform_inverse.y0;
|
||||
r.width = image->width;
|
||||
r.height = image->height;
|
||||
|
||||
TRACE ((stderr, "%s: adding damage (%d,%d)x(%d,%d)\n",
|
||||
__FUNCTION__, r.x, r.y, r.width, r.height));
|
||||
surface->shm->damage =
|
||||
_cairo_damage_add_rectangle (surface->shm->damage, &r);
|
||||
|
||||
return _cairo_image_surface_unmap_image (surface->shm, image);
|
||||
}
|
||||
|
||||
status = _cairo_xlib_surface_draw_image (abstract_surface, image,
|
||||
0, 0,
|
||||
image->width, image->height,
|
||||
|
|
@ -1308,6 +1414,32 @@ _cairo_xlib_surface_unmap_image (void *abstract_surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_flush (void *abstract_surface,
|
||||
unsigned flags)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (flags)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_xlib_surface_put_shm (surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
surface->fallback >>= 1;
|
||||
if (surface->shm && _cairo_xlib_shm_surface_is_idle (surface->shm)) {
|
||||
cairo_surface_destroy (surface->shm);
|
||||
surface->shm = NULL;
|
||||
|
||||
_cairo_damage_destroy (surface->base.damage);
|
||||
surface->base.damage = NULL;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_xlib_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
|
|
@ -1332,6 +1464,31 @@ _cairo_xlib_surface_get_font_options (void *abstract_surface,
|
|||
*options = *_cairo_xlib_screen_get_font_options (surface->screen);
|
||||
}
|
||||
|
||||
static inline cairo_int_status_t
|
||||
get_compositor (cairo_xlib_surface_t **surface,
|
||||
const cairo_compositor_t **compositor)
|
||||
{
|
||||
cairo_xlib_surface_t *s = *surface;
|
||||
cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;;
|
||||
|
||||
if (s->fallback) {
|
||||
assert (s->base.damage != NULL);
|
||||
assert (s->shm != NULL);
|
||||
assert (s->shm->damage != NULL);
|
||||
if (! _cairo_xlib_shm_surface_is_active (s->shm)) {
|
||||
*surface = (cairo_xlib_surface_t *) s->shm;
|
||||
*compositor = ((cairo_image_surface_t *) s->shm)->compositor;
|
||||
s->fallback++;
|
||||
} else {
|
||||
status = _cairo_xlib_surface_put_shm (s);
|
||||
s->fallback = 0;
|
||||
*compositor = s->compositor;
|
||||
}
|
||||
} else
|
||||
*compositor = s->compositor;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_surface_paint (void *_surface,
|
||||
|
|
@ -1340,8 +1497,15 @@ _cairo_xlib_surface_paint (void *_surface,
|
|||
const cairo_clip_t *clip)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = _surface;
|
||||
return _cairo_compositor_paint (surface->compositor,
|
||||
&surface->base, op, source,
|
||||
const cairo_compositor_t *compositor;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = get_compositor (&surface, &compositor);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return _cairo_compositor_paint (compositor, &surface->base,
|
||||
op, source,
|
||||
clip);
|
||||
}
|
||||
|
||||
|
|
@ -1353,8 +1517,15 @@ _cairo_xlib_surface_mask (void *_surface,
|
|||
const cairo_clip_t *clip)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = _surface;
|
||||
return _cairo_compositor_mask (surface->compositor,
|
||||
&surface->base, op, source, mask,
|
||||
const cairo_compositor_t *compositor;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = get_compositor (&surface, &compositor);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return _cairo_compositor_mask (compositor, &surface->base,
|
||||
op, source, mask,
|
||||
clip);
|
||||
}
|
||||
|
||||
|
|
@ -1371,8 +1542,15 @@ _cairo_xlib_surface_stroke (void *_surface,
|
|||
const cairo_clip_t *clip)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = _surface;
|
||||
return _cairo_compositor_stroke (surface->compositor,
|
||||
&surface->base, op, source,
|
||||
const cairo_compositor_t *compositor;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = get_compositor (&surface, &compositor);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return _cairo_compositor_stroke (compositor, &surface->base,
|
||||
op, source,
|
||||
path, style, ctm, ctm_inverse,
|
||||
tolerance, antialias,
|
||||
clip);
|
||||
|
|
@ -1389,8 +1567,15 @@ _cairo_xlib_surface_fill (void *_surface,
|
|||
const cairo_clip_t *clip)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = _surface;
|
||||
return _cairo_compositor_fill (surface->compositor,
|
||||
&surface->base, op, source,
|
||||
const cairo_compositor_t *compositor;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = get_compositor (&surface, &compositor);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return _cairo_compositor_fill (compositor, &surface->base,
|
||||
op, source,
|
||||
path, fill_rule, tolerance, antialias,
|
||||
clip);
|
||||
}
|
||||
|
|
@ -1405,8 +1590,15 @@ _cairo_xlib_surface_glyphs (void *_surface,
|
|||
const cairo_clip_t *clip)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = _surface;
|
||||
return _cairo_compositor_glyphs (surface->compositor,
|
||||
&surface->base, op, source,
|
||||
const cairo_compositor_t *compositor;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = get_compositor (&surface, &compositor);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return _cairo_compositor_glyphs (compositor, &surface->base,
|
||||
op, source,
|
||||
glyphs, num_glyphs, scaled_font,
|
||||
clip);
|
||||
}
|
||||
|
|
@ -1418,7 +1610,7 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = {
|
|||
_cairo_default_context_create,
|
||||
|
||||
_cairo_xlib_surface_create_similar,
|
||||
NULL, //_cairo_xlib_surface_create_similar_image, /* XXX shm */
|
||||
_cairo_xlib_surface_create_similar_shm,
|
||||
_cairo_xlib_surface_map_to_image,
|
||||
_cairo_xlib_surface_unmap_image,
|
||||
|
||||
|
|
@ -1433,7 +1625,7 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = {
|
|||
_cairo_xlib_surface_get_extents,
|
||||
_cairo_xlib_surface_get_font_options,
|
||||
|
||||
NULL, /* flush */
|
||||
_cairo_xlib_surface_flush,
|
||||
NULL, /* mark_dirty_rectangle */
|
||||
|
||||
_cairo_xlib_surface_paint,
|
||||
|
|
@ -1539,6 +1731,8 @@ found:
|
|||
|
||||
surface->screen = screen;
|
||||
surface->compositor = display->compositor;
|
||||
surface->shm = NULL;
|
||||
surface->fallback = 0;
|
||||
|
||||
surface->drawable = drawable;
|
||||
surface->owns_pixmap = FALSE;
|
||||
|
|
@ -1830,6 +2024,7 @@ cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
|
|||
int height)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
if (unlikely (abstract_surface->status))
|
||||
return;
|
||||
|
|
@ -1851,6 +2046,12 @@ cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
|
|||
return;
|
||||
}
|
||||
|
||||
status = _cairo_surface_begin_modification (abstract_surface);
|
||||
if (unlikely (status)) {
|
||||
_cairo_surface_set_error (abstract_surface, status);
|
||||
return;
|
||||
}
|
||||
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
}
|
||||
|
|
@ -1903,7 +2104,13 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
|
|||
if (surface->owns_pixmap)
|
||||
return;
|
||||
|
||||
if (surface->drawable != drawable) {
|
||||
status = _cairo_surface_begin_modification (abstract_surface);
|
||||
if (unlikely (status)) {
|
||||
_cairo_surface_set_error (abstract_surface, status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (surface->drawable == drawable) {
|
||||
cairo_xlib_display_t *display;
|
||||
|
||||
status = _cairo_xlib_display_acquire (surface->base.device, &display);
|
||||
|
|
@ -1926,6 +2133,7 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
|
|||
|
||||
surface->drawable = drawable;
|
||||
}
|
||||
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,12 +249,11 @@ _cairo_xlib_xcb_surface_glyphs (void *abstract_surface,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_xcb_surface_flush (void *abstract_surface)
|
||||
_cairo_xlib_xcb_surface_flush (void *abstract_surface, unsigned flags)
|
||||
{
|
||||
cairo_xlib_xcb_surface_t *surface = abstract_surface;
|
||||
/* We have to call cairo_surface_flush() to make sure snapshots are detached */
|
||||
cairo_surface_flush (&surface->xcb->base);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return _cairo_surface_flush (&surface->xcb->base, flags);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
|
|||
|
|
@ -1394,7 +1394,7 @@ _cairo_surface_has_snapshot (cairo_surface_t *surface,
|
|||
cairo_private void
|
||||
_cairo_surface_detach_snapshot (cairo_surface_t *snapshot);
|
||||
|
||||
cairo_private void
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_begin_modification (cairo_surface_t *surface);
|
||||
|
||||
cairo_private_no_warn cairo_bool_t
|
||||
|
|
|
|||
|
|
@ -314,12 +314,16 @@ gallium_surface_release_source_image (void *abstract_surface,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
gallium_surface_flush (void *abstract_surface)
|
||||
gallium_surface_flush (void *abstract_surface,
|
||||
unsigned flags)
|
||||
{
|
||||
gallium_surface_t *surface = abstract_surface;
|
||||
gallium_device_t *device = gallium_device (surface);
|
||||
cairo_status_t status;
|
||||
|
||||
if (flags)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (surface->fallback == NULL) {
|
||||
device->pipe->flush (device->pipe,
|
||||
PIPE_FLUSH_RENDER_CACHE,
|
||||
|
|
|
|||
|
|
@ -1258,7 +1258,7 @@ i915_surface_fallback_flush (i915_surface_t *surface)
|
|||
cairo_status_t status;
|
||||
|
||||
if (unlikely (surface->intel.drm.fallback != NULL))
|
||||
return intel_surface_flush (&surface->intel);
|
||||
return intel_surface_flush (&surface->intel, 0);
|
||||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
if (unlikely (surface->deferred_clear))
|
||||
|
|
|
|||
|
|
@ -716,11 +716,15 @@ i915_surface_batch_flush (i915_surface_t *surface)
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
i915_surface_flush (void *abstract_surface)
|
||||
i915_surface_flush (void *abstract_surface,
|
||||
unsigned flags)
|
||||
{
|
||||
i915_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
if (flags)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (surface->intel.drm.fallback == NULL) {
|
||||
if (surface->intel.drm.base.finished) {
|
||||
/* Forgo flushing on finish as the user cannot access the surface directly. */
|
||||
|
|
@ -736,7 +740,7 @@ i915_surface_flush (void *abstract_surface)
|
|||
return i915_surface_batch_flush (surface);
|
||||
}
|
||||
|
||||
return intel_surface_flush (abstract_surface);
|
||||
return intel_surface_flush (abstract_surface, flags);
|
||||
}
|
||||
|
||||
/* rasterisation */
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@ i965_shader_acquire_surface (i965_shader_t *shader,
|
|||
int x;
|
||||
|
||||
if (s->intel.drm.fallback != NULL) {
|
||||
status = intel_surface_flush (s);
|
||||
status = intel_surface_flush (s, 0);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
|
@ -489,7 +489,7 @@ i965_shader_acquire_surface (i965_shader_t *shader,
|
|||
if (s->intel.drm.base.device == shader->target->intel.drm.base.device) {
|
||||
if (s != shader->target) {
|
||||
if (s->intel.drm.fallback != NULL) {
|
||||
status = intel_surface_flush (s);
|
||||
status = intel_surface_flush (s, 0);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -695,11 +695,14 @@ i965_surface_finish (void *abstract_surface)
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
i965_surface_flush (void *abstract_surface)
|
||||
i965_surface_flush (void *abstract_surface, unsigned flags)
|
||||
{
|
||||
i965_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (flags)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (surface->intel.drm.fallback != NULL)
|
||||
return intel_surface_flush (abstract_surface);
|
||||
|
||||
|
|
|
|||
|
|
@ -394,7 +394,8 @@ cairo_private cairo_surface_t *
|
|||
intel_surface_map_to_image (void *abstract_surface);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
intel_surface_flush (void *abstract_surface);
|
||||
intel_surface_flush (void *abstract_surface,
|
||||
unsigned flags);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
intel_surface_finish (void *abstract_surface);
|
||||
|
|
|
|||
|
|
@ -157,11 +157,14 @@ intel_surface_map_to_image (void *abstract_surface)
|
|||
}
|
||||
|
||||
cairo_status_t
|
||||
intel_surface_flush (void *abstract_surface)
|
||||
intel_surface_flush (void *abstract_surface, unsigned flags)
|
||||
{
|
||||
intel_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
if (flags)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (surface->drm.fallback == NULL)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
|
|||
|
|
@ -159,11 +159,15 @@ radeon_surface_map_to_image (radeon_surface_t *surface)
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
radeon_surface_flush (void *abstract_surface)
|
||||
radeon_surface_flush (void *abstract_surface,
|
||||
unsigned flags)
|
||||
{
|
||||
radeon_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
if (flags)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (surface->base.fallback == NULL)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
|
|||
|
|
@ -503,11 +503,14 @@ _cairo_win32_display_surface_unmap_image (void *abstract_surf
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_display_surface_flush (void *abstract_surface)
|
||||
_cairo_win32_display_surface_flush (void *abstract_surface, unsigned flags)
|
||||
{
|
||||
cairo_win32_display_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (flags)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
TRACE ((stderr, "%s (surface=%d)\n",
|
||||
__FUNCTION__, surface->win32.base.unique_id));
|
||||
if (surface->fallback == NULL)
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ copy_boxes (cairo_win32_display_surface_t *dst,
|
|||
if (! _cairo_boxes_for_each_box (boxes, source_contains_box, &cb))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_surface_flush (surface);
|
||||
status = __cairo_surface_flush (surface, 0);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
|
@ -360,7 +360,7 @@ alpha_blend_boxes (cairo_win32_display_surface_t *dst,
|
|||
if (! _cairo_boxes_for_each_box (boxes, source_contains_box, &cb))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_surface_flush (&src->win32.base);
|
||||
status = __cairo_surface_flush (&src->win32.base, 0);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue