Back to index

libdrm  2.4.37
vmwgfx.c
Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00019  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00020  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00021  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
00022  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
00023  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
00024  * USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  *
00026  **************************************************************************/
00027 
00028 
00029 #define HAVE_STDINT_H
00030 #define _FILE_OFFSET_BITS 64
00031 
00032 #include <errno.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include "internal.h"
00036 
00037 #include <sys/mman.h>
00038 #include "xf86drm.h"
00039 #include "vmwgfx_drm.h"
00040 
00041 struct vmwgfx_bo
00042 {
00043        struct kms_bo base;
00044        uint64_t map_handle;
00045        unsigned map_count;
00046 };
00047 
00048 static int
00049 vmwgfx_get_prop(struct kms_driver *kms, unsigned key, unsigned *out)
00050 {
00051        switch (key) {
00052        case KMS_BO_TYPE:
00053               *out = KMS_BO_TYPE_SCANOUT_X8R8G8B8 | KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8;
00054               break;
00055        default:
00056               return -EINVAL;
00057        }
00058        return 0;
00059 }
00060 
00061 static int
00062 vmwgfx_destroy(struct kms_driver *kms)
00063 {
00064        free(kms);
00065        return 0;
00066 }
00067 
00068 static int
00069 vmwgfx_bo_create(struct kms_driver *kms,
00070                const unsigned width, const unsigned height,
00071                const enum kms_bo_type type, const unsigned *attr,
00072                struct kms_bo **out)
00073 {
00074        struct vmwgfx_bo *bo;
00075        int i, ret;
00076 
00077        for (i = 0; attr[i]; i += 2) {
00078               switch (attr[i]) {
00079               case KMS_WIDTH:
00080               case KMS_HEIGHT:
00081               case KMS_BO_TYPE:
00082                      break;
00083               default:
00084                      return -EINVAL;
00085               }
00086        }
00087 
00088        bo = calloc(1, sizeof(*bo));
00089        if (!bo)
00090               return -EINVAL;
00091 
00092        {
00093               union drm_vmw_alloc_dmabuf_arg arg;
00094               struct drm_vmw_alloc_dmabuf_req *req = &arg.req;
00095               struct drm_vmw_dmabuf_rep *rep = &arg.rep;
00096 
00097               memset(&arg, 0, sizeof(arg));
00098               req->size = width * height * 4;
00099               bo->base.size = req->size;
00100               bo->base.pitch = width * 4;
00101               bo->base.kms = kms;
00102 
00103               do {
00104                      ret = drmCommandWriteRead(bo->base.kms->fd,
00105                                             DRM_VMW_ALLOC_DMABUF,
00106                                             &arg, sizeof(arg));
00107               } while (ret == -ERESTART);
00108 
00109               if (ret)
00110                      goto err_free;
00111 
00112               bo->base.handle = rep->handle;
00113               bo->map_handle = rep->map_handle;
00114               bo->base.handle = rep->cur_gmr_id;
00115               bo->base.offset = rep->cur_gmr_offset;
00116        }
00117 
00118        *out = &bo->base;
00119 
00120        return 0;
00121 
00122 err_free:
00123        free(bo);
00124        return ret;
00125 }
00126 
00127 static int
00128 vmwgfx_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out)
00129 {
00130        switch (key) {
00131        default:
00132               return -EINVAL;
00133        }
00134 }
00135 
00136 static int
00137 vmwgfx_bo_map(struct kms_bo *_bo, void **out)
00138 {
00139        struct vmwgfx_bo *bo = (struct vmwgfx_bo *)_bo;
00140        void *map;
00141 
00142        if (bo->base.ptr) {
00143               bo->map_count++;
00144               *out = bo->base.ptr;
00145               return 0;
00146        }
00147 
00148        map = mmap(NULL, bo->base.size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->base.kms->fd, bo->map_handle);
00149        if (map == MAP_FAILED)
00150               return -errno;
00151 
00152        bo->base.ptr = map;
00153        bo->map_count++;
00154        *out = bo->base.ptr;
00155 
00156        return 0;
00157 }
00158 
00159 static int
00160 vmwgfx_bo_unmap(struct kms_bo *_bo)
00161 {
00162        struct vmwgfx_bo *bo = (struct vmwgfx_bo *)_bo;
00163        bo->map_count--;
00164        return 0;
00165 }
00166 
00167 static int
00168 vmwgfx_bo_destroy(struct kms_bo *_bo)
00169 {
00170        struct vmwgfx_bo *bo = (struct vmwgfx_bo *)_bo;
00171        struct drm_vmw_unref_dmabuf_arg arg;
00172 
00173        if (bo->base.ptr) {
00174               /* XXX Sanity check map_count */
00175               munmap(bo->base.ptr, bo->base.size);
00176               bo->base.ptr = NULL;
00177        }
00178 
00179        memset(&arg, 0, sizeof(arg));
00180        arg.handle = bo->base.handle;
00181        drmCommandWrite(bo->base.kms->fd, DRM_VMW_UNREF_DMABUF, &arg, sizeof(arg));
00182 
00183        free(bo);
00184        return 0;
00185 }
00186 
00187 int
00188 vmwgfx_create(int fd, struct kms_driver **out)
00189 {
00190        struct kms_driver *kms;
00191 
00192        kms = calloc(1, sizeof(*kms));
00193        if (!kms)
00194               return -ENOMEM;
00195 
00196        kms->fd = fd;
00197 
00198        kms->bo_create = vmwgfx_bo_create;
00199        kms->bo_map = vmwgfx_bo_map;
00200        kms->bo_unmap = vmwgfx_bo_unmap;
00201        kms->bo_get_prop = vmwgfx_bo_get_prop;
00202        kms->bo_destroy = vmwgfx_bo_destroy;
00203        kms->get_prop = vmwgfx_get_prop;
00204        kms->destroy = vmwgfx_destroy;
00205        *out = kms;
00206        return 0;
00207 }