Back to index

libdrm  2.4.37
radeon_bo_gem.c
Go to the documentation of this file.
00001 /*
00002  * Copyright © 2008 Dave Airlie
00003  * Copyright © 2008 Jérôme Glisse
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining
00007  * a 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00015  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00016  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00017  * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
00018  * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00020  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
00021  * USE OR OTHER DEALINGS IN THE SOFTWARE.
00022  *
00023  * The above copyright notice and this permission notice (including the
00024  * next paragraph) shall be included in all copies or substantial portions
00025  * of the Software.
00026  */
00027 /*
00028  * Authors:
00029  *      Dave Airlie
00030  *      Jérôme Glisse <glisse@freedesktop.org>
00031  */
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035 #include <stdio.h>
00036 #include <stdint.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <sys/mman.h>
00040 #include <errno.h>
00041 #include "xf86drm.h"
00042 #include "xf86atomic.h"
00043 #include "drm.h"
00044 #include "radeon_drm.h"
00045 #include "radeon_bo.h"
00046 #include "radeon_bo_int.h"
00047 #include "radeon_bo_gem.h"
00048 
00049 struct radeon_bo_gem {
00050     struct radeon_bo_int base;
00051     uint32_t            name;
00052     int                 map_count;
00053     atomic_t            reloc_in_cs;
00054     void *priv_ptr;
00055 };
00056 
00057 struct bo_manager_gem {
00058     struct radeon_bo_manager    base;
00059 };
00060 
00061 static int bo_wait(struct radeon_bo_int *boi);
00062     
00063 static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
00064                                  uint32_t handle,
00065                                  uint32_t size,
00066                                  uint32_t alignment,
00067                                  uint32_t domains,
00068                                  uint32_t flags)
00069 {
00070     struct radeon_bo_gem *bo;
00071     int r;
00072 
00073     bo = (struct radeon_bo_gem*)calloc(1, sizeof(struct radeon_bo_gem));
00074     if (bo == NULL) {
00075         return NULL;
00076     }
00077 
00078     bo->base.bom = bom;
00079     bo->base.handle = 0;
00080     bo->base.size = size;
00081     bo->base.alignment = alignment;
00082     bo->base.domains = domains;
00083     bo->base.flags = flags;
00084     bo->base.ptr = NULL;
00085     atomic_set(&bo->reloc_in_cs, 0);
00086     bo->map_count = 0;
00087     if (handle) {
00088         struct drm_gem_open open_arg;
00089 
00090         memset(&open_arg, 0, sizeof(open_arg));
00091         open_arg.name = handle;
00092         r = drmIoctl(bom->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
00093         if (r != 0) {
00094             free(bo);
00095             return NULL;
00096         }
00097         bo->base.handle = open_arg.handle;
00098         bo->base.size = open_arg.size;
00099         bo->name = handle;
00100     } else {
00101         struct drm_radeon_gem_create args;
00102 
00103         args.size = size;
00104         args.alignment = alignment;
00105         args.initial_domain = bo->base.domains;
00106         args.flags = 0;
00107         args.handle = 0;
00108         r = drmCommandWriteRead(bom->fd, DRM_RADEON_GEM_CREATE,
00109                                 &args, sizeof(args));
00110         bo->base.handle = args.handle;
00111         if (r) {
00112             fprintf(stderr, "Failed to allocate :\n");
00113             fprintf(stderr, "   size      : %d bytes\n", size);
00114             fprintf(stderr, "   alignment : %d bytes\n", alignment);
00115             fprintf(stderr, "   domains   : %d\n", bo->base.domains);
00116             free(bo);
00117             return NULL;
00118         }
00119     }
00120     radeon_bo_ref((struct radeon_bo*)bo);
00121     return (struct radeon_bo*)bo;
00122 }
00123 
00124 static void bo_ref(struct radeon_bo_int *boi)
00125 {
00126 }
00127 
00128 static struct radeon_bo *bo_unref(struct radeon_bo_int *boi)
00129 {
00130     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)boi;
00131     struct drm_gem_close args;
00132 
00133     if (boi->cref) {
00134         return (struct radeon_bo *)boi;
00135     }
00136     if (bo_gem->priv_ptr) {
00137         munmap(bo_gem->priv_ptr, boi->size);
00138     }
00139 
00140     /* Zero out args to make valgrind happy */
00141     memset(&args, 0, sizeof(args));
00142 
00143     /* close object */
00144     args.handle = boi->handle;
00145     drmIoctl(boi->bom->fd, DRM_IOCTL_GEM_CLOSE, &args);
00146     memset(bo_gem, 0, sizeof(struct radeon_bo_gem));
00147     free(bo_gem);
00148     return NULL;
00149 }
00150 
00151 static int bo_map(struct radeon_bo_int *boi, int write)
00152 {
00153     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)boi;
00154     struct drm_radeon_gem_mmap args;
00155     int r;
00156     void *ptr;
00157 
00158     if (bo_gem->map_count++ != 0) {
00159         return 0;
00160     }
00161     if (bo_gem->priv_ptr) {
00162         goto wait;
00163     }
00164 
00165     boi->ptr = NULL;
00166 
00167     /* Zero out args to make valgrind happy */
00168     memset(&args, 0, sizeof(args));
00169     args.handle = boi->handle;
00170     args.offset = 0;
00171     args.size = (uint64_t)boi->size;
00172     r = drmCommandWriteRead(boi->bom->fd,
00173                             DRM_RADEON_GEM_MMAP,
00174                             &args,
00175                             sizeof(args));
00176     if (r) {
00177         fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n",
00178                 boi, boi->handle, r);
00179         return r;
00180     }
00181     ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, boi->bom->fd, args.addr_ptr);
00182     if (ptr == MAP_FAILED)
00183         return -errno;
00184     bo_gem->priv_ptr = ptr;
00185 wait:
00186     boi->ptr = bo_gem->priv_ptr;
00187     r = bo_wait(boi);
00188     if (r)
00189         return r;
00190     return 0;
00191 }
00192 
00193 static int bo_unmap(struct radeon_bo_int *boi)
00194 {
00195     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)boi;
00196 
00197     if (--bo_gem->map_count > 0) {
00198         return 0;
00199     }
00200     //munmap(bo->ptr, bo->size);
00201     boi->ptr = NULL;
00202     return 0;
00203 }
00204 
00205 static int bo_wait(struct radeon_bo_int *boi)
00206 {
00207     struct drm_radeon_gem_wait_idle args;
00208     int ret;
00209 
00210     /* Zero out args to make valgrind happy */
00211     memset(&args, 0, sizeof(args));
00212     args.handle = boi->handle;
00213     do {
00214         ret = drmCommandWriteRead(boi->bom->fd, DRM_RADEON_GEM_WAIT_IDLE,
00215                                   &args, sizeof(args));
00216     } while (ret == -EBUSY);
00217     return ret;
00218 }
00219 
00220 static int bo_is_busy(struct radeon_bo_int *boi, uint32_t *domain)
00221 {
00222     struct drm_radeon_gem_busy args;
00223     int ret;
00224 
00225     args.handle = boi->handle;
00226     args.domain = 0;
00227 
00228     ret = drmCommandWriteRead(boi->bom->fd, DRM_RADEON_GEM_BUSY,
00229                               &args, sizeof(args));
00230 
00231     *domain = args.domain;
00232     return ret;
00233 }
00234 
00235 static int bo_set_tiling(struct radeon_bo_int *boi, uint32_t tiling_flags,
00236                          uint32_t pitch)
00237 {
00238     struct drm_radeon_gem_set_tiling args;
00239     int r;
00240 
00241     args.handle = boi->handle;
00242     args.tiling_flags = tiling_flags;
00243     args.pitch = pitch;
00244 
00245     r = drmCommandWriteRead(boi->bom->fd,
00246                             DRM_RADEON_GEM_SET_TILING,
00247                             &args,
00248                             sizeof(args));
00249     return r;
00250 }
00251 
00252 static int bo_get_tiling(struct radeon_bo_int *boi, uint32_t *tiling_flags,
00253                          uint32_t *pitch)
00254 {
00255     struct drm_radeon_gem_set_tiling args = {};
00256     int r;
00257 
00258     args.handle = boi->handle;
00259 
00260     r = drmCommandWriteRead(boi->bom->fd,
00261                             DRM_RADEON_GEM_GET_TILING,
00262                             &args,
00263                             sizeof(args));
00264 
00265     if (r)
00266         return r;
00267 
00268     *tiling_flags = args.tiling_flags;
00269     *pitch = args.pitch;
00270     return r;
00271 }
00272 
00273 static struct radeon_bo_funcs bo_gem_funcs = {
00274     bo_open,
00275     bo_ref,
00276     bo_unref,
00277     bo_map,
00278     bo_unmap,
00279     bo_wait,
00280     NULL,
00281     bo_set_tiling,
00282     bo_get_tiling,
00283     bo_is_busy,
00284 };
00285 
00286 struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd)
00287 {
00288     struct bo_manager_gem *bomg;
00289 
00290     bomg = (struct bo_manager_gem*)calloc(1, sizeof(struct bo_manager_gem));
00291     if (bomg == NULL) {
00292         return NULL;
00293     }
00294     bomg->base.funcs = &bo_gem_funcs;
00295     bomg->base.fd = fd;
00296     return (struct radeon_bo_manager*)bomg;
00297 }
00298 
00299 void radeon_bo_manager_gem_dtor(struct radeon_bo_manager *bom)
00300 {
00301     struct bo_manager_gem *bomg = (struct bo_manager_gem*)bom;
00302 
00303     if (bom == NULL) {
00304         return;
00305     }
00306     free(bomg);
00307 }
00308 
00309 uint32_t radeon_gem_name_bo(struct radeon_bo *bo)
00310 {
00311     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
00312     return bo_gem->name;
00313 }
00314 
00315 void *radeon_gem_get_reloc_in_cs(struct radeon_bo *bo)
00316 {
00317     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
00318     return &bo_gem->reloc_in_cs;
00319 }
00320 
00321 int radeon_gem_get_kernel_name(struct radeon_bo *bo, uint32_t *name)
00322 {
00323     struct radeon_bo_int *boi = (struct radeon_bo_int *)bo;
00324     struct drm_gem_flink flink;
00325     int r;
00326 
00327     flink.handle = bo->handle;
00328     r = drmIoctl(boi->bom->fd, DRM_IOCTL_GEM_FLINK, &flink);
00329     if (r) {
00330         return r;
00331     }
00332     *name = flink.name;
00333     return 0;
00334 }
00335 
00336 int radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain)
00337 {
00338     struct radeon_bo_int *boi = (struct radeon_bo_int *)bo;
00339     struct drm_radeon_gem_set_domain args;
00340     int r;
00341 
00342     args.handle = bo->handle;
00343     args.read_domains = read_domains;
00344     args.write_domain = write_domain;
00345 
00346     r = drmCommandWriteRead(boi->bom->fd,
00347                             DRM_RADEON_GEM_SET_DOMAIN,
00348                             &args,
00349                             sizeof(args));
00350     return r;
00351 }