Add cairo_device_t

The device is a generic method for accessing the underlying interface
with the native graphics subsystem, typically the X connection or
perhaps the GL context. By exposing a cairo_device_t on a surface and
its various methods we enable finer control over interoperability with
external interactions of the device by applications. The use case in
mind is, for example, a multi-threaded gstreamer which needs to serialise
its own direct access to the device along with Cairo's across many
threads.

Secondly, the cairo_device_t is a unifying API for the mismash of
backend specific methods for controlling creation of surfaces with
explicit devices and a convenient hook for debugging and introspection.

The principal components of the API are the memory management of:

  cairo_device_reference(),
  cairo_device_finish() and
  cairo_device_destroy();

along with a pair of routines for serialising interaction:

  cairo_device_acquire() and
  cairo_device_release()

and a method to flush any outstanding accesses:

  cairo_device_flush().

The device for a particular surface may be retrieved using:

  cairo_surface_get_device().

The device returned is owned by the surface.
This commit is contained in:
Chris Wilson 2010-01-18 21:53:42 +00:00
parent 82f8aa548d
commit f617d5fc98
46 changed files with 607 additions and 24 deletions

View file

@ -59,6 +59,7 @@ cairo_private = \
cairo-clip-private.h \
cairo-combsort-private.h \
cairo-compiler-private.h \
cairo-device-private.h \
cairo-error-private.h \
cairo-fixed-private.h \
cairo-fixed-type-private.h \
@ -114,6 +115,7 @@ cairo_sources = \
cairo-clip.c \
cairo-color.c \
cairo-debug.c \
cairo-device.c \
cairo-fixed.c \
cairo-font-face.c \
cairo-font-face-twin.c \

View file

@ -717,7 +717,9 @@ _cairo_analysis_surface_create (cairo_surface_t *target)
/* I believe the content type here is truly arbitrary. I'm quite
* sure nothing will ever use this value. */
_cairo_surface_init (&surface->base, &cairo_analysis_surface_backend,
_cairo_surface_init (&surface->base,
&cairo_analysis_surface_backend,
NULL, /* device */
CAIRO_CONTENT_COLOR_ALPHA);
cairo_matrix_init_identity (&surface->ctm);
@ -907,7 +909,10 @@ _cairo_null_surface_create (cairo_content_t content)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
_cairo_surface_init (surface, &cairo_null_surface_backend, content);
_cairo_surface_init (surface,
&cairo_null_surface_backend,
NULL, /* device */
content);
return surface;
}

View file

@ -915,7 +915,10 @@ _cairo_beos_surface_create_internal (BView* view,
cairo_content_t content = CAIRO_CONTENT_COLOR;
if (bmp && (bmp->ColorSpace() == B_RGBA32 || bmp->ColorSpace() == B_RGBA15))
content = CAIRO_CONTENT_COLOR_ALPHA;
_cairo_surface_init(&surface->base, &cairo_beos_surface_backend, content);
_cairo_surface_init (&surface->base,
&cairo_beos_surface_backend,
NULL, /* device */
content);
surface->view = view;
surface->bitmap = bmp;

View file

@ -0,0 +1,85 @@
/* Cairo - a vector graphics library with display and print output
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Intel Corporation.
*
* Contributors(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#ifndef _CAIRO_DEVICE_PRIVATE_H_
#define _CAIRO_DEVICE_PRIVATE_H_
#include "cairo-compiler-private.h"
#include "cairo-mutex-private.h"
#include "cairo-reference-count-private.h"
#include "cairo-types-private.h"
struct _cairo_device {
cairo_reference_count_t ref_count;
cairo_status_t status;
const cairo_device_backend_t *backend;
cairo_recursive_mutex_t mutex;
unsigned mutex_depth;
cairo_bool_t finished;
};
struct _cairo_device_backend {
cairo_device_type_t type;
void (*lock) (void *device);
void (*unlock) (void *device);
void (*flush) (void *device);
void (*finish) (void *device);
void (*destroy) (void *device);
};
cairo_private cairo_device_t *
_cairo_device_create_in_error (cairo_status_t status);
cairo_private void
_cairo_device_init (cairo_device_t *device,
const cairo_device_backend_t *backend);
cairo_private cairo_status_t
_cairo_device_set_error (cairo_device_t *device,
cairo_status_t error);
slim_hidden_proto_no_warn (cairo_device_reference);
slim_hidden_proto (cairo_device_acquire);
slim_hidden_proto (cairo_device_release);
slim_hidden_proto (cairo_device_flush);
slim_hidden_proto (cairo_device_finish);
slim_hidden_proto (cairo_device_destroy);
#endif /* _CAIRO_DEVICE_PRIVATE_H_ */

265
src/cairo-device.c Normal file
View file

@ -0,0 +1,265 @@
/* Cairo - a vector graphics library with display and print output
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Intel Corporation.
*
* Contributors(s):
* Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairoint.h"
#include "cairo-device-private.h"
#include "cairo-error-private.h"
static const cairo_device_t _nil_device = {
CAIRO_REFERENCE_COUNT_INVALID,
CAIRO_STATUS_NO_MEMORY,
};
static const cairo_device_t _mismatch_device = {
CAIRO_REFERENCE_COUNT_INVALID,
CAIRO_STATUS_DEVICE_TYPE_MISMATCH,
};
static const cairo_device_t _invalid_device = {
CAIRO_REFERENCE_COUNT_INVALID,
CAIRO_STATUS_DEVICE_ERROR,
};
cairo_device_t *
_cairo_device_create_in_error (cairo_status_t status)
{
switch (status) {
case CAIRO_STATUS_NO_MEMORY:
return (cairo_device_t *) &_nil_device;
case CAIRO_STATUS_DEVICE_ERROR:
return (cairo_device_t *) &_invalid_device;
case CAIRO_STATUS_DEVICE_TYPE_MISMATCH:
return (cairo_device_t *) &_mismatch_device;
case CAIRO_STATUS_SUCCESS:
case CAIRO_STATUS_LAST_STATUS:
ASSERT_NOT_REACHED;
/* fall-through */
case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
case CAIRO_STATUS_INVALID_STATUS:
case CAIRO_STATUS_INVALID_FORMAT:
case CAIRO_STATUS_INVALID_VISUAL:
case CAIRO_STATUS_READ_ERROR:
case CAIRO_STATUS_WRITE_ERROR:
case CAIRO_STATUS_FILE_NOT_FOUND:
case CAIRO_STATUS_TEMP_FILE_ERROR:
case CAIRO_STATUS_INVALID_STRIDE:
case CAIRO_STATUS_INVALID_SIZE:
case CAIRO_STATUS_INVALID_RESTORE:
case CAIRO_STATUS_INVALID_POP_GROUP:
case CAIRO_STATUS_NO_CURRENT_POINT:
case CAIRO_STATUS_INVALID_MATRIX:
case CAIRO_STATUS_NULL_POINTER:
case CAIRO_STATUS_INVALID_STRING:
case CAIRO_STATUS_INVALID_PATH_DATA:
case CAIRO_STATUS_SURFACE_FINISHED:
case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
case CAIRO_STATUS_INVALID_DASH:
case CAIRO_STATUS_INVALID_DSC_COMMENT:
case CAIRO_STATUS_INVALID_INDEX:
case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
case CAIRO_STATUS_FONT_TYPE_MISMATCH:
case CAIRO_STATUS_USER_FONT_IMMUTABLE:
case CAIRO_STATUS_USER_FONT_ERROR:
case CAIRO_STATUS_NEGATIVE_COUNT:
case CAIRO_STATUS_INVALID_CLUSTERS:
case CAIRO_STATUS_INVALID_SLANT:
case CAIRO_STATUS_INVALID_WEIGHT:
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
case CAIRO_STATUS_INVALID_CONTENT:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_device_t *) &_nil_device;
}
}
void
_cairo_device_init (cairo_device_t *device,
const cairo_device_backend_t *backend)
{
CAIRO_REFERENCE_COUNT_INIT (&device->ref_count, 1);
device->status = CAIRO_STATUS_SUCCESS;
device->backend = backend;
CAIRO_RECURSIVE_MUTEX_INIT (device->mutex);
device->mutex_depth = 0;
device->finished = FALSE;
}
cairo_device_t *
cairo_device_reference (cairo_device_t *device)
{
if (device == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
{
return device;
}
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
_cairo_reference_count_inc (&device->ref_count);
return device;
}
slim_hidden_def (cairo_device_reference);
cairo_status_t
cairo_device_status (cairo_device_t *device)
{
if (device == NULL)
return CAIRO_STATUS_NULL_POINTER;
return device->status;
}
void
cairo_device_flush (cairo_device_t *device)
{
if (device == NULL || device->status)
return;
if (device->backend->flush != NULL)
device->backend->flush (device);
}
slim_hidden_def (cairo_device_flush);
void
cairo_device_finish (cairo_device_t *device)
{
if (device == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
{
return;
}
if (device->finished)
return;
device->finished = TRUE;
cairo_device_flush (device);
if (device->backend->finish != NULL)
device->backend->finish (device);
}
slim_hidden_def (cairo_device_finish);
void
cairo_device_destroy (cairo_device_t *device)
{
if (device == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
{
return;
}
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
if (! _cairo_reference_count_dec_and_test (&device->ref_count))
return;
cairo_device_finish (device);
assert (device->mutex_depth == 0);
CAIRO_MUTEX_FINI (device->mutex);
device->backend->destroy (device);
}
slim_hidden_def (cairo_device_destroy);
cairo_device_type_t
cairo_device_get_type (cairo_device_t *device)
{
if (device == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
{
return (cairo_device_type_t) -1;
}
return device->backend->type;
}
cairo_status_t
cairo_device_acquire (cairo_device_t *device)
{
if (device == NULL)
return CAIRO_STATUS_SUCCESS;
if (unlikely (device->status))
return device->status;
if (unlikely (device->finished))
return _cairo_device_set_error (device, CAIRO_STATUS_SURFACE_FINISHED); /* XXX */
CAIRO_MUTEX_LOCK (device->mutex);
if (device->mutex_depth++ == 0) {
if (device->backend->lock != NULL)
device->backend->lock (device);
}
return CAIRO_STATUS_SUCCESS;
}
slim_hidden_def (cairo_device_acquire);
void
cairo_device_release (cairo_device_t *device)
{
if (device == NULL)
return;
assert (device->mutex_depth > 0);
if (--device->mutex_depth == 0) {
if (device->backend->unlock != NULL)
device->backend->unlock (device);
}
CAIRO_MUTEX_UNLOCK (device->mutex);
}
slim_hidden_def (cairo_device_release);
cairo_status_t
_cairo_device_set_error (cairo_device_t *device,
cairo_status_t status)
{
if (status == CAIRO_STATUS_SUCCESS || status >= CAIRO_INT_STATUS_UNSUPPORTED)
return status;
/* Don't overwrite an existing error. This preserves the first
* error, which is the most significant. */
_cairo_status_set_error (&device->status, status);
return _cairo_error (status);
}

View file

@ -565,6 +565,7 @@ _cairo_directfb_surface_create_internal (IDirectFB *dfb,
_cairo_surface_init (&surface->base,
&_cairo_directfb_surface_backend,
NULL, /* device */
content);
surface->pixman_format = _directfb_to_pixman_format (format);
surface->supported_destination = pixman_format_supported_destination (surface->pixman_format);
@ -1956,6 +1957,7 @@ cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface)
_cairo_surface_init (&surface->base,
&_cairo_directfb_surface_backend,
NULL, /* device */
_directfb_format_to_content (format));
return &surface->base;

View file

@ -462,6 +462,7 @@ _cairo_gl_surface_init (cairo_gl_context_t *ctx,
{
_cairo_surface_init (&surface->base,
&_cairo_gl_surface_backend,
NULL, /* device */
content);
surface->ctx = cairo_gl_context_reference (ctx);

View file

@ -2430,7 +2430,9 @@ cairo_glitz_surface_create (glitz_surface_t *surface)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
format = glitz_surface_get_format (surface);
_cairo_surface_init (&crsurface->base, &cairo_glitz_surface_backend,
_cairo_surface_init (&crsurface->base,
&cairo_glitz_surface_backend,
NULL, /* device */
_glitz_format_to_content (format));
glitz_surface_reference (surface);

View file

@ -176,7 +176,9 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_surface_init (&surface->base, &_cairo_image_surface_backend,
_cairo_surface_init (&surface->base,
&_cairo_image_surface_backend,
NULL, /* device */
_cairo_content_from_pixman_format (pixman_format));
surface->pixman_image = pixman_image;

View file

@ -126,6 +126,10 @@ cairo_status_to_string (cairo_status_t status)
return "invalid value (typically too big) for the size of the input (surface, pattern, etc.)";
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
return "user-font method not implemented";
case CAIRO_STATUS_DEVICE_TYPE_MISMATCH:
return "the device type is not appropriate for the operation";
case CAIRO_STATUS_DEVICE_ERROR:
return "an operation to the device caused an unspecified error";
default:
case CAIRO_STATUS_LAST_STATUS:
return "<unknown error status>";

View file

@ -845,6 +845,7 @@ cairo_os2_surface_create (HPS hps_client_window,
/* Initialize base surface */
_cairo_surface_init (&local_os2_surface->base,
&cairo_os2_surface_backend,
NULL, /* device */
_cairo_content_from_format (CAIRO_FORMAT_ARGB32));
return (cairo_surface_t *)local_os2_surface;

View file

@ -102,7 +102,9 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
goto FAIL;
}
_cairo_surface_init (&surface->base, &cairo_paginated_surface_backend,
_cairo_surface_init (&surface->base,
&cairo_paginated_surface_backend,
NULL, /* device */
content);
/* Override surface->base.type with target's type so we don't leak

View file

@ -304,7 +304,9 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
_cairo_surface_init (&surface->base, &cairo_pdf_surface_backend,
_cairo_surface_init (&surface->base,
&cairo_pdf_surface_backend,
NULL, /* device */
CAIRO_CONTENT_COLOR_ALPHA);
surface->output = output;

View file

@ -910,7 +910,9 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
goto CLEANUP;
}
_cairo_surface_init (&surface->base, &cairo_ps_surface_backend,
_cairo_surface_init (&surface->base,
&cairo_ps_surface_backend,
NULL, /* device */
CAIRO_CONTENT_COLOR_ALPHA);
surface->final_stream = stream;

View file

@ -1697,6 +1697,7 @@ cairo_qt_surface_create (QPainter *painter)
_cairo_surface_init (&qs->base,
&cairo_qt_surface_backend,
NULL, /* device */
CAIRO_CONTENT_COLOR_ALPHA);
_cairo_surface_clipper_init (&qs->clipper,
@ -1739,6 +1740,7 @@ cairo_qt_surface_create_with_qimage (cairo_format_t format,
_cairo_surface_init (&qs->base,
&cairo_qt_surface_backend,
NULL, /* device */
_cairo_content_from_format (format));
_cairo_surface_clipper_init (&qs->clipper,
@ -1797,7 +1799,10 @@ cairo_qt_surface_create_with_qpixmap (cairo_content_t content,
if (content == CAIRO_CONTENT_COLOR_ALPHA)
pixmap->fill(Qt::transparent);
_cairo_surface_init (&qs->base, &cairo_qt_surface_backend, content);
_cairo_surface_init (&qs->base,
&cairo_qt_surface_backend,
NULL, /* device */
content);
_cairo_surface_clipper_init (&qs->clipper,
_cairo_qt_surface_clipper_intersect_clip_path);

View file

@ -260,6 +260,7 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface)
_cairo_surface_init (&qisurf->base,
&cairo_quartz_image_surface_backend,
NULL, /* device */
_cairo_content_from_format (format));
qisurf->extents.x = qisurf->extents.y = 0;

View file

@ -2611,8 +2611,10 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
memset(surface, 0, sizeof(cairo_quartz_surface_t));
_cairo_surface_init(&surface->base, &cairo_quartz_surface_backend,
content);
_cairo_surface_init (&surface->base,
&cairo_quartz_surface_backend,
NULL, /* device */
content);
_cairo_surface_clipper_init (&surface->clipper,
_cairo_quartz_surface_clipper_intersect_clip_path);

View file

@ -123,7 +123,10 @@ cairo_recording_surface_create (cairo_content_t content,
if (unlikely (recording_surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_surface_init (&recording_surface->base, &cairo_recording_surface_backend, content);
_cairo_surface_init (&recording_surface->base,
&cairo_recording_surface_backend,
NULL, /* device */
content);
recording_surface->content = content;
@ -616,7 +619,9 @@ _cairo_recording_surface_snapshot (void *abstract_other)
if (unlikely (recording_surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_surface_init (&recording_surface->base, &cairo_recording_surface_backend,
_cairo_surface_init (&recording_surface->base,
&cairo_recording_surface_backend,
NULL, /* device */
other->base.content);
recording_surface->extents_pixels = other->extents_pixels;

View file

@ -3257,6 +3257,7 @@ _cairo_script_surface_create_internal (cairo_script_context_t *ctx,
_cairo_surface_init (&surface->base,
&_cairo_script_surface_backend,
NULL, /* device */
content);
_cairo_surface_wrapper_init (&surface->wrapper, passthrough);

View file

@ -1027,6 +1027,7 @@ _cairo_skia_surface_create_internal (SkBitmap::Config config,
_cairo_surface_init (&surface->base,
&cairo_skia_surface_backend,
NULL, /* device */
_cairo_content_from_format (format));
_cairo_surface_clipper_init (&surface->clipper,

View file

@ -266,6 +266,8 @@ _cairo_scan_converter_create_in_error (cairo_status_t status)
case CAIRO_STATUS_NO_MEMORY: RETURN_NIL;
case CAIRO_STATUS_INVALID_SIZE: RETURN_NIL;
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED: RETURN_NIL;
case CAIRO_STATUS_DEVICE_TYPE_MISMATCH: RETURN_NIL;
case CAIRO_STATUS_DEVICE_ERROR: RETURN_NIL;
default:
break;
}
@ -372,6 +374,8 @@ _cairo_span_renderer_create_in_error (cairo_status_t status)
case CAIRO_STATUS_NO_MEMORY: RETURN_NIL;
case CAIRO_STATUS_INVALID_SIZE: RETURN_NIL;
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED: RETURN_NIL;
case CAIRO_STATUS_DEVICE_TYPE_MISMATCH: RETURN_NIL;
case CAIRO_STATUS_DEVICE_ERROR: RETURN_NIL;
default:
break;
}

View file

@ -48,6 +48,7 @@ typedef void (*cairo_surface_func_t) (cairo_surface_t *);
struct _cairo_surface {
const cairo_surface_backend_t *backend;
cairo_device_t *device;
/* We allow surfaces to override the backend->type by shoving something
* else into surface->type. This is for "wrapper" surfaces that want to

View file

@ -199,6 +199,7 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
_cairo_surface_init (&snapshot->base,
&_cairo_surface_snapshot_backend,
NULL, /* device */
surface->content);
snapshot->target = surface;

View file

@ -451,6 +451,7 @@ cairo_surface_create_for_region (cairo_surface_t *target,
_cairo_surface_init (&surface->base,
&_cairo_surface_subsurface_backend,
NULL, /* device */
target->content);
surface->base.type = target->type;

View file

@ -40,6 +40,7 @@
#include "cairo-surface-fallback-private.h"
#include "cairo-clip-private.h"
#include "cairo-device-private.h"
#include "cairo-error-private.h"
#include "cairo-recording-surface-private.h"
#include "cairo-region-private.h"
@ -48,6 +49,7 @@
#define DEFINE_NIL_SURFACE(status, name) \
const cairo_surface_t name = { \
NULL, /* backend */ \
NULL, /* device */ \
CAIRO_SURFACE_TYPE_IMAGE, /* type */ \
CAIRO_CONTENT_COLOR, /* content */ \
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ \
@ -92,6 +94,8 @@ static DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error
static DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_STRIDE, _cairo_surface_nil_invalid_stride);
static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_SIZE, _cairo_surface_nil_invalid_size);
static DEFINE_NIL_SURFACE(CAIRO_STATUS_DEVICE_TYPE_MISMATCH, _cairo_surface_nil_device_type_mismatch);
static DEFINE_NIL_SURFACE(CAIRO_STATUS_DEVICE_ERROR, _cairo_surface_nil_device_error);
/**
* _cairo_surface_set_error:
@ -210,6 +214,23 @@ _cairo_surface_allocate_unique_id (void)
#endif
}
/**
* cairo_surface_get_device:
* @surface: a #cairo_surface_t
*
* This function returns the device for a @surface.
* See #cairo_device_t.
*
* Return value: The device for @surface.
*
* Since: 1.10
**/
cairo_device_t *
cairo_surface_get_device (cairo_surface_t *surface)
{
return surface->device;
}
static cairo_bool_t
_cairo_surface_has_snapshots (cairo_surface_t *surface)
{
@ -330,11 +351,13 @@ _cairo_surface_begin_modification (cairo_surface_t *surface)
void
_cairo_surface_init (cairo_surface_t *surface,
const cairo_surface_backend_t *backend,
cairo_device_t *device,
cairo_content_t content)
{
CAIRO_MUTEX_INITIALIZE ();
surface->backend = backend;
surface->device = cairo_device_reference (device);
surface->content = content;
surface->type = backend->type;
@ -579,6 +602,8 @@ cairo_surface_destroy (cairo_surface_t *surface)
/* paranoid check that nobody took a reference whilst finishing */
assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count));
cairo_device_destroy (surface->device);
_cairo_user_data_array_fini (&surface->user_data);
_cairo_user_data_array_fini (&surface->mime_data);
_cairo_array_fini (&surface->snapshots);
@ -2931,6 +2956,10 @@ _cairo_surface_create_in_error (cairo_status_t status)
return (cairo_surface_t *) &_cairo_surface_nil_invalid_stride;
case CAIRO_STATUS_INVALID_SIZE:
return (cairo_surface_t *) &_cairo_surface_nil_invalid_size;
case CAIRO_STATUS_DEVICE_TYPE_MISMATCH:
return (cairo_surface_t *) &_cairo_surface_nil_device_type_mismatch;
case CAIRO_STATUS_DEVICE_ERROR:
return (cairo_surface_t *) &_cairo_surface_nil_device_error;
case CAIRO_STATUS_SUCCESS:
case CAIRO_STATUS_LAST_STATUS:
ASSERT_NOT_REACHED;

View file

@ -416,7 +416,9 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_surface_init (&surface->base, &cairo_svg_surface_backend,
_cairo_surface_init (&surface->base,
&cairo_svg_surface_backend,
NULL, /* device */
content);
surface->width = width;

View file

@ -444,6 +444,7 @@ cairo_tee_surface_create (cairo_surface_t *master)
_cairo_surface_init (&surface->base,
&cairo_tee_surface_backend,
master->device,
master->content);
_cairo_surface_wrapper_init (&surface->master, master);

View file

@ -84,7 +84,9 @@ _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_surface_init (&surface->base, &cairo_type3_glyph_surface_backend,
_cairo_surface_init (&surface->base,
&cairo_type3_glyph_surface_backend,
NULL, /* device */
CAIRO_CONTENT_COLOR_ALPHA);
surface->scaled_font = scaled_font;

View file

@ -50,6 +50,7 @@ typedef struct _cairo_cache cairo_cache_t;
typedef struct _cairo_clip cairo_clip_t;
typedef struct _cairo_clip_path cairo_clip_path_t;
typedef struct _cairo_color cairo_color_t;
typedef struct _cairo_device_backend cairo_device_backend_t;
typedef struct _cairo_font_face_backend cairo_font_face_backend_t;
typedef struct _cairo_gstate cairo_gstate_t;
typedef struct _cairo_hash_entry cairo_hash_entry_t;

View file

@ -1606,6 +1606,7 @@ _vg_surface_create_internal (cairo_vg_context_t *context,
_cairo_surface_init (&surface->base,
&cairo_vg_surface_backend,
NULL, /* device */
_vg_format_to_content (format));
surface->width = width;

View file

@ -1807,6 +1807,7 @@ cairo_win32_printing_surface_create (HDC hdc)
_cairo_win32_printing_surface_init_language_pack (surface);
_cairo_surface_init (&surface->base,
&cairo_win32_printing_surface_backend,
NULL, /* device */
CAIRO_CONTENT_COLOR_ALPHA);
paginated = _cairo_paginated_surface_create (&surface->base,

View file

@ -367,7 +367,9 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
surface->extents = surface->clip_rect;
surface->font_subsets = NULL;
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend,
_cairo_surface_init (&surface->base,
&cairo_win32_surface_backend,
NULL, /* device */
_cairo_content_from_format (format));
return &surface->base;
@ -1676,7 +1678,9 @@ cairo_win32_surface_create (HDC hdc)
surface->flags = _cairo_win32_flags_for_dc (surface->dc);
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend,
_cairo_surface_init (&surface->base,
&cairo_win32_surface_backend,
NULL, /* device */
_cairo_content_from_format (format));
return (cairo_surface_t *)surface;

View file

@ -2041,7 +2041,9 @@ _cairo_xcb_surface_create_internal (xcb_connection_t *dpy,
xrender_format = NULL;
}
_cairo_surface_init (&surface->base, &cairo_xcb_surface_backend,
_cairo_surface_init (&surface->base,
&cairo_xcb_surface_backend,
NULL, /* device */
_xcb_render_format_to_content (xrender_format));
surface->dpy = dpy;

View file

@ -2941,7 +2941,9 @@ found:
surface->render_minor = -1;
}
_cairo_surface_init (&surface->base, &cairo_xlib_surface_backend,
_cairo_surface_init (&surface->base,
&cairo_xlib_surface_backend,
NULL, /* device */
_xrender_format_to_content (xrender_format));
surface->screen = _cairo_xlib_screen_reference (screen);

View file

@ -1050,6 +1050,7 @@ _cairo_xml_surface_create_internal (cairo_xml_t *xml,
_cairo_surface_init (&surface->base,
&_cairo_xml_surface_backend,
NULL, /* device */
content);
surface->xml = xml;

View file

@ -146,6 +146,22 @@ typedef struct _cairo cairo_t;
**/
typedef struct _cairo_surface cairo_surface_t;
/**
* cairo_device_t:
*
* A #cairo_device_t represents the driver interface for drawing
* operations to a #cairo_surface_t. There are different subtypes of
* #cairo_device_t for different drawing backends; for example,
* cairo_xcb_device_create() creates a device that wraps the connection
* to an X Windows System using the XCB library.
*
* The type of a surface can be queried with cairo_device_get_type().
*
* Memory management of #cairo_device_t is done with
* cairo_device_reference() and cairo_device_destroy().
**/
typedef struct _cairo_device cairo_device_t;
/**
* cairo_matrix_t:
* @xx: xx component of the affine transformation
@ -250,6 +266,8 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_INVALID_WEIGHT: invalid value for an input #cairo_font_weight_t (Since 1.8)
* @CAIRO_STATUS_INVALID_SIZE: invalid value (typically too big) for the size of the input (surface, pattern, etc.) (Since 1.10)
* @CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED: user-font method not implemented (Since 1.10)
* @CAIRO_STATUS_DEVICE_TYPE_MISMATCH: the device type is not appropriate for the operation (Since 1.10)
* @CAIRO_STATUS_DEVICE_ERROR: an operation to the device caused an unspecified error (Since 1.10)
* @CAIRO_STATUS_LAST_STATUS: this is a special value indicating the number of
* status values defined in this enumeration. When using this value, note
* that the version of cairo at run-time may have additional status values
@ -299,6 +317,8 @@ typedef enum _cairo_status {
CAIRO_STATUS_INVALID_WEIGHT,
CAIRO_STATUS_INVALID_SIZE,
CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED,
CAIRO_STATUS_DEVICE_TYPE_MISMATCH,
CAIRO_STATUS_DEVICE_ERROR,
CAIRO_STATUS_LAST_STATUS
} cairo_status_t;
@ -1912,6 +1932,100 @@ cairo_status (cairo_t *cr);
cairo_public const char *
cairo_status_to_string (cairo_status_t status);
/* Backend device manipulation */
cairo_public cairo_device_t *
cairo_device_reference (cairo_device_t *device);
/**
* cairo_device_type_t:
* @CAIRO_DEVICE_TYPE_IMAGE: The surface is of type image
* @CAIRO_DEVICE_TYPE_PDF: The surface is of type pdf
* @CAIRO_DEVICE_TYPE_PS: The surface is of type ps
* @CAIRO_DEVICE_TYPE_XLIB: The surface is of type xlib
* @CAIRO_DEVICE_TYPE_XCB: The surface is of type xcb
* @CAIRO_DEVICE_TYPE_GLITZ: The surface is of type glitz
* @CAIRO_DEVICE_TYPE_QUARTZ: The surface is of type quartz
* @CAIRO_DEVICE_TYPE_WIN32: The surface is of type win32
* @CAIRO_DEVICE_TYPE_BEOS: The surface is of type beos
* @CAIRO_DEVICE_TYPE_DIRECTFB: The surface is of type directfb
* @CAIRO_DEVICE_TYPE_SVG: The surface is of type svg
* @CAIRO_DEVICE_TYPE_OS2: The surface is of type os2
* @CAIRO_DEVICE_TYPE_WIN32_PRINTING: The surface is a win32 printing surface
* @CAIRO_DEVICE_TYPE_QUARTZ_IMAGE: The surface is of type quartz_image
* @CAIRO_DEVICE_TYPE_SCRIPT: The surface is of type script
* @CAIRO_DEVICE_TYPE_QT: The surface is of type Qt
* @CAIRO_DEVICE_TYPE_RECORDING: The surface is of type recording
* @CAIRO_DEVICE_TYPE_VG: The surface is a OpenVG surface
* @CAIRO_DEVICE_TYPE_GL: The surface is of type OpenGL
* @CAIRO_DEVICE_TYPE_DRM: The surface is of type Direct Render Manager
* @CAIRO_DEVICE_TYPE_XML: The surface is of type XML
* @CAIRO_DEVICE_TYPE_SKIA: The surface is of type Skia
*
* #cairo_device_type_t is used to describe the type of a given
* device. The devices types are also known as "backends" within cairo.
*
* The device type can be queried with cairo_device_get_type()
*
* The various #cairo_device_t functions can be used with surfaces of
* any type, but some backends also provide type-specific functions
* that must only be called with a device of the appropriate
* type. These functions have names that begin with
* cairo_<emphasis>type</emphasis>_device<!-- --> such as cairo_xcb_device_debug_set_render_version().
*
* The behavior of calling a type-specific function with a surface of
* the wrong type is undefined.
*
* New entries may be added in future versions.
*
* Since: 1.10
**/
typedef enum _cairo_device_type {
CAIRO_DEVICE_TYPE_IMAGE,
CAIRO_DEVICE_TYPE_PDF,
CAIRO_DEVICE_TYPE_PS,
CAIRO_DEVICE_TYPE_XLIB,
CAIRO_DEVICE_TYPE_XCB,
CAIRO_DEVICE_TYPE_GLITZ,
CAIRO_DEVICE_TYPE_QUARTZ,
CAIRO_DEVICE_TYPE_WIN32,
CAIRO_DEVICE_TYPE_BEOS,
CAIRO_DEVICE_TYPE_DIRECTFB,
CAIRO_DEVICE_TYPE_SVG,
CAIRO_DEVICE_TYPE_OS2,
CAIRO_DEVICE_TYPE_WIN32_PRINTING,
CAIRO_DEVICE_TYPE_QUARTZ_IMAGE,
CAIRO_DEVICE_TYPE_SCRIPT,
CAIRO_DEVICE_TYPE_QT,
CAIRO_DEVICE_TYPE_RECORDING,
CAIRO_DEVICE_TYPE_VG,
CAIRO_DEVICE_TYPE_GL,
CAIRO_DEVICE_TYPE_DRM,
CAIRO_DEVICE_TYPE_XML,
CAIRO_DEVICE_TYPE_SKIA
} cairo_device_type_t;
cairo_public cairo_device_type_t
cairo_device_get_type (cairo_device_t *device);
cairo_public cairo_status_t
cairo_device_status (cairo_device_t *device);
cairo_public cairo_status_t
cairo_device_acquire (cairo_device_t *device);
cairo_public void
cairo_device_release (cairo_device_t *device);
cairo_public void
cairo_device_flush (cairo_device_t *device);
cairo_public void
cairo_device_finish (cairo_device_t *device);
cairo_public void
cairo_device_destroy (cairo_device_t *device);
/* Surface manipulation */
cairo_public cairo_surface_t *
@ -1936,6 +2050,9 @@ cairo_surface_finish (cairo_surface_t *surface);
cairo_public void
cairo_surface_destroy (cairo_surface_t *surface);
cairo_public cairo_device_t *
cairo_surface_get_device (cairo_surface_t *surface);
cairo_public unsigned int
cairo_surface_get_reference_count (cairo_surface_t *surface);

View file

@ -1813,6 +1813,7 @@ _cairo_surface_repaint_solid_pattern_surface (cairo_surface_t *other,
cairo_private void
_cairo_surface_init (cairo_surface_t *surface,
const cairo_surface_backend_t *backend,
cairo_device_t *device,
cairo_content_t content);
cairo_private void

View file

@ -444,6 +444,7 @@ gallium_surface_create_internal (gallium_device_t *device,
_cairo_surface_init (&surface->base.base,
&gallium_surface_backend,
NULL, /* device */
content);
_cairo_drm_surface_init (&surface->base, &device->base);
@ -550,6 +551,7 @@ gallium_surface_create_for_name (cairo_drm_device_t *base_dev,
content = _cairo_content_from_format (format);
_cairo_surface_init (&surface->base.base,
&gallium_surface_backend,
NULL, /* device */
content);
_cairo_drm_surface_init (&surface->base, base_dev);

View file

@ -279,7 +279,10 @@ intel_surface_init (intel_surface_t *surface,
cairo_content_t content,
cairo_drm_device_t *device)
{
_cairo_surface_init (&surface->base.base, &intel_surface_backend, content);
_cairo_surface_init (&surface->base.base,
&intel_surface_backend,
NULL, /* device */
content);
_cairo_drm_surface_init (&surface->base, device);
switch (content) {

View file

@ -276,7 +276,10 @@ radeon_surface_init (radeon_surface_t *surface,
cairo_content_t content,
cairo_drm_device_t *device)
{
_cairo_surface_init (&surface->base.base, &radeon_surface_backend, content);
_cairo_surface_init (&surface->base.base,
&radeon_surface_backend,
NULL, /* device */
content);
_cairo_drm_surface_init (&surface->base, device);
switch (content) {

View file

@ -85,7 +85,9 @@ _cairo_test_fallback_surface_create (cairo_content_t content,
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
_cairo_surface_init (&surface->base, &test_fallback_surface_backend,
_cairo_surface_init (&surface->base,
&test_fallback_surface_backend,
NULL, /* device */
content);
surface->backing = backing;

View file

@ -81,6 +81,7 @@ _cairo_test_fallback16_surface_create (cairo_content_t content,
_cairo_surface_init (&surface->base,
&test_fallback16_surface_backend,
NULL, /* device */
content);
surface->backing = backing;

View file

@ -179,7 +179,10 @@ _cairo_test_null_surface_create (cairo_content_t content)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
_cairo_surface_init (surface, &null_surface_backend, content);
_cairo_surface_init (surface,
&null_surface_backend,
NULL, /* device */
content);
return surface;
}

View file

@ -76,7 +76,9 @@ _cairo_test_paginated_surface_create (cairo_surface_t *target)
if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_surface_init (&surface->base, &test_paginated_surface_backend,
_cairo_surface_init (&surface->base,
&test_paginated_surface_backend,
NULL, /* device */
target->content);
surface->target = cairo_surface_reference (target);

View file

@ -69,6 +69,7 @@ _cairo_test_wrapping_surface_create (cairo_surface_t *target)
_cairo_surface_init (&surface->base,
&test_wrapping_surface_backend,
NULL, /* device */
target->content);
_cairo_surface_wrapper_init (&surface->wrapper, target);

View file

@ -1487,6 +1487,8 @@ _status_to_string (cairo_status_t status)
f(INVALID_WEIGHT);
f(INVALID_SIZE);
f(USER_FONT_NOT_IMPLEMENTED);
f(DEVICE_TYPE_MISMATCH);
f(DEVICE_ERROR);
case CAIRO_STATUS_LAST_STATUS:
break;
}