## cairo_device_t

cairo_device_t — interface to underlying rendering system

## Synopsis

    typedef             cairo_device_t;
    cairo_device_t *    cairo_device_reference              (cairo_device_t *device);
    void                cairo_device_destroy                (cairo_device_t *device);
    cairo_status_t      cairo_device_status                 (cairo_device_t *device);
    void                cairo_device_finish                 (cairo_device_t *device);
    void                cairo_device_flush                  (cairo_device_t *device);
    enum                cairo_device_type_t;
    cairo_device_type_t  cairo_device_get_type              (cairo_device_t *device);
    unsigned int        cairo_device_get_reference_count    (cairo_device_t *device);
    cairo_status_t      cairo_device_set_user_data          (cairo_device_t *device,
                                                             const cairo_user_data_key_t *key,
                                                             void *user_data,
                                                             cairo_destroy_func_t destroy);
    void *              cairo_device_get_user_data          (cairo_device_t *device,
                                                             const cairo_user_data_key_t *key);
    cairo_status_t      cairo_device_acquire                (cairo_device_t *device);
    void                cairo_device_release                (cairo_device_t *device);

## Description

Devices are the abstraction Cairo employs for the rendering system used by a cairo_surface_t. You can get the device of a surface using `cairo_surface_get_device()`.

Devices are created using custom functions specific to the rendering system you want to use. See the documentation for the surface types for those functions.

An important function that devices fulfill is sharing access to the rendering system between Cairo and your application. If you want to access a device directly that you used to draw to with Cairo, you must first call `cairo_device_flush()` to ensure that Cairo finishes all operations on the device and resets it to a clean state.

Cairo also provides the functions `cairo_device_acquire()` and `cairo_device_release()` to synchronize access to the rendering system in a multithreaded environment. This is done internally, but can also be used by applications.

Putting this all together, a function that works with devices should look something like this:

    void
    my_device_modifying_function (cairo_device_t *device)
    {
      cairo_status_t status;

      // Ensure the device is properly reset
      cairo_device_flush (device);
      // Try to acquire the device
      status = cairo_device_acquire (device);
      if (status != CAIRO_STATUS_SUCCESS) {
        printf ("Failed to acquire the device: %s\n", cairo_status_to_string (status));
        return;
      }

      // Do the custom operations on the device here.
      // But do not call any Cairo functions that might acquire devices.

      // Release the device when done.
      cairo_device_release (device);
    }

### Note

Please refer to the documentation of each backend for additional usage requirements, guarantees provided, and interactions with existing surface API of the device functions for surfaces of that type.

## Details

### cairo_device_t

    typedef struct _cairo_device 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 device can be queried with `cairo_device_get_type()`.

Memory management of cairo_device_t is done with `cairo_device_reference()` and `cairo_device_destroy()`.

Since 1.10

### cairo_device_reference ()

    cairo_device_t *    cairo_device_reference              (cairo_device_t *device);

Increases the reference count on `device` by one. This prevents `device` from being destroyed until a matching call to `cairo_device_destroy()` is made.

The number of references to a cairo_device_t can be get using `cairo_device_get_reference_count()`.

`device` : | a cairo_device_t
Returns : | the referenced cairo_device_t.

Since 1.10

### cairo_device_destroy ()

    void                cairo_device_destroy                (cairo_device_t *device);

Decreases the reference count on `device` by one. If the result is zero, then `device` and all associated resources are freed. See `cairo_device_reference()`.

This function may acquire devices if the last reference was dropped.

`device` : | a cairo_device_t

Since 1.10

### cairo_device_status ()

    cairo_status_t      cairo_device_status                 (cairo_device_t *device);

Checks whether an error has previously occurred for this device.

`device` : | a cairo_device_t
Returns : | `CAIRO_STATUS_SUCCESS` on success or an error code if the device is in an error state.

Since 1.10

### cairo_device_finish ()

    void                cairo_device_finish                 (cairo_device_t *device);

This function finishes the device and drops all references to external resources. All surfaces, fonts and other objects created for this `device` will be finished, too. Further operations on the `device` will not affect the `device` but will instead trigger a `CAIRO_STATUS_DEVICE_FINISHED` error.

When the last call to `cairo_device_destroy()` decreases the reference count to zero, cairo will call `cairo_device_finish()` if it hasn't been called already, before freeing the resources associated with the device.

This function may acquire devices.

`device` : | the cairo_device_t to finish

Since 1.10

### cairo_device_flush ()

    void                cairo_device_flush                  (cairo_device_t *device);

Finish any pending operations for the device and also restore any temporary modifications cairo has made to the device's state. This function must be called before switching from using the device with Cairo to operating on it directly with native APIs. If the device doesn't support direct access, then this function does nothing.

This function may acquire devices.

`device` : | a cairo_device_t

Since 1.10

### enum cairo_device_type_t

    typedef enum _cairo_device_type {
        CAIRO_DEVICE_TYPE_DRM,
        CAIRO_DEVICE_TYPE_GL,
        CAIRO_DEVICE_TYPE_SCRIPT,
        CAIRO_DEVICE_TYPE_XCB,
        CAIRO_DEVICE_TYPE_XLIB,
        CAIRO_DEVICE_TYPE_XML
    } cairo_device_type_t;

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_type_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.

`CAIRO_DEVICE_TYPE_DRM` | The surface is of type Direct Render Manager
`CAIRO_DEVICE_TYPE_GL` | The surface is of type OpenGL
`CAIRO_DEVICE_TYPE_SCRIPT` | The surface is of type script
`CAIRO_DEVICE_TYPE_XCB` | The surface is of type xcb
`CAIRO_DEVICE_TYPE_XLIB` | The surface is of type xlib
`CAIRO_DEVICE_TYPE_XML` | The surface is of type XML `cairo_surface_create_for_rectangle()`

Since 1.10

### cairo_device_get_type ()

    cairo_device_type_t  cairo_device_get_type              (cairo_device_t *device);

This function returns the type of the device. See cairo_device_type_t for available types.

`device` : | a cairo_device_t
Returns : | The type of `device`.

Since 1.10

### cairo_device_get_reference_count ()

    unsigned int        cairo_device_get_reference_count    (cairo_device_t *device);

Returns the current reference count of `device`.

`device` : | a cairo_device_t
Returns : | the current reference count of `device`. If the object is a nil object, 0 will be returned.

Since 1.10

### cairo_device_set_user_data ()

    cairo_status_t      cairo_device_set_user_data          (cairo_device_t *device,
                                                             const cairo_user_data_key_t *key,
                                                             void *user_data,
                                                             cairo_destroy_func_t destroy);

Attach user data to `device`. To remove user data from a surface, call this function with the key that was used to set it and `NULL` for `data`.

`device` : | a cairo_device_t
`key` : | the address of a cairo_user_data_key_t to attach the user data to
`user_data` : | the user data to attach to the cairo_device_t
`destroy` : | a cairo_destroy_func_t which will be called when the cairo_t is destroyed or when new user data is attached using the same key.
Returns : | `CAIRO_STATUS_SUCCESS` or `CAIRO_STATUS_NO_MEMORY` if a slot could not be allocated for the user data.

Since 1.10

### cairo_device_get_user_data ()

    void *              cairo_device_get_user_data          (cairo_device_t *device,
                                                             const cairo_user_data_key_t *key);

Return user data previously attached to `device` using the specified key. If no user data has been attached with the given key this function returns `NULL`.

`device` : | a cairo_device_t
`key` : | the address of the cairo_user_data_key_t the user data was attached to
Returns : | the user data previously attached or `NULL`.

Since 1.10

### cairo_device_acquire ()

    cairo_status_t      cairo_device_acquire                (cairo_device_t *device);

Acquires the `device` for the current thread. This function will block until no other thread has acquired the device.

If the return value is `CAIRO_STATUS_SUCCESS`, you successfully acquired the device. From now on your thread owns the device and no other thread will be able to acquire it until a matching call to `cairo_device_release()`. It is allowed to recursively acquire the device multiple times from the same thread.

### Note

You must never acquire two different devices at the same time unless this is explicitly allowed. Otherwise the possibility of deadlocks exist.

As various Cairo functions can acquire devices when called, these functions may also cause deadlocks when you call them with an acquired device. So you must not have a device acquired when calling them. These functions are marked in the documentation.

`device` : | a cairo_device_t
Returns : | `CAIRO_STATUS_SUCCESS` on success or an error code if the device is in an error state and could not be acquired. After a successful call to `cairo_device_acquire()`, a matching call to `cairo_device_release()` is required.

Since 1.10

### cairo_device_release ()

    void                cairo_device_release                (cairo_device_t *device);

Releases a `device` previously acquired using `cairo_device_acquire()`. See that function for details.

`device` : | a cairo_device_t

Since 1.10

## See Also

cairo_surface_t