Merge remote-tracking branch 'origin/master' into pipe-video
[mesa.git] / src / gallium / winsys / r600 / drm / r600_drm.c
index f5cd48d39c67367746958bba4f77f0953fb9cee8..311324f4f7135c2c3c00cf9b239fdd134cbbb847 100644 (file)
@@ -30,6 +30,7 @@
 #include <sys/ioctl.h>
 #include "util/u_inlines.h"
 #include "util/u_debug.h"
+#include "util/u_hash_table.h"
 #include <pipebuffer/pb_bufmgr.h>
 #include "r600.h"
 #include "r600_priv.h"
 #define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x9
 #endif
 
+#ifndef RADEON_INFO_NUM_BACKENDS
+#define RADEON_INFO_NUM_BACKENDS 0xa
+#endif
+
 enum radeon_family r600_get_family(struct radeon *r600)
 {
        return r600->family;
@@ -65,6 +70,17 @@ unsigned r600_get_clock_crystal_freq(struct radeon *radeon)
        return radeon->clock_crystal_freq;
 }
 
+unsigned r600_get_num_backends(struct radeon *radeon)
+{
+       return radeon->num_backends;
+}
+
+unsigned r600_get_minor_version(struct radeon *radeon)
+{
+       return radeon->minor_version;
+}
+
+
 static int radeon_get_device(struct radeon *radeon)
 {
        struct drm_radeon_info info = {};
@@ -183,7 +199,6 @@ static int radeon_get_clock_crystal_freq(struct radeon *radeon)
        uint32_t clock_crystal_freq;
        int r;
 
-       radeon->device = 0;
        info.request = RADEON_INFO_CLOCK_CRYSTAL_FREQ;
        info.value = (uintptr_t)&clock_crystal_freq;
        r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
@@ -195,6 +210,25 @@ static int radeon_get_clock_crystal_freq(struct radeon *radeon)
        return 0;
 }
 
+
+static int radeon_get_num_backends(struct radeon *radeon)
+{
+       struct drm_radeon_info info;
+       uint32_t num_backends;
+       int r;
+
+       info.request = RADEON_INFO_NUM_BACKENDS;
+       info.value = (uintptr_t)&num_backends;
+       r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
+                       sizeof(struct drm_radeon_info));
+       if (r)
+               return r;
+
+       radeon->num_backends = num_backends;
+       return 0;
+}
+
+
 static int radeon_init_fence(struct radeon *radeon)
 {
        radeon->fence = 1;
@@ -207,10 +241,23 @@ static int radeon_init_fence(struct radeon *radeon)
        return 0;
 }
 
+#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
+
+static unsigned handle_hash(void *key)
+{
+    return PTR_TO_UINT(key);
+}
+
+static int handle_compare(void *key1, void *key2)
+{
+    return PTR_TO_UINT(key1) != PTR_TO_UINT(key2);
+}
+
 static struct radeon *radeon_new(int fd, unsigned device)
 {
        struct radeon *radeon;
        int r;
+       drmVersionPtr version;
 
        radeon = calloc(1, sizeof(*radeon));
        if (radeon == NULL) {
@@ -219,13 +266,27 @@ static struct radeon *radeon_new(int fd, unsigned device)
        radeon->fd = fd;
        radeon->device = device;
        radeon->refcount = 1;
-       if (fd >= 0) {
-               r = radeon_get_device(radeon);
-               if (r) {
-                       fprintf(stderr, "Failed to get device id\n");
-                       return radeon_decref(radeon);
-               }
+
+       version = drmGetVersion(radeon->fd);
+       if (version->version_major != 2) {
+               fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is "
+                       "only compatible with 2.x.x\n", __FUNCTION__,
+                       version->version_major, version->version_minor,
+                       version->version_patchlevel);
+               drmFreeVersion(version);
+               exit(1);
        }
+
+       radeon->minor_version = version->version_minor;
+
+       drmFreeVersion(version);
+
+       r = radeon_get_device(radeon);
+       if (r) {
+               fprintf(stderr, "Failed to get device id\n");
+               return radeon_decref(radeon);
+       }
+
        radeon->family = radeon_family_from_device(radeon->device);
        if (radeon->family == CHIP_UNKNOWN) {
                fprintf(stderr, "Unknown chipset 0x%04X\n", radeon->device);
@@ -278,6 +339,9 @@ static struct radeon *radeon_new(int fd, unsigned device)
        /* get the GPU counter frequency, failure is non fatal */
        radeon_get_clock_crystal_freq(radeon);
 
+       if (radeon->minor_version >= 9)
+               radeon_get_num_backends(radeon);
+
        radeon->bomgr = r600_bomgr_create(radeon, 1000000);
        if (radeon->bomgr == NULL) {
                return NULL;
@@ -287,6 +351,9 @@ static struct radeon *radeon_new(int fd, unsigned device)
                radeon_decref(radeon);
                return NULL;
        }
+
+       radeon->bo_handles = util_hash_table_create(handle_hash, handle_compare);
+       pipe_mutex_init(radeon->bo_handles_mutex);
        return radeon;
 }
 
@@ -303,6 +370,8 @@ struct radeon *radeon_decref(struct radeon *radeon)
                return NULL;
        }
 
+       util_hash_table_destroy(radeon->bo_handles);
+       pipe_mutex_destroy(radeon->bo_handles_mutex);
        if (radeon->fence_bo) {
                r600_bo_reference(radeon, &radeon->fence_bo, NULL);
        }
@@ -310,9 +379,6 @@ struct radeon *radeon_decref(struct radeon *radeon)
        if (radeon->bomgr)
                r600_bomgr_destroy(radeon->bomgr);
 
-       if (radeon->fd >= 0)
-               drmClose(radeon->fd);
-
        free(radeon);
        return NULL;
 }