Back to index

libdrm  2.4.37
rbo.c
Go to the documentation of this file.
00001 /*
00002  * Copyright © 2011 Red Hat
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice (including the next
00012  * paragraph) shall be included in all copies or substantial portions of the
00013  * Software.
00014  *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00018  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00020  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
00021  * IN THE SOFTWARE.
00022  *
00023  * Authors:
00024  *    Jerome Glisse <j.glisse@gmail.com>
00025  */
00026 #define _FILE_OFFSET_BITS 64
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <sys/mman.h>
00031 #include <errno.h>
00032 #include "xf86drm.h"
00033 #include "radeon_drm.h"
00034 #include "rbo.h"
00035 
00036 struct rbo *rbo(int fd, unsigned handle, unsigned size,
00037                 unsigned alignment, void *ptr)
00038 {
00039     struct rbo *bo;
00040     int r;
00041 
00042     bo = calloc(1, sizeof(*bo));
00043     if (bo == NULL) {
00044         return NULL;
00045     }
00046     list_inithead(&bo->list);
00047     bo->fd = fd;
00048     bo->size = size;
00049     bo->handle = handle;
00050     bo->refcount = 1;
00051     bo->alignment = alignment;
00052 
00053     if (handle) {
00054         struct drm_gem_open open_arg;
00055 
00056         memset(&open_arg, 0, sizeof(open_arg));
00057         open_arg.name = handle;
00058         r = drmIoctl(fd, DRM_IOCTL_GEM_OPEN, &open_arg);
00059         if (r != 0) {
00060             free(bo);
00061             return NULL;
00062         }
00063         bo->handle = open_arg.handle;
00064     } else {
00065         struct drm_radeon_gem_create args;
00066 
00067         args.size = size;
00068         args.alignment = alignment;
00069         args.initial_domain = RADEON_GEM_DOMAIN_CPU;
00070         args.flags = 0;
00071         args.handle = 0;
00072         r = drmCommandWriteRead(fd, DRM_RADEON_GEM_CREATE,
00073                                 &args, sizeof(args));
00074         bo->handle = args.handle;
00075         if (r) {
00076             fprintf(stderr, "Failed to allocate :\n");
00077             fprintf(stderr, "   size      : %d bytes\n", size);
00078             fprintf(stderr, "   alignment : %d bytes\n", alignment);
00079             free(bo);
00080             return NULL;
00081         }
00082     }
00083     if (ptr) {
00084         if (rbo_map(bo)) {
00085             fprintf(stderr, "%s failed to copy data into bo\n", __func__);
00086             return rbo_decref(bo);
00087         }
00088         memcpy(bo->data, ptr, size);
00089         rbo_unmap(bo);
00090     }
00091     return bo;
00092 }
00093 
00094 int rbo_map(struct rbo *bo)
00095 {
00096     struct drm_radeon_gem_mmap args;
00097     void *ptr;
00098     int r;
00099 
00100     if (bo->mapcount++ != 0) {
00101         return 0;
00102     }
00103     /* Zero out args to make valgrind happy */
00104     memset(&args, 0, sizeof(args));
00105     args.handle = bo->handle;
00106     args.offset = 0;
00107     args.size = (uint64_t)bo->size;
00108     r = drmCommandWriteRead(bo->fd, DRM_RADEON_GEM_MMAP,
00109                             &args, sizeof(args));
00110     if (r) {
00111         fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n",
00112             bo, bo->handle, r);
00113         return r;
00114     }
00115     ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, bo->fd, args.addr_ptr);
00116     if (ptr == MAP_FAILED) {
00117         fprintf(stderr, "%s failed to map bo\n", __func__);
00118         return -errno;
00119     }
00120     bo->data = ptr;
00121     return 0;
00122 }
00123 
00124 void rbo_unmap(struct rbo *bo)
00125 {
00126     if (--bo->mapcount > 0) {
00127         return;
00128     }
00129     munmap(bo->data, bo->size);
00130     bo->data = NULL;
00131 }
00132 
00133 struct rbo *rbo_incref(struct rbo *bo)
00134 {
00135     bo->refcount++;
00136     return bo;
00137 }
00138 
00139 struct rbo *rbo_decref(struct rbo *bo)
00140 {
00141     struct drm_gem_close args;
00142 
00143     if (bo == NULL)
00144         return NULL;
00145     if (--bo->refcount > 0) {
00146         return NULL;
00147     }
00148 
00149     munmap(bo->data, bo->size);
00150     memset(&args, 0, sizeof(args));
00151     args.handle = bo->handle;
00152     drmIoctl(bo->fd, DRM_IOCTL_GEM_CLOSE, &args);
00153     memset(bo, 0, sizeof(struct rbo));
00154     free(bo);
00155     return NULL;
00156 }
00157 
00158 int rbo_wait(struct rbo *bo)
00159 {
00160     struct drm_radeon_gem_wait_idle args;
00161     int ret;
00162 
00163     /* Zero out args to make valgrind happy */
00164     memset(&args, 0, sizeof(args));
00165     args.handle = bo->handle;
00166     do {
00167         ret = drmCommandWriteRead(bo->fd, DRM_RADEON_GEM_WAIT_IDLE,
00168                                   &args, sizeof(args));
00169     } while (ret == -EBUSY);
00170     return ret;
00171 }