xref: /aosp_15_r20/external/mesa3d/src/loader/loader_dri_helper.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Permission to use, copy, modify, distribute, and sell this software and its
3*61046927SAndroid Build Coastguard Worker  * documentation for any purpose is hereby granted without fee, provided that
4*61046927SAndroid Build Coastguard Worker  * the above copyright notice appear in all copies and that both that copyright
5*61046927SAndroid Build Coastguard Worker  * notice and this permission notice appear in supporting documentation, and
6*61046927SAndroid Build Coastguard Worker  * that the name of the copyright holders not be used in advertising or
7*61046927SAndroid Build Coastguard Worker  * publicity pertaining to distribution of the software without specific,
8*61046927SAndroid Build Coastguard Worker  * written prior permission.  The copyright holders make no representations
9*61046927SAndroid Build Coastguard Worker  * about the suitability of this software for any purpose.  It is provided "as
10*61046927SAndroid Build Coastguard Worker  * is" without express or implied warranty.
11*61046927SAndroid Build Coastguard Worker  *
12*61046927SAndroid Build Coastguard Worker  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
13*61046927SAndroid Build Coastguard Worker  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
14*61046927SAndroid Build Coastguard Worker  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
15*61046927SAndroid Build Coastguard Worker  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
16*61046927SAndroid Build Coastguard Worker  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
17*61046927SAndroid Build Coastguard Worker  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
18*61046927SAndroid Build Coastguard Worker  * OF THIS SOFTWARE.
19*61046927SAndroid Build Coastguard Worker  */
20*61046927SAndroid Build Coastguard Worker 
21*61046927SAndroid Build Coastguard Worker #include <errno.h>
22*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
23*61046927SAndroid Build Coastguard Worker #include <stdio.h>
24*61046927SAndroid Build Coastguard Worker #include <sys/types.h>
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker #include <GL/gl.h> /* mesa_interface needs GL types */
27*61046927SAndroid Build Coastguard Worker #include "mesa_interface.h"
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker #include "drm-uapi/drm_fourcc.h"
30*61046927SAndroid Build Coastguard Worker #include "loader_dri_helper.h"
31*61046927SAndroid Build Coastguard Worker #include "util/driconf.h"
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker /* the DRIimage createImage function takes __DRI_IMAGE_FORMAT codes, while
35*61046927SAndroid Build Coastguard Worker  * the createImageFromDmaBufs call takes DRM_FORMAT codes. To avoid
36*61046927SAndroid Build Coastguard Worker  * complete confusion, just deal in __DRI_IMAGE_FORMAT codes for now and
37*61046927SAndroid Build Coastguard Worker  * translate to DRM_FORMAT codes in the call to createImageFromDmaBufs
38*61046927SAndroid Build Coastguard Worker  */
39*61046927SAndroid Build Coastguard Worker int
loader_fourcc_to_image_format(int fourcc)40*61046927SAndroid Build Coastguard Worker loader_fourcc_to_image_format(int fourcc)
41*61046927SAndroid Build Coastguard Worker {
42*61046927SAndroid Build Coastguard Worker    /* Convert from DRM_FORMAT to __DRI_IMAGE_FORMAT (sigh) */
43*61046927SAndroid Build Coastguard Worker    switch (fourcc) {
44*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FOURCC_SARGB8888: return __DRI_IMAGE_FORMAT_SARGB8;
45*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FOURCC_SABGR8888: return __DRI_IMAGE_FORMAT_SABGR8;
46*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FOURCC_SXRGB8888: return __DRI_IMAGE_FORMAT_SXRGB8;
47*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_RGB565: return __DRI_IMAGE_FORMAT_RGB565;
48*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_XRGB8888: return __DRI_IMAGE_FORMAT_XRGB8888;
49*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_ARGB8888: return __DRI_IMAGE_FORMAT_ARGB8888;
50*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_ABGR8888: return __DRI_IMAGE_FORMAT_ABGR8888;
51*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_XBGR8888: return __DRI_IMAGE_FORMAT_XBGR8888;
52*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_XRGB2101010: return __DRI_IMAGE_FORMAT_XRGB2101010;
53*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_ARGB2101010: return __DRI_IMAGE_FORMAT_ARGB2101010;
54*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_XBGR2101010: return __DRI_IMAGE_FORMAT_XBGR2101010;
55*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_ABGR2101010: return __DRI_IMAGE_FORMAT_ABGR2101010;
56*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_ABGR16161616: return __DRI_IMAGE_FORMAT_ABGR16161616;
57*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_XBGR16161616: return __DRI_IMAGE_FORMAT_XBGR16161616;
58*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_XBGR16161616F: return __DRI_IMAGE_FORMAT_XBGR16161616F;
59*61046927SAndroid Build Coastguard Worker    case DRM_FORMAT_ABGR16161616F: return __DRI_IMAGE_FORMAT_ABGR16161616F;
60*61046927SAndroid Build Coastguard Worker    }
61*61046927SAndroid Build Coastguard Worker    return 0;
62*61046927SAndroid Build Coastguard Worker }
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker int
loader_image_format_to_fourcc(int format)65*61046927SAndroid Build Coastguard Worker loader_image_format_to_fourcc(int format)
66*61046927SAndroid Build Coastguard Worker {
67*61046927SAndroid Build Coastguard Worker    /* Convert from __DRI_IMAGE_FORMAT to DRM_FORMAT (sigh) */
68*61046927SAndroid Build Coastguard Worker    switch (format) {
69*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_SARGB8: return __DRI_IMAGE_FOURCC_SARGB8888;
70*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_SABGR8: return __DRI_IMAGE_FOURCC_SABGR8888;
71*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_SXRGB8: return __DRI_IMAGE_FOURCC_SXRGB8888;
72*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_RGB565: return DRM_FORMAT_RGB565;
73*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_XRGB8888: return DRM_FORMAT_XRGB8888;
74*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_ARGB8888: return DRM_FORMAT_ARGB8888;
75*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_ABGR8888: return DRM_FORMAT_ABGR8888;
76*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_XBGR8888: return DRM_FORMAT_XBGR8888;
77*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_XRGB2101010: return DRM_FORMAT_XRGB2101010;
78*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_ARGB2101010: return DRM_FORMAT_ARGB2101010;
79*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_XBGR2101010: return DRM_FORMAT_XBGR2101010;
80*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_ABGR2101010: return DRM_FORMAT_ABGR2101010;
81*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_ABGR16161616: return DRM_FORMAT_ABGR16161616;
82*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_XBGR16161616: return DRM_FORMAT_XBGR16161616;
83*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_XBGR16161616F: return DRM_FORMAT_XBGR16161616F;
84*61046927SAndroid Build Coastguard Worker    case __DRI_IMAGE_FORMAT_ABGR16161616F: return DRM_FORMAT_ABGR16161616F;
85*61046927SAndroid Build Coastguard Worker    }
86*61046927SAndroid Build Coastguard Worker    return 0;
87*61046927SAndroid Build Coastguard Worker }
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker #ifdef HAVE_X11_PLATFORM
90*61046927SAndroid Build Coastguard Worker void
loader_init_screen_resources(struct loader_screen_resources * res,xcb_connection_t * conn,xcb_screen_t * screen)91*61046927SAndroid Build Coastguard Worker loader_init_screen_resources(struct loader_screen_resources *res,
92*61046927SAndroid Build Coastguard Worker                              xcb_connection_t *conn,
93*61046927SAndroid Build Coastguard Worker                              xcb_screen_t *screen)
94*61046927SAndroid Build Coastguard Worker {
95*61046927SAndroid Build Coastguard Worker    res->conn = conn;
96*61046927SAndroid Build Coastguard Worker    res->screen = screen;
97*61046927SAndroid Build Coastguard Worker    res->crtcs = NULL;
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker    mtx_init(&res->mtx, mtx_plain);
100*61046927SAndroid Build Coastguard Worker }
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker void
loader_destroy_screen_resources(struct loader_screen_resources * res)103*61046927SAndroid Build Coastguard Worker loader_destroy_screen_resources(struct loader_screen_resources *res)
104*61046927SAndroid Build Coastguard Worker {
105*61046927SAndroid Build Coastguard Worker    mtx_destroy(&res->mtx);
106*61046927SAndroid Build Coastguard Worker }
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker static unsigned
gcd_u32(unsigned a,unsigned b)109*61046927SAndroid Build Coastguard Worker gcd_u32(unsigned a, unsigned b)
110*61046927SAndroid Build Coastguard Worker {
111*61046927SAndroid Build Coastguard Worker    assert(a > 0 || b > 0);
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker    while (b != 0) {
114*61046927SAndroid Build Coastguard Worker       unsigned remainder = a % b;
115*61046927SAndroid Build Coastguard Worker       a = b;
116*61046927SAndroid Build Coastguard Worker       b = remainder;
117*61046927SAndroid Build Coastguard Worker    }
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker    return a;
120*61046927SAndroid Build Coastguard Worker }
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker static void
calculate_refresh_rate(const xcb_randr_mode_info_t * mode,unsigned * numerator,unsigned * denominator)123*61046927SAndroid Build Coastguard Worker calculate_refresh_rate(const xcb_randr_mode_info_t *mode,
124*61046927SAndroid Build Coastguard Worker                        unsigned *numerator, unsigned *denominator)
125*61046927SAndroid Build Coastguard Worker {
126*61046927SAndroid Build Coastguard Worker    unsigned vtotal = mode->vtotal;
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker    /* Double-scan doubles the number of lines */
129*61046927SAndroid Build Coastguard Worker    if (mode->mode_flags & XCB_RANDR_MODE_FLAG_DOUBLE_SCAN)
130*61046927SAndroid Build Coastguard Worker       vtotal *= 2;
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker    /* Interlace splits the frame into two fields; typically the monitor
133*61046927SAndroid Build Coastguard Worker     * reports field rate.
134*61046927SAndroid Build Coastguard Worker     */
135*61046927SAndroid Build Coastguard Worker    if (mode->mode_flags & XCB_RANDR_MODE_FLAG_INTERLACE)
136*61046927SAndroid Build Coastguard Worker       vtotal /= 2;
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker    uint32_t dots = mode->htotal * vtotal;
139*61046927SAndroid Build Coastguard Worker 
140*61046927SAndroid Build Coastguard Worker    if (dots == 0) {
141*61046927SAndroid Build Coastguard Worker       *numerator = 0;
142*61046927SAndroid Build Coastguard Worker       *denominator = 1;
143*61046927SAndroid Build Coastguard Worker    } else {
144*61046927SAndroid Build Coastguard Worker       uint32_t gcd = gcd_u32(mode->dot_clock, dots);
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker       *numerator = mode->dot_clock / gcd;
147*61046927SAndroid Build Coastguard Worker       *denominator = dots / gcd;
148*61046927SAndroid Build Coastguard Worker    }
149*61046927SAndroid Build Coastguard Worker }
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker bool
loader_update_screen_resources(struct loader_screen_resources * res)152*61046927SAndroid Build Coastguard Worker loader_update_screen_resources(struct loader_screen_resources *res)
153*61046927SAndroid Build Coastguard Worker {
154*61046927SAndroid Build Coastguard Worker    xcb_randr_get_crtc_info_cookie_t *crtc_cookies;
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker    /* If we have cached screen resources information, check each CRTC to
157*61046927SAndroid Build Coastguard Worker     * see if it's up to date.  Ideally, we'd watch PresentConfigureNotify
158*61046927SAndroid Build Coastguard Worker     * events on the root window to see if something changed, but those only
159*61046927SAndroid Build Coastguard Worker     * fire if the geometry changes.  It misses CRTC changes which only
160*61046927SAndroid Build Coastguard Worker     * alter the refresh rate.  We also can't watch RandR events internally
161*61046927SAndroid Build Coastguard Worker     * because they aren't XGE events.  So, we just check every CRTC for now.
162*61046927SAndroid Build Coastguard Worker     */
163*61046927SAndroid Build Coastguard Worker    bool config_unchanged = res->crtcs != NULL;
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker    crtc_cookies = malloc(res->num_crtcs * sizeof(*crtc_cookies));
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker    for (unsigned c = 0; c < res->num_crtcs; c++) {
168*61046927SAndroid Build Coastguard Worker       crtc_cookies[c] =
169*61046927SAndroid Build Coastguard Worker          xcb_randr_get_crtc_info_unchecked(res->conn, res->crtcs[c].id,
170*61046927SAndroid Build Coastguard Worker                                            res->config_timestamp);
171*61046927SAndroid Build Coastguard Worker    }
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker    for (unsigned c = 0; c < res->num_crtcs; c++) {
174*61046927SAndroid Build Coastguard Worker       xcb_randr_get_crtc_info_reply_t *reply =
175*61046927SAndroid Build Coastguard Worker          xcb_randr_get_crtc_info_reply(res->conn, crtc_cookies[c], NULL);
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker       /* Although randrproto 1.4.0 says that RRGetCrtcInfo is supposed to
178*61046927SAndroid Build Coastguard Worker        * return InvalidConfigTime if config_timestamp is out of date, the
179*61046927SAndroid Build Coastguard Worker        * implementation in xserver as of 21.x doesn't actually do so.  To
180*61046927SAndroid Build Coastguard Worker        * detect changes in refresh rate, we check the returned timestamp
181*61046927SAndroid Build Coastguard Worker        * on each tracked CRTC.
182*61046927SAndroid Build Coastguard Worker        */
183*61046927SAndroid Build Coastguard Worker       if (!reply ||
184*61046927SAndroid Build Coastguard Worker           reply->status == XCB_RANDR_SET_CONFIG_INVALID_CONFIG_TIME ||
185*61046927SAndroid Build Coastguard Worker           reply->timestamp != res->crtcs[c].timestamp) {
186*61046927SAndroid Build Coastguard Worker          config_unchanged = false;
187*61046927SAndroid Build Coastguard Worker          /* continue to consume all replies */
188*61046927SAndroid Build Coastguard Worker       }
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker       free(reply);
191*61046927SAndroid Build Coastguard Worker    }
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker    free(crtc_cookies);
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker    if (config_unchanged)
196*61046927SAndroid Build Coastguard Worker       return false;
197*61046927SAndroid Build Coastguard Worker 
198*61046927SAndroid Build Coastguard Worker    /* Do RRGetScreenResourcesCurrent to query the list of CRTCs and modes,
199*61046927SAndroid Build Coastguard Worker     * then RRGetCrtcInfo on each CRTC to determine what mode each uses, and
200*61046927SAndroid Build Coastguard Worker     * use the mode to calculate the refresh rate.
201*61046927SAndroid Build Coastguard Worker     */
202*61046927SAndroid Build Coastguard Worker    mtx_lock(&res->mtx);
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker    xcb_randr_get_screen_resources_current_cookie_t cookie =
205*61046927SAndroid Build Coastguard Worker       xcb_randr_get_screen_resources_current_unchecked(res->conn,
206*61046927SAndroid Build Coastguard Worker                                                        res->screen->root);
207*61046927SAndroid Build Coastguard Worker    xcb_randr_get_screen_resources_current_reply_t *reply =
208*61046927SAndroid Build Coastguard Worker       xcb_randr_get_screen_resources_current_reply(res->conn, cookie, NULL);
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker    xcb_randr_crtc_t *new_crtcs =
211*61046927SAndroid Build Coastguard Worker       xcb_randr_get_screen_resources_current_crtcs(reply);
212*61046927SAndroid Build Coastguard Worker 
213*61046927SAndroid Build Coastguard Worker    xcb_randr_mode_info_t *new_modes =
214*61046927SAndroid Build Coastguard Worker       xcb_randr_get_screen_resources_current_modes(reply);
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker    res->config_timestamp = reply->config_timestamp;
217*61046927SAndroid Build Coastguard Worker 
218*61046927SAndroid Build Coastguard Worker    free(res->crtcs);
219*61046927SAndroid Build Coastguard Worker    res->crtcs = calloc(reply->num_crtcs, sizeof(*res->crtcs));
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker    crtc_cookies = malloc(reply->num_crtcs * sizeof(*crtc_cookies));
222*61046927SAndroid Build Coastguard Worker 
223*61046927SAndroid Build Coastguard Worker    for (unsigned c = 0; c < reply->num_crtcs; c++) {
224*61046927SAndroid Build Coastguard Worker       crtc_cookies[c] =
225*61046927SAndroid Build Coastguard Worker          xcb_randr_get_crtc_info_unchecked(res->conn, new_crtcs[c],
226*61046927SAndroid Build Coastguard Worker                                            res->config_timestamp);
227*61046927SAndroid Build Coastguard Worker    }
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker    unsigned i = 0;
230*61046927SAndroid Build Coastguard Worker    for (unsigned c = 0; c < reply->num_crtcs; c++) {
231*61046927SAndroid Build Coastguard Worker       xcb_randr_get_crtc_info_reply_t *crtc_info =
232*61046927SAndroid Build Coastguard Worker          xcb_randr_get_crtc_info_reply(res->conn, crtc_cookies[c], NULL);
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker       if (!crtc_info || crtc_info->mode == XCB_NONE)
235*61046927SAndroid Build Coastguard Worker          continue;
236*61046927SAndroid Build Coastguard Worker 
237*61046927SAndroid Build Coastguard Worker       res->crtcs[i].id = new_crtcs[c];
238*61046927SAndroid Build Coastguard Worker       res->crtcs[i].timestamp = crtc_info->timestamp;
239*61046927SAndroid Build Coastguard Worker       res->crtcs[i].x = crtc_info->x;
240*61046927SAndroid Build Coastguard Worker       res->crtcs[i].y = crtc_info->y;
241*61046927SAndroid Build Coastguard Worker       res->crtcs[i].width = crtc_info->width;
242*61046927SAndroid Build Coastguard Worker       res->crtcs[i].height = crtc_info->height;
243*61046927SAndroid Build Coastguard Worker 
244*61046927SAndroid Build Coastguard Worker       for (int m = 0; m < reply->num_modes; m++) {
245*61046927SAndroid Build Coastguard Worker          if (new_modes[m].id == crtc_info->mode) {
246*61046927SAndroid Build Coastguard Worker             calculate_refresh_rate(&new_modes[m],
247*61046927SAndroid Build Coastguard Worker                                    &res->crtcs[i].refresh_numerator,
248*61046927SAndroid Build Coastguard Worker                                    &res->crtcs[i].refresh_denominator);
249*61046927SAndroid Build Coastguard Worker             break;
250*61046927SAndroid Build Coastguard Worker          }
251*61046927SAndroid Build Coastguard Worker       }
252*61046927SAndroid Build Coastguard Worker 
253*61046927SAndroid Build Coastguard Worker       i++;
254*61046927SAndroid Build Coastguard Worker       free(crtc_info);
255*61046927SAndroid Build Coastguard Worker    }
256*61046927SAndroid Build Coastguard Worker 
257*61046927SAndroid Build Coastguard Worker    res->num_crtcs = i;
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker    free(crtc_cookies);
260*61046927SAndroid Build Coastguard Worker    free(reply);
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker    mtx_unlock(&res->mtx);
263*61046927SAndroid Build Coastguard Worker    return true;
264*61046927SAndroid Build Coastguard Worker }
265*61046927SAndroid Build Coastguard Worker #endif
266