summaryrefslogtreecommitdiff
path: root/src/qxl_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/qxl_driver.c')
-rw-r--r--src/qxl_driver.c84
1 files changed, 82 insertions, 2 deletions
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