diff options
Diffstat (limited to 'src/qxl_driver.c')
-rw-r--r-- | src/qxl_driver.c | 84 |
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 |