Back to index

libdrm  2.4.37
radeon.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 <stdio.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include "internal.h"
00037 
00038 #include <sys/mman.h>
00039 #include <sys/ioctl.h>
00040 #include "xf86drm.h"
00041 
00042 #include "radeon_drm.h"
00043 
00044 
00045 #define ALIGNMENT 512
00046 
00047 struct radeon_bo
00048 {
00049        struct kms_bo base;
00050        unsigned map_count;
00051 };
00052 
00053 static int
00054 radeon_get_prop(struct kms_driver *kms, unsigned key, unsigned *out)
00055 {
00056        switch (key) {
00057        case KMS_BO_TYPE:
00058               *out = KMS_BO_TYPE_SCANOUT_X8R8G8B8 | KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8;
00059               break;
00060        default:
00061               return -EINVAL;
00062        }
00063        return 0;
00064 }
00065 
00066 static int
00067 radeon_destroy(struct kms_driver *kms)
00068 {
00069        free(kms);
00070        return 0;
00071 }
00072 
00073 static int
00074 radeon_bo_create(struct kms_driver *kms,
00075                const unsigned width, const unsigned height,
00076                const enum kms_bo_type type, const unsigned *attr,
00077                struct kms_bo **out)
00078 {
00079        struct drm_radeon_gem_create arg;
00080        unsigned size, pitch;
00081        struct radeon_bo *bo;
00082        int i, ret;
00083 
00084        for (i = 0; attr[i]; i += 2) {
00085               switch (attr[i]) {
00086               case KMS_WIDTH:
00087               case KMS_HEIGHT:
00088               case KMS_BO_TYPE:
00089                      break;
00090               default:
00091                      return -EINVAL;
00092               }
00093        }
00094 
00095        switch (type) {
00096        case KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8:
00097               pitch = 4 * 64;
00098               size  = 4 * 64 * 64;
00099               break;
00100        case KMS_BO_TYPE_SCANOUT_X8R8G8B8:
00101               pitch = width * 4;
00102               pitch = (pitch + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
00103               size  = pitch * height;
00104               break;
00105        default:
00106               return -EINVAL;
00107        }
00108 
00109        bo = calloc(1, sizeof(*bo));
00110        if (!bo)
00111               return -ENOMEM;
00112 
00113        memset(&arg, 0, sizeof(arg));
00114        arg.size = size;
00115        arg.alignment = ALIGNMENT;
00116        arg.initial_domain = RADEON_GEM_DOMAIN_CPU;
00117        arg.flags = 0;
00118        arg.handle = 0;
00119 
00120        ret = drmCommandWriteRead(kms->fd, DRM_RADEON_GEM_CREATE,
00121                                  &arg, sizeof(arg));
00122        if (ret)
00123               goto err_free;
00124 
00125        bo->base.kms = kms;
00126        bo->base.handle = arg.handle;
00127        bo->base.size = size;
00128        bo->base.pitch = pitch;
00129        bo->base.offset = 0;
00130        bo->map_count = 0;
00131 
00132        *out = &bo->base;
00133 
00134        return 0;
00135 
00136 err_free:
00137        free(bo);
00138        return ret;
00139 }
00140 
00141 static int
00142 radeon_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out)
00143 {
00144        switch (key) {
00145        default:
00146               return -EINVAL;
00147        }
00148 }
00149 
00150 static int
00151 radeon_bo_map(struct kms_bo *_bo, void **out)
00152 {
00153        struct radeon_bo *bo = (struct radeon_bo *)_bo;
00154        struct drm_radeon_gem_mmap arg;
00155        void *map = NULL;
00156        int ret;
00157 
00158        if (bo->base.ptr) {
00159               bo->map_count++;
00160               *out = bo->base.ptr;
00161               return 0;
00162        }
00163 
00164        memset(&arg, 0, sizeof(arg));
00165        arg.handle = bo->base.handle;
00166        arg.offset = bo->base.offset;
00167        arg.size = (uint64_t)bo->base.size;
00168 
00169        ret = drmCommandWriteRead(bo->base.kms->fd, DRM_RADEON_GEM_MMAP,
00170                                &arg, sizeof(arg));
00171        if (ret)
00172               return -errno;
00173 
00174        map = mmap(0, arg.size, PROT_READ | PROT_WRITE, MAP_SHARED,
00175                   bo->base.kms->fd, arg.addr_ptr);
00176        if (map == MAP_FAILED)
00177               return -errno;
00178 
00179        bo->base.ptr = map;
00180        bo->map_count++;
00181        *out = bo->base.ptr;
00182 
00183        return 0;
00184 }
00185 
00186 static int
00187 radeon_bo_unmap(struct kms_bo *_bo)
00188 {
00189        struct radeon_bo *bo = (struct radeon_bo *)_bo;
00190        if (--bo->map_count == 0) {
00191               munmap(bo->base.ptr, bo->base.size);
00192               bo->base.ptr = NULL;
00193        }
00194        return 0;
00195 }
00196 
00197 static int
00198 radeon_bo_destroy(struct kms_bo *_bo)
00199 {
00200        struct radeon_bo *bo = (struct radeon_bo *)_bo;
00201        struct drm_gem_close arg;
00202        int ret;
00203 
00204        if (bo->base.ptr) {
00205               /* XXX Sanity check map_count */
00206               munmap(bo->base.ptr, bo->base.size);
00207               bo->base.ptr = NULL;
00208        }
00209 
00210        memset(&arg, 0, sizeof(arg));
00211        arg.handle = bo->base.handle;
00212 
00213        ret = drmIoctl(bo->base.kms->fd, DRM_IOCTL_GEM_CLOSE, &arg);
00214        if (ret)
00215               return -errno;
00216 
00217        free(bo);
00218        return 0;
00219 }
00220 
00221 int
00222 radeon_create(int fd, struct kms_driver **out)
00223 {
00224        struct kms_driver *kms;
00225 
00226        kms = calloc(1, sizeof(*kms));
00227        if (!kms)
00228               return -ENOMEM;
00229 
00230        kms->fd = fd;
00231 
00232        kms->bo_create = radeon_bo_create;
00233        kms->bo_map = radeon_bo_map;
00234        kms->bo_unmap = radeon_bo_unmap;
00235        kms->bo_get_prop = radeon_bo_get_prop;
00236        kms->bo_destroy = radeon_bo_destroy;
00237        kms->get_prop = radeon_get_prop;
00238        kms->destroy = radeon_destroy;
00239        *out = kms;
00240 
00241        return 0;
00242 }