1 /* Cairo - a vector graphics library with display and print output
3 * Copyright © 2009 Intel Corporation
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.org/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is Intel Corporation.
33 * Chris Wilson <chris@chris-wilson.co.uk>
37 #include "cairo-device-private.h"
38 #include "cairo-error-private.h"
39 #include "cairo-list-inline.h"
40 #include "cairo-ttrace.h"
43 * SECTION:cairo-device
44 * @Title: cairo_device_t
45 * @Short_Description: interface to underlying rendering system
46 * @See_Also: #cairo_surface_t
48 * Devices are the abstraction Cairo employs for the rendering system
49 * used by a #cairo_surface_t. You can get the device of a surface using
50 * cairo_surface_get_device().
52 * Devices are created using custom functions specific to the rendering
53 * system you want to use. See the documentation for the surface types
54 * for those functions.
56 * An important function that devices fulfill is sharing access to the
57 * rendering system between Cairo and your application. If you want to
58 * access a device directly that you used to draw to with Cairo, you must
59 * first call cairo_device_flush() to ensure that Cairo finishes all
60 * operations on the device and resets it to a clean state.
62 * Cairo also provides the functions cairo_device_acquire() and
63 * cairo_device_release() to synchronize access to the rendering system
64 * in a multithreaded environment. This is done internally, but can also
65 * be used by applications.
67 * Putting this all together, a function that works with devices should
68 * look something like this:
69 * <informalexample><programlisting>
71 * my_device_modifying_function (cairo_device_t *device)
73 * cairo_status_t status;
75 * // Ensure the device is properly reset
76 * cairo_device_flush (device);
77 * // Try to acquire the device
78 * status = cairo_device_acquire (device);
79 * if (status != CAIRO_STATUS_SUCCESS) {
80 * printf ("Failed to acquire the device: %s\n", cairo_status_to_string (status));
84 * // Do the custom operations on the device here.
85 * // But do not call any Cairo functions that might acquire devices.
87 * // Release the device when done.
88 * cairo_device_release (device);
90 * </programlisting></informalexample>
92 * <note><para>Please refer to the documentation of each backend for
93 * additional usage requirements, guarantees provided, and
94 * interactions with existing surface API of the device functions for
95 * surfaces of that type.
99 static const cairo_device_t _nil_device = {
100 CAIRO_REFERENCE_COUNT_INVALID,
101 CAIRO_STATUS_NO_MEMORY,
104 static const cairo_device_t _mismatch_device = {
105 CAIRO_REFERENCE_COUNT_INVALID,
106 CAIRO_STATUS_DEVICE_TYPE_MISMATCH,
109 static const cairo_device_t _invalid_device = {
110 CAIRO_REFERENCE_COUNT_INVALID,
111 CAIRO_STATUS_DEVICE_ERROR,
115 _cairo_device_create_in_error (cairo_status_t status)
118 case CAIRO_STATUS_NO_MEMORY:
119 return (cairo_device_t *) &_nil_device;
120 case CAIRO_STATUS_DEVICE_ERROR:
121 return (cairo_device_t *) &_invalid_device;
122 case CAIRO_STATUS_DEVICE_TYPE_MISMATCH:
123 return (cairo_device_t *) &_mismatch_device;
125 case CAIRO_STATUS_SUCCESS:
126 case CAIRO_STATUS_LAST_STATUS:
129 case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
130 case CAIRO_STATUS_INVALID_STATUS:
131 case CAIRO_STATUS_INVALID_FORMAT:
132 case CAIRO_STATUS_INVALID_VISUAL:
133 case CAIRO_STATUS_READ_ERROR:
134 case CAIRO_STATUS_WRITE_ERROR:
135 case CAIRO_STATUS_FILE_NOT_FOUND:
136 case CAIRO_STATUS_TEMP_FILE_ERROR:
137 case CAIRO_STATUS_INVALID_STRIDE:
138 case CAIRO_STATUS_INVALID_SIZE:
139 case CAIRO_STATUS_INVALID_RESTORE:
140 case CAIRO_STATUS_INVALID_POP_GROUP:
141 case CAIRO_STATUS_NO_CURRENT_POINT:
142 case CAIRO_STATUS_INVALID_MATRIX:
143 case CAIRO_STATUS_NULL_POINTER:
144 case CAIRO_STATUS_INVALID_STRING:
145 case CAIRO_STATUS_INVALID_PATH_DATA:
146 case CAIRO_STATUS_SURFACE_FINISHED:
147 case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
148 case CAIRO_STATUS_INVALID_DASH:
149 case CAIRO_STATUS_INVALID_DSC_COMMENT:
150 case CAIRO_STATUS_INVALID_INDEX:
151 case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
152 case CAIRO_STATUS_FONT_TYPE_MISMATCH:
153 case CAIRO_STATUS_USER_FONT_IMMUTABLE:
154 case CAIRO_STATUS_USER_FONT_ERROR:
155 case CAIRO_STATUS_NEGATIVE_COUNT:
156 case CAIRO_STATUS_INVALID_CLUSTERS:
157 case CAIRO_STATUS_INVALID_SLANT:
158 case CAIRO_STATUS_INVALID_WEIGHT:
159 case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
160 case CAIRO_STATUS_INVALID_CONTENT:
161 case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION:
162 case CAIRO_STATUS_DEVICE_FINISHED:
163 case CAIRO_STATUS_JBIG2_GLOBAL_MISSING:
165 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
166 return (cairo_device_t *) &_nil_device;
171 _cairo_device_init (cairo_device_t *device,
172 const cairo_device_backend_t *backend)
174 CAIRO_TRACE_BEGIN (__func__);
175 CAIRO_REFERENCE_COUNT_INIT (&device->ref_count, 1);
176 device->status = CAIRO_STATUS_SUCCESS;
178 device->backend = backend;
180 CAIRO_RECURSIVE_MUTEX_INIT (device->mutex);
181 device->mutex_depth = 0;
183 device->finished = FALSE;
185 _cairo_user_data_array_init (&device->user_data);
187 cairo_list_init (&device->shadow_caches);
188 device->shadow_caches_size = 0;
189 CAIRO_TRACE_END (__func__);
193 * cairo_device_reference:
194 * @device: a #cairo_device_t
196 * Increases the reference count on @device by one. This prevents
197 * @device from being destroyed until a matching call to
198 * cairo_device_destroy() is made.
200 * The number of references to a #cairo_device_t can be get using
201 * cairo_device_get_reference_count().
203 * Return value: the referenced #cairo_device_t.
208 cairo_device_reference (cairo_device_t *device)
210 if (device == NULL ||
211 CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
216 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
217 _cairo_reference_count_inc (&device->ref_count);
221 slim_hidden_def (cairo_device_reference);
224 * cairo_device_status:
225 * @device: a #cairo_device_t
227 * Checks whether an error has previously occurred for this
230 * Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
231 * the device is in an error state.
236 cairo_device_status (cairo_device_t *device)
239 return CAIRO_STATUS_NULL_POINTER;
241 return device->status;
245 * cairo_device_flush:
246 * @device: a #cairo_device_t
248 * Finish any pending operations for the device and also restore any
249 * temporary modifications cairo has made to the device's state.
250 * This function must be called before switching from using the
251 * device with Cairo to operating on it directly with native APIs.
252 * If the device doesn't support direct access, then this function
255 * This function may acquire devices.
260 cairo_device_flush (cairo_device_t *device)
262 cairo_status_t status;
264 if (device == NULL || device->status)
267 if (device->finished)
270 if (device->backend->flush != NULL) {
271 status = device->backend->flush (device);
272 if (unlikely (status))
273 status = _cairo_device_set_error (device, status);
276 slim_hidden_def (cairo_device_flush);
279 * cairo_device_finish:
280 * @device: the #cairo_device_t to finish
282 * This function finishes the device and drops all references to
283 * external resources. All surfaces, fonts and other objects created
284 * for this @device will be finished, too.
285 * Further operations on the @device will not affect the @device but
286 * will instead trigger a %CAIRO_STATUS_DEVICE_FINISHED error.
288 * When the last call to cairo_device_destroy() decreases the
289 * reference count to zero, cairo will call cairo_device_finish() if
290 * it hasn't been called already, before freeing the resources
291 * associated with the device.
293 * This function may acquire devices.
298 cairo_device_finish (cairo_device_t *device)
300 if (device == NULL ||
301 CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
306 if (device->finished)
309 cairo_device_flush (device);
311 if (device->backend->finish != NULL)
312 device->backend->finish (device);
314 /* We only finish the device after the backend's callback returns because
315 * the device might still be needed during the callback
316 * (e.g. for cairo_device_acquire ()).
318 device->finished = TRUE;
320 slim_hidden_def (cairo_device_finish);
323 * cairo_device_destroy:
324 * @device: a #cairo_device_t
326 * Decreases the reference count on @device by one. If the result is
327 * zero, then @device and all associated resources are freed. See
328 * cairo_device_reference().
330 * This function may acquire devices if the last reference was dropped.
335 cairo_device_destroy (cairo_device_t *device)
337 CAIRO_TRACE_BEGIN (__func__);
338 cairo_user_data_array_t user_data;
340 if (device == NULL ||
341 CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
343 CAIRO_TRACE_END (__func__);
347 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
348 if (! _cairo_reference_count_dec_and_test (&device->ref_count)) {
349 CAIRO_TRACE_END (__func__);
353 while (! cairo_list_is_empty (&device->shadow_caches)) {
354 cairo_shadow_cache_t *shadow;
356 shadow = cairo_list_first_entry (&device->shadow_caches,
357 cairo_shadow_cache_t,
360 cairo_list_del (&shadow->link);
361 cairo_surface_destroy (shadow->surface);
364 device->shadow_caches_size = 0;
366 cairo_device_finish (device);
368 assert (device->mutex_depth == 0);
369 CAIRO_MUTEX_FINI (device->mutex);
371 user_data = device->user_data;
373 device->backend->destroy (device);
375 _cairo_user_data_array_fini (&user_data);
376 CAIRO_TRACE_END (__func__);
379 slim_hidden_def (cairo_device_destroy);
382 * cairo_device_get_type:
383 * @device: a #cairo_device_t
385 * This function returns the type of the device. See #cairo_device_type_t
386 * for available types.
388 * Return value: The type of @device.
393 cairo_device_get_type (cairo_device_t *device)
395 if (device == NULL ||
396 CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
398 return CAIRO_DEVICE_TYPE_INVALID;
401 return device->backend->type;
405 * cairo_device_acquire:
406 * @device: a #cairo_device_t
408 * Acquires the @device for the current thread. This function will block
409 * until no other thread has acquired the device.
411 * If the return value is %CAIRO_STATUS_SUCCESS, you successfully acquired the
412 * device. From now on your thread owns the device and no other thread will be
413 * able to acquire it until a matching call to cairo_device_release(). It is
414 * allowed to recursively acquire the device multiple times from the same
417 * <note><para>You must never acquire two different devices at the same time
418 * unless this is explicitly allowed. Otherwise the possibility of deadlocks
421 * As various Cairo functions can acquire devices when called, these functions
422 * may also cause deadlocks when you call them with an acquired device. So you
423 * must not have a device acquired when calling them. These functions are
424 * marked in the documentation.
427 * Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
428 * the device is in an error state and could not be
429 * acquired. After a successful call to cairo_device_acquire(),
430 * a matching call to cairo_device_release() is required.
435 cairo_device_acquire (cairo_device_t *device)
438 return CAIRO_STATUS_SUCCESS;
440 if (unlikely (device->status))
441 return device->status;
443 if (unlikely (device->finished))
444 return _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_FINISHED);
446 CAIRO_MUTEX_LOCK (device->mutex);
447 if (device->mutex_depth++ == 0) {
448 if (device->backend->lock != NULL)
449 device->backend->lock (device);
452 return CAIRO_STATUS_SUCCESS;
454 slim_hidden_def (cairo_device_acquire);
457 * cairo_device_release:
458 * @device: a #cairo_device_t
460 * Releases a @device previously acquired using cairo_device_acquire(). See
461 * that function for details.
466 cairo_device_release (cairo_device_t *device)
471 assert (device->mutex_depth > 0);
473 if (--device->mutex_depth == 0) {
474 if (device->backend->unlock != NULL)
475 device->backend->unlock (device);
478 CAIRO_MUTEX_UNLOCK (device->mutex);
480 slim_hidden_def (cairo_device_release);
483 _cairo_device_set_error (cairo_device_t *device,
484 cairo_status_t status)
486 if (status == CAIRO_STATUS_SUCCESS)
487 return CAIRO_STATUS_SUCCESS;
489 _cairo_status_set_error (&device->status, status);
491 return _cairo_error (status);
495 * cairo_device_get_reference_count:
496 * @device: a #cairo_device_t
498 * Returns the current reference count of @device.
500 * Return value: the current reference count of @device. If the
501 * object is a nil object, 0 will be returned.
506 cairo_device_get_reference_count (cairo_device_t *device)
508 if (device == NULL ||
509 CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
512 return CAIRO_REFERENCE_COUNT_GET_VALUE (&device->ref_count);
516 * cairo_device_get_user_data:
517 * @device: a #cairo_device_t
518 * @key: the address of the #cairo_user_data_key_t the user data was
521 * Return user data previously attached to @device using the
522 * specified key. If no user data has been attached with the given
523 * key this function returns %NULL.
525 * Return value: the user data previously attached or %NULL.
530 cairo_device_get_user_data (cairo_device_t *device,
531 const cairo_user_data_key_t *key)
533 return _cairo_user_data_array_get_data (&device->user_data,
538 * cairo_device_set_user_data:
539 * @device: a #cairo_device_t
540 * @key: the address of a #cairo_user_data_key_t to attach the user data to
541 * @user_data: the user data to attach to the #cairo_device_t
542 * @destroy: a #cairo_destroy_func_t which will be called when the
543 * #cairo_t is destroyed or when new user data is attached using the
546 * Attach user data to @device. To remove user data from a surface,
547 * call this function with the key that was used to set it and %NULL
550 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
551 * slot could not be allocated for the user data.
556 cairo_device_set_user_data (cairo_device_t *device,
557 const cairo_user_data_key_t *key,
559 cairo_destroy_func_t destroy)
561 if (CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
562 return device->status;
564 return _cairo_user_data_array_set_data (&device->user_data,
565 key, user_data, destroy);