Home | History | Annotate | Download | only in radeon
      1 /*
      2  * Copyright  2011 Red Hat
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  *
     23  * Authors:
     24  *    Jerome Glisse <j.glisse (at) gmail.com>
     25  */
     26 #define _FILE_OFFSET_BITS 64
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <string.h>
     30 #include <sys/mman.h>
     31 #include <errno.h>
     32 #include "xf86drm.h"
     33 #include "radeon_drm.h"
     34 #include "rbo.h"
     35 
     36 struct rbo *rbo(int fd, unsigned handle, unsigned size,
     37                 unsigned alignment, void *ptr)
     38 {
     39     struct rbo *bo;
     40     int r;
     41 
     42     bo = calloc(1, sizeof(*bo));
     43     if (bo == NULL) {
     44         return NULL;
     45     }
     46     list_inithead(&bo->list);
     47     bo->fd = fd;
     48     bo->size = size;
     49     bo->handle = handle;
     50     bo->refcount = 1;
     51     bo->alignment = alignment;
     52 
     53     if (handle) {
     54         struct drm_gem_open open_arg;
     55 
     56         memset(&open_arg, 0, sizeof(open_arg));
     57         open_arg.name = handle;
     58         r = drmIoctl(fd, DRM_IOCTL_GEM_OPEN, &open_arg);
     59         if (r != 0) {
     60             free(bo);
     61             return NULL;
     62         }
     63         bo->handle = open_arg.handle;
     64     } else {
     65         struct drm_radeon_gem_create args;
     66 
     67         args.size = size;
     68         args.alignment = alignment;
     69         args.initial_domain = RADEON_GEM_DOMAIN_CPU;
     70         args.flags = 0;
     71         args.handle = 0;
     72         r = drmCommandWriteRead(fd, DRM_RADEON_GEM_CREATE,
     73                                 &args, sizeof(args));
     74         bo->handle = args.handle;
     75         if (r) {
     76             fprintf(stderr, "Failed to allocate :\n");
     77             fprintf(stderr, "   size      : %d bytes\n", size);
     78             fprintf(stderr, "   alignment : %d bytes\n", alignment);
     79             free(bo);
     80             return NULL;
     81         }
     82     }
     83     if (ptr) {
     84         if (rbo_map(bo)) {
     85             fprintf(stderr, "%s failed to copy data into bo\n", __func__);
     86             return rbo_decref(bo);
     87         }
     88         memcpy(bo->data, ptr, size);
     89         rbo_unmap(bo);
     90     }
     91     return bo;
     92 }
     93 
     94 int rbo_map(struct rbo *bo)
     95 {
     96     struct drm_radeon_gem_mmap args;
     97     void *ptr;
     98     int r;
     99 
    100     if (bo->mapcount++ != 0) {
    101         return 0;
    102     }
    103     /* Zero out args to make valgrind happy */
    104     memset(&args, 0, sizeof(args));
    105     args.handle = bo->handle;
    106     args.offset = 0;
    107     args.size = (uint64_t)bo->size;
    108     r = drmCommandWriteRead(bo->fd, DRM_RADEON_GEM_MMAP,
    109                             &args, sizeof(args));
    110     if (r) {
    111         fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n",
    112             bo, bo->handle, r);
    113         return r;
    114     }
    115     ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, bo->fd, args.addr_ptr);
    116     if (ptr == MAP_FAILED) {
    117         fprintf(stderr, "%s failed to map bo\n", __func__);
    118         return -errno;
    119     }
    120     bo->data = ptr;
    121     return 0;
    122 }
    123 
    124 void rbo_unmap(struct rbo *bo)
    125 {
    126     if (--bo->mapcount > 0) {
    127         return;
    128     }
    129     munmap(bo->data, bo->size);
    130     bo->data = NULL;
    131 }
    132 
    133 struct rbo *rbo_incref(struct rbo *bo)
    134 {
    135     bo->refcount++;
    136     return bo;
    137 }
    138 
    139 struct rbo *rbo_decref(struct rbo *bo)
    140 {
    141     struct drm_gem_close args;
    142 
    143     if (bo == NULL)
    144         return NULL;
    145     if (--bo->refcount > 0) {
    146         return NULL;
    147     }
    148 
    149     munmap(bo->data, bo->size);
    150     memset(&args, 0, sizeof(args));
    151     args.handle = bo->handle;
    152     drmIoctl(bo->fd, DRM_IOCTL_GEM_CLOSE, &args);
    153     memset(bo, 0, sizeof(struct rbo));
    154     free(bo);
    155     return NULL;
    156 }
    157 
    158 int rbo_wait(struct rbo *bo)
    159 {
    160     struct drm_radeon_gem_wait_idle args;
    161     int ret;
    162 
    163     /* Zero out args to make valgrind happy */
    164     memset(&args, 0, sizeof(args));
    165     args.handle = bo->handle;
    166     do {
    167         ret = drmCommandWriteRead(bo->fd, DRM_RADEON_GEM_WAIT_IDLE,
    168                                   &args, sizeof(args));
    169     } while (ret == -EBUSY);
    170     return ret;
    171 }
    172