tizen 2.3.1 release
[framework/graphics/cairo.git] / src / cairo-device.c
1 /* Cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2009 Intel Corporation
4  *
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.
12  *
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
18  *
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/
23  *
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.
27  *
28  * The Original Code is the cairo graphics library.
29  *
30  * The Initial Developer of the Original Code is Intel Corporation.
31  *
32  * Contributors(s):
33  *      Chris Wilson <chris@chris-wilson.co.uk>
34  */
35
36 #include "cairoint.h"
37 #include "cairo-device-private.h"
38 #include "cairo-error-private.h"
39 #include "cairo-list-inline.h"
40
41 /**
42  * SECTION:cairo-device
43  * @Title: cairo_device_t
44  * @Short_Description: interface to underlying rendering system
45  * @See_Also: #cairo_surface_t
46  *
47  * Devices are the abstraction Cairo employs for the rendering system
48  * used by a #cairo_surface_t. You can get the device of a surface using
49  * cairo_surface_get_device().
50  *
51  * Devices are created using custom functions specific to the rendering
52  * system you want to use. See the documentation for the surface types
53  * for those functions.
54  *
55  * An important function that devices fulfill is sharing access to the
56  * rendering system between Cairo and your application. If you want to
57  * access a device directly that you used to draw to with Cairo, you must
58  * first call cairo_device_flush() to ensure that Cairo finishes all
59  * operations on the device and resets it to a clean state.
60  *
61  * Cairo also provides the functions cairo_device_acquire() and
62  * cairo_device_release() to synchronize access to the rendering system
63  * in a multithreaded environment. This is done internally, but can also
64  * be used by applications.
65  *
66  * Putting this all together, a function that works with devices should
67  * look something like this:
68  * <informalexample><programlisting>
69  * void
70  * my_device_modifying_function (cairo_device_t *device)
71  * {
72  *   cairo_status_t status;
73  *
74  *   // Ensure the device is properly reset
75  *   cairo_device_flush (device);
76  *   // Try to acquire the device
77  *   status = cairo_device_acquire (device);
78  *   if (status != CAIRO_STATUS_SUCCESS) {
79  *     printf ("Failed to acquire the device: %s\n", cairo_status_to_string (status));
80  *     return;
81  *   }
82  *
83  *   // Do the custom operations on the device here.
84  *   // But do not call any Cairo functions that might acquire devices.
85  *   
86  *   // Release the device when done.
87  *   cairo_device_release (device);
88  * }
89  * </programlisting></informalexample>
90  *
91  * <note><para>Please refer to the documentation of each backend for
92  * additional usage requirements, guarantees provided, and
93  * interactions with existing surface API of the device functions for
94  * surfaces of that type.
95  * </para></note>
96  **/
97
98 static const cairo_device_t _nil_device = {
99     CAIRO_REFERENCE_COUNT_INVALID,
100     CAIRO_STATUS_NO_MEMORY,
101 };
102
103 static const cairo_device_t _mismatch_device = {
104     CAIRO_REFERENCE_COUNT_INVALID,
105     CAIRO_STATUS_DEVICE_TYPE_MISMATCH,
106 };
107
108 static const cairo_device_t _invalid_device = {
109     CAIRO_REFERENCE_COUNT_INVALID,
110     CAIRO_STATUS_DEVICE_ERROR,
111 };
112
113 cairo_device_t *
114 _cairo_device_create_in_error (cairo_status_t status)
115 {
116     switch (status) {
117     case CAIRO_STATUS_NO_MEMORY:
118         return (cairo_device_t *) &_nil_device;
119     case CAIRO_STATUS_DEVICE_ERROR:
120         return (cairo_device_t *) &_invalid_device;
121     case CAIRO_STATUS_DEVICE_TYPE_MISMATCH:
122         return (cairo_device_t *) &_mismatch_device;
123
124     case CAIRO_STATUS_SUCCESS:
125     case CAIRO_STATUS_LAST_STATUS:
126         ASSERT_NOT_REACHED;
127         /* fall-through */
128     case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
129     case CAIRO_STATUS_INVALID_STATUS:
130     case CAIRO_STATUS_INVALID_FORMAT:
131     case CAIRO_STATUS_INVALID_VISUAL:
132     case CAIRO_STATUS_READ_ERROR:
133     case CAIRO_STATUS_WRITE_ERROR:
134     case CAIRO_STATUS_FILE_NOT_FOUND:
135     case CAIRO_STATUS_TEMP_FILE_ERROR:
136     case CAIRO_STATUS_INVALID_STRIDE:
137     case CAIRO_STATUS_INVALID_SIZE:
138     case CAIRO_STATUS_INVALID_RESTORE:
139     case CAIRO_STATUS_INVALID_POP_GROUP:
140     case CAIRO_STATUS_NO_CURRENT_POINT:
141     case CAIRO_STATUS_INVALID_MATRIX:
142     case CAIRO_STATUS_NULL_POINTER:
143     case CAIRO_STATUS_INVALID_STRING:
144     case CAIRO_STATUS_INVALID_PATH_DATA:
145     case CAIRO_STATUS_SURFACE_FINISHED:
146     case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
147     case CAIRO_STATUS_INVALID_DASH:
148     case CAIRO_STATUS_INVALID_DSC_COMMENT:
149     case CAIRO_STATUS_INVALID_INDEX:
150     case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
151     case CAIRO_STATUS_FONT_TYPE_MISMATCH:
152     case CAIRO_STATUS_USER_FONT_IMMUTABLE:
153     case CAIRO_STATUS_USER_FONT_ERROR:
154     case CAIRO_STATUS_NEGATIVE_COUNT:
155     case CAIRO_STATUS_INVALID_CLUSTERS:
156     case CAIRO_STATUS_INVALID_SLANT:
157     case CAIRO_STATUS_INVALID_WEIGHT:
158     case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
159     case CAIRO_STATUS_INVALID_CONTENT:
160     case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION:
161     case CAIRO_STATUS_DEVICE_FINISHED:
162     default:
163         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
164         return (cairo_device_t *) &_nil_device;
165     }
166 }
167
168 void
169 _cairo_device_init (cairo_device_t *device,
170                     const cairo_device_backend_t *backend)
171 {
172     CAIRO_REFERENCE_COUNT_INIT (&device->ref_count, 1);
173     device->status = CAIRO_STATUS_SUCCESS;
174
175     device->backend = backend;
176
177     CAIRO_RECURSIVE_MUTEX_INIT (device->mutex);
178     device->mutex_depth = 0;
179
180     device->finished = FALSE;
181
182     _cairo_user_data_array_init (&device->user_data);
183
184     cairo_list_init (&device->shadow_caches);
185     device->shadow_caches_size = 0;
186 }
187
188 /**
189  * cairo_device_reference:
190  * @device: a #cairo_device_t
191  *
192  * Increases the reference count on @device by one. This prevents
193  * @device from being destroyed until a matching call to
194  * cairo_device_destroy() is made.
195  *
196  * The number of references to a #cairo_device_t can be get using
197  * cairo_device_get_reference_count().
198  *
199  * Return value: the referenced #cairo_device_t.
200  *
201  * Since: 1.10
202  **/
203 cairo_device_t *
204 cairo_device_reference (cairo_device_t *device)
205 {
206     if (device == NULL ||
207         CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
208     {
209         return device;
210     }
211
212     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
213     _cairo_reference_count_inc (&device->ref_count);
214
215     return device;
216 }
217 slim_hidden_def (cairo_device_reference);
218
219 /**
220  * cairo_device_status:
221  * @device: a #cairo_device_t
222  *
223  * Checks whether an error has previously occurred for this
224  * device.
225  *
226  * Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
227  *               the device is in an error state.
228  *
229  * Since: 1.10
230  **/
231 cairo_status_t
232 cairo_device_status (cairo_device_t *device)
233 {
234     if (device == NULL)
235         return CAIRO_STATUS_NULL_POINTER;
236
237     return device->status;
238 }
239
240 /**
241  * cairo_device_flush:
242  * @device: a #cairo_device_t
243  *
244  * Finish any pending operations for the device and also restore any
245  * temporary modifications cairo has made to the device's state.
246  * This function must be called before switching from using the 
247  * device with Cairo to operating on it directly with native APIs.
248  * If the device doesn't support direct access, then this function
249  * does nothing.
250  *
251  * This function may acquire devices.
252  *
253  * Since: 1.10
254  **/
255 void
256 cairo_device_flush (cairo_device_t *device)
257 {
258     cairo_status_t status;
259
260     if (device == NULL || device->status)
261         return;
262
263     if (device->finished)
264         return;
265
266     if (device->backend->flush != NULL) {
267         status = device->backend->flush (device);
268         if (unlikely (status))
269             status = _cairo_device_set_error (device, status);
270     }
271 }
272 slim_hidden_def (cairo_device_flush);
273
274 /**
275  * cairo_device_finish:
276  * @device: the #cairo_device_t to finish
277  *
278  * This function finishes the device and drops all references to
279  * external resources. All surfaces, fonts and other objects created
280  * for this @device will be finished, too.
281  * Further operations on the @device will not affect the @device but
282  * will instead trigger a %CAIRO_STATUS_DEVICE_FINISHED error.
283  *
284  * When the last call to cairo_device_destroy() decreases the
285  * reference count to zero, cairo will call cairo_device_finish() if
286  * it hasn't been called already, before freeing the resources
287  * associated with the device.
288  *
289  * This function may acquire devices.
290  *
291  * Since: 1.10
292  **/
293 void
294 cairo_device_finish (cairo_device_t *device)
295 {
296     if (device == NULL ||
297         CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
298     {
299         return;
300     }
301
302     if (device->finished)
303         return;
304
305     cairo_device_flush (device);
306
307     if (device->backend->finish != NULL)
308         device->backend->finish (device);
309
310     /* We only finish the device after the backend's callback returns because
311      * the device might still be needed during the callback
312      * (e.g. for cairo_device_acquire ()).
313      */
314     device->finished = TRUE;
315 }
316 slim_hidden_def (cairo_device_finish);
317
318 /**
319  * cairo_device_destroy:
320  * @device: a #cairo_device_t
321  *
322  * Decreases the reference count on @device by one. If the result is
323  * zero, then @device and all associated resources are freed.  See
324  * cairo_device_reference().
325  *
326  * This function may acquire devices if the last reference was dropped.
327  *
328  * Since: 1.10
329  **/
330 void
331 cairo_device_destroy (cairo_device_t *device)
332 {
333     cairo_user_data_array_t user_data;
334
335     if (device == NULL ||
336         CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
337     {
338         return;
339     }
340
341     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
342     if (! _cairo_reference_count_dec_and_test (&device->ref_count))
343         return;
344
345     while (! cairo_list_is_empty (&device->shadow_caches)) {
346         cairo_shadow_cache_t *shadow;
347
348         shadow = cairo_list_first_entry (&device->shadow_caches,
349                                          cairo_shadow_cache_t,
350                                          link);
351
352         cairo_list_del (&shadow->link);
353         cairo_surface_destroy (shadow->surface);
354         free (shadow);
355     }
356     device->shadow_caches_size = 0;
357
358     cairo_device_finish (device);
359
360     assert (device->mutex_depth == 0);
361     CAIRO_MUTEX_FINI (device->mutex);
362
363     user_data = device->user_data;
364
365     device->backend->destroy (device);
366
367     _cairo_user_data_array_fini (&user_data);
368
369 }
370 slim_hidden_def (cairo_device_destroy);
371
372 /**
373  * cairo_device_get_type:
374  * @device: a #cairo_device_t
375  *
376  * This function returns the type of the device. See #cairo_device_type_t
377  * for available types.
378  *
379  * Return value: The type of @device.
380  *
381  * Since: 1.10
382  **/
383 cairo_device_type_t
384 cairo_device_get_type (cairo_device_t *device)
385 {
386     if (device == NULL ||
387         CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
388     {
389         return CAIRO_DEVICE_TYPE_INVALID;
390     }
391
392     return device->backend->type;
393 }
394
395 /**
396  * cairo_device_acquire:
397  * @device: a #cairo_device_t
398  *
399  * Acquires the @device for the current thread. This function will block
400  * until no other thread has acquired the device.
401  *
402  * If the return value is %CAIRO_STATUS_SUCCESS, you successfully acquired the
403  * device. From now on your thread owns the device and no other thread will be
404  * able to acquire it until a matching call to cairo_device_release(). It is
405  * allowed to recursively acquire the device multiple times from the same
406  * thread.
407  *
408  * <note><para>You must never acquire two different devices at the same time
409  * unless this is explicitly allowed. Otherwise the possibility of deadlocks
410  * exist.
411  *
412  * As various Cairo functions can acquire devices when called, these functions
413  * may also cause deadlocks when you call them with an acquired device. So you
414  * must not have a device acquired when calling them. These functions are
415  * marked in the documentation.
416  * </para></note>
417  *
418  * Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
419  *               the device is in an error state and could not be
420  *               acquired. After a successful call to cairo_device_acquire(),
421  *               a matching call to cairo_device_release() is required.
422  *
423  * Since: 1.10
424  **/
425 cairo_status_t
426 cairo_device_acquire (cairo_device_t *device)
427 {
428     if (device == NULL)
429         return CAIRO_STATUS_SUCCESS;
430
431     if (unlikely (device->status))
432         return device->status;
433
434     if (unlikely (device->finished))
435         return _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_FINISHED);
436
437     CAIRO_MUTEX_LOCK (device->mutex);
438     if (device->mutex_depth++ == 0) {
439         if (device->backend->lock != NULL)
440             device->backend->lock (device);
441     }
442
443     return CAIRO_STATUS_SUCCESS;
444 }
445 slim_hidden_def (cairo_device_acquire);
446
447 /**
448  * cairo_device_release:
449  * @device: a #cairo_device_t
450  *
451  * Releases a @device previously acquired using cairo_device_acquire(). See
452  * that function for details.
453  *
454  * Since: 1.10
455  **/
456 void
457 cairo_device_release (cairo_device_t *device)
458 {
459     if (device == NULL)
460         return;
461
462     assert (device->mutex_depth > 0);
463
464     if (--device->mutex_depth == 0) {
465         if (device->backend->unlock != NULL)
466             device->backend->unlock (device);
467     }
468
469     CAIRO_MUTEX_UNLOCK (device->mutex);
470 }
471 slim_hidden_def (cairo_device_release);
472
473 cairo_status_t
474 _cairo_device_set_error (cairo_device_t *device,
475                          cairo_status_t  status)
476 {
477     if (status == CAIRO_STATUS_SUCCESS)
478         return CAIRO_STATUS_SUCCESS;
479
480     _cairo_status_set_error (&device->status, status);
481
482     return _cairo_error (status);
483 }
484
485 /**
486  * cairo_device_get_reference_count:
487  * @device: a #cairo_device_t
488  *
489  * Returns the current reference count of @device.
490  *
491  * Return value: the current reference count of @device.  If the
492  * object is a nil object, 0 will be returned.
493  *
494  * Since: 1.10
495  **/
496 unsigned int
497 cairo_device_get_reference_count (cairo_device_t *device)
498 {
499     if (device == NULL ||
500         CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
501         return 0;
502
503     return CAIRO_REFERENCE_COUNT_GET_VALUE (&device->ref_count);
504 }
505
506 /**
507  * cairo_device_get_user_data:
508  * @device: a #cairo_device_t
509  * @key: the address of the #cairo_user_data_key_t the user data was
510  * attached to
511  *
512  * Return user data previously attached to @device using the
513  * specified key.  If no user data has been attached with the given
514  * key this function returns %NULL.
515  *
516  * Return value: the user data previously attached or %NULL.
517  *
518  * Since: 1.10
519  **/
520 void *
521 cairo_device_get_user_data (cairo_device_t               *device,
522                             const cairo_user_data_key_t *key)
523 {
524     return _cairo_user_data_array_get_data (&device->user_data,
525                                             key);
526 }
527
528 /**
529  * cairo_device_set_user_data:
530  * @device: a #cairo_device_t
531  * @key: the address of a #cairo_user_data_key_t to attach the user data to
532  * @user_data: the user data to attach to the #cairo_device_t
533  * @destroy: a #cairo_destroy_func_t which will be called when the
534  * #cairo_t is destroyed or when new user data is attached using the
535  * same key.
536  *
537  * Attach user data to @device.  To remove user data from a surface,
538  * call this function with the key that was used to set it and %NULL
539  * for @data.
540  *
541  * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
542  * slot could not be allocated for the user data.
543  *
544  * Since: 1.10
545  **/
546 cairo_status_t
547 cairo_device_set_user_data (cairo_device_t               *device,
548                             const cairo_user_data_key_t *key,
549                             void                         *user_data,
550                             cairo_destroy_func_t          destroy)
551 {
552     if (CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
553         return device->status;
554
555     return _cairo_user_data_array_set_data (&device->user_data,
556                                             key, user_data, destroy);
557 }