summaryrefslogtreecommitdiff
path: root/src/drm/cairo-drm.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-01-22 20:48:54 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2010-01-22 23:01:52 +0000
commit77afe8491ed7038a8399c01f10d8f062a7239225 (patch)
tree0af0013ef61936fffb9e4a69605856866da5b677 /src/drm/cairo-drm.c
parentb9407af6a4bc792c1bcb52c90aa8a618627bb618 (diff)
drm: Add backends for i915 and i965.
As proof-of-principle add the nearly working demonstrations of using DRM to render directly with the GPU bypassing both RENDER and GL for performance whilst preserving high quality rendering. The basis behind developing these chip specific backends is that this is the idealised interface that we desire for this chips, and so a target for cairo-gl as we continue to develop both it and our GL stack. Note that this backends do not yet fully pass the test suite, so only use if you are brave and willing to help develop them further.
Diffstat (limited to 'src/drm/cairo-drm.c')
-rw-r--r--src/drm/cairo-drm.c232
1 files changed, 128 insertions, 104 deletions
diff --git a/src/drm/cairo-drm.c b/src/drm/cairo-drm.c
index a218fa52..9ccb10d5 100644
--- a/src/drm/cairo-drm.c
+++ b/src/drm/cairo-drm.c
@@ -33,6 +33,8 @@
#include "cairoint.h"
#include "cairo-drm-private.h"
+
+#include "cairo-device-private.h"
#include "cairo-error-private.h"
#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
@@ -43,29 +45,6 @@
static cairo_drm_device_t *_cairo_drm_known_devices;
static cairo_drm_device_t *_cairo_drm_default_device;
-static const cairo_drm_device_t _nil_device = {
- CAIRO_REFERENCE_COUNT_INVALID,
- CAIRO_STATUS_NO_MEMORY
-};
-
-static const cairo_drm_device_t _invalid_device = {
- CAIRO_REFERENCE_COUNT_INVALID,
- CAIRO_STATUS_INVALID_CONTENT
-};
-
-cairo_drm_device_t *
-_cairo_drm_device_create_in_error (cairo_status_t status)
-{
- switch ((int) status) {
- default:
- ASSERT_NOT_REACHED;
- case CAIRO_STATUS_NO_MEMORY:
- return (cairo_drm_device_t *) &_nil_device;
- case CAIRO_STATUS_INVALID_CONTENT:
- return (cairo_drm_device_t *) &_invalid_device;
- }
-}
-
static const char *
get_udev_property(struct udev_device *device, const char *name)
{
@@ -81,16 +60,69 @@ get_udev_property(struct udev_device *device, const char *name)
return NULL;
}
+static void
+_device_flush (void *abstract_device)
+{
+ cairo_drm_device_t *device = abstract_device;
+
+ device->device.flush (device);
+}
+
+static void
+_device_finish (void *abstract_device)
+{
+ cairo_drm_device_t *device = abstract_device;
+
+ CAIRO_MUTEX_LOCK (_cairo_drm_device_mutex);
+ if (device->prev != NULL)
+ device->prev->next = device->next;
+ else
+ _cairo_drm_known_devices = device->next;
+ if (device->next != NULL)
+ device->next->prev = device->prev;
+
+ CAIRO_MUTEX_UNLOCK (_cairo_drm_device_mutex);
+
+ if (_cairo_atomic_ptr_cmpxchg (&_cairo_drm_default_device,
+ device, NULL) == device)
+ {
+ cairo_device_destroy (&device->base);
+ }
+}
+
+static void
+_device_destroy (void *abstract_device)
+{
+ cairo_drm_device_t *device = abstract_device;
+
+ device->device.destroy (device);
+}
+
+static const cairo_device_backend_t _cairo_drm_device_backend = {
+ CAIRO_DEVICE_TYPE_DRM,
+
+ NULL, NULL, /* lock, unlock */
+
+ _device_flush,
+ _device_finish,
+ _device_destroy,
+};
+
cairo_drm_device_t *
_cairo_drm_device_init (cairo_drm_device_t *dev,
int fd,
dev_t devid,
+ int vendor_id,
+ int chip_id,
int max_surface_size)
{
- CAIRO_REFERENCE_COUNT_INIT (&dev->ref_count, 1);
- dev->status = CAIRO_STATUS_SUCCESS;
+ assert (CAIRO_MUTEX_IS_LOCKED (_cairo_drm_device_mutex));
+
+ _cairo_device_init (&dev->base, &_cairo_drm_device_backend);
dev->id = devid;
+ dev->vendor_id = vendor_id;
+ dev->chip_id = chip_id;
dev->fd = fd;
dev->max_surface_size = max_surface_size;
@@ -102,12 +134,12 @@ _cairo_drm_device_init (cairo_drm_device_t *dev,
_cairo_drm_known_devices = dev;
if (_cairo_drm_default_device == NULL)
- _cairo_drm_default_device = cairo_drm_device_reference (dev);
+ _cairo_drm_default_device = (cairo_drm_device_t *) cairo_device_reference (&dev->base);
return dev;
}
-cairo_drm_device_t *
+cairo_device_t *
cairo_drm_device_get (struct udev_device *device)
{
static const struct dri_driver_entry {
@@ -115,7 +147,34 @@ cairo_drm_device_get (struct udev_device *device)
uint32_t chip_id;
cairo_drm_device_create_func_t create_func;
} driver_map[] = {
+ { 0x8086, 0x29a2, _cairo_drm_i965_device_create }, /* I965_G */
+ { 0x8086, 0x2982, _cairo_drm_i965_device_create }, /* G35_G */
+ { 0x8086, 0x2992, _cairo_drm_i965_device_create }, /* I965_Q */
+ { 0x8086, 0x2972, _cairo_drm_i965_device_create }, /* I946_GZ */
+ { 0x8086, 0x2a02, _cairo_drm_i965_device_create }, /* I965_GM */
+ { 0x8086, 0x2a12, _cairo_drm_i965_device_create }, /* I965_GME */
+ { 0x8086, 0x2e02, _cairo_drm_i965_device_create }, /* IGD_E_G */
+ { 0x8086, 0x2e22, _cairo_drm_i965_device_create }, /* G45_G */
+ { 0x8086, 0x2e12, _cairo_drm_i965_device_create }, /* Q45_G */
+ { 0x8086, 0x2e32, _cairo_drm_i965_device_create }, /* G41_G */
+ { 0x8086, 0x2a42, _cairo_drm_i965_device_create }, /* GM45_GM */
+
+ { 0x8086, 0x2582, _cairo_drm_i915_device_create }, /* I915_G */
+ { 0x8086, 0x2592, _cairo_drm_i915_device_create }, /* I915_GM */
+ { 0x8086, 0x258a, _cairo_drm_i915_device_create }, /* E7221_G */
+ { 0x8086, 0x2772, _cairo_drm_i915_device_create }, /* I945_G */
+ { 0x8086, 0x27a2, _cairo_drm_i915_device_create }, /* I945_GM */
+ { 0x8086, 0x27ae, _cairo_drm_i915_device_create }, /* I945_GME */
+ { 0x8086, 0x29c2, _cairo_drm_i915_device_create }, /* G33_G */
+ { 0x8086, 0x29b2, _cairo_drm_i915_device_create }, /* Q35_G */
+ { 0x8086, 0x29d2, _cairo_drm_i915_device_create }, /* Q33_G */
+ { 0x8086, 0xa011, _cairo_drm_i915_device_create }, /* IGD_GM */
+ { 0x8086, 0xa001, _cairo_drm_i915_device_create }, /* IGD_G */
+
+ /* XXX i830 */
+
{ 0x8086, ~0, _cairo_drm_intel_device_create },
+
{ 0x1002, ~0, _cairo_drm_radeon_device_create },
#if CAIRO_HAS_GALLIUM_SURFACE
{ ~0, ~0, _cairo_drm_gallium_device_create },
@@ -135,16 +194,16 @@ cairo_drm_device_get (struct udev_device *device)
CAIRO_MUTEX_LOCK (_cairo_drm_device_mutex);
for (dev = _cairo_drm_known_devices; dev != NULL; dev = dev->next) {
if (dev->id == devid) {
- dev = cairo_drm_device_reference (dev);
+ dev = (cairo_drm_device_t *) cairo_device_reference (&dev->base);
goto DONE;
}
}
- dev = (cairo_drm_device_t *) &_nil_device;
parent = udev_device_get_parent (device);
pci_id = get_udev_property (parent, "PCI_ID");
if (sscanf (pci_id, "%x:%x", &vendor_id, &chip_id) != 2) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ dev = (cairo_drm_device_t *)
+ _cairo_device_create_in_error (CAIRO_STATUS_DEVICE_ERROR);
goto DONE;
}
@@ -166,8 +225,8 @@ cairo_drm_device_get (struct udev_device *device)
}
if (i == ARRAY_LENGTH (driver_map)) {
- /* XXX should be no driver or something*/
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ dev = (cairo_drm_device_t *)
+ _cairo_device_create_in_error (CAIRO_STATUS_DEVICE_ERROR);
goto DONE;
}
}
@@ -190,22 +249,21 @@ cairo_drm_device_get (struct udev_device *device)
DONE:
CAIRO_MUTEX_UNLOCK (_cairo_drm_device_mutex);
- return dev;
+ return &dev->base;
}
slim_hidden_def (cairo_drm_device_get);
-cairo_drm_device_t *
+cairo_device_t *
cairo_drm_device_get_for_fd (int fd)
{
struct stat st;
struct udev *udev;
struct udev_device *device;
- cairo_drm_device_t *dev = NULL;
+ cairo_device_t *dev = NULL;
if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode)) {
//_cairo_error_throw (CAIRO_STATUS_INVALID_DEVICE);
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- return (cairo_drm_device_t *) &_nil_device;
+ return _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
}
udev = udev_new ();
@@ -220,25 +278,24 @@ cairo_drm_device_get_for_fd (int fd)
return dev;
}
+slim_hidden_def (cairo_drm_device_get_for_fd);
-cairo_drm_device_t *
+cairo_device_t *
cairo_drm_device_default (void)
{
struct udev *udev;
struct udev_enumerate *e;
struct udev_list_entry *entry;
- cairo_drm_device_t *dev;
+ cairo_device_t *dev;
/* optimistic atomic pointer read */
- dev = _cairo_drm_default_device;
+ dev = &_cairo_drm_default_device->base;
if (dev != NULL)
return dev;
udev = udev_new();
- if (udev == NULL) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- return (cairo_drm_device_t *) &_nil_device;
- }
+ if (udev == NULL)
+ return _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
e = udev_enumerate_new (udev);
udev_enumerate_add_match_subsystem (e, "drm");
@@ -255,8 +312,9 @@ cairo_drm_device_default (void)
udev_device_unref (device);
if (dev != NULL) {
- if (dev->fd == -1) { /* try again, we may find a usable card */
- cairo_drm_device_destroy (dev);
+ if (((cairo_drm_device_t *) dev)->fd == -1) {
+ /* try again, we may find a usable card */
+ cairo_device_destroy (dev);
dev = NULL;
} else
break;
@@ -265,7 +323,7 @@ cairo_drm_device_default (void)
udev_enumerate_unref (e);
udev_unref (udev);
- cairo_drm_device_destroy (dev); /* owned by _cairo_drm_default_device */
+ cairo_device_destroy (dev); /* owned by _cairo_drm_default_device */
return dev;
}
slim_hidden_def (cairo_drm_device_default);
@@ -274,90 +332,56 @@ void
_cairo_drm_device_reset_static_data (void)
{
if (_cairo_drm_default_device != NULL) {
- cairo_drm_device_destroy (_cairo_drm_default_device);
+ cairo_device_t *device = &_cairo_drm_default_device->base;
_cairo_drm_default_device = NULL;
+ cairo_device_destroy (device);
}
}
-cairo_drm_device_t *
-cairo_drm_device_reference (cairo_drm_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_drm_device_reference);
-
int
-cairo_drm_device_get_fd (cairo_drm_device_t *device)
+cairo_drm_device_get_fd (cairo_device_t *abstract_device)
{
- if (device->status)
+ cairo_drm_device_t *device = (cairo_drm_device_t *) abstract_device;
+
+ if (device->base.status)
return -1;
return device->fd;
}
-cairo_status_t
-cairo_drm_device_status (cairo_drm_device_t *device)
-{
- if (device == NULL)
- return CAIRO_STATUS_NULL_POINTER;
-
- return device->status;
-}
-
void
_cairo_drm_device_fini (cairo_drm_device_t *device)
{
- CAIRO_MUTEX_LOCK (_cairo_drm_device_mutex);
- if (device->prev != NULL)
- device->prev->next = device->next;
- else
- _cairo_drm_known_devices = device->next;
- if (device->next != NULL)
- device->next->prev = device->prev;
- CAIRO_MUTEX_UNLOCK (_cairo_drm_device_mutex);
-
if (device->fd != -1)
close (device->fd);
}
void
-cairo_drm_device_destroy (cairo_drm_device_t *device)
+cairo_drm_device_throttle (cairo_device_t *abstract_device)
{
- if (device == NULL ||
- CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
- {
+ cairo_drm_device_t *device = (cairo_drm_device_t *) abstract_device;
+ cairo_status_t status;
+
+ if (unlikely (device->base.status))
return;
- }
- assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
- if (! _cairo_reference_count_dec_and_test (&device->ref_count))
+ if (device->device.throttle == NULL)
return;
- device->device.destroy (device);
+ status = device->device.throttle (device);
+ if (unlikely (status))
+ _cairo_status_set_error (&device->base.status, status);
}
-slim_hidden_def (cairo_drm_device_destroy);
-void
-cairo_drm_device_throttle (cairo_drm_device_t *dev)
+cairo_bool_t
+_cairo_drm_size_is_valid (cairo_device_t *abstract_device,
+ int width, int height)
{
- cairo_status_t status;
+ cairo_drm_device_t *device = (cairo_drm_device_t *) abstract_device;
- if (unlikely (dev->status))
- return;
+ if (unlikely (device->base.status))
+ return FALSE;
- if (dev->device.throttle == NULL)
- return;
-
- status = dev->device.throttle (dev);
- if (unlikely (status))
- _cairo_status_set_error (&dev->status, status);
+ return width <= device->max_surface_size &&
+ height <= device->max_surface_size;
}