xref: /aosp_15_r20/external/libva/va/x11/dri2_util.c (revision 54e60f844a168e9a219354de272cd517ee8cd4b7)
1*54e60f84SAndroid Build Coastguard Worker /*
2*54e60f84SAndroid Build Coastguard Worker  * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
3*54e60f84SAndroid Build Coastguard Worker  *
4*54e60f84SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*54e60f84SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the
6*54e60f84SAndroid Build Coastguard Worker  * "Software"), to deal in the Software without restriction, including
7*54e60f84SAndroid Build Coastguard Worker  * without limitation the rights to use, copy, modify, merge, publish,
8*54e60f84SAndroid Build Coastguard Worker  * distribute, sub license, and/or sell copies of the Software, and to
9*54e60f84SAndroid Build Coastguard Worker  * permit persons to whom the Software is furnished to do so, subject to
10*54e60f84SAndroid Build Coastguard Worker  * the following conditions:
11*54e60f84SAndroid Build Coastguard Worker  *
12*54e60f84SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the
13*54e60f84SAndroid Build Coastguard Worker  * next paragraph) shall be included in all copies or substantial portions
14*54e60f84SAndroid Build Coastguard Worker  * of the Software.
15*54e60f84SAndroid Build Coastguard Worker  *
16*54e60f84SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17*54e60f84SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*54e60f84SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19*54e60f84SAndroid Build Coastguard Worker  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20*54e60f84SAndroid Build Coastguard Worker  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21*54e60f84SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22*54e60f84SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23*54e60f84SAndroid Build Coastguard Worker  */
24*54e60f84SAndroid Build Coastguard Worker #include <stdlib.h>
25*54e60f84SAndroid Build Coastguard Worker #include <fcntl.h>
26*54e60f84SAndroid Build Coastguard Worker #include <unistd.h>
27*54e60f84SAndroid Build Coastguard Worker #include <assert.h>
28*54e60f84SAndroid Build Coastguard Worker #include <sys/stat.h>
29*54e60f84SAndroid Build Coastguard Worker 
30*54e60f84SAndroid Build Coastguard Worker #include <xf86drm.h>
31*54e60f84SAndroid Build Coastguard Worker 
32*54e60f84SAndroid Build Coastguard Worker #include <X11/Xlibint.h>
33*54e60f84SAndroid Build Coastguard Worker #include <X11/Xlib.h>
34*54e60f84SAndroid Build Coastguard Worker #include "va.h"
35*54e60f84SAndroid Build Coastguard Worker #include "va_backend.h"
36*54e60f84SAndroid Build Coastguard Worker 
37*54e60f84SAndroid Build Coastguard Worker #include "va_dri2.h"
38*54e60f84SAndroid Build Coastguard Worker #include "va_dri2tokens.h"
39*54e60f84SAndroid Build Coastguard Worker #include "va_dricommon.h"
40*54e60f84SAndroid Build Coastguard Worker 
41*54e60f84SAndroid Build Coastguard Worker #define __DRI_BUFFER_FRONT_LEFT         0
42*54e60f84SAndroid Build Coastguard Worker #define __DRI_BUFFER_BACK_LEFT          1
43*54e60f84SAndroid Build Coastguard Worker #define __DRI_BUFFER_FRONT_RIGHT        2
44*54e60f84SAndroid Build Coastguard Worker #define __DRI_BUFFER_BACK_RIGHT         3
45*54e60f84SAndroid Build Coastguard Worker #define __DRI_BUFFER_DEPTH              4
46*54e60f84SAndroid Build Coastguard Worker #define __DRI_BUFFER_STENCIL            5
47*54e60f84SAndroid Build Coastguard Worker #define __DRI_BUFFER_ACCUM              6
48*54e60f84SAndroid Build Coastguard Worker #define __DRI_BUFFER_FAKE_FRONT_LEFT    7
49*54e60f84SAndroid Build Coastguard Worker #define __DRI_BUFFER_FAKE_FRONT_RIGHT   8
50*54e60f84SAndroid Build Coastguard Worker 
51*54e60f84SAndroid Build Coastguard Worker struct dri2_drawable {
52*54e60f84SAndroid Build Coastguard Worker     struct dri_drawable base;
53*54e60f84SAndroid Build Coastguard Worker     union dri_buffer buffers[5];
54*54e60f84SAndroid Build Coastguard Worker     int width;
55*54e60f84SAndroid Build Coastguard Worker     int height;
56*54e60f84SAndroid Build Coastguard Worker     int has_backbuffer;
57*54e60f84SAndroid Build Coastguard Worker     int back_index;
58*54e60f84SAndroid Build Coastguard Worker     int front_index;
59*54e60f84SAndroid Build Coastguard Worker };
60*54e60f84SAndroid Build Coastguard Worker 
61*54e60f84SAndroid Build Coastguard Worker static int gsDRI2SwapAvailable;
62*54e60f84SAndroid Build Coastguard Worker 
63*54e60f84SAndroid Build Coastguard Worker static struct dri_drawable *
dri2CreateDrawable(VADriverContextP ctx,XID x_drawable)64*54e60f84SAndroid Build Coastguard Worker dri2CreateDrawable(VADriverContextP ctx, XID x_drawable)
65*54e60f84SAndroid Build Coastguard Worker {
66*54e60f84SAndroid Build Coastguard Worker     struct dri2_drawable *dri2_drawable;
67*54e60f84SAndroid Build Coastguard Worker 
68*54e60f84SAndroid Build Coastguard Worker     dri2_drawable = calloc(1, sizeof(*dri2_drawable));
69*54e60f84SAndroid Build Coastguard Worker 
70*54e60f84SAndroid Build Coastguard Worker     if (!dri2_drawable)
71*54e60f84SAndroid Build Coastguard Worker         return NULL;
72*54e60f84SAndroid Build Coastguard Worker 
73*54e60f84SAndroid Build Coastguard Worker     dri2_drawable->base.x_drawable = x_drawable;
74*54e60f84SAndroid Build Coastguard Worker     dri2_drawable->base.x = 0;
75*54e60f84SAndroid Build Coastguard Worker     dri2_drawable->base.y = 0;
76*54e60f84SAndroid Build Coastguard Worker     VA_DRI2CreateDrawable(ctx->native_dpy, x_drawable);
77*54e60f84SAndroid Build Coastguard Worker 
78*54e60f84SAndroid Build Coastguard Worker     return &dri2_drawable->base;
79*54e60f84SAndroid Build Coastguard Worker }
80*54e60f84SAndroid Build Coastguard Worker 
81*54e60f84SAndroid Build Coastguard Worker static void
dri2DestroyDrawable(VADriverContextP ctx,struct dri_drawable * dri_drawable)82*54e60f84SAndroid Build Coastguard Worker dri2DestroyDrawable(VADriverContextP ctx, struct dri_drawable *dri_drawable)
83*54e60f84SAndroid Build Coastguard Worker {
84*54e60f84SAndroid Build Coastguard Worker     VA_DRI2DestroyDrawable(ctx->native_dpy, dri_drawable->x_drawable);
85*54e60f84SAndroid Build Coastguard Worker     free(dri_drawable);
86*54e60f84SAndroid Build Coastguard Worker }
87*54e60f84SAndroid Build Coastguard Worker 
88*54e60f84SAndroid Build Coastguard Worker static void
dri2SwapBuffer(VADriverContextP ctx,struct dri_drawable * dri_drawable)89*54e60f84SAndroid Build Coastguard Worker dri2SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
90*54e60f84SAndroid Build Coastguard Worker {
91*54e60f84SAndroid Build Coastguard Worker     struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
92*54e60f84SAndroid Build Coastguard Worker     XRectangle xrect;
93*54e60f84SAndroid Build Coastguard Worker     XserverRegion region;
94*54e60f84SAndroid Build Coastguard Worker 
95*54e60f84SAndroid Build Coastguard Worker     if (dri2_drawable->has_backbuffer) {
96*54e60f84SAndroid Build Coastguard Worker         if (gsDRI2SwapAvailable) {
97*54e60f84SAndroid Build Coastguard Worker             CARD64 ret;
98*54e60f84SAndroid Build Coastguard Worker             VA_DRI2SwapBuffers(ctx->native_dpy, dri_drawable->x_drawable,
99*54e60f84SAndroid Build Coastguard Worker                                0, 1, 0,
100*54e60f84SAndroid Build Coastguard Worker                                &ret);
101*54e60f84SAndroid Build Coastguard Worker         } else {
102*54e60f84SAndroid Build Coastguard Worker             xrect.x = 0;
103*54e60f84SAndroid Build Coastguard Worker             xrect.y = 0;
104*54e60f84SAndroid Build Coastguard Worker             xrect.width = dri2_drawable->width;
105*54e60f84SAndroid Build Coastguard Worker             xrect.height = dri2_drawable->height;
106*54e60f84SAndroid Build Coastguard Worker 
107*54e60f84SAndroid Build Coastguard Worker             region = XFixesCreateRegion(ctx->native_dpy, &xrect, 1);
108*54e60f84SAndroid Build Coastguard Worker             VA_DRI2CopyRegion(ctx->native_dpy, dri_drawable->x_drawable, region,
109*54e60f84SAndroid Build Coastguard Worker                               DRI2BufferFrontLeft, DRI2BufferBackLeft);
110*54e60f84SAndroid Build Coastguard Worker             XFixesDestroyRegion(ctx->native_dpy, region);
111*54e60f84SAndroid Build Coastguard Worker         }
112*54e60f84SAndroid Build Coastguard Worker     }
113*54e60f84SAndroid Build Coastguard Worker }
114*54e60f84SAndroid Build Coastguard Worker 
115*54e60f84SAndroid Build Coastguard Worker static union dri_buffer *
dri2GetRenderingBuffer(VADriverContextP ctx,struct dri_drawable * dri_drawable)116*54e60f84SAndroid Build Coastguard Worker     dri2GetRenderingBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
117*54e60f84SAndroid Build Coastguard Worker {
118*54e60f84SAndroid Build Coastguard Worker     struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
119*54e60f84SAndroid Build Coastguard Worker     int i;
120*54e60f84SAndroid Build Coastguard Worker     int count;
121*54e60f84SAndroid Build Coastguard Worker     unsigned int attachments[5];
122*54e60f84SAndroid Build Coastguard Worker     VA_DRI2Buffer *buffers;
123*54e60f84SAndroid Build Coastguard Worker 
124*54e60f84SAndroid Build Coastguard Worker     i = 0;
125*54e60f84SAndroid Build Coastguard Worker     if (dri_drawable->is_window)
126*54e60f84SAndroid Build Coastguard Worker         attachments[i++] = __DRI_BUFFER_BACK_LEFT;
127*54e60f84SAndroid Build Coastguard Worker     else
128*54e60f84SAndroid Build Coastguard Worker         attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
129*54e60f84SAndroid Build Coastguard Worker 
130*54e60f84SAndroid Build Coastguard Worker     buffers = VA_DRI2GetBuffers(ctx->native_dpy, dri_drawable->x_drawable,
131*54e60f84SAndroid Build Coastguard Worker                                 &dri2_drawable->width, &dri2_drawable->height,
132*54e60f84SAndroid Build Coastguard Worker                                 attachments, i, &count);
133*54e60f84SAndroid Build Coastguard Worker     if (buffers == NULL)
134*54e60f84SAndroid Build Coastguard Worker         return NULL;
135*54e60f84SAndroid Build Coastguard Worker 
136*54e60f84SAndroid Build Coastguard Worker     dri2_drawable->has_backbuffer = 0;
137*54e60f84SAndroid Build Coastguard Worker 
138*54e60f84SAndroid Build Coastguard Worker     for (i = 0; i < count; i++) {
139*54e60f84SAndroid Build Coastguard Worker         dri2_drawable->buffers[i].dri2.attachment = buffers[i].attachment;
140*54e60f84SAndroid Build Coastguard Worker         dri2_drawable->buffers[i].dri2.name = buffers[i].name;
141*54e60f84SAndroid Build Coastguard Worker         dri2_drawable->buffers[i].dri2.pitch = buffers[i].pitch;
142*54e60f84SAndroid Build Coastguard Worker         dri2_drawable->buffers[i].dri2.cpp = buffers[i].cpp;
143*54e60f84SAndroid Build Coastguard Worker         dri2_drawable->buffers[i].dri2.flags = buffers[i].flags;
144*54e60f84SAndroid Build Coastguard Worker 
145*54e60f84SAndroid Build Coastguard Worker         if (buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) {
146*54e60f84SAndroid Build Coastguard Worker             dri2_drawable->has_backbuffer = 1;
147*54e60f84SAndroid Build Coastguard Worker             dri2_drawable->back_index = i;
148*54e60f84SAndroid Build Coastguard Worker         }
149*54e60f84SAndroid Build Coastguard Worker 
150*54e60f84SAndroid Build Coastguard Worker         if (buffers[i].attachment == __DRI_BUFFER_FRONT_LEFT)
151*54e60f84SAndroid Build Coastguard Worker             dri2_drawable->front_index = i;
152*54e60f84SAndroid Build Coastguard Worker     }
153*54e60f84SAndroid Build Coastguard Worker 
154*54e60f84SAndroid Build Coastguard Worker     dri_drawable->width = dri2_drawable->width;
155*54e60f84SAndroid Build Coastguard Worker     dri_drawable->height = dri2_drawable->height;
156*54e60f84SAndroid Build Coastguard Worker     Xfree(buffers);
157*54e60f84SAndroid Build Coastguard Worker 
158*54e60f84SAndroid Build Coastguard Worker     if (dri2_drawable->has_backbuffer)
159*54e60f84SAndroid Build Coastguard Worker         return &dri2_drawable->buffers[dri2_drawable->back_index];
160*54e60f84SAndroid Build Coastguard Worker 
161*54e60f84SAndroid Build Coastguard Worker     return &dri2_drawable->buffers[dri2_drawable->front_index];
162*54e60f84SAndroid Build Coastguard Worker }
163*54e60f84SAndroid Build Coastguard Worker 
164*54e60f84SAndroid Build Coastguard Worker static void
dri2Close(VADriverContextP ctx)165*54e60f84SAndroid Build Coastguard Worker dri2Close(VADriverContextP ctx)
166*54e60f84SAndroid Build Coastguard Worker {
167*54e60f84SAndroid Build Coastguard Worker     struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
168*54e60f84SAndroid Build Coastguard Worker 
169*54e60f84SAndroid Build Coastguard Worker     va_dri_free_drawable_hashtable(ctx);
170*54e60f84SAndroid Build Coastguard Worker 
171*54e60f84SAndroid Build Coastguard Worker     if (dri_state->base.fd >= 0)
172*54e60f84SAndroid Build Coastguard Worker         close(dri_state->base.fd);
173*54e60f84SAndroid Build Coastguard Worker }
174*54e60f84SAndroid Build Coastguard Worker 
175*54e60f84SAndroid Build Coastguard Worker int
va_isRenderNodeFd(int fd)176*54e60f84SAndroid Build Coastguard Worker va_isRenderNodeFd(int fd)
177*54e60f84SAndroid Build Coastguard Worker {
178*54e60f84SAndroid Build Coastguard Worker     struct stat st;
179*54e60f84SAndroid Build Coastguard Worker     char *name;
180*54e60f84SAndroid Build Coastguard Worker 
181*54e60f84SAndroid Build Coastguard Worker     /* Check by device node */
182*54e60f84SAndroid Build Coastguard Worker     if (fstat(fd, &st) == 0)
183*54e60f84SAndroid Build Coastguard Worker         return S_ISCHR(st.st_mode) && (st.st_rdev & 0x80);
184*54e60f84SAndroid Build Coastguard Worker 
185*54e60f84SAndroid Build Coastguard Worker     /* Check by device name */
186*54e60f84SAndroid Build Coastguard Worker     name = drmGetDeviceNameFromFd(fd);
187*54e60f84SAndroid Build Coastguard Worker     if (name) {
188*54e60f84SAndroid Build Coastguard Worker         /* drmGetDeviceNameFromFd returns a strdup'ed string */
189*54e60f84SAndroid Build Coastguard Worker         int r = (strncmp(name, "/dev/dri/renderD", 16) == 0);
190*54e60f84SAndroid Build Coastguard Worker         drmFree(name);
191*54e60f84SAndroid Build Coastguard Worker         return r;
192*54e60f84SAndroid Build Coastguard Worker     }
193*54e60f84SAndroid Build Coastguard Worker 
194*54e60f84SAndroid Build Coastguard Worker     /* Unrecoverable error */
195*54e60f84SAndroid Build Coastguard Worker     return -1;
196*54e60f84SAndroid Build Coastguard Worker }
197*54e60f84SAndroid Build Coastguard Worker 
198*54e60f84SAndroid Build Coastguard Worker Bool
va_isDRI2Connected(VADriverContextP ctx,char ** driver_name)199*54e60f84SAndroid Build Coastguard Worker va_isDRI2Connected(VADriverContextP ctx, char **driver_name)
200*54e60f84SAndroid Build Coastguard Worker {
201*54e60f84SAndroid Build Coastguard Worker     struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
202*54e60f84SAndroid Build Coastguard Worker     int major, minor;
203*54e60f84SAndroid Build Coastguard Worker     int error_base;
204*54e60f84SAndroid Build Coastguard Worker     int event_base;
205*54e60f84SAndroid Build Coastguard Worker     char *device_name = NULL;
206*54e60f84SAndroid Build Coastguard Worker     int is_render_nodes;
207*54e60f84SAndroid Build Coastguard Worker     drm_magic_t magic;
208*54e60f84SAndroid Build Coastguard Worker     *driver_name = NULL;
209*54e60f84SAndroid Build Coastguard Worker 
210*54e60f84SAndroid Build Coastguard Worker     if (!VA_DRI2QueryExtension(ctx->native_dpy, &event_base, &error_base))
211*54e60f84SAndroid Build Coastguard Worker         goto err_out;
212*54e60f84SAndroid Build Coastguard Worker 
213*54e60f84SAndroid Build Coastguard Worker     if (!VA_DRI2QueryVersion(ctx->native_dpy, &major, &minor))
214*54e60f84SAndroid Build Coastguard Worker         goto err_out;
215*54e60f84SAndroid Build Coastguard Worker 
216*54e60f84SAndroid Build Coastguard Worker 
217*54e60f84SAndroid Build Coastguard Worker     if (!VA_DRI2Connect(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
218*54e60f84SAndroid Build Coastguard Worker                         driver_name, &device_name))
219*54e60f84SAndroid Build Coastguard Worker         goto err_out;
220*54e60f84SAndroid Build Coastguard Worker 
221*54e60f84SAndroid Build Coastguard Worker     if ((dri_state->base.fd != -1) && (dri_state->base.auth_type != VA_NONE))
222*54e60f84SAndroid Build Coastguard Worker         goto success_out;
223*54e60f84SAndroid Build Coastguard Worker 
224*54e60f84SAndroid Build Coastguard Worker     dri_state->base.fd = open(device_name, O_RDWR);
225*54e60f84SAndroid Build Coastguard Worker 
226*54e60f84SAndroid Build Coastguard Worker     if (dri_state->base.fd < 0 || (is_render_nodes = va_isRenderNodeFd(dri_state->base.fd)) < 0)
227*54e60f84SAndroid Build Coastguard Worker         goto err_out;
228*54e60f84SAndroid Build Coastguard Worker 
229*54e60f84SAndroid Build Coastguard Worker     if (!is_render_nodes) {
230*54e60f84SAndroid Build Coastguard Worker         if (drmGetMagic(dri_state->base.fd, &magic))
231*54e60f84SAndroid Build Coastguard Worker             goto err_out;
232*54e60f84SAndroid Build Coastguard Worker 
233*54e60f84SAndroid Build Coastguard Worker         if (!VA_DRI2Authenticate(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
234*54e60f84SAndroid Build Coastguard Worker                                  magic))
235*54e60f84SAndroid Build Coastguard Worker             goto err_out;
236*54e60f84SAndroid Build Coastguard Worker     }
237*54e60f84SAndroid Build Coastguard Worker     dri_state->base.auth_type = VA_DRI2;
238*54e60f84SAndroid Build Coastguard Worker     dri_state->createDrawable = dri2CreateDrawable;
239*54e60f84SAndroid Build Coastguard Worker     dri_state->destroyDrawable = dri2DestroyDrawable;
240*54e60f84SAndroid Build Coastguard Worker     dri_state->swapBuffer = dri2SwapBuffer;
241*54e60f84SAndroid Build Coastguard Worker     dri_state->getRenderingBuffer = dri2GetRenderingBuffer;
242*54e60f84SAndroid Build Coastguard Worker     dri_state->close = dri2Close;
243*54e60f84SAndroid Build Coastguard Worker     gsDRI2SwapAvailable = (minor >= 2);
244*54e60f84SAndroid Build Coastguard Worker 
245*54e60f84SAndroid Build Coastguard Worker success_out:
246*54e60f84SAndroid Build Coastguard Worker     Xfree(device_name);
247*54e60f84SAndroid Build Coastguard Worker 
248*54e60f84SAndroid Build Coastguard Worker     return True;
249*54e60f84SAndroid Build Coastguard Worker 
250*54e60f84SAndroid Build Coastguard Worker err_out:
251*54e60f84SAndroid Build Coastguard Worker     if (device_name)
252*54e60f84SAndroid Build Coastguard Worker         Xfree(device_name);
253*54e60f84SAndroid Build Coastguard Worker 
254*54e60f84SAndroid Build Coastguard Worker     if (*driver_name)
255*54e60f84SAndroid Build Coastguard Worker         Xfree(*driver_name);
256*54e60f84SAndroid Build Coastguard Worker 
257*54e60f84SAndroid Build Coastguard Worker     if (dri_state->base.fd >= 0)
258*54e60f84SAndroid Build Coastguard Worker         close(dri_state->base.fd);
259*54e60f84SAndroid Build Coastguard Worker 
260*54e60f84SAndroid Build Coastguard Worker     *driver_name = NULL;
261*54e60f84SAndroid Build Coastguard Worker     dri_state->base.fd = -1;
262*54e60f84SAndroid Build Coastguard Worker 
263*54e60f84SAndroid Build Coastguard Worker     return False;
264*54e60f84SAndroid Build Coastguard Worker }
265*54e60f84SAndroid Build Coastguard Worker 
266