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