summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Levy <alevy@redhat.com>2012-07-22 17:31:22 +0300
committerAlon Levy <alevy@redhat.com>2012-10-23 18:46:58 +0200
commit3bf1fc61a7a9b902d5a64530a62f2df34090e2c7 (patch)
treee05cb3b7c1db1edb5a4052dfb115b4414afad4ab
parent80675313563b28158de8773cf2ca156ef573200d (diff)
qxl: add cb create_primary_surface
-rw-r--r--src/qxl.h1
-rw-r--r--src/qxl_driver.c84
-rw-r--r--src/qxl_surface.c21
3 files changed, 88 insertions, 18 deletions
diff --git a/src/qxl.h b/src/qxl.h
index c0b5625..8674162 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -239,6 +239,7 @@ struct _qxl_screen_t
int drm_fd;
void (*reset_and_create_mem_slots)(qxl_screen_t *qxl);
+ uint8_t *(*create_primary_surface)(qxl_screen_t *qxl, QXLMode *mode);
#ifdef XSPICE
/* XSpice specific */
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index 976d9e0..83d7252 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -38,10 +38,12 @@
#include <errno.h>
#include <time.h>
#include <stdlib.h>
+#include <sys/mman.h>
#include <xf86drm.h>
#include <xf86Crtc.h>
#include <xf86RandR12.h>
+#include <libdrm/qxl_drm.h>
#include "mspace.h"
@@ -222,8 +224,84 @@ qxl_io_create_primary (qxl_screen_t *qxl)
qxl->device_primary = QXL_DEVICE_PRIMARY_CREATED;
}
-void
-qxl_io_destroy_primary (qxl_screen_t *qxl)
+static uint64_t qxl_kms_alloc_resource(qxl_screen_t *qxl,
+ uint32_t size, uint32_t type)
+{
+ struct drm_qxl_alloc alloc;
+ int ret;
+
+ alloc.type = type;
+ alloc.size = size;
+ alloc.handle = 0;
+ ret = drmIoctl(qxl->drm_fd, DRM_IOCTL_QXL_ALLOC, &alloc);
+ if (ret) {
+ xf86DrvMsg(qxl->pScrn->scrnIndex, X_ERROR,
+ "error doing QXL_ALLOC\n");
+ return 0; // an invalid handle
+ }
+ return alloc.handle;
+}
+
+static void *
+qxl_kms_mmap(qxl_screen_t *qxl, uint32_t handle, size_t size)
+{
+ struct drm_qxl_map qxl_map;
+ void *map;
+
+ memset(&qxl_map, 0, sizeof(qxl_map));
+ qxl_map.handle = handle;
+ qxl_map.offset = 0; // filled by kernel
+
+ if (drmIoctl(qxl->drm_fd, DRM_IOCTL_QXL_MAP, &qxl_map)) {
+ xf86DrvMsg(qxl->pScrn->scrnIndex, X_ERROR,
+ "error doing QXL_MAP: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ map = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, qxl->drm_fd,
+ qxl_map.offset);
+ if (map == MAP_FAILED) {
+ xf86DrvMsg(qxl->pScrn->scrnIndex, X_ERROR,
+ "mmap failure: %s\n", strerror(errno));
+ return NULL;
+ }
+ return map;
+}
+
+static uint8_t *
+qxl_kms_create_primary_surface(qxl_screen_t *qxl, QXLMode *mode)
+{
+ // TODO - actually set primary to mode. Requires no new ioctl introduction,
+ // reuse the dumb ones for this, should be perfect.
+ // NB: size needs to match closely with mode.
+ size_t size = 640*480*4;
+
+ uint64_t handle = qxl_kms_alloc_resource(qxl, size,
+ QXL_ALLOC_TYPE_SURFACE_PRIMARY);
+ // NB: we may be repeatedly mapping here. should be cached.
+ return qxl_kms_mmap(qxl, handle, size);
+}
+
+static uint8_t *
+qxl_ums_create_primary_surface(qxl_screen_t *qxl, QXLMode *mode)
+{
+ struct QXLRam *ram_header =
+ (void *)((unsigned long)qxl->ram + qxl->rom->ram_header_offset);
+ struct QXLSurfaceCreate *create = &(ram_header->create_surface);
+
+ create->width = mode->x_res;
+ create->height = mode->y_res;
+ create->stride = - mode->stride;
+ create->format = mode->bits;
+ create->position = 0; /* What is this? The Windows driver doesn't use it */
+ create->flags = 0;
+ create->type = QXL_SURF_TYPE_PRIMARY;
+ create->mem = physical_address (qxl, qxl->ram, qxl->main_mem_slot);
+ qxl_io_create_primary(qxl);
+ return (uint8_t *)qxl->ram + mode->stride * (mode->y_res - 1);
+}
+
+void qxl_io_destroy_primary(qxl_screen_t *qxl)
{
#ifndef XSPICE
if (qxl->pci->revision >= 3)
@@ -2390,6 +2468,7 @@ static void
set_callbacks_to_ums(qxl_screen_t *qxl)
{
qxl->reset_and_create_mem_slots = qxl_ums_reset_and_create_mem_slots;
+ qxl->create_primary_surface = qxl_ums_create_primary_surface;
}
#ifndef XSPICE
@@ -2397,6 +2476,7 @@ static void
set_callbacks_to_kms(qxl_screen_t *qxl)
{
qxl->reset_and_create_mem_slots = qxl_kms_reset_and_create_mem_slots;
+ qxl->create_primary_surface = qxl_kms_create_primary_surface;
}
#endif
diff --git a/src/qxl_surface.c b/src/qxl_surface.c
index e88675f..8f0d227 100644
--- a/src/qxl_surface.c
+++ b/src/qxl_surface.c
@@ -364,9 +364,6 @@ qxl_surface_t *
qxl_surface_cache_create_primary (surface_cache_t *cache,
struct QXLMode *mode)
{
- struct QXLRam *ram_header =
- (void *)((unsigned long)cache->qxl->ram + cache->qxl->rom->ram_header_offset);
- struct QXLSurfaceCreate *create = &(ram_header->create_surface);
pixman_format_code_t format;
uint8_t *dev_addr;
pixman_image_t *dev_image, *host_image;
@@ -387,19 +384,11 @@ qxl_surface_cache_create_primary (surface_cache_t *cache,
"Unknown bit depth %d\n", mode->bits);
return NULL;
}
-
- create->width = mode->x_res;
- create->height = mode->y_res;
- create->stride = - mode->stride;
- create->format = mode->bits;
- create->position = 0; /* What is this? The Windows driver doesn't use it */
- create->flags = 0;
- create->type = QXL_SURF_TYPE_PRIMARY;
- create->mem = physical_address (cache->qxl, cache->qxl->ram, cache->qxl->main_mem_slot);
-
- qxl_io_create_primary(qxl);
-
- dev_addr = (uint8_t *)qxl->ram + mode->stride * (mode->y_res - 1);
+
+ dev_addr = qxl->create_primary_surface(qxl, mode);
+ if (!dev_addr) {
+ return NULL;
+ }
dev_image = pixman_image_create_bits (format, mode->x_res, mode->y_res,
(uint32_t *)dev_addr, -mode->stride);