]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
[drm] Add initial support for radeon cards
authorRay Strode <rstrode@redhat.com>
Sun, 20 Sep 2009 04:09:37 +0000 (00:09 -0400)
committerRay Strode <rstrode@redhat.com>
Mon, 28 Sep 2009 21:55:34 +0000 (17:55 -0400)
configure.ac
src/plugins/renderers/drm/Makefile.am
src/plugins/renderers/drm/plugin.c
src/plugins/renderers/drm/ply-renderer-radeon-driver.c [new file with mode: 0644]
src/plugins/renderers/drm/ply-renderer-radeon-driver.h [new file with mode: 0644]

index 9e92eaa6053e501fbac0354e484461cfed7a8196..5dee12a933b66e26df47551d8b7b6ba73b7f7058 100644 (file)
@@ -56,7 +56,7 @@ PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.12.0 ])
 AC_SUBST(GTK_CFLAGS)
 AC_SUBST(GTK_LIBS)
 
-PKG_CHECK_MODULES(DRM, [libdrm libdrm_intel])
+PKG_CHECK_MODULES(DRM, [libdrm libdrm_intel libdrm_radeon])
 AC_SUBST(DRM_CFLAGS)
 AC_SUBST(DRM_LIBS)
 
index a9ea2f931ed766ce27db779fbcfbb0d3eb505218..29bc642779e40983d9b627d04d3f89d0118dd677 100644 (file)
@@ -18,6 +18,8 @@ drm_la_LIBADD = $(PLYMOUTH_LIBS) $(DRM_LIBS)                                  \
 drm_la_SOURCES = $(srcdir)/plugin.c                                           \
                 $(srcdir)/ply-renderer-driver.h                              \
                 $(srcdir)/ply-renderer-i915-driver.h                         \
-                $(srcdir)/ply-renderer-i915-driver.c
+                $(srcdir)/ply-renderer-i915-driver.c                         \
+                $(srcdir)/ply-renderer-radeon-driver.h                       \
+                $(srcdir)/ply-renderer-radeon-driver.c
 
 MAINTAINERCLEANFILES = Makefile.in
index dd0a55a07318ffec0e60b21ea85657ecf9485d5f..0be43f0b312950bf258f4bbdd2cc6ed5c72a5571 100644 (file)
@@ -58,6 +58,7 @@
 #include "ply-renderer-plugin.h"
 #include "ply-renderer-driver.h"
 #include "ply-renderer-i915-driver.h"
+#include "ply-renderer-radeon-driver.h"
 
 #define BYTES_PER_PIXEL (4)
 
@@ -408,6 +409,10 @@ load_driver (ply_renderer_backend_t *backend)
     {
       backend->driver_interface = ply_renderer_i915_driver_get_interface ();
     }
+  else if (strcmp (driver_name, "radeon") == 0)
+    {
+      backend->driver_interface = ply_renderer_radeon_driver_get_interface ();
+    }
   free (driver_name);
 
   if (backend->driver_interface == NULL)
diff --git a/src/plugins/renderers/drm/ply-renderer-radeon-driver.c b/src/plugins/renderers/drm/ply-renderer-radeon-driver.c
new file mode 100644 (file)
index 0000000..be11dbf
--- /dev/null
@@ -0,0 +1,354 @@
+/* ply-renderer-radeon-driver.c - interface to radeon drm driver
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by: Ray Strode <rstrode@redhat.com>
+ */
+#include "config.h"
+
+#include "ply-renderer-radeon-driver.h"
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <values.h>
+#include <unistd.h>
+
+#include <drm/drm.h>
+#include <drm/radeon_drm.h>
+#include <drm/radeon_bo.h>
+#include <drm/radeon_bo_gem.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include "ply-hashtable.h"
+#include "ply-logger.h"
+#include "ply-renderer-driver.h"
+
+typedef struct _ply_renderer_buffer ply_renderer_buffer_t;
+
+struct _ply_renderer_buffer
+{
+  struct radeon_bo *object;
+  uint32_t id;
+  unsigned long width;
+  unsigned long height;
+  unsigned long row_stride;
+};
+
+struct _ply_renderer_driver
+{
+  int device_fd;
+  struct radeon_bo_manager *manager;
+
+  ply_hashtable_t *buffers;
+};
+
+static ply_renderer_driver_t *
+create_driver (int device_fd)
+{
+  ply_renderer_driver_t *driver;
+
+  driver = calloc (1, sizeof (ply_renderer_driver_t));
+  driver->device_fd = device_fd;
+
+  driver->manager = radeon_bo_manager_gem_ctor (driver->device_fd);
+  if (driver->manager == NULL)
+    {
+      free (driver);
+      return NULL;
+    }
+
+  driver->buffers = ply_hashtable_new (ply_hashtable_direct_hash,
+                                       ply_hashtable_direct_compare);
+
+  return driver;
+}
+
+static void
+destroy_driver (ply_renderer_driver_t *driver)
+{
+  ply_hashtable_free (driver->buffers);
+
+  radeon_bo_manager_gem_dtor (driver->manager);
+  free (driver);
+}
+
+static ply_renderer_buffer_t *
+ply_renderer_buffer_new (ply_renderer_driver_t *driver,
+                         struct radeon_bo *buffer_object,
+                         uint32_t id,
+                         unsigned long width,
+                         unsigned long height,
+                         unsigned long row_stride)
+{
+  ply_renderer_buffer_t *buffer;
+
+  buffer = calloc (1, sizeof (ply_renderer_buffer_t));
+  buffer->object = buffer_object;
+  buffer->id = id;
+  buffer->width = width;
+  buffer->height = height;
+  buffer->row_stride = row_stride;
+
+  return buffer;
+}
+
+static ply_renderer_buffer_t *
+get_buffer_from_id (ply_renderer_driver_t *driver,
+                    uint32_t               id)
+{
+  static ply_renderer_buffer_t *buffer;
+
+  buffer = ply_hashtable_lookup (driver->buffers, (void *) (uintptr_t) id);
+
+  return buffer;
+}
+
+static struct radeon_bo *
+create_radeon_bo_from_handle (ply_renderer_driver_t *driver,
+                              uint32_t               handle)
+{
+  struct drm_gem_flink flink_request;
+  struct radeon_bo *buffer_object;
+
+  /* FIXME: This can't be the right way to do this.
+   *
+   * 1) It requires skirting around the API and using ioctls
+   * 2) It requires taking a local handle, turning it into a
+   * a global handle ("name"), just so we can use an api that
+   * will open the global name and grab the local handle from it.
+   */
+
+  memset (&flink_request, 0, sizeof (struct drm_gem_flink));
+  flink_request.handle = handle;
+
+  if (ioctl (driver->device_fd, DRM_IOCTL_GEM_FLINK, &flink_request) < 0)
+    return NULL;
+
+  buffer_object = radeon_bo_open (driver->manager, flink_request.name,
+                                  0, 0, RADEON_GEM_DOMAIN_GTT, 0);
+
+  return buffer_object;
+}
+
+static ply_renderer_buffer_t *
+ply_renderer_buffer_new_from_id (ply_renderer_driver_t *driver,
+                                 uint32_t               buffer_id)
+{
+  ply_renderer_buffer_t *buffer;
+  drmModeFB *fb;
+  struct radeon_bo *buffer_object;
+
+  fb = drmModeGetFB (driver->device_fd, buffer_id);
+
+  if (fb == NULL)
+    return NULL;
+
+  buffer_object = create_radeon_bo_from_handle (driver, fb->handle);
+
+  if (buffer_object == NULL)
+    {
+      drmModeFreeFB (fb);
+      return NULL;
+    }
+
+  buffer = ply_renderer_buffer_new (driver, buffer_object, buffer_id,
+                                    fb->width, fb->height, fb->pitch);
+  drmModeFreeFB (fb);
+
+  return buffer;
+}
+
+
+static bool
+fetch_buffer (ply_renderer_driver_t *driver,
+              uint32_t               buffer_id,
+              unsigned long         *width,
+              unsigned long         *height,
+              unsigned long         *row_stride)
+{
+  ply_renderer_buffer_t *buffer;
+
+  buffer = get_buffer_from_id (driver, buffer_id);
+
+  if (buffer == NULL)
+    {
+      buffer = ply_renderer_buffer_new_from_id (driver, buffer_id);
+
+      if (buffer == NULL)
+        return false;
+
+      ply_hashtable_insert (driver->buffers,
+                            (void *) (uintptr_t) buffer_id,
+                            buffer);
+    }
+
+  if (width != NULL)
+    *width = buffer->width;
+
+  if (height != NULL)
+    *height = buffer->height;
+
+  if (row_stride != NULL)
+    *row_stride = buffer->row_stride;
+
+  return true;
+}
+
+static uint32_t
+create_buffer (ply_renderer_driver_t *driver,
+               unsigned long          width,
+               unsigned long          height,
+               unsigned long         *row_stride)
+{
+  struct radeon_bo *buffer_object;
+  ply_renderer_buffer_t *buffer;
+  uint32_t buffer_id;
+
+  *row_stride = ply_round_to_multiple (width * 4, 256);
+
+  buffer_object = radeon_bo_open (driver->manager, 0,
+                                  height * *row_stride,
+                                  0, RADEON_GEM_DOMAIN_GTT, 0);
+
+  if (buffer_object == NULL)
+    {
+      ply_trace ("Could not allocate GEM object for frame buffer: %m");
+      return 0;
+    }
+
+  if (drmModeAddFB (driver->device_fd, width, height,
+                    24, 32, *row_stride, buffer_object->handle,
+                    &buffer_id) != 0)
+    {
+      ply_trace ("Could not set up GEM object as frame buffer: %m");
+      radeon_bo_unref (buffer_object);
+      return 0;
+    }
+
+  buffer = ply_renderer_buffer_new (driver,
+                                    buffer_object, buffer_id,
+                                    width, height, *row_stride);
+  ply_hashtable_insert (driver->buffers,
+                        (void *) (uintptr_t) buffer_id,
+                        buffer);
+
+  return buffer_id;
+}
+
+static bool
+map_buffer (ply_renderer_driver_t *driver,
+            uint32_t               buffer_id)
+{
+  ply_renderer_buffer_t *buffer;
+
+  buffer = get_buffer_from_id (driver, buffer_id);
+
+  assert (buffer != NULL);
+
+  return radeon_bo_map (buffer->object, true) == 0;
+}
+
+static void
+unmap_buffer (ply_renderer_driver_t *driver,
+              uint32_t               buffer_id)
+{
+  ply_renderer_buffer_t *buffer;
+
+  buffer = get_buffer_from_id (driver, buffer_id);
+
+  assert (buffer != NULL);
+
+  radeon_bo_unmap (buffer->object);
+}
+
+static char *
+begin_flush (ply_renderer_driver_t *driver,
+             uint32_t               buffer_id)
+{
+  ply_renderer_buffer_t *buffer;
+
+  buffer = get_buffer_from_id (driver, buffer_id);
+
+  assert (buffer != NULL);
+
+  return buffer->object->ptr;
+}
+
+static void
+end_flush (ply_renderer_driver_t *driver,
+           uint32_t               buffer_id)
+{
+  ply_renderer_buffer_t *buffer;
+
+  buffer = get_buffer_from_id (driver, buffer_id);
+
+  assert (buffer != NULL);
+}
+
+static void
+destroy_buffer (ply_renderer_driver_t *driver,
+                uint32_t               buffer_id)
+{
+  ply_renderer_buffer_t *buffer;
+
+  buffer = get_buffer_from_id (driver, buffer_id);
+
+  assert (buffer != NULL);
+
+  drmModeRmFB (driver->device_fd, buffer->id);
+
+  radeon_bo_unref (buffer->object);
+
+  ply_hashtable_remove (driver->buffers,
+                        (void *) (uintptr_t) buffer_id);
+  free (buffer);
+}
+
+ply_renderer_driver_interface_t *
+ply_renderer_radeon_driver_get_interface (void)
+{
+  static ply_renderer_driver_interface_t driver_interface =
+    {
+      .create_driver = create_driver,
+      .destroy_driver = destroy_driver,
+      .create_buffer = create_buffer,
+      .fetch_buffer = fetch_buffer,
+      .map_buffer = map_buffer,
+      .unmap_buffer = unmap_buffer,
+      .begin_flush = begin_flush,
+      .end_flush = end_flush,
+      .destroy_buffer = destroy_buffer,
+    };
+
+  return &driver_interface;
+}
+
+/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
diff --git a/src/plugins/renderers/drm/ply-renderer-radeon-driver.h b/src/plugins/renderers/drm/ply-renderer-radeon-driver.h
new file mode 100644 (file)
index 0000000..dcec1b1
--- /dev/null
@@ -0,0 +1,32 @@
+/* ply-renderer-radeon-driver.h
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written By: Ray Strode <rstrode@redhat.com>
+ */
+#ifndef PLY_RENDERER_RADEON_DRIVER_H
+#define PLY_RENDERER_RADEON_DRIVER_H
+
+#include "ply-renderer-driver.h"
+
+#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
+ply_renderer_driver_interface_t *ply_renderer_radeon_driver_get_interface (void);
+#endif
+
+#endif /* PLY_RENDERER_RADEON_DRIVER_H */
+/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */