Home | History | Annotate | Download | only in radeon
      1 /*
      2  * Copyright  2008 Dave Airlie
      3  * Copyright  2008 Jrme Glisse
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining
      7  * a copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     16  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     17  * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
     18  * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     22  *
     23  * The above copyright notice and this permission notice (including the
     24  * next paragraph) shall be included in all copies or substantial portions
     25  * of the Software.
     26  */
     27 /*
     28  * Authors:
     29  *      Dave Airlie
     30  *      Jrme Glisse <glisse (at) freedesktop.org>
     31  */
     32 #ifdef HAVE_CONFIG_H
     33 #include <config.h>
     34 #endif
     35 #include <stdio.h>
     36 #include <stdint.h>
     37 #include <stdlib.h>
     38 #include <string.h>
     39 #include <sys/mman.h>
     40 #include <sys/ioctl.h>
     41 #include <errno.h>
     42 #include "xf86drm.h"
     43 #include "drm.h"
     44 #include "radeon_drm.h"
     45 #include "radeon_bo.h"
     46 #include "radeon_bo_gem.h"
     47 
     48 struct radeon_bo_gem {
     49     struct radeon_bo    base;
     50     uint32_t            name;
     51     int                 map_count;
     52     void *priv_ptr;
     53 };
     54 
     55 struct bo_manager_gem {
     56     struct radeon_bo_manager    base;
     57 };
     58 
     59 static int bo_wait(struct radeon_bo *bo);
     60 
     61 static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
     62                                  uint32_t handle,
     63                                  uint32_t size,
     64                                  uint32_t alignment,
     65                                  uint32_t domains,
     66                                  uint32_t flags)
     67 {
     68     struct radeon_bo_gem *bo;
     69     int r;
     70 
     71     bo = (struct radeon_bo_gem*)calloc(1, sizeof(struct radeon_bo_gem));
     72     if (bo == NULL) {
     73         return NULL;
     74     }
     75 
     76     bo->base.bom = bom;
     77     bo->base.handle = 0;
     78     bo->base.size = size;
     79     bo->base.alignment = alignment;
     80     bo->base.domains = domains;
     81     bo->base.flags = flags;
     82     bo->base.ptr = NULL;
     83     bo->map_count = 0;
     84     if (handle) {
     85         struct drm_gem_open open_arg;
     86 
     87         memset(&open_arg, 0, sizeof(open_arg));
     88         open_arg.name = handle;
     89         r = ioctl(bom->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
     90         if (r != 0) {
     91             free(bo);
     92             return NULL;
     93         }
     94         bo->base.handle = open_arg.handle;
     95         bo->base.size = open_arg.size;
     96         bo->name = handle;
     97     } else {
     98         struct drm_radeon_gem_create args;
     99 
    100         args.size = size;
    101         args.alignment = alignment;
    102         args.initial_domain = bo->base.domains;
    103         args.flags = 0;
    104         args.handle = 0;
    105         r = drmCommandWriteRead(bom->fd, DRM_RADEON_GEM_CREATE,
    106                                 &args, sizeof(args));
    107         bo->base.handle = args.handle;
    108         if (r) {
    109             fprintf(stderr, "Failed to allocate :\n");
    110             fprintf(stderr, "   size      : %d bytes\n", size);
    111             fprintf(stderr, "   alignment : %d bytes\n", alignment);
    112             fprintf(stderr, "   domains   : %d\n", bo->base.domains);
    113             free(bo);
    114             return NULL;
    115         }
    116     }
    117     radeon_bo_ref((struct radeon_bo*)bo);
    118     return (struct radeon_bo*)bo;
    119 }
    120 
    121 static void bo_ref(struct radeon_bo *bo)
    122 {
    123 }
    124 
    125 static struct radeon_bo *bo_unref(struct radeon_bo *bo)
    126 {
    127     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
    128     struct drm_gem_close args;
    129 
    130     if (bo == NULL) {
    131         return NULL;
    132     }
    133     if (bo->cref) {
    134         return bo;
    135     }
    136     if (bo_gem->priv_ptr) {
    137         munmap(bo_gem->priv_ptr, bo->size);
    138     }
    139 
    140     /* close object */
    141     args.handle = bo->handle;
    142     ioctl(bo->bom->fd, DRM_IOCTL_GEM_CLOSE, &args);
    143     memset(bo_gem, 0, sizeof(struct radeon_bo_gem));
    144     free(bo_gem);
    145     return NULL;
    146 }
    147 
    148 static int bo_map(struct radeon_bo *bo, int write)
    149 {
    150     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
    151     struct drm_radeon_gem_mmap args;
    152     int r;
    153     void *ptr;
    154 
    155     if (bo_gem->map_count++ != 0) {
    156         return 0;
    157     }
    158     if (bo_gem->priv_ptr) {
    159 	goto wait;
    160     }
    161 
    162     bo->ptr = NULL;
    163     args.handle = bo->handle;
    164     args.offset = 0;
    165     args.size = (uint64_t)bo->size;
    166     r = drmCommandWriteRead(bo->bom->fd,
    167                             DRM_RADEON_GEM_MMAP,
    168                             &args,
    169                             sizeof(args));
    170     if (r) {
    171         fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n",
    172                 bo, bo->handle, r);
    173         return r;
    174     }
    175     ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, bo->bom->fd, args.addr_ptr);
    176     if (ptr == MAP_FAILED)
    177         return -errno;
    178     bo_gem->priv_ptr = ptr;
    179 wait:
    180     bo->ptr = bo_gem->priv_ptr;
    181     r = bo_wait(bo);
    182     if (r)
    183 	return r;
    184     return 0;
    185 }
    186 
    187 static int bo_unmap(struct radeon_bo *bo)
    188 {
    189     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
    190 
    191     if (--bo_gem->map_count > 0) {
    192         return 0;
    193     }
    194     //munmap(bo->ptr, bo->size);
    195     bo->ptr = NULL;
    196     return 0;
    197 }
    198 
    199 static int bo_wait(struct radeon_bo *bo)
    200 {
    201     struct drm_radeon_gem_wait_idle args;
    202     int ret;
    203 
    204     args.handle = bo->handle;
    205     do {
    206         ret = drmCommandWriteRead(bo->bom->fd, DRM_RADEON_GEM_WAIT_IDLE,
    207                                   &args, sizeof(args));
    208     } while (ret == -EBUSY);
    209     return ret;
    210 }
    211 
    212 static int bo_is_busy(struct radeon_bo *bo, uint32_t *domain)
    213 {
    214     struct drm_radeon_gem_busy args;
    215     int ret;
    216 
    217     args.handle = bo->handle;
    218     args.domain = 0;
    219 
    220     ret = drmCommandWriteRead(bo->bom->fd, DRM_RADEON_GEM_BUSY,
    221 	    &args, sizeof(args));
    222 
    223     *domain = args.domain;
    224     return ret;
    225 }
    226 
    227 static int bo_set_tiling(struct radeon_bo *bo, uint32_t tiling_flags,
    228 				 uint32_t pitch)
    229 {
    230     struct drm_radeon_gem_set_tiling args;
    231     int r;
    232 
    233     args.handle = bo->handle;
    234     args.tiling_flags = tiling_flags;
    235     args.pitch = pitch;
    236 
    237     r = drmCommandWriteRead(bo->bom->fd,
    238 			    DRM_RADEON_GEM_SET_TILING,
    239 			    &args,
    240 			    sizeof(args));
    241     return r;
    242 }
    243 
    244 static int bo_get_tiling(struct radeon_bo *bo, uint32_t *tiling_flags,
    245 				 uint32_t *pitch)
    246 {
    247     struct drm_radeon_gem_set_tiling args;
    248     int r;
    249 
    250     args.handle = bo->handle;
    251 
    252     r = drmCommandWriteRead(bo->bom->fd,
    253 			    DRM_RADEON_GEM_GET_TILING,
    254 			    &args,
    255 			    sizeof(args));
    256 
    257     if (r)
    258 	return r;
    259 
    260     *tiling_flags = args.tiling_flags;
    261     *pitch = args.pitch;
    262     return r;
    263 }
    264 
    265 static struct radeon_bo_funcs bo_gem_funcs = {
    266     bo_open,
    267     bo_ref,
    268     bo_unref,
    269     bo_map,
    270     bo_unmap,
    271     bo_wait,
    272     NULL,
    273     bo_set_tiling,
    274     bo_get_tiling,
    275     bo_is_busy,
    276 };
    277 
    278 struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd)
    279 {
    280     struct bo_manager_gem *bomg;
    281 
    282     bomg = (struct bo_manager_gem*)calloc(1, sizeof(struct bo_manager_gem));
    283     if (bomg == NULL) {
    284         return NULL;
    285     }
    286     bomg->base.funcs = &bo_gem_funcs;
    287     bomg->base.fd = fd;
    288     return (struct radeon_bo_manager*)bomg;
    289 }
    290 
    291 void radeon_bo_manager_gem_dtor(struct radeon_bo_manager *bom)
    292 {
    293     struct bo_manager_gem *bomg = (struct bo_manager_gem*)bom;
    294 
    295     if (bom == NULL) {
    296         return;
    297     }
    298     free(bomg);
    299 }
    300 
    301 uint32_t radeon_gem_name_bo(struct radeon_bo *bo)
    302 {
    303     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
    304     return bo_gem->name;
    305 }
    306 
    307 int radeon_gem_get_kernel_name(struct radeon_bo *bo, uint32_t *name)
    308 {
    309     struct drm_gem_flink flink;
    310     int r;
    311 
    312     flink.handle = bo->handle;
    313     r = ioctl(bo->bom->fd, DRM_IOCTL_GEM_FLINK, &flink);
    314     if (r) {
    315 	return r;
    316     }
    317     *name = flink.name;
    318     return 0;
    319 }
    320 
    321 int radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain)
    322 {
    323     struct drm_radeon_gem_set_domain args;
    324     int r;
    325 
    326     args.handle = bo->handle;
    327     args.read_domains = read_domains;
    328     args.write_domain = write_domain;
    329 
    330     r = drmCommandWriteRead(bo->bom->fd,
    331                             DRM_RADEON_GEM_SET_DOMAIN,
    332                             &args,
    333                             sizeof(args));
    334     return r;
    335 }
    336