1bb994653667986757b4c906b8f144737667f7374Dave Airlie/************************************************************************** 2bb994653667986757b4c906b8f144737667f7374Dave Airlie * 3bb994653667986757b4c906b8f144737667f7374Dave Airlie * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA 4bb994653667986757b4c906b8f144737667f7374Dave Airlie * All Rights Reserved. 5bb994653667986757b4c906b8f144737667f7374Dave Airlie * 6bb994653667986757b4c906b8f144737667f7374Dave Airlie * Permission is hereby granted, free of charge, to any person obtaining a 7bb994653667986757b4c906b8f144737667f7374Dave Airlie * copy of this software and associated documentation files (the 8bb994653667986757b4c906b8f144737667f7374Dave Airlie * "Software"), to deal in the Software without restriction, including 9bb994653667986757b4c906b8f144737667f7374Dave Airlie * without limitation the rights to use, copy, modify, merge, publish, 10bb994653667986757b4c906b8f144737667f7374Dave Airlie * distribute, sub license, and/or sell copies of the Software, and to 11bb994653667986757b4c906b8f144737667f7374Dave Airlie * permit persons to whom the Software is furnished to do so, subject to 12bb994653667986757b4c906b8f144737667f7374Dave Airlie * the following conditions: 13bb994653667986757b4c906b8f144737667f7374Dave Airlie * 14bb994653667986757b4c906b8f144737667f7374Dave Airlie * The above copyright notice and this permission notice (including the 15bb994653667986757b4c906b8f144737667f7374Dave Airlie * next paragraph) shall be included in all copies or substantial portions 16bb994653667986757b4c906b8f144737667f7374Dave Airlie * of the Software. 17bb994653667986757b4c906b8f144737667f7374Dave Airlie * 18bb994653667986757b4c906b8f144737667f7374Dave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19bb994653667986757b4c906b8f144737667f7374Dave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20bb994653667986757b4c906b8f144737667f7374Dave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21bb994653667986757b4c906b8f144737667f7374Dave Airlie * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22bb994653667986757b4c906b8f144737667f7374Dave Airlie * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23bb994653667986757b4c906b8f144737667f7374Dave Airlie * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24bb994653667986757b4c906b8f144737667f7374Dave Airlie * USE OR OTHER DEALINGS IN THE SOFTWARE. 25bb994653667986757b4c906b8f144737667f7374Dave Airlie * 26bb994653667986757b4c906b8f144737667f7374Dave Airlie **************************************************************************/ 27bb994653667986757b4c906b8f144737667f7374Dave Airlie 28bb994653667986757b4c906b8f144737667f7374Dave Airlie 298e93afc9765f1de613c65a76e9a86e17db96e653Emil Velikov#ifdef HAVE_CONFIG_H 308e93afc9765f1de613c65a76e9a86e17db96e653Emil Velikov#include "config.h" 318e93afc9765f1de613c65a76e9a86e17db96e653Emil Velikov#endif 32bb994653667986757b4c906b8f144737667f7374Dave Airlie 33bb994653667986757b4c906b8f144737667f7374Dave Airlie#include <errno.h> 34bb994653667986757b4c906b8f144737667f7374Dave Airlie#include <stdio.h> 35bb994653667986757b4c906b8f144737667f7374Dave Airlie#include <stdlib.h> 36bb994653667986757b4c906b8f144737667f7374Dave Airlie#include <string.h> 37bb994653667986757b4c906b8f144737667f7374Dave Airlie#include "internal.h" 38bb994653667986757b4c906b8f144737667f7374Dave Airlie 39bb994653667986757b4c906b8f144737667f7374Dave Airlie#include <sys/ioctl.h> 40bb994653667986757b4c906b8f144737667f7374Dave Airlie#include "xf86drm.h" 41dadc9eff9fd606335a7b3d5d58065a2e8d629672Emil Velikov#include "libdrm.h" 42bb994653667986757b4c906b8f144737667f7374Dave Airlie 43bb994653667986757b4c906b8f144737667f7374Dave Airliestruct dumb_bo 44bb994653667986757b4c906b8f144737667f7374Dave Airlie{ 45bb994653667986757b4c906b8f144737667f7374Dave Airlie struct kms_bo base; 46bb994653667986757b4c906b8f144737667f7374Dave Airlie unsigned map_count; 47bb994653667986757b4c906b8f144737667f7374Dave Airlie}; 48bb994653667986757b4c906b8f144737667f7374Dave Airlie 49bb994653667986757b4c906b8f144737667f7374Dave Airliestatic int 50bb994653667986757b4c906b8f144737667f7374Dave Airliedumb_get_prop(struct kms_driver *kms, unsigned key, unsigned *out) 51bb994653667986757b4c906b8f144737667f7374Dave Airlie{ 52bb994653667986757b4c906b8f144737667f7374Dave Airlie switch (key) { 53bb994653667986757b4c906b8f144737667f7374Dave Airlie case KMS_BO_TYPE: 54bb994653667986757b4c906b8f144737667f7374Dave Airlie *out = KMS_BO_TYPE_SCANOUT_X8R8G8B8 | KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8; 55bb994653667986757b4c906b8f144737667f7374Dave Airlie break; 56bb994653667986757b4c906b8f144737667f7374Dave Airlie default: 57bb994653667986757b4c906b8f144737667f7374Dave Airlie return -EINVAL; 58bb994653667986757b4c906b8f144737667f7374Dave Airlie } 59bb994653667986757b4c906b8f144737667f7374Dave Airlie return 0; 60bb994653667986757b4c906b8f144737667f7374Dave Airlie} 61bb994653667986757b4c906b8f144737667f7374Dave Airlie 62bb994653667986757b4c906b8f144737667f7374Dave Airliestatic int 63bb994653667986757b4c906b8f144737667f7374Dave Airliedumb_destroy(struct kms_driver *kms) 64bb994653667986757b4c906b8f144737667f7374Dave Airlie{ 65bb994653667986757b4c906b8f144737667f7374Dave Airlie free(kms); 66bb994653667986757b4c906b8f144737667f7374Dave Airlie return 0; 67bb994653667986757b4c906b8f144737667f7374Dave Airlie} 68bb994653667986757b4c906b8f144737667f7374Dave Airlie 69bb994653667986757b4c906b8f144737667f7374Dave Airliestatic int 70bb994653667986757b4c906b8f144737667f7374Dave Airliedumb_bo_create(struct kms_driver *kms, 71bb994653667986757b4c906b8f144737667f7374Dave Airlie const unsigned width, const unsigned height, 72bb994653667986757b4c906b8f144737667f7374Dave Airlie const enum kms_bo_type type, const unsigned *attr, 73bb994653667986757b4c906b8f144737667f7374Dave Airlie struct kms_bo **out) 74bb994653667986757b4c906b8f144737667f7374Dave Airlie{ 75bb994653667986757b4c906b8f144737667f7374Dave Airlie struct drm_mode_create_dumb arg; 76bb994653667986757b4c906b8f144737667f7374Dave Airlie struct dumb_bo *bo; 77bb994653667986757b4c906b8f144737667f7374Dave Airlie int i, ret; 78bb994653667986757b4c906b8f144737667f7374Dave Airlie 79bb994653667986757b4c906b8f144737667f7374Dave Airlie for (i = 0; attr[i]; i += 2) { 80bb994653667986757b4c906b8f144737667f7374Dave Airlie switch (attr[i]) { 81bb994653667986757b4c906b8f144737667f7374Dave Airlie case KMS_WIDTH: 82bb994653667986757b4c906b8f144737667f7374Dave Airlie case KMS_HEIGHT: 83bb994653667986757b4c906b8f144737667f7374Dave Airlie break; 84bb994653667986757b4c906b8f144737667f7374Dave Airlie case KMS_BO_TYPE: 85bb994653667986757b4c906b8f144737667f7374Dave Airlie break; 86bb994653667986757b4c906b8f144737667f7374Dave Airlie default: 87bb994653667986757b4c906b8f144737667f7374Dave Airlie return -EINVAL; 88bb994653667986757b4c906b8f144737667f7374Dave Airlie } 89bb994653667986757b4c906b8f144737667f7374Dave Airlie } 90bb994653667986757b4c906b8f144737667f7374Dave Airlie 91bb994653667986757b4c906b8f144737667f7374Dave Airlie bo = calloc(1, sizeof(*bo)); 92bb994653667986757b4c906b8f144737667f7374Dave Airlie if (!bo) 93bb994653667986757b4c906b8f144737667f7374Dave Airlie return -ENOMEM; 94bb994653667986757b4c906b8f144737667f7374Dave Airlie 95bb994653667986757b4c906b8f144737667f7374Dave Airlie memset(&arg, 0, sizeof(arg)); 96bb994653667986757b4c906b8f144737667f7374Dave Airlie 9761be94018ae9c403517d53f69357719224fa6ff3Chris Wilson /* All BO_TYPE currently are 32bpp formats */ 9861be94018ae9c403517d53f69357719224fa6ff3Chris Wilson arg.bpp = 32; 99bb994653667986757b4c906b8f144737667f7374Dave Airlie arg.width = width; 100bb994653667986757b4c906b8f144737667f7374Dave Airlie arg.height = height; 101bb994653667986757b4c906b8f144737667f7374Dave Airlie 102bb994653667986757b4c906b8f144737667f7374Dave Airlie ret = drmIoctl(kms->fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg); 103bb994653667986757b4c906b8f144737667f7374Dave Airlie if (ret) 104bb994653667986757b4c906b8f144737667f7374Dave Airlie goto err_free; 105bb994653667986757b4c906b8f144737667f7374Dave Airlie 106bb994653667986757b4c906b8f144737667f7374Dave Airlie bo->base.kms = kms; 107bb994653667986757b4c906b8f144737667f7374Dave Airlie bo->base.handle = arg.handle; 108bb994653667986757b4c906b8f144737667f7374Dave Airlie bo->base.size = arg.size; 109bb994653667986757b4c906b8f144737667f7374Dave Airlie bo->base.pitch = arg.pitch; 110bb994653667986757b4c906b8f144737667f7374Dave Airlie 111bb994653667986757b4c906b8f144737667f7374Dave Airlie *out = &bo->base; 112bb994653667986757b4c906b8f144737667f7374Dave Airlie 113bb994653667986757b4c906b8f144737667f7374Dave Airlie return 0; 114bb994653667986757b4c906b8f144737667f7374Dave Airlie 115bb994653667986757b4c906b8f144737667f7374Dave Airlieerr_free: 116bb994653667986757b4c906b8f144737667f7374Dave Airlie free(bo); 117bb994653667986757b4c906b8f144737667f7374Dave Airlie return ret; 118bb994653667986757b4c906b8f144737667f7374Dave Airlie} 119bb994653667986757b4c906b8f144737667f7374Dave Airlie 120bb994653667986757b4c906b8f144737667f7374Dave Airliestatic int 121bb994653667986757b4c906b8f144737667f7374Dave Airliedumb_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out) 122bb994653667986757b4c906b8f144737667f7374Dave Airlie{ 123bb994653667986757b4c906b8f144737667f7374Dave Airlie switch (key) { 124bb994653667986757b4c906b8f144737667f7374Dave Airlie default: 125bb994653667986757b4c906b8f144737667f7374Dave Airlie return -EINVAL; 126bb994653667986757b4c906b8f144737667f7374Dave Airlie } 127bb994653667986757b4c906b8f144737667f7374Dave Airlie} 128bb994653667986757b4c906b8f144737667f7374Dave Airlie 129bb994653667986757b4c906b8f144737667f7374Dave Airliestatic int 130bb994653667986757b4c906b8f144737667f7374Dave Airliedumb_bo_map(struct kms_bo *_bo, void **out) 131bb994653667986757b4c906b8f144737667f7374Dave Airlie{ 132bb994653667986757b4c906b8f144737667f7374Dave Airlie struct dumb_bo *bo = (struct dumb_bo *)_bo; 133bb994653667986757b4c906b8f144737667f7374Dave Airlie struct drm_mode_map_dumb arg; 134bb994653667986757b4c906b8f144737667f7374Dave Airlie void *map = NULL; 135bb994653667986757b4c906b8f144737667f7374Dave Airlie int ret; 136bb994653667986757b4c906b8f144737667f7374Dave Airlie 137bb994653667986757b4c906b8f144737667f7374Dave Airlie if (bo->base.ptr) { 138bb994653667986757b4c906b8f144737667f7374Dave Airlie bo->map_count++; 139bb994653667986757b4c906b8f144737667f7374Dave Airlie *out = bo->base.ptr; 140bb994653667986757b4c906b8f144737667f7374Dave Airlie return 0; 141bb994653667986757b4c906b8f144737667f7374Dave Airlie } 142bb994653667986757b4c906b8f144737667f7374Dave Airlie 143bb994653667986757b4c906b8f144737667f7374Dave Airlie memset(&arg, 0, sizeof(arg)); 144bb994653667986757b4c906b8f144737667f7374Dave Airlie arg.handle = bo->base.handle; 145bb994653667986757b4c906b8f144737667f7374Dave Airlie 146bb994653667986757b4c906b8f144737667f7374Dave Airlie ret = drmIoctl(bo->base.kms->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg); 147bb994653667986757b4c906b8f144737667f7374Dave Airlie if (ret) 148bb994653667986757b4c906b8f144737667f7374Dave Airlie return ret; 149bb994653667986757b4c906b8f144737667f7374Dave Airlie 150dadc9eff9fd606335a7b3d5d58065a2e8d629672Emil Velikov map = drm_mmap(0, bo->base.size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->base.kms->fd, arg.offset); 151bb994653667986757b4c906b8f144737667f7374Dave Airlie if (map == MAP_FAILED) 152bb994653667986757b4c906b8f144737667f7374Dave Airlie return -errno; 153bb994653667986757b4c906b8f144737667f7374Dave Airlie 154bb994653667986757b4c906b8f144737667f7374Dave Airlie bo->base.ptr = map; 155bb994653667986757b4c906b8f144737667f7374Dave Airlie bo->map_count++; 156bb994653667986757b4c906b8f144737667f7374Dave Airlie *out = bo->base.ptr; 157bb994653667986757b4c906b8f144737667f7374Dave Airlie 158bb994653667986757b4c906b8f144737667f7374Dave Airlie return 0; 159bb994653667986757b4c906b8f144737667f7374Dave Airlie} 160bb994653667986757b4c906b8f144737667f7374Dave Airlie 161bb994653667986757b4c906b8f144737667f7374Dave Airliestatic int 162bb994653667986757b4c906b8f144737667f7374Dave Airliedumb_bo_unmap(struct kms_bo *_bo) 163bb994653667986757b4c906b8f144737667f7374Dave Airlie{ 164bb994653667986757b4c906b8f144737667f7374Dave Airlie struct dumb_bo *bo = (struct dumb_bo *)_bo; 165bb994653667986757b4c906b8f144737667f7374Dave Airlie bo->map_count--; 166bb994653667986757b4c906b8f144737667f7374Dave Airlie return 0; 167bb994653667986757b4c906b8f144737667f7374Dave Airlie} 168bb994653667986757b4c906b8f144737667f7374Dave Airlie 169bb994653667986757b4c906b8f144737667f7374Dave Airliestatic int 170bb994653667986757b4c906b8f144737667f7374Dave Airliedumb_bo_destroy(struct kms_bo *_bo) 171bb994653667986757b4c906b8f144737667f7374Dave Airlie{ 172bb994653667986757b4c906b8f144737667f7374Dave Airlie struct dumb_bo *bo = (struct dumb_bo *)_bo; 173bb994653667986757b4c906b8f144737667f7374Dave Airlie struct drm_mode_destroy_dumb arg; 174bb994653667986757b4c906b8f144737667f7374Dave Airlie int ret; 175bb994653667986757b4c906b8f144737667f7374Dave Airlie 176bb994653667986757b4c906b8f144737667f7374Dave Airlie if (bo->base.ptr) { 177bb994653667986757b4c906b8f144737667f7374Dave Airlie /* XXX Sanity check map_count */ 178dadc9eff9fd606335a7b3d5d58065a2e8d629672Emil Velikov drm_munmap(bo->base.ptr, bo->base.size); 179bb994653667986757b4c906b8f144737667f7374Dave Airlie bo->base.ptr = NULL; 180bb994653667986757b4c906b8f144737667f7374Dave Airlie } 181bb994653667986757b4c906b8f144737667f7374Dave Airlie 182bb994653667986757b4c906b8f144737667f7374Dave Airlie memset(&arg, 0, sizeof(arg)); 183bb994653667986757b4c906b8f144737667f7374Dave Airlie arg.handle = bo->base.handle; 184bb994653667986757b4c906b8f144737667f7374Dave Airlie 185bb994653667986757b4c906b8f144737667f7374Dave Airlie ret = drmIoctl(bo->base.kms->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg); 186bb994653667986757b4c906b8f144737667f7374Dave Airlie if (ret) 187bb994653667986757b4c906b8f144737667f7374Dave Airlie return -errno; 188bb994653667986757b4c906b8f144737667f7374Dave Airlie 189bb994653667986757b4c906b8f144737667f7374Dave Airlie free(bo); 190bb994653667986757b4c906b8f144737667f7374Dave Airlie return 0; 191bb994653667986757b4c906b8f144737667f7374Dave Airlie} 192bb994653667986757b4c906b8f144737667f7374Dave Airlie 193bb994653667986757b4c906b8f144737667f7374Dave Airlieint 194bb994653667986757b4c906b8f144737667f7374Dave Airliedumb_create(int fd, struct kms_driver **out) 195bb994653667986757b4c906b8f144737667f7374Dave Airlie{ 196bb994653667986757b4c906b8f144737667f7374Dave Airlie struct kms_driver *kms; 197bb994653667986757b4c906b8f144737667f7374Dave Airlie int ret; 198bb994653667986757b4c906b8f144737667f7374Dave Airlie uint64_t cap = 0; 199bb994653667986757b4c906b8f144737667f7374Dave Airlie 200bb994653667986757b4c906b8f144737667f7374Dave Airlie ret = drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &cap); 201bb994653667986757b4c906b8f144737667f7374Dave Airlie if (ret || cap == 0) 202bb994653667986757b4c906b8f144737667f7374Dave Airlie return -EINVAL; 203bb994653667986757b4c906b8f144737667f7374Dave Airlie 204bb994653667986757b4c906b8f144737667f7374Dave Airlie kms = calloc(1, sizeof(*kms)); 205bb994653667986757b4c906b8f144737667f7374Dave Airlie if (!kms) 206bb994653667986757b4c906b8f144737667f7374Dave Airlie return -ENOMEM; 207bb994653667986757b4c906b8f144737667f7374Dave Airlie 208bb994653667986757b4c906b8f144737667f7374Dave Airlie kms->fd = fd; 209bb994653667986757b4c906b8f144737667f7374Dave Airlie 210bb994653667986757b4c906b8f144737667f7374Dave Airlie kms->bo_create = dumb_bo_create; 211bb994653667986757b4c906b8f144737667f7374Dave Airlie kms->bo_map = dumb_bo_map; 212bb994653667986757b4c906b8f144737667f7374Dave Airlie kms->bo_unmap = dumb_bo_unmap; 213bb994653667986757b4c906b8f144737667f7374Dave Airlie kms->bo_get_prop = dumb_bo_get_prop; 214bb994653667986757b4c906b8f144737667f7374Dave Airlie kms->bo_destroy = dumb_bo_destroy; 215bb994653667986757b4c906b8f144737667f7374Dave Airlie kms->get_prop = dumb_get_prop; 216bb994653667986757b4c906b8f144737667f7374Dave Airlie kms->destroy = dumb_destroy; 217bb994653667986757b4c906b8f144737667f7374Dave Airlie *out = kms; 218bb994653667986757b4c906b8f144737667f7374Dave Airlie 219bb994653667986757b4c906b8f144737667f7374Dave Airlie return 0; 220bb994653667986757b4c906b8f144737667f7374Dave Airlie} 221