xref: /aosp_15_r20/external/mesa3d/src/gallium/auxiliary/renderonly/renderonly.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2016 Christian Gmeiner <[email protected]>
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20*61046927SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21*61046927SAndroid Build Coastguard Worker  * SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  *
23*61046927SAndroid Build Coastguard Worker  * Authors:
24*61046927SAndroid Build Coastguard Worker  *    Christian Gmeiner <[email protected]>
25*61046927SAndroid Build Coastguard Worker  */
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker #include "renderonly/renderonly.h"
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker #include <errno.h>
30*61046927SAndroid Build Coastguard Worker #include <fcntl.h>
31*61046927SAndroid Build Coastguard Worker #include <stdio.h>
32*61046927SAndroid Build Coastguard Worker #include <xf86drm.h>
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker #include "frontend/drm_driver.h"
35*61046927SAndroid Build Coastguard Worker #include "pipe/p_screen.h"
36*61046927SAndroid Build Coastguard Worker #include "util/format/u_format.h"
37*61046927SAndroid Build Coastguard Worker #include "util/u_inlines.h"
38*61046927SAndroid Build Coastguard Worker #include "util/u_memory.h"
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker void
renderonly_scanout_destroy(struct renderonly_scanout * scanout,struct renderonly * ro)41*61046927SAndroid Build Coastguard Worker renderonly_scanout_destroy(struct renderonly_scanout *scanout,
42*61046927SAndroid Build Coastguard Worker 			   struct renderonly *ro)
43*61046927SAndroid Build Coastguard Worker {
44*61046927SAndroid Build Coastguard Worker    struct drm_mode_destroy_dumb destroy_dumb = {0};
45*61046927SAndroid Build Coastguard Worker 
46*61046927SAndroid Build Coastguard Worker    assert(p_atomic_read(&scanout->refcnt) > 0);
47*61046927SAndroid Build Coastguard Worker    if (p_atomic_dec_return(&scanout->refcnt))
48*61046927SAndroid Build Coastguard Worker       return;
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&ro->bo_map_lock);
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker    /* Someone might have imported this BO while we were waiting for the
53*61046927SAndroid Build Coastguard Worker     * lock, let's make sure it's still not referenced before freeing it.
54*61046927SAndroid Build Coastguard Worker     */
55*61046927SAndroid Build Coastguard Worker    if (p_atomic_read(&scanout->refcnt) == 0 && ro->kms_fd != -1) {
56*61046927SAndroid Build Coastguard Worker       destroy_dumb.handle = scanout->handle;
57*61046927SAndroid Build Coastguard Worker       scanout->handle = 0;
58*61046927SAndroid Build Coastguard Worker       scanout->stride = 0;
59*61046927SAndroid Build Coastguard Worker       drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
60*61046927SAndroid Build Coastguard Worker    }
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&ro->bo_map_lock);
63*61046927SAndroid Build Coastguard Worker }
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker struct renderonly_scanout *
renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource * rsc,struct renderonly * ro,struct winsys_handle * out_handle)66*61046927SAndroid Build Coastguard Worker renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
67*61046927SAndroid Build Coastguard Worker                                                struct renderonly *ro,
68*61046927SAndroid Build Coastguard Worker                                                struct winsys_handle *out_handle)
69*61046927SAndroid Build Coastguard Worker {
70*61046927SAndroid Build Coastguard Worker    struct renderonly_scanout *scanout = NULL;
71*61046927SAndroid Build Coastguard Worker    int err;
72*61046927SAndroid Build Coastguard Worker    struct drm_mode_create_dumb create_dumb = {
73*61046927SAndroid Build Coastguard Worker       .width = rsc->width0,
74*61046927SAndroid Build Coastguard Worker       .height = rsc->height0,
75*61046927SAndroid Build Coastguard Worker       .bpp = util_format_get_blocksizebits(rsc->format),
76*61046927SAndroid Build Coastguard Worker    };
77*61046927SAndroid Build Coastguard Worker    struct drm_mode_destroy_dumb destroy_dumb = {0};
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker    /* create dumb buffer at scanout GPU */
80*61046927SAndroid Build Coastguard Worker    err = drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
81*61046927SAndroid Build Coastguard Worker    if (err < 0) {
82*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "DRM_IOCTL_MODE_CREATE_DUMB failed: %s\n",
83*61046927SAndroid Build Coastguard Worker             strerror(errno));
84*61046927SAndroid Build Coastguard Worker       return NULL;
85*61046927SAndroid Build Coastguard Worker    }
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&ro->bo_map_lock);
88*61046927SAndroid Build Coastguard Worker    scanout = util_sparse_array_get(&ro->bo_map, create_dumb.handle);
89*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&ro->bo_map_lock);
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker    if (!scanout)
92*61046927SAndroid Build Coastguard Worker       goto free_dumb;
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker    scanout->handle = create_dumb.handle;
95*61046927SAndroid Build Coastguard Worker    scanout->stride = create_dumb.pitch;
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker    assert(p_atomic_read(&scanout->refcnt) == 0);
98*61046927SAndroid Build Coastguard Worker    p_atomic_set(&scanout->refcnt, 1);
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker    if (!out_handle)
101*61046927SAndroid Build Coastguard Worker       return scanout;
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker    /* fill in winsys handle */
104*61046927SAndroid Build Coastguard Worker    memset(out_handle, 0, sizeof(*out_handle));
105*61046927SAndroid Build Coastguard Worker    out_handle->type = WINSYS_HANDLE_TYPE_FD;
106*61046927SAndroid Build Coastguard Worker    out_handle->stride = create_dumb.pitch;
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker    err = drmPrimeHandleToFD(ro->kms_fd, create_dumb.handle, O_CLOEXEC,
109*61046927SAndroid Build Coastguard Worker          (int *)&out_handle->handle);
110*61046927SAndroid Build Coastguard Worker    if (err < 0) {
111*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "failed to export dumb buffer: %s\n", strerror(errno));
112*61046927SAndroid Build Coastguard Worker       goto free_dumb;
113*61046927SAndroid Build Coastguard Worker    }
114*61046927SAndroid Build Coastguard Worker 
115*61046927SAndroid Build Coastguard Worker    return scanout;
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker free_dumb:
118*61046927SAndroid Build Coastguard Worker    /* If an error occured, make sure we reset the scanout object before
119*61046927SAndroid Build Coastguard Worker     * leaving.
120*61046927SAndroid Build Coastguard Worker     */
121*61046927SAndroid Build Coastguard Worker    if (scanout)
122*61046927SAndroid Build Coastguard Worker       memset(scanout, 0, sizeof(*scanout));
123*61046927SAndroid Build Coastguard Worker 
124*61046927SAndroid Build Coastguard Worker    destroy_dumb.handle = create_dumb.handle;
125*61046927SAndroid Build Coastguard Worker    drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker    return NULL;
128*61046927SAndroid Build Coastguard Worker }
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker struct renderonly_scanout *
renderonly_create_gpu_import_for_resource(struct pipe_resource * rsc,struct renderonly * ro,struct winsys_handle * out_handle)131*61046927SAndroid Build Coastguard Worker renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
132*61046927SAndroid Build Coastguard Worker                                           struct renderonly *ro,
133*61046927SAndroid Build Coastguard Worker                                           struct winsys_handle *out_handle)
134*61046927SAndroid Build Coastguard Worker {
135*61046927SAndroid Build Coastguard Worker    struct pipe_screen *screen = rsc->screen;
136*61046927SAndroid Build Coastguard Worker    struct renderonly_scanout *scanout = NULL;
137*61046927SAndroid Build Coastguard Worker    bool status;
138*61046927SAndroid Build Coastguard Worker    uint32_t scanout_handle;
139*61046927SAndroid Build Coastguard Worker    int fd, err;
140*61046927SAndroid Build Coastguard Worker    struct winsys_handle handle = {
141*61046927SAndroid Build Coastguard Worker       .type = WINSYS_HANDLE_TYPE_FD
142*61046927SAndroid Build Coastguard Worker    };
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker    status = screen->resource_get_handle(screen, NULL, rsc, &handle,
145*61046927SAndroid Build Coastguard Worker          PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
146*61046927SAndroid Build Coastguard Worker    if (!status)
147*61046927SAndroid Build Coastguard Worker       return NULL;
148*61046927SAndroid Build Coastguard Worker 
149*61046927SAndroid Build Coastguard Worker    fd = handle.handle;
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&ro->bo_map_lock);
152*61046927SAndroid Build Coastguard Worker    err = drmPrimeFDToHandle(ro->kms_fd, fd, &scanout_handle);
153*61046927SAndroid Build Coastguard Worker    close(fd);
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker    if (err < 0)
156*61046927SAndroid Build Coastguard Worker       goto err_unlock;
157*61046927SAndroid Build Coastguard Worker 
158*61046927SAndroid Build Coastguard Worker    scanout = util_sparse_array_get(&ro->bo_map, scanout_handle);
159*61046927SAndroid Build Coastguard Worker    if (!scanout)
160*61046927SAndroid Build Coastguard Worker       goto err_unlock;
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker    if (p_atomic_inc_return(&scanout->refcnt) == 1) {
163*61046927SAndroid Build Coastguard Worker       scanout->handle = scanout_handle;
164*61046927SAndroid Build Coastguard Worker       scanout->stride = handle.stride;
165*61046927SAndroid Build Coastguard Worker    }
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker err_unlock:
168*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&ro->bo_map_lock);
169*61046927SAndroid Build Coastguard Worker 
170*61046927SAndroid Build Coastguard Worker    return scanout;
171*61046927SAndroid Build Coastguard Worker }
172*61046927SAndroid Build Coastguard Worker 
173