1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright 2009, VMware, Inc.
5 * All Rights Reserved.
6 * Copyright (C) 2010 LunarG Inc.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Keith Whitwell <keithw@vmware.com> Jakob Bornecrantz
28 * <wallbraker@gmail.com> Chia-I Wu <olv@lunarg.com>
29 */
30
31 #include <xf86drm.h>
32 #include <fcntl.h>
33 #include "GL/mesa_glinterop.h"
34 #include "util/u_memory.h"
35 #include "util/u_inlines.h"
36 #include "util/u_format.h"
37 #include "util/u_debug.h"
38 #include "state_tracker/drm_driver.h"
39 #include "state_tracker/st_cb_bufferobjects.h"
40 #include "state_tracker/st_cb_fbo.h"
41 #include "state_tracker/st_cb_texture.h"
42 #include "state_tracker/st_texture.h"
43 #include "state_tracker/st_context.h"
44 #include "pipe-loader/pipe_loader.h"
45 #include "main/bufferobj.h"
46 #include "main/texobj.h"
47
48 #include "dri_helpers.h"
49 #include "dri_drawable.h"
50 #include "dri_query_renderer.h"
51 #include "dri2_buffer.h"
52
53 #ifndef DRM_FORMAT_MOD_INVALID
54 #define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
55 #endif
56
57 static const int fourcc_formats[] = {
58 __DRI_IMAGE_FOURCC_ARGB2101010,
59 __DRI_IMAGE_FOURCC_XRGB2101010,
60 __DRI_IMAGE_FOURCC_ARGB8888,
61 __DRI_IMAGE_FOURCC_ABGR8888,
62 __DRI_IMAGE_FOURCC_SARGB8888,
63 __DRI_IMAGE_FOURCC_XRGB8888,
64 __DRI_IMAGE_FOURCC_XBGR8888,
65 __DRI_IMAGE_FOURCC_ARGB1555,
66 __DRI_IMAGE_FOURCC_RGB565,
67 __DRI_IMAGE_FOURCC_R8,
68 __DRI_IMAGE_FOURCC_R16,
69 __DRI_IMAGE_FOURCC_GR88,
70 __DRI_IMAGE_FOURCC_GR1616,
71 __DRI_IMAGE_FOURCC_YUV410,
72 __DRI_IMAGE_FOURCC_YUV411,
73 __DRI_IMAGE_FOURCC_YUV420,
74 __DRI_IMAGE_FOURCC_YUV422,
75 __DRI_IMAGE_FOURCC_YUV444,
76 __DRI_IMAGE_FOURCC_YVU410,
77 __DRI_IMAGE_FOURCC_YVU411,
78 __DRI_IMAGE_FOURCC_YVU420,
79 __DRI_IMAGE_FOURCC_YVU422,
80 __DRI_IMAGE_FOURCC_YVU444,
81 __DRI_IMAGE_FOURCC_NV12,
82 __DRI_IMAGE_FOURCC_NV16,
83 __DRI_IMAGE_FOURCC_YUYV
84 };
85
convert_fourcc(int format,int * dri_components_p)86 static int convert_fourcc(int format, int *dri_components_p)
87 {
88 int dri_components;
89 switch(format) {
90 case __DRI_IMAGE_FOURCC_RGB565:
91 format = __DRI_IMAGE_FORMAT_RGB565;
92 dri_components = __DRI_IMAGE_COMPONENTS_RGB;
93 break;
94 case __DRI_IMAGE_FOURCC_ARGB8888:
95 format = __DRI_IMAGE_FORMAT_ARGB8888;
96 dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
97 break;
98 case __DRI_IMAGE_FOURCC_XRGB8888:
99 format = __DRI_IMAGE_FORMAT_XRGB8888;
100 dri_components = __DRI_IMAGE_COMPONENTS_RGB;
101 break;
102 case __DRI_IMAGE_FOURCC_ABGR8888:
103 format = __DRI_IMAGE_FORMAT_ABGR8888;
104 dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
105 break;
106 case __DRI_IMAGE_FOURCC_XBGR8888:
107 format = __DRI_IMAGE_FORMAT_XBGR8888;
108 dri_components = __DRI_IMAGE_COMPONENTS_RGB;
109 break;
110 case __DRI_IMAGE_FOURCC_ARGB2101010:
111 format = __DRI_IMAGE_FORMAT_ARGB2101010;
112 dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
113 break;
114 case __DRI_IMAGE_FOURCC_XRGB2101010:
115 format = __DRI_IMAGE_FORMAT_XRGB2101010;
116 dri_components = __DRI_IMAGE_COMPONENTS_RGB;
117 break;
118 case __DRI_IMAGE_FOURCC_R8:
119 format = __DRI_IMAGE_FORMAT_R8;
120 dri_components = __DRI_IMAGE_COMPONENTS_R;
121 break;
122 case __DRI_IMAGE_FOURCC_GR88:
123 format = __DRI_IMAGE_FORMAT_GR88;
124 dri_components = __DRI_IMAGE_COMPONENTS_RG;
125 break;
126 case __DRI_IMAGE_FOURCC_R16:
127 format = __DRI_IMAGE_FORMAT_R16;
128 dri_components = __DRI_IMAGE_COMPONENTS_R;
129 break;
130 case __DRI_IMAGE_FOURCC_GR1616:
131 format = __DRI_IMAGE_FORMAT_GR1616;
132 dri_components = __DRI_IMAGE_COMPONENTS_RG;
133 break;
134 case __DRI_IMAGE_FOURCC_YUYV:
135 format = __DRI_IMAGE_FORMAT_YUYV;
136 dri_components = __DRI_IMAGE_COMPONENTS_Y_XUXV;
137 break;
138 /*
139 * For multi-planar YUV formats, we return the format of the first
140 * plane only. Since there is only one caller which supports multi-
141 * planar YUV it gets to figure out the remaining planes on it's
142 * own.
143 */
144 case __DRI_IMAGE_FOURCC_YUV420:
145 case __DRI_IMAGE_FOURCC_YVU420:
146 format = __DRI_IMAGE_FORMAT_R8;
147 dri_components = __DRI_IMAGE_COMPONENTS_Y_U_V;
148 break;
149 case __DRI_IMAGE_FOURCC_NV12:
150 format = __DRI_IMAGE_FORMAT_R8;
151 dri_components = __DRI_IMAGE_COMPONENTS_Y_UV;
152 break;
153 default:
154 return -1;
155 }
156 *dri_components_p = dri_components;
157 return format;
158 }
159
160 /* NOTE this probably isn't going to do the right thing for YUV images
161 * (but I think the same can be said for intel_query_image()). I think
162 * only needed for exporting dmabuf's, so I think I won't loose much
163 * sleep over it.
164 */
convert_to_fourcc(int format)165 static int convert_to_fourcc(int format)
166 {
167 switch(format) {
168 case __DRI_IMAGE_FORMAT_RGB565:
169 format = __DRI_IMAGE_FOURCC_RGB565;
170 break;
171 case __DRI_IMAGE_FORMAT_ARGB8888:
172 format = __DRI_IMAGE_FOURCC_ARGB8888;
173 break;
174 case __DRI_IMAGE_FORMAT_XRGB8888:
175 format = __DRI_IMAGE_FOURCC_XRGB8888;
176 break;
177 case __DRI_IMAGE_FORMAT_ABGR8888:
178 format = __DRI_IMAGE_FOURCC_ABGR8888;
179 break;
180 case __DRI_IMAGE_FORMAT_XBGR8888:
181 format = __DRI_IMAGE_FOURCC_XBGR8888;
182 break;
183 case __DRI_IMAGE_FORMAT_ARGB2101010:
184 format = __DRI_IMAGE_FOURCC_ARGB2101010;
185 break;
186 case __DRI_IMAGE_FORMAT_XRGB2101010:
187 format = __DRI_IMAGE_FOURCC_XRGB2101010;
188 break;
189 case __DRI_IMAGE_FORMAT_R8:
190 format = __DRI_IMAGE_FOURCC_R8;
191 break;
192 case __DRI_IMAGE_FORMAT_GR88:
193 format = __DRI_IMAGE_FOURCC_GR88;
194 break;
195 default:
196 return -1;
197 }
198 return format;
199 }
200
dri2_format_to_pipe_format(int format)201 static enum pipe_format dri2_format_to_pipe_format (int format)
202 {
203 enum pipe_format pf;
204
205 switch (format) {
206 case __DRI_IMAGE_FORMAT_RGB565:
207 pf = PIPE_FORMAT_B5G6R5_UNORM;
208 break;
209 case __DRI_IMAGE_FORMAT_XRGB8888:
210 pf = PIPE_FORMAT_BGRX8888_UNORM;
211 break;
212 case __DRI_IMAGE_FORMAT_ARGB8888:
213 pf = PIPE_FORMAT_BGRA8888_UNORM;
214 break;
215 case __DRI_IMAGE_FORMAT_XBGR8888:
216 pf = PIPE_FORMAT_RGBX8888_UNORM;
217 break;
218 case __DRI_IMAGE_FORMAT_ABGR8888:
219 pf = PIPE_FORMAT_RGBA8888_UNORM;
220 break;
221 case __DRI_IMAGE_FORMAT_XRGB2101010:
222 pf = PIPE_FORMAT_B10G10R10X2_UNORM;
223 break;
224 case __DRI_IMAGE_FORMAT_ARGB2101010:
225 pf = PIPE_FORMAT_B10G10R10A2_UNORM;
226 break;
227 case __DRI_IMAGE_FORMAT_R8:
228 pf = PIPE_FORMAT_R8_UNORM;
229 break;
230 case __DRI_IMAGE_FORMAT_GR88:
231 pf = PIPE_FORMAT_RG88_UNORM;
232 break;
233 case __DRI_IMAGE_FORMAT_R16:
234 pf = PIPE_FORMAT_R16_UNORM;
235 break;
236 case __DRI_IMAGE_FORMAT_GR1616:
237 pf = PIPE_FORMAT_R16G16_UNORM;
238 break;
239 case __DRI_IMAGE_FORMAT_YUYV:
240 pf = PIPE_FORMAT_YUYV;
241 break;
242 default:
243 pf = PIPE_FORMAT_NONE;
244 break;
245 }
246
247 return pf;
248 }
249
fourcc_to_pipe_format(int fourcc)250 static enum pipe_format fourcc_to_pipe_format(int fourcc)
251 {
252 enum pipe_format pf;
253
254 switch (fourcc) {
255 case __DRI_IMAGE_FOURCC_R8:
256 pf = PIPE_FORMAT_R8_UNORM;
257 break;
258 case __DRI_IMAGE_FOURCC_GR88:
259 pf = PIPE_FORMAT_RG88_UNORM;
260 break;
261 case __DRI_IMAGE_FOURCC_ARGB1555:
262 pf = PIPE_FORMAT_B5G5R5A1_UNORM;
263 break;
264 case __DRI_IMAGE_FOURCC_R16:
265 pf = PIPE_FORMAT_R16_UNORM;
266 break;
267 case __DRI_IMAGE_FOURCC_GR1616:
268 pf = PIPE_FORMAT_RG1616_UNORM;
269 break;
270 case __DRI_IMAGE_FOURCC_RGB565:
271 pf = PIPE_FORMAT_B5G6R5_UNORM;
272 break;
273 case __DRI_IMAGE_FOURCC_ARGB8888:
274 pf = PIPE_FORMAT_BGRA8888_UNORM;
275 break;
276 case __DRI_IMAGE_FOURCC_XRGB8888:
277 pf = PIPE_FORMAT_BGRX8888_UNORM;
278 break;
279 case __DRI_IMAGE_FOURCC_ABGR8888:
280 pf = PIPE_FORMAT_RGBA8888_UNORM;
281 break;
282 case __DRI_IMAGE_FOURCC_XBGR8888:
283 pf = PIPE_FORMAT_RGBX8888_UNORM;
284 break;
285 case __DRI_IMAGE_FOURCC_ARGB2101010:
286 pf = PIPE_FORMAT_B10G10R10A2_UNORM;
287 break;
288 case __DRI_IMAGE_FOURCC_XRGB2101010:
289 pf = PIPE_FORMAT_B10G10R10X2_UNORM;
290 break;
291
292 case __DRI_IMAGE_FOURCC_NV12:
293 pf = PIPE_FORMAT_NV12;
294 break;
295 case __DRI_IMAGE_FOURCC_YUYV:
296 pf = PIPE_FORMAT_YUYV;
297 break;
298 case __DRI_IMAGE_FOURCC_YUV420:
299 case __DRI_IMAGE_FOURCC_YVU420:
300 pf = PIPE_FORMAT_YV12;
301 break;
302
303 case __DRI_IMAGE_FOURCC_SARGB8888:
304 case __DRI_IMAGE_FOURCC_YUV410:
305 case __DRI_IMAGE_FOURCC_YUV411:
306 case __DRI_IMAGE_FOURCC_YUV422:
307 case __DRI_IMAGE_FOURCC_YUV444:
308 case __DRI_IMAGE_FOURCC_NV16:
309 case __DRI_IMAGE_FOURCC_YVU410:
310 case __DRI_IMAGE_FOURCC_YVU411:
311 case __DRI_IMAGE_FOURCC_YVU422:
312 case __DRI_IMAGE_FOURCC_YVU444:
313 default:
314 pf = PIPE_FORMAT_NONE;
315 }
316
317 return pf;
318 }
319
320 /**
321 * DRI2 flush extension.
322 */
323 static void
dri2_flush_drawable(__DRIdrawable * dPriv)324 dri2_flush_drawable(__DRIdrawable *dPriv)
325 {
326 dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);
327 }
328
329 static void
dri2_invalidate_drawable(__DRIdrawable * dPriv)330 dri2_invalidate_drawable(__DRIdrawable *dPriv)
331 {
332 struct dri_drawable *drawable = dri_drawable(dPriv);
333
334 dri2InvalidateDrawable(dPriv);
335 drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
336 drawable->texture_mask = 0;
337
338 p_atomic_inc(&drawable->base.stamp);
339 }
340
341 static const __DRI2flushExtension dri2FlushExtension = {
342 .base = { __DRI2_FLUSH, 4 },
343
344 .flush = dri2_flush_drawable,
345 .invalidate = dri2_invalidate_drawable,
346 .flush_with_flags = dri_flush,
347 };
348
349 /**
350 * Retrieve __DRIbuffer from the DRI loader.
351 */
352 static __DRIbuffer *
dri2_drawable_get_buffers(struct dri_drawable * drawable,const enum st_attachment_type * atts,unsigned * count)353 dri2_drawable_get_buffers(struct dri_drawable *drawable,
354 const enum st_attachment_type *atts,
355 unsigned *count)
356 {
357 __DRIdrawable *dri_drawable = drawable->dPriv;
358 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
359 boolean with_format;
360 __DRIbuffer *buffers;
361 int num_buffers;
362 unsigned attachments[10];
363 unsigned num_attachments, i;
364
365 assert(loader);
366 with_format = dri_with_format(drawable->sPriv);
367
368 num_attachments = 0;
369
370 /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
371 if (!with_format)
372 attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
373
374 for (i = 0; i < *count; i++) {
375 enum pipe_format format;
376 unsigned bind;
377 int att, depth;
378
379 dri_drawable_get_format(drawable, atts[i], &format, &bind);
380 if (format == PIPE_FORMAT_NONE)
381 continue;
382
383 switch (atts[i]) {
384 case ST_ATTACHMENT_FRONT_LEFT:
385 /* already added */
386 if (!with_format)
387 continue;
388 att = __DRI_BUFFER_FRONT_LEFT;
389 break;
390 case ST_ATTACHMENT_BACK_LEFT:
391 att = __DRI_BUFFER_BACK_LEFT;
392 break;
393 case ST_ATTACHMENT_FRONT_RIGHT:
394 att = __DRI_BUFFER_FRONT_RIGHT;
395 break;
396 case ST_ATTACHMENT_BACK_RIGHT:
397 att = __DRI_BUFFER_BACK_RIGHT;
398 break;
399 default:
400 continue;
401 }
402
403 /*
404 * In this switch statement we must support all formats that
405 * may occur as the stvis->color_format.
406 */
407 switch(format) {
408 case PIPE_FORMAT_B10G10R10A2_UNORM:
409 case PIPE_FORMAT_BGRA8888_UNORM:
410 case PIPE_FORMAT_RGBA8888_UNORM:
411 depth = 32;
412 break;
413 case PIPE_FORMAT_B10G10R10X2_UNORM:
414 depth = 30;
415 break;
416 case PIPE_FORMAT_BGRX8888_UNORM:
417 case PIPE_FORMAT_RGBX8888_UNORM:
418 depth = 24;
419 break;
420 case PIPE_FORMAT_B5G6R5_UNORM:
421 depth = 16;
422 break;
423 default:
424 depth = util_format_get_blocksizebits(format);
425 assert(!"Unexpected format in dri2_drawable_get_buffers()");
426 }
427
428 attachments[num_attachments++] = att;
429 if (with_format) {
430 attachments[num_attachments++] = depth;
431 }
432 }
433
434 if (with_format) {
435 num_attachments /= 2;
436 buffers = loader->getBuffersWithFormat(dri_drawable,
437 &dri_drawable->w, &dri_drawable->h,
438 attachments, num_attachments,
439 &num_buffers, dri_drawable->loaderPrivate);
440 }
441 else {
442 buffers = loader->getBuffers(dri_drawable,
443 &dri_drawable->w, &dri_drawable->h,
444 attachments, num_attachments,
445 &num_buffers, dri_drawable->loaderPrivate);
446 }
447
448 if (buffers)
449 *count = num_buffers;
450
451 return buffers;
452 }
453
454 static bool
dri_image_drawable_get_buffers(struct dri_drawable * drawable,struct __DRIimageList * images,const enum st_attachment_type * statts,unsigned statts_count)455 dri_image_drawable_get_buffers(struct dri_drawable *drawable,
456 struct __DRIimageList *images,
457 const enum st_attachment_type *statts,
458 unsigned statts_count)
459 {
460 __DRIdrawable *dPriv = drawable->dPriv;
461 __DRIscreen *sPriv = drawable->sPriv;
462 unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;
463 enum pipe_format pf;
464 uint32_t buffer_mask = 0;
465 unsigned i, bind;
466
467 for (i = 0; i < statts_count; i++) {
468 dri_drawable_get_format(drawable, statts[i], &pf, &bind);
469 if (pf == PIPE_FORMAT_NONE)
470 continue;
471
472 switch (statts[i]) {
473 case ST_ATTACHMENT_FRONT_LEFT:
474 buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
475 break;
476 case ST_ATTACHMENT_BACK_LEFT:
477 buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
478 break;
479 default:
480 continue;
481 }
482
483 switch (pf) {
484 case PIPE_FORMAT_B5G6R5_UNORM:
485 image_format = __DRI_IMAGE_FORMAT_RGB565;
486 break;
487 case PIPE_FORMAT_BGRX8888_UNORM:
488 image_format = __DRI_IMAGE_FORMAT_XRGB8888;
489 break;
490 case PIPE_FORMAT_BGRA8888_UNORM:
491 image_format = __DRI_IMAGE_FORMAT_ARGB8888;
492 break;
493 case PIPE_FORMAT_RGBX8888_UNORM:
494 image_format = __DRI_IMAGE_FORMAT_XBGR8888;
495 break;
496 case PIPE_FORMAT_RGBA8888_UNORM:
497 image_format = __DRI_IMAGE_FORMAT_ABGR8888;
498 break;
499 case PIPE_FORMAT_B10G10R10X2_UNORM:
500 image_format = __DRI_IMAGE_FORMAT_XRGB2101010;
501 break;
502 case PIPE_FORMAT_B10G10R10A2_UNORM:
503 image_format = __DRI_IMAGE_FORMAT_ARGB2101010;
504 break;
505 default:
506 image_format = __DRI_IMAGE_FORMAT_NONE;
507 break;
508 }
509 }
510
511 return (*sPriv->image.loader->getBuffers) (dPriv, image_format,
512 (uint32_t *) &drawable->base.stamp,
513 dPriv->loaderPrivate, buffer_mask,
514 images);
515 }
516
517 static __DRIbuffer *
dri2_allocate_buffer(__DRIscreen * sPriv,unsigned attachment,unsigned format,int width,int height)518 dri2_allocate_buffer(__DRIscreen *sPriv,
519 unsigned attachment, unsigned format,
520 int width, int height)
521 {
522 struct dri_screen *screen = dri_screen(sPriv);
523 struct dri2_buffer *buffer;
524 struct pipe_resource templ;
525 enum pipe_format pf;
526 unsigned bind = 0;
527 struct winsys_handle whandle;
528
529 switch (attachment) {
530 case __DRI_BUFFER_FRONT_LEFT:
531 case __DRI_BUFFER_FAKE_FRONT_LEFT:
532 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
533 break;
534 case __DRI_BUFFER_BACK_LEFT:
535 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
536 break;
537 case __DRI_BUFFER_DEPTH:
538 case __DRI_BUFFER_DEPTH_STENCIL:
539 case __DRI_BUFFER_STENCIL:
540 bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
541 break;
542 }
543
544 /* because we get the handle and stride */
545 bind |= PIPE_BIND_SHARED;
546
547 switch (format) {
548 case 32:
549 pf = PIPE_FORMAT_BGRA8888_UNORM;
550 break;
551 case 30:
552 pf = PIPE_FORMAT_B10G10R10X2_UNORM;
553 break;
554 case 24:
555 pf = PIPE_FORMAT_BGRX8888_UNORM;
556 break;
557 case 16:
558 pf = PIPE_FORMAT_Z16_UNORM;
559 break;
560 default:
561 return NULL;
562 }
563
564 buffer = CALLOC_STRUCT(dri2_buffer);
565 if (!buffer)
566 return NULL;
567
568 memset(&templ, 0, sizeof(templ));
569 templ.bind = bind;
570 templ.format = pf;
571 templ.target = PIPE_TEXTURE_2D;
572 templ.last_level = 0;
573 templ.width0 = width;
574 templ.height0 = height;
575 templ.depth0 = 1;
576 templ.array_size = 1;
577
578 buffer->resource =
579 screen->base.screen->resource_create(screen->base.screen, &templ);
580 if (!buffer->resource) {
581 FREE(buffer);
582 return NULL;
583 }
584
585 memset(&whandle, 0, sizeof(whandle));
586 if (screen->can_share_buffer)
587 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
588 else
589 whandle.type = DRM_API_HANDLE_TYPE_KMS;
590
591 screen->base.screen->resource_get_handle(screen->base.screen, NULL,
592 buffer->resource, &whandle,
593 PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ);
594
595 buffer->base.attachment = attachment;
596 buffer->base.name = whandle.handle;
597 buffer->base.cpp = util_format_get_blocksize(pf);
598 buffer->base.pitch = whandle.stride;
599
600 return &buffer->base;
601 }
602
603 static void
dri2_release_buffer(__DRIscreen * sPriv,__DRIbuffer * bPriv)604 dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
605 {
606 struct dri2_buffer *buffer = dri2_buffer(bPriv);
607
608 pipe_resource_reference(&buffer->resource, NULL);
609 FREE(buffer);
610 }
611
612 /*
613 * Backend functions for st_framebuffer interface.
614 */
615
616 static void
dri2_allocate_textures(struct dri_context * ctx,struct dri_drawable * drawable,const enum st_attachment_type * statts,unsigned statts_count)617 dri2_allocate_textures(struct dri_context *ctx,
618 struct dri_drawable *drawable,
619 const enum st_attachment_type *statts,
620 unsigned statts_count)
621 {
622 __DRIscreen *sPriv = drawable->sPriv;
623 __DRIdrawable *dri_drawable = drawable->dPriv;
624 struct dri_screen *screen = dri_screen(sPriv);
625 struct pipe_resource templ;
626 boolean alloc_depthstencil = FALSE;
627 unsigned i, j, bind;
628 const __DRIimageLoaderExtension *image = sPriv->image.loader;
629 /* Image specific variables */
630 struct __DRIimageList images;
631 /* Dri2 specific variables */
632 __DRIbuffer *buffers = NULL;
633 struct winsys_handle whandle;
634 unsigned num_buffers = statts_count;
635
636 /* First get the buffers from the loader */
637 if (image) {
638 if (!dri_image_drawable_get_buffers(drawable, &images,
639 statts, statts_count))
640 return;
641 }
642 else {
643 buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
644 if (!buffers || (drawable->old_num == num_buffers &&
645 drawable->old_w == dri_drawable->w &&
646 drawable->old_h == dri_drawable->h &&
647 memcmp(drawable->old, buffers,
648 sizeof(__DRIbuffer) * num_buffers) == 0))
649 return;
650 }
651
652 /* Second clean useless resources*/
653
654 /* See if we need a depth-stencil buffer. */
655 for (i = 0; i < statts_count; i++) {
656 if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
657 alloc_depthstencil = TRUE;
658 break;
659 }
660 }
661
662 /* Delete the resources we won't need. */
663 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
664 /* Don't delete the depth-stencil buffer, we can reuse it. */
665 if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
666 continue;
667
668 /* Flush the texture before unreferencing, so that other clients can
669 * see what the driver has rendered.
670 */
671 if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {
672 struct pipe_context *pipe = ctx->st->pipe;
673 pipe->flush_resource(pipe, drawable->textures[i]);
674 }
675
676 pipe_resource_reference(&drawable->textures[i], NULL);
677 }
678
679 if (drawable->stvis.samples > 1) {
680 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
681 boolean del = TRUE;
682
683 /* Don't delete MSAA resources for the attachments which are enabled,
684 * we can reuse them. */
685 for (j = 0; j < statts_count; j++) {
686 if (i == statts[j]) {
687 del = FALSE;
688 break;
689 }
690 }
691
692 if (del) {
693 pipe_resource_reference(&drawable->msaa_textures[i], NULL);
694 }
695 }
696 }
697
698 /* Third use the buffers retrieved to fill the drawable info */
699
700 memset(&templ, 0, sizeof(templ));
701 templ.target = screen->target;
702 templ.last_level = 0;
703 templ.depth0 = 1;
704 templ.array_size = 1;
705
706 if (image) {
707 if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
708 struct pipe_resource **buf =
709 &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
710 struct pipe_resource *texture = images.front->texture;
711
712 dri_drawable->w = texture->width0;
713 dri_drawable->h = texture->height0;
714
715 pipe_resource_reference(buf, texture);
716 }
717
718 if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
719 struct pipe_resource **buf =
720 &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
721 struct pipe_resource *texture = images.back->texture;
722
723 dri_drawable->w = texture->width0;
724 dri_drawable->h = texture->height0;
725
726 pipe_resource_reference(buf, texture);
727 }
728
729 /* Note: if there is both a back and a front buffer,
730 * then they have the same size.
731 */
732 templ.width0 = dri_drawable->w;
733 templ.height0 = dri_drawable->h;
734 }
735 else {
736 memset(&whandle, 0, sizeof(whandle));
737
738 /* Process DRI-provided buffers and get pipe_resources. */
739 for (i = 0; i < num_buffers; i++) {
740 __DRIbuffer *buf = &buffers[i];
741 enum st_attachment_type statt;
742 enum pipe_format format;
743
744 switch (buf->attachment) {
745 case __DRI_BUFFER_FRONT_LEFT:
746 if (!screen->auto_fake_front) {
747 continue; /* invalid attachment */
748 }
749 /* fallthrough */
750 case __DRI_BUFFER_FAKE_FRONT_LEFT:
751 statt = ST_ATTACHMENT_FRONT_LEFT;
752 break;
753 case __DRI_BUFFER_BACK_LEFT:
754 statt = ST_ATTACHMENT_BACK_LEFT;
755 break;
756 default:
757 continue; /* invalid attachment */
758 }
759
760 dri_drawable_get_format(drawable, statt, &format, &bind);
761 if (format == PIPE_FORMAT_NONE)
762 continue;
763
764 /* dri2_drawable_get_buffers has already filled dri_drawable->w
765 * and dri_drawable->h */
766 templ.width0 = dri_drawable->w;
767 templ.height0 = dri_drawable->h;
768 templ.format = format;
769 templ.bind = bind;
770 whandle.handle = buf->name;
771 whandle.stride = buf->pitch;
772 whandle.offset = 0;
773 whandle.modifier = DRM_FORMAT_MOD_INVALID;
774 if (screen->can_share_buffer)
775 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
776 else
777 whandle.type = DRM_API_HANDLE_TYPE_KMS;
778 drawable->textures[statt] =
779 screen->base.screen->resource_from_handle(screen->base.screen,
780 &templ, &whandle,
781 PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ);
782 assert(drawable->textures[statt]);
783 }
784 }
785
786 /* Allocate private MSAA colorbuffers. */
787 if (drawable->stvis.samples > 1) {
788 for (i = 0; i < statts_count; i++) {
789 enum st_attachment_type statt = statts[i];
790
791 if (statt == ST_ATTACHMENT_DEPTH_STENCIL)
792 continue;
793
794 if (drawable->textures[statt]) {
795 templ.format = drawable->textures[statt]->format;
796 templ.bind = drawable->textures[statt]->bind &
797 ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED);
798 templ.nr_samples = drawable->stvis.samples;
799
800 /* Try to reuse the resource.
801 * (the other resource parameters should be constant)
802 */
803 if (!drawable->msaa_textures[statt] ||
804 drawable->msaa_textures[statt]->width0 != templ.width0 ||
805 drawable->msaa_textures[statt]->height0 != templ.height0) {
806 /* Allocate a new one. */
807 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
808
809 drawable->msaa_textures[statt] =
810 screen->base.screen->resource_create(screen->base.screen,
811 &templ);
812 assert(drawable->msaa_textures[statt]);
813
814 /* If there are any MSAA resources, we should initialize them
815 * such that they contain the same data as the single-sample
816 * resources we just got from the X server.
817 *
818 * The reason for this is that the state tracker (and
819 * therefore the app) can access the MSAA resources only.
820 * The single-sample resources are not exposed
821 * to the state tracker.
822 *
823 */
824 dri_pipe_blit(ctx->st->pipe,
825 drawable->msaa_textures[statt],
826 drawable->textures[statt]);
827 }
828 }
829 else {
830 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
831 }
832 }
833 }
834
835 /* Allocate a private depth-stencil buffer. */
836 if (alloc_depthstencil) {
837 enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;
838 struct pipe_resource **zsbuf;
839 enum pipe_format format;
840 unsigned bind;
841
842 dri_drawable_get_format(drawable, statt, &format, &bind);
843
844 if (format) {
845 templ.format = format;
846 templ.bind = bind & ~PIPE_BIND_SHARED;
847
848 if (drawable->stvis.samples > 1) {
849 templ.nr_samples = drawable->stvis.samples;
850 zsbuf = &drawable->msaa_textures[statt];
851 }
852 else {
853 templ.nr_samples = 0;
854 zsbuf = &drawable->textures[statt];
855 }
856
857 /* Try to reuse the resource.
858 * (the other resource parameters should be constant)
859 */
860 if (!*zsbuf ||
861 (*zsbuf)->width0 != templ.width0 ||
862 (*zsbuf)->height0 != templ.height0) {
863 /* Allocate a new one. */
864 pipe_resource_reference(zsbuf, NULL);
865 *zsbuf = screen->base.screen->resource_create(screen->base.screen,
866 &templ);
867 assert(*zsbuf);
868 }
869 }
870 else {
871 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
872 pipe_resource_reference(&drawable->textures[statt], NULL);
873 }
874 }
875
876 /* For DRI2, we may get the same buffers again from the server.
877 * To prevent useless imports of gem names, drawable->old* is used
878 * to bypass the import if we get the same buffers. This doesn't apply
879 * to DRI3/Wayland, users of image.loader, since the buffer is managed
880 * by the client (no import), and the back buffer is going to change
881 * at every redraw.
882 */
883 if (!image) {
884 drawable->old_num = num_buffers;
885 drawable->old_w = dri_drawable->w;
886 drawable->old_h = dri_drawable->h;
887 memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);
888 }
889 }
890
891 static void
dri2_flush_frontbuffer(struct dri_context * ctx,struct dri_drawable * drawable,enum st_attachment_type statt)892 dri2_flush_frontbuffer(struct dri_context *ctx,
893 struct dri_drawable *drawable,
894 enum st_attachment_type statt)
895 {
896 __DRIdrawable *dri_drawable = drawable->dPriv;
897 const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
898 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
899 struct pipe_context *pipe = ctx->st->pipe;
900
901 if (statt != ST_ATTACHMENT_FRONT_LEFT)
902 return;
903
904 if (drawable->stvis.samples > 1) {
905 /* Resolve the front buffer. */
906 dri_pipe_blit(ctx->st->pipe,
907 drawable->textures[ST_ATTACHMENT_FRONT_LEFT],
908 drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]);
909 }
910
911 if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) {
912 pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]);
913 }
914
915 pipe->flush(pipe, NULL, 0);
916
917 if (image) {
918 image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
919 }
920 else if (loader->flushFrontBuffer) {
921 loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
922 }
923 }
924
925 /**
926 * The struct dri_drawable flush_swapbuffers callback
927 */
928 static void
dri2_flush_swapbuffers(struct dri_context * ctx,struct dri_drawable * drawable)929 dri2_flush_swapbuffers(struct dri_context *ctx,
930 struct dri_drawable *drawable)
931 {
932 __DRIdrawable *dri_drawable = drawable->dPriv;
933 const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
934
935 if (image && image->base.version >= 3 && image->flushSwapBuffers) {
936 image->flushSwapBuffers(dri_drawable, dri_drawable->loaderPrivate);
937 }
938 }
939
940 static void
dri2_update_tex_buffer(struct dri_drawable * drawable,struct dri_context * ctx,struct pipe_resource * res)941 dri2_update_tex_buffer(struct dri_drawable *drawable,
942 struct dri_context *ctx,
943 struct pipe_resource *res)
944 {
945 /* no-op */
946 }
947
948 static __DRIimage *
dri2_create_image_from_winsys(__DRIscreen * _screen,int width,int height,int format,int num_handles,struct winsys_handle * whandle,void * loaderPrivate)949 dri2_create_image_from_winsys(__DRIscreen *_screen,
950 int width, int height, int format,
951 int num_handles, struct winsys_handle *whandle,
952 void *loaderPrivate)
953 {
954 struct dri_screen *screen = dri_screen(_screen);
955 struct pipe_screen *pscreen = screen->base.screen;
956 __DRIimage *img;
957 struct pipe_resource templ;
958 unsigned tex_usage;
959 enum pipe_format pf;
960 int i;
961
962 tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
963
964 pf = dri2_format_to_pipe_format (format);
965 if (pf == PIPE_FORMAT_NONE)
966 return NULL;
967
968 img = CALLOC_STRUCT(__DRIimageRec);
969 if (!img)
970 return NULL;
971
972 memset(&templ, 0, sizeof(templ));
973 templ.bind = tex_usage;
974 templ.target = screen->target;
975 templ.last_level = 0;
976 templ.depth0 = 1;
977 templ.array_size = 1;
978
979 for (i = num_handles - 1; i >= 0; i--) {
980 struct pipe_resource *tex;
981
982 /* TODO: something a lot less ugly */
983 switch (i) {
984 case 0:
985 templ.width0 = width;
986 templ.height0 = height;
987 templ.format = pf;
988 break;
989 case 1:
990 templ.width0 = width / 2;
991 templ.height0 = height / 2;
992 templ.format = (num_handles == 2) ?
993 PIPE_FORMAT_RG88_UNORM : /* NV12, etc */
994 PIPE_FORMAT_R8_UNORM; /* I420, etc */
995 break;
996 case 2:
997 templ.width0 = width / 2;
998 templ.height0 = height / 2;
999 templ.format = PIPE_FORMAT_R8_UNORM;
1000 break;
1001 default:
1002 unreachable("too many planes!");
1003 }
1004
1005 tex = pscreen->resource_from_handle(pscreen,
1006 &templ, &whandle[i], PIPE_HANDLE_USAGE_READ_WRITE);
1007 if (!tex) {
1008 pipe_resource_reference(&img->texture, NULL);
1009 FREE(img);
1010 return NULL;
1011 }
1012
1013 tex->next = img->texture;
1014 img->texture = tex;
1015 }
1016
1017 img->level = 0;
1018 img->layer = 0;
1019 img->dri_format = format;
1020 img->use = 0;
1021 img->loader_private = loaderPrivate;
1022
1023 return img;
1024 }
1025
1026 static __DRIimage *
dri2_create_image_from_name(__DRIscreen * _screen,int width,int height,int format,int name,int pitch,void * loaderPrivate)1027 dri2_create_image_from_name(__DRIscreen *_screen,
1028 int width, int height, int format,
1029 int name, int pitch, void *loaderPrivate)
1030 {
1031 struct winsys_handle whandle;
1032 enum pipe_format pf;
1033
1034 memset(&whandle, 0, sizeof(whandle));
1035 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
1036 whandle.handle = name;
1037 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1038
1039 pf = dri2_format_to_pipe_format (format);
1040 if (pf == PIPE_FORMAT_NONE)
1041 return NULL;
1042
1043 whandle.stride = pitch * util_format_get_blocksize(pf);
1044
1045 return dri2_create_image_from_winsys(_screen, width, height, format,
1046 1, &whandle, loaderPrivate);
1047 }
1048
1049 static __DRIimage *
dri2_create_image_from_fd(__DRIscreen * _screen,int width,int height,int fourcc,uint64_t modifier,int * fds,int num_fds,int * strides,int * offsets,unsigned * error,int * dri_components,void * loaderPrivate)1050 dri2_create_image_from_fd(__DRIscreen *_screen,
1051 int width, int height, int fourcc,
1052 uint64_t modifier, int *fds, int num_fds,
1053 int *strides, int *offsets, unsigned *error,
1054 int *dri_components, void *loaderPrivate)
1055 {
1056 struct winsys_handle whandles[3];
1057 int format;
1058 __DRIimage *img = NULL;
1059 unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
1060 int expected_num_fds, i;
1061
1062 switch (fourcc) {
1063 case __DRI_IMAGE_FOURCC_YUV420:
1064 case __DRI_IMAGE_FOURCC_YVU420:
1065 expected_num_fds = 3;
1066 break;
1067 case __DRI_IMAGE_FOURCC_NV12:
1068 expected_num_fds = 2;
1069 break;
1070 default:
1071 expected_num_fds = 1;
1072 break;
1073 }
1074
1075 if (num_fds != expected_num_fds) {
1076 err = __DRI_IMAGE_ERROR_BAD_MATCH;
1077 goto exit;
1078 }
1079
1080 format = convert_fourcc(fourcc, dri_components);
1081 if (format == -1) {
1082 err = __DRI_IMAGE_ERROR_BAD_MATCH;
1083 goto exit;
1084 }
1085
1086 memset(whandles, 0, sizeof(whandles));
1087
1088 for (i = 0; i < num_fds; i++) {
1089 if (fds[i] < 0) {
1090 err = __DRI_IMAGE_ERROR_BAD_ALLOC;
1091 goto exit;
1092 }
1093
1094 whandles[i].type = DRM_API_HANDLE_TYPE_FD;
1095 whandles[i].handle = (unsigned)fds[i];
1096 whandles[i].stride = (unsigned)strides[i];
1097 whandles[i].offset = (unsigned)offsets[i];
1098 whandles[i].modifier = modifier;
1099 }
1100
1101 if (fourcc == __DRI_IMAGE_FOURCC_YVU420) {
1102 /* convert to YUV420 by swapping 2nd and 3rd planes: */
1103 struct winsys_handle tmp = whandles[1];
1104 whandles[1] = whandles[2];
1105 whandles[2] = tmp;
1106 fourcc = __DRI_IMAGE_FOURCC_YUV420;
1107 }
1108
1109 img = dri2_create_image_from_winsys(_screen, width, height, format,
1110 num_fds, whandles, loaderPrivate);
1111 if(img == NULL)
1112 err = __DRI_IMAGE_ERROR_BAD_ALLOC;
1113
1114 exit:
1115 if (error)
1116 *error = err;
1117
1118 return img;
1119 }
1120
1121 static __DRIimage *
dri2_create_image_common(__DRIscreen * _screen,int width,int height,int format,unsigned int use,const uint64_t * modifiers,const unsigned count,void * loaderPrivate)1122 dri2_create_image_common(__DRIscreen *_screen,
1123 int width, int height,
1124 int format, unsigned int use,
1125 const uint64_t *modifiers,
1126 const unsigned count,
1127 void *loaderPrivate)
1128 {
1129 struct dri_screen *screen = dri_screen(_screen);
1130 __DRIimage *img;
1131 struct pipe_resource templ;
1132 unsigned tex_usage;
1133 enum pipe_format pf;
1134
1135 /* createImageWithModifiers doesn't supply usage, and we should not get
1136 * here with both modifiers and a usage flag.
1137 */
1138 assert(!(use && (modifiers != NULL)));
1139
1140 tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
1141
1142 if (use & __DRI_IMAGE_USE_SCANOUT)
1143 tex_usage |= PIPE_BIND_SCANOUT;
1144 if (use & __DRI_IMAGE_USE_SHARE)
1145 tex_usage |= PIPE_BIND_SHARED;
1146 if (use & __DRI_IMAGE_USE_LINEAR)
1147 tex_usage |= PIPE_BIND_LINEAR;
1148 if (use & __DRI_IMAGE_USE_CURSOR) {
1149 if (width != 64 || height != 64)
1150 return NULL;
1151 tex_usage |= PIPE_BIND_CURSOR;
1152 }
1153
1154 pf = dri2_format_to_pipe_format (format);
1155 if (pf == PIPE_FORMAT_NONE)
1156 return NULL;
1157
1158 img = CALLOC_STRUCT(__DRIimageRec);
1159 if (!img)
1160 return NULL;
1161
1162 memset(&templ, 0, sizeof(templ));
1163 templ.bind = tex_usage;
1164 templ.format = pf;
1165 templ.target = PIPE_TEXTURE_2D;
1166 templ.last_level = 0;
1167 templ.width0 = width;
1168 templ.height0 = height;
1169 templ.depth0 = 1;
1170 templ.array_size = 1;
1171
1172 if (modifiers)
1173 img->texture =
1174 screen->base.screen
1175 ->resource_create_with_modifiers(screen->base.screen,
1176 &templ,
1177 modifiers,
1178 count);
1179 else
1180 img->texture =
1181 screen->base.screen->resource_create(screen->base.screen, &templ);
1182 if (!img->texture) {
1183 FREE(img);
1184 return NULL;
1185 }
1186
1187 img->level = 0;
1188 img->layer = 0;
1189 img->dri_format = format;
1190 img->dri_components = 0;
1191 img->use = use;
1192
1193 img->loader_private = loaderPrivate;
1194 return img;
1195 }
1196
1197 static __DRIimage *
dri2_create_image(__DRIscreen * _screen,int width,int height,int format,unsigned int use,void * loaderPrivate)1198 dri2_create_image(__DRIscreen *_screen,
1199 int width, int height, int format,
1200 unsigned int use, void *loaderPrivate)
1201 {
1202 return dri2_create_image_common(_screen, width, height, format, use,
1203 NULL /* modifiers */, 0 /* count */,
1204 loaderPrivate);
1205 }
1206
1207 static __DRIimage *
dri2_create_image_with_modifiers(__DRIscreen * dri_screen,int width,int height,int format,const uint64_t * modifiers,const unsigned count,void * loaderPrivate)1208 dri2_create_image_with_modifiers(__DRIscreen *dri_screen,
1209 int width, int height, int format,
1210 const uint64_t *modifiers,
1211 const unsigned count,
1212 void *loaderPrivate)
1213 {
1214 return dri2_create_image_common(dri_screen, width, height, format,
1215 0 /* use */, modifiers, count,
1216 loaderPrivate);
1217 }
1218
1219 static GLboolean
dri2_query_image(__DRIimage * image,int attrib,int * value)1220 dri2_query_image(__DRIimage *image, int attrib, int *value)
1221 {
1222 struct winsys_handle whandle;
1223 unsigned usage;
1224
1225 if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
1226 usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
1227 else
1228 usage = PIPE_HANDLE_USAGE_READ_WRITE;
1229
1230 memset(&whandle, 0, sizeof(whandle));
1231
1232 switch (attrib) {
1233 case __DRI_IMAGE_ATTRIB_STRIDE:
1234 whandle.type = DRM_API_HANDLE_TYPE_KMS;
1235 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1236 NULL, image->texture, &whandle, usage))
1237 return GL_FALSE;
1238 *value = whandle.stride;
1239 return GL_TRUE;
1240 case __DRI_IMAGE_ATTRIB_OFFSET:
1241 whandle.type = DRM_API_HANDLE_TYPE_KMS;
1242 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1243 NULL, image->texture, &whandle, usage))
1244 return GL_FALSE;
1245 *value = whandle.offset;
1246 return GL_TRUE;
1247 case __DRI_IMAGE_ATTRIB_HANDLE:
1248 whandle.type = DRM_API_HANDLE_TYPE_KMS;
1249 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1250 NULL, image->texture, &whandle, usage))
1251 return GL_FALSE;
1252 *value = whandle.handle;
1253 return GL_TRUE;
1254 case __DRI_IMAGE_ATTRIB_NAME:
1255 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
1256 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1257 NULL, image->texture, &whandle, usage))
1258 return GL_FALSE;
1259 *value = whandle.handle;
1260 return GL_TRUE;
1261 case __DRI_IMAGE_ATTRIB_FD:
1262 whandle.type= DRM_API_HANDLE_TYPE_FD;
1263 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1264 NULL, image->texture, &whandle, usage))
1265 return GL_FALSE;
1266
1267 *value = whandle.handle;
1268 return GL_TRUE;
1269 case __DRI_IMAGE_ATTRIB_FORMAT:
1270 *value = image->dri_format;
1271 return GL_TRUE;
1272 case __DRI_IMAGE_ATTRIB_WIDTH:
1273 *value = image->texture->width0;
1274 return GL_TRUE;
1275 case __DRI_IMAGE_ATTRIB_HEIGHT:
1276 *value = image->texture->height0;
1277 return GL_TRUE;
1278 case __DRI_IMAGE_ATTRIB_COMPONENTS:
1279 if (image->dri_components == 0)
1280 return GL_FALSE;
1281 *value = image->dri_components;
1282 return GL_TRUE;
1283 case __DRI_IMAGE_ATTRIB_FOURCC:
1284 *value = convert_to_fourcc(image->dri_format);
1285 return GL_TRUE;
1286 case __DRI_IMAGE_ATTRIB_NUM_PLANES:
1287 *value = 1;
1288 return GL_TRUE;
1289 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
1290 whandle.type = DRM_API_HANDLE_TYPE_KMS;
1291 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1292 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1293 NULL, image->texture, &whandle, usage))
1294 return GL_FALSE;
1295 if (whandle.modifier == DRM_FORMAT_MOD_INVALID)
1296 return GL_FALSE;
1297 *value = (whandle.modifier >> 32) & 0xffffffff;
1298 return GL_TRUE;
1299 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
1300 whandle.type = DRM_API_HANDLE_TYPE_KMS;
1301 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1302 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1303 NULL, image->texture, &whandle, usage))
1304 return GL_FALSE;
1305 if (whandle.modifier == DRM_FORMAT_MOD_INVALID)
1306 return GL_FALSE;
1307 *value = whandle.modifier & 0xffffffff;
1308 return GL_TRUE;
1309 default:
1310 return GL_FALSE;
1311 }
1312 }
1313
1314 static __DRIimage *
dri2_dup_image(__DRIimage * image,void * loaderPrivate)1315 dri2_dup_image(__DRIimage *image, void *loaderPrivate)
1316 {
1317 __DRIimage *img;
1318
1319 img = CALLOC_STRUCT(__DRIimageRec);
1320 if (!img)
1321 return NULL;
1322
1323 img->texture = NULL;
1324 pipe_resource_reference(&img->texture, image->texture);
1325 img->level = image->level;
1326 img->layer = image->layer;
1327 img->dri_format = image->dri_format;
1328 /* This should be 0 for sub images, but dup is also used for base images. */
1329 img->dri_components = image->dri_components;
1330 img->loader_private = loaderPrivate;
1331
1332 return img;
1333 }
1334
1335 static GLboolean
dri2_validate_usage(__DRIimage * image,unsigned int use)1336 dri2_validate_usage(__DRIimage *image, unsigned int use)
1337 {
1338 if (!image || !image->texture)
1339 return false;
1340
1341 struct pipe_screen *screen = image->texture->screen;
1342 if (!screen->check_resource_capability)
1343 return true;
1344
1345 /* We don't want to check these:
1346 * __DRI_IMAGE_USE_SHARE (all images are shareable)
1347 * __DRI_IMAGE_USE_BACKBUFFER (all images support this)
1348 */
1349 unsigned bind = 0;
1350 if (use & __DRI_IMAGE_USE_SCANOUT)
1351 bind |= PIPE_BIND_SCANOUT;
1352 if (use & __DRI_IMAGE_USE_LINEAR)
1353 bind |= PIPE_BIND_LINEAR;
1354 if (use & __DRI_IMAGE_USE_CURSOR)
1355 bind |= PIPE_BIND_CURSOR;
1356
1357 if (!bind)
1358 return true;
1359
1360 return screen->check_resource_capability(screen, image->texture, bind);
1361 }
1362
1363 static __DRIimage *
dri2_from_names(__DRIscreen * screen,int width,int height,int format,int * names,int num_names,int * strides,int * offsets,void * loaderPrivate)1364 dri2_from_names(__DRIscreen *screen, int width, int height, int format,
1365 int *names, int num_names, int *strides, int *offsets,
1366 void *loaderPrivate)
1367 {
1368 __DRIimage *img;
1369 int dri_components;
1370 struct winsys_handle whandle;
1371
1372 if (num_names != 1)
1373 return NULL;
1374
1375 format = convert_fourcc(format, &dri_components);
1376 if (format == -1)
1377 return NULL;
1378
1379 memset(&whandle, 0, sizeof(whandle));
1380 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
1381 whandle.handle = names[0];
1382 whandle.stride = strides[0];
1383 whandle.offset = offsets[0];
1384 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1385
1386 img = dri2_create_image_from_winsys(screen, width, height, format,
1387 1, &whandle, loaderPrivate);
1388 if (img == NULL)
1389 return NULL;
1390
1391 img->dri_components = dri_components;
1392 return img;
1393 }
1394
1395 static __DRIimage *
dri2_from_planar(__DRIimage * image,int plane,void * loaderPrivate)1396 dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
1397 {
1398 __DRIimage *img;
1399
1400 if (plane != 0)
1401 return NULL;
1402
1403 if (image->dri_components == 0)
1404 return NULL;
1405
1406 img = dri2_dup_image(image, loaderPrivate);
1407 if (img == NULL)
1408 return NULL;
1409
1410 if (img->texture->screen->resource_changed)
1411 img->texture->screen->resource_changed(img->texture->screen,
1412 img->texture);
1413
1414 /* set this to 0 for sub images. */
1415 img->dri_components = 0;
1416 return img;
1417 }
1418
1419 static __DRIimage *
dri2_from_fds(__DRIscreen * screen,int width,int height,int fourcc,int * fds,int num_fds,int * strides,int * offsets,void * loaderPrivate)1420 dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
1421 int *fds, int num_fds, int *strides, int *offsets,
1422 void *loaderPrivate)
1423 {
1424 __DRIimage *img;
1425 int dri_components;
1426
1427 img = dri2_create_image_from_fd(screen, width, height, fourcc,
1428 DRM_FORMAT_MOD_INVALID, fds, num_fds,
1429 strides, offsets, NULL,
1430 &dri_components, loaderPrivate);
1431 if (img == NULL)
1432 return NULL;
1433
1434 img->dri_components = dri_components;
1435 return img;
1436 }
1437
1438 static boolean
dri2_query_dma_buf_formats(__DRIscreen * _screen,int max,int * formats,int * count)1439 dri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats,
1440 int *count)
1441 {
1442 struct dri_screen *screen = dri_screen(_screen);
1443 struct pipe_screen *pscreen = screen->base.screen;
1444 const unsigned bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
1445 int i, j;
1446
1447 for (i = 0, j = 0; (i < ARRAY_SIZE(fourcc_formats)) &&
1448 (j < max || max == 0); i++) {
1449 if (pscreen->is_format_supported(pscreen,
1450 fourcc_to_pipe_format(
1451 fourcc_formats[i]),
1452 screen->target,
1453 0, bind)) {
1454 if (j < max)
1455 formats[j] = fourcc_formats[i];
1456 j++;
1457 }
1458 }
1459 *count = j;
1460 return true;
1461 }
1462
1463 static boolean
dri2_query_dma_buf_modifiers(__DRIscreen * _screen,int fourcc,int max,uint64_t * modifiers,unsigned int * external_only,int * count)1464 dri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max,
1465 uint64_t *modifiers, unsigned int *external_only,
1466 int *count)
1467 {
1468 struct dri_screen *screen = dri_screen(_screen);
1469 struct pipe_screen *pscreen = screen->base.screen;
1470 enum pipe_format format = fourcc_to_pipe_format(fourcc);
1471 const unsigned usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
1472
1473 if (pscreen->query_dmabuf_modifiers != NULL &&
1474 pscreen->is_format_supported(pscreen, format, screen->target, 0, usage)) {
1475 pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers,
1476 external_only, count);
1477 return true;
1478 }
1479 return false;
1480 }
1481
1482 static __DRIimage *
dri2_from_dma_bufs(__DRIscreen * screen,int width,int height,int fourcc,int * fds,int num_fds,int * strides,int * offsets,enum __DRIYUVColorSpace yuv_color_space,enum __DRISampleRange sample_range,enum __DRIChromaSiting horizontal_siting,enum __DRIChromaSiting vertical_siting,unsigned * error,void * loaderPrivate)1483 dri2_from_dma_bufs(__DRIscreen *screen,
1484 int width, int height, int fourcc,
1485 int *fds, int num_fds,
1486 int *strides, int *offsets,
1487 enum __DRIYUVColorSpace yuv_color_space,
1488 enum __DRISampleRange sample_range,
1489 enum __DRIChromaSiting horizontal_siting,
1490 enum __DRIChromaSiting vertical_siting,
1491 unsigned *error,
1492 void *loaderPrivate)
1493 {
1494 __DRIimage *img;
1495 int dri_components;
1496
1497 img = dri2_create_image_from_fd(screen, width, height, fourcc,
1498 DRM_FORMAT_MOD_INVALID, fds, num_fds,
1499 strides, offsets, error,
1500 &dri_components, loaderPrivate);
1501 if (img == NULL)
1502 return NULL;
1503
1504 img->yuv_color_space = yuv_color_space;
1505 img->sample_range = sample_range;
1506 img->horizontal_siting = horizontal_siting;
1507 img->vertical_siting = vertical_siting;
1508 img->dri_components = dri_components;
1509
1510 *error = __DRI_IMAGE_ERROR_SUCCESS;
1511 return img;
1512 }
1513
1514 static __DRIimage *
dri2_from_dma_bufs2(__DRIscreen * screen,int width,int height,int fourcc,uint64_t modifier,int * fds,int num_fds,int * strides,int * offsets,enum __DRIYUVColorSpace yuv_color_space,enum __DRISampleRange sample_range,enum __DRIChromaSiting horizontal_siting,enum __DRIChromaSiting vertical_siting,unsigned * error,void * loaderPrivate)1515 dri2_from_dma_bufs2(__DRIscreen *screen,
1516 int width, int height, int fourcc,
1517 uint64_t modifier, int *fds, int num_fds,
1518 int *strides, int *offsets,
1519 enum __DRIYUVColorSpace yuv_color_space,
1520 enum __DRISampleRange sample_range,
1521 enum __DRIChromaSiting horizontal_siting,
1522 enum __DRIChromaSiting vertical_siting,
1523 unsigned *error,
1524 void *loaderPrivate)
1525 {
1526 __DRIimage *img;
1527 int dri_components;
1528
1529 img = dri2_create_image_from_fd(screen, width, height, fourcc,
1530 modifier, fds, num_fds, strides, offsets,
1531 error, &dri_components, loaderPrivate);
1532 if (img == NULL)
1533 return NULL;
1534
1535 img->yuv_color_space = yuv_color_space;
1536 img->sample_range = sample_range;
1537 img->horizontal_siting = horizontal_siting;
1538 img->vertical_siting = vertical_siting;
1539 img->dri_components = dri_components;
1540
1541 *error = __DRI_IMAGE_ERROR_SUCCESS;
1542 return img;
1543 }
1544
1545 static void
dri2_blit_image(__DRIcontext * context,__DRIimage * dst,__DRIimage * src,int dstx0,int dsty0,int dstwidth,int dstheight,int srcx0,int srcy0,int srcwidth,int srcheight,int flush_flag)1546 dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
1547 int dstx0, int dsty0, int dstwidth, int dstheight,
1548 int srcx0, int srcy0, int srcwidth, int srcheight,
1549 int flush_flag)
1550 {
1551 struct dri_context *ctx = dri_context(context);
1552 struct pipe_context *pipe = ctx->st->pipe;
1553 struct pipe_screen *screen;
1554 struct pipe_fence_handle *fence;
1555 struct pipe_blit_info blit;
1556
1557 if (!dst || !src)
1558 return;
1559
1560 memset(&blit, 0, sizeof(blit));
1561 blit.dst.resource = dst->texture;
1562 blit.dst.box.x = dstx0;
1563 blit.dst.box.y = dsty0;
1564 blit.dst.box.width = dstwidth;
1565 blit.dst.box.height = dstheight;
1566 blit.dst.box.depth = 1;
1567 blit.dst.format = dst->texture->format;
1568 blit.src.resource = src->texture;
1569 blit.src.box.x = srcx0;
1570 blit.src.box.y = srcy0;
1571 blit.src.box.width = srcwidth;
1572 blit.src.box.height = srcheight;
1573 blit.src.box.depth = 1;
1574 blit.src.format = src->texture->format;
1575 blit.mask = PIPE_MASK_RGBA;
1576 blit.filter = PIPE_TEX_FILTER_NEAREST;
1577
1578 pipe->blit(pipe, &blit);
1579
1580 if (flush_flag == __BLIT_FLAG_FLUSH) {
1581 pipe->flush_resource(pipe, dst->texture);
1582 ctx->st->flush(ctx->st, 0, NULL);
1583 } else if (flush_flag == __BLIT_FLAG_FINISH) {
1584 screen = dri_screen(ctx->sPriv)->base.screen;
1585 pipe->flush_resource(pipe, dst->texture);
1586 ctx->st->flush(ctx->st, 0, &fence);
1587 (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
1588 screen->fence_reference(screen, &fence, NULL);
1589 }
1590 }
1591
1592 static void *
dri2_map_image(__DRIcontext * context,__DRIimage * image,int x0,int y0,int width,int height,unsigned int flags,int * stride,void ** data)1593 dri2_map_image(__DRIcontext *context, __DRIimage *image,
1594 int x0, int y0, int width, int height,
1595 unsigned int flags, int *stride, void **data)
1596 {
1597 struct dri_context *ctx = dri_context(context);
1598 struct pipe_context *pipe = ctx->st->pipe;
1599 enum pipe_transfer_usage pipe_access = 0;
1600 struct pipe_transfer *trans;
1601 void *map;
1602
1603 if (!image || !data || *data)
1604 return NULL;
1605
1606 if (flags & __DRI_IMAGE_TRANSFER_READ)
1607 pipe_access |= PIPE_TRANSFER_READ;
1608 if (flags & __DRI_IMAGE_TRANSFER_WRITE)
1609 pipe_access |= PIPE_TRANSFER_WRITE;
1610
1611 map = pipe_transfer_map(pipe, image->texture,
1612 0, 0, pipe_access, x0, y0, width, height,
1613 &trans);
1614 if (map) {
1615 *data = trans;
1616 *stride = trans->stride;
1617 }
1618
1619 return map;
1620 }
1621
1622 static void
dri2_unmap_image(__DRIcontext * context,__DRIimage * image,void * data)1623 dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
1624 {
1625 struct dri_context *ctx = dri_context(context);
1626 struct pipe_context *pipe = ctx->st->pipe;
1627
1628 pipe_transfer_unmap(pipe, (struct pipe_transfer *)data);
1629 }
1630
1631 static int
dri2_get_capabilities(__DRIscreen * _screen)1632 dri2_get_capabilities(__DRIscreen *_screen)
1633 {
1634 struct dri_screen *screen = dri_screen(_screen);
1635
1636 return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
1637 }
1638
1639 /* The extension is modified during runtime if DRI_PRIME is detected */
1640 static __DRIimageExtension dri2ImageExtension = {
1641 .base = { __DRI_IMAGE, 17 },
1642
1643 .createImageFromName = dri2_create_image_from_name,
1644 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
1645 .destroyImage = dri2_destroy_image,
1646 .createImage = dri2_create_image,
1647 .queryImage = dri2_query_image,
1648 .dupImage = dri2_dup_image,
1649 .validateUsage = dri2_validate_usage,
1650 .createImageFromNames = dri2_from_names,
1651 .fromPlanar = dri2_from_planar,
1652 .createImageFromTexture = dri2_create_from_texture,
1653 .createImageFromFds = NULL,
1654 .createImageFromDmaBufs = NULL,
1655 .blitImage = dri2_blit_image,
1656 .getCapabilities = dri2_get_capabilities,
1657 .mapImage = dri2_map_image,
1658 .unmapImage = dri2_unmap_image,
1659 .createImageWithModifiers = NULL,
1660 .createImageFromDmaBufs2 = NULL,
1661 .queryDmaBufFormats = NULL,
1662 .queryDmaBufModifiers = NULL,
1663 .queryDmaBufFormatModifierAttribs = NULL,
1664 .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2,
1665 };
1666
1667 static const __DRIrobustnessExtension dri2Robustness = {
1668 .base = { __DRI2_ROBUSTNESS, 1 }
1669 };
1670
1671 static int
dri2_interop_query_device_info(__DRIcontext * _ctx,struct mesa_glinterop_device_info * out)1672 dri2_interop_query_device_info(__DRIcontext *_ctx,
1673 struct mesa_glinterop_device_info *out)
1674 {
1675 struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen;
1676
1677 /* There is no version 0, thus we do not support it */
1678 if (out->version == 0)
1679 return MESA_GLINTEROP_INVALID_VERSION;
1680
1681 out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP);
1682 out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS);
1683 out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE);
1684 out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION);
1685
1686 out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID);
1687 out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID);
1688
1689 /* Instruct the caller that we support up-to version one of the interface */
1690 out->version = 1;
1691
1692 return MESA_GLINTEROP_SUCCESS;
1693 }
1694
1695 static int
dri2_interop_export_object(__DRIcontext * _ctx,struct mesa_glinterop_export_in * in,struct mesa_glinterop_export_out * out)1696 dri2_interop_export_object(__DRIcontext *_ctx,
1697 struct mesa_glinterop_export_in *in,
1698 struct mesa_glinterop_export_out *out)
1699 {
1700 struct st_context_iface *st = dri_context(_ctx)->st;
1701 struct pipe_screen *screen = st->pipe->screen;
1702 struct gl_context *ctx = ((struct st_context *)st)->ctx;
1703 struct pipe_resource *res = NULL;
1704 struct winsys_handle whandle;
1705 unsigned target, usage;
1706 boolean success;
1707
1708 /* There is no version 0, thus we do not support it */
1709 if (in->version == 0 || out->version == 0)
1710 return MESA_GLINTEROP_INVALID_VERSION;
1711
1712 /* Validate the target. */
1713 switch (in->target) {
1714 case GL_TEXTURE_BUFFER:
1715 case GL_TEXTURE_1D:
1716 case GL_TEXTURE_2D:
1717 case GL_TEXTURE_3D:
1718 case GL_TEXTURE_RECTANGLE:
1719 case GL_TEXTURE_1D_ARRAY:
1720 case GL_TEXTURE_2D_ARRAY:
1721 case GL_TEXTURE_CUBE_MAP_ARRAY:
1722 case GL_TEXTURE_CUBE_MAP:
1723 case GL_TEXTURE_2D_MULTISAMPLE:
1724 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1725 case GL_TEXTURE_EXTERNAL_OES:
1726 case GL_RENDERBUFFER:
1727 case GL_ARRAY_BUFFER:
1728 target = in->target;
1729 break;
1730 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1731 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1732 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1733 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1734 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1735 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1736 target = GL_TEXTURE_CUBE_MAP;
1737 break;
1738 default:
1739 return MESA_GLINTEROP_INVALID_TARGET;
1740 }
1741
1742 /* Validate the simple case of miplevel. */
1743 if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) &&
1744 in->miplevel != 0)
1745 return MESA_GLINTEROP_INVALID_MIP_LEVEL;
1746
1747 /* Validate the OpenGL object and get pipe_resource. */
1748 simple_mtx_lock(&ctx->Shared->Mutex);
1749
1750 if (target == GL_ARRAY_BUFFER) {
1751 /* Buffer objects.
1752 *
1753 * The error checking is based on the documentation of
1754 * clCreateFromGLBuffer from OpenCL 2.0 SDK.
1755 */
1756 struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj);
1757
1758 /* From OpenCL 2.0 SDK, clCreateFromGLBuffer:
1759 * "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is
1760 * a GL buffer object but does not have an existing data store or
1761 * the size of the buffer is 0."
1762 */
1763 if (!buf || buf->Size == 0) {
1764 simple_mtx_unlock(&ctx->Shared->Mutex);
1765 return MESA_GLINTEROP_INVALID_OBJECT;
1766 }
1767
1768 res = st_buffer_object(buf)->buffer;
1769 if (!res) {
1770 /* this shouldn't happen */
1771 simple_mtx_unlock(&ctx->Shared->Mutex);
1772 return MESA_GLINTEROP_INVALID_OBJECT;
1773 }
1774
1775 out->buf_offset = 0;
1776 out->buf_size = buf->Size;
1777
1778 buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
1779 } else if (target == GL_RENDERBUFFER) {
1780 /* Renderbuffers.
1781 *
1782 * The error checking is based on the documentation of
1783 * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK.
1784 */
1785 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj);
1786
1787 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1788 * "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer
1789 * object or if the width or height of renderbuffer is zero."
1790 */
1791 if (!rb || rb->Width == 0 || rb->Height == 0) {
1792 simple_mtx_unlock(&ctx->Shared->Mutex);
1793 return MESA_GLINTEROP_INVALID_OBJECT;
1794 }
1795
1796 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1797 * "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL
1798 * renderbuffer object."
1799 */
1800 if (rb->NumSamples > 1) {
1801 simple_mtx_unlock(&ctx->Shared->Mutex);
1802 return MESA_GLINTEROP_INVALID_OPERATION;
1803 }
1804
1805 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1806 * "CL_OUT_OF_RESOURCES if there is a failure to allocate resources
1807 * required by the OpenCL implementation on the device."
1808 */
1809 res = st_renderbuffer(rb)->texture;
1810 if (!res) {
1811 simple_mtx_unlock(&ctx->Shared->Mutex);
1812 return MESA_GLINTEROP_OUT_OF_RESOURCES;
1813 }
1814
1815 out->internal_format = rb->InternalFormat;
1816 out->view_minlevel = 0;
1817 out->view_numlevels = 1;
1818 out->view_minlayer = 0;
1819 out->view_numlayers = 1;
1820 } else {
1821 /* Texture objects.
1822 *
1823 * The error checking is based on the documentation of
1824 * clCreateFromGLTexture from OpenCL 2.0 SDK.
1825 */
1826 struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj);
1827
1828 if (obj)
1829 _mesa_test_texobj_completeness(ctx, obj);
1830
1831 /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
1832 * "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose
1833 * type matches texture_target, if the specified miplevel of texture
1834 * is not defined, or if the width or height of the specified
1835 * miplevel is zero or if the GL texture object is incomplete."
1836 */
1837 if (!obj ||
1838 obj->Target != target ||
1839 !obj->_BaseComplete ||
1840 (in->miplevel > 0 && !obj->_MipmapComplete)) {
1841 simple_mtx_unlock(&ctx->Shared->Mutex);
1842 return MESA_GLINTEROP_INVALID_OBJECT;
1843 }
1844
1845 if (target == GL_TEXTURE_BUFFER) {
1846 struct st_buffer_object *stBuf =
1847 st_buffer_object(obj->BufferObject);
1848
1849 if (!stBuf || !stBuf->buffer) {
1850 /* this shouldn't happen */
1851 simple_mtx_unlock(&ctx->Shared->Mutex);
1852 return MESA_GLINTEROP_INVALID_OBJECT;
1853 }
1854 res = stBuf->buffer;
1855
1856 out->internal_format = obj->BufferObjectFormat;
1857 out->buf_offset = obj->BufferOffset;
1858 out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size :
1859 obj->BufferSize;
1860
1861 obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
1862 } else {
1863 /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
1864 * "CL_INVALID_MIP_LEVEL if miplevel is less than the value of
1865 * levelbase (for OpenGL implementations) or zero (for OpenGL ES
1866 * implementations); or greater than the value of q (for both OpenGL
1867 * and OpenGL ES). levelbase and q are defined for the texture in
1868 * section 3.8.10 (Texture Completeness) of the OpenGL 2.1
1869 * specification and section 3.7.10 of the OpenGL ES 2.0."
1870 */
1871 if (in->miplevel < obj->BaseLevel || in->miplevel > obj->_MaxLevel) {
1872 simple_mtx_unlock(&ctx->Shared->Mutex);
1873 return MESA_GLINTEROP_INVALID_MIP_LEVEL;
1874 }
1875
1876 if (!st_finalize_texture(ctx, st->pipe, obj, 0)) {
1877 simple_mtx_unlock(&ctx->Shared->Mutex);
1878 return MESA_GLINTEROP_OUT_OF_RESOURCES;
1879 }
1880
1881 res = st_get_texobj_resource(obj);
1882 if (!res) {
1883 /* Incomplete texture buffer object? This shouldn't really occur. */
1884 simple_mtx_unlock(&ctx->Shared->Mutex);
1885 return MESA_GLINTEROP_INVALID_OBJECT;
1886 }
1887
1888 out->internal_format = obj->Image[0][0]->InternalFormat;
1889 out->view_minlevel = obj->MinLevel;
1890 out->view_numlevels = obj->NumLevels;
1891 out->view_minlayer = obj->MinLayer;
1892 out->view_numlayers = obj->NumLayers;
1893 }
1894 }
1895
1896 /* Get the handle. */
1897 switch (in->access) {
1898 case MESA_GLINTEROP_ACCESS_READ_WRITE:
1899 usage = PIPE_HANDLE_USAGE_READ_WRITE;
1900 break;
1901 case MESA_GLINTEROP_ACCESS_READ_ONLY:
1902 usage = PIPE_HANDLE_USAGE_READ;
1903 break;
1904 case MESA_GLINTEROP_ACCESS_WRITE_ONLY:
1905 usage = PIPE_HANDLE_USAGE_WRITE;
1906 break;
1907 default:
1908 usage = 0;
1909 }
1910
1911 memset(&whandle, 0, sizeof(whandle));
1912 whandle.type = DRM_API_HANDLE_TYPE_FD;
1913
1914 success = screen->resource_get_handle(screen, st->pipe, res, &whandle,
1915 usage);
1916 simple_mtx_unlock(&ctx->Shared->Mutex);
1917
1918 if (!success)
1919 return MESA_GLINTEROP_OUT_OF_HOST_MEMORY;
1920
1921 out->dmabuf_fd = whandle.handle;
1922 out->out_driver_data_written = 0;
1923
1924 if (res->target == PIPE_BUFFER)
1925 out->buf_offset += whandle.offset;
1926
1927 /* Instruct the caller that we support up-to version one of the interface */
1928 in->version = 1;
1929 out->version = 1;
1930
1931 return MESA_GLINTEROP_SUCCESS;
1932 }
1933
1934 static const __DRI2interopExtension dri2InteropExtension = {
1935 .base = { __DRI2_INTEROP, 1 },
1936 .query_device_info = dri2_interop_query_device_info,
1937 .export_object = dri2_interop_export_object
1938 };
1939
1940 /**
1941 * \brief the DRI2ConfigQueryExtension configQueryb method
1942 */
1943 static int
dri2GalliumConfigQueryb(__DRIscreen * sPriv,const char * var,unsigned char * val)1944 dri2GalliumConfigQueryb(__DRIscreen *sPriv, const char *var,
1945 unsigned char *val)
1946 {
1947 struct dri_screen *screen = dri_screen(sPriv);
1948
1949 if (!driCheckOption(&screen->dev->option_cache, var, DRI_BOOL))
1950 return dri2ConfigQueryExtension.configQueryb(sPriv, var, val);
1951
1952 *val = driQueryOptionb(&screen->dev->option_cache, var);
1953
1954 return 0;
1955 }
1956
1957 /**
1958 * \brief the DRI2ConfigQueryExtension configQueryi method
1959 */
1960 static int
dri2GalliumConfigQueryi(__DRIscreen * sPriv,const char * var,int * val)1961 dri2GalliumConfigQueryi(__DRIscreen *sPriv, const char *var, int *val)
1962 {
1963 struct dri_screen *screen = dri_screen(sPriv);
1964
1965 if (!driCheckOption(&screen->dev->option_cache, var, DRI_INT) &&
1966 !driCheckOption(&screen->dev->option_cache, var, DRI_ENUM))
1967 return dri2ConfigQueryExtension.configQueryi(sPriv, var, val);
1968
1969 *val = driQueryOptioni(&screen->dev->option_cache, var);
1970
1971 return 0;
1972 }
1973
1974 /**
1975 * \brief the DRI2ConfigQueryExtension configQueryf method
1976 */
1977 static int
dri2GalliumConfigQueryf(__DRIscreen * sPriv,const char * var,float * val)1978 dri2GalliumConfigQueryf(__DRIscreen *sPriv, const char *var, float *val)
1979 {
1980 struct dri_screen *screen = dri_screen(sPriv);
1981
1982 if (!driCheckOption(&screen->dev->option_cache, var, DRI_FLOAT))
1983 return dri2ConfigQueryExtension.configQueryf(sPriv, var, val);
1984
1985 *val = driQueryOptionf(&screen->dev->option_cache, var);
1986
1987 return 0;
1988 }
1989
1990 /**
1991 * \brief the DRI2ConfigQueryExtension struct.
1992 *
1993 * We first query the driver option cache. Then the dri2 option cache.
1994 */
1995 static const __DRI2configQueryExtension dri2GalliumConfigQueryExtension = {
1996 .base = { __DRI2_CONFIG_QUERY, 1 },
1997
1998 .configQueryb = dri2GalliumConfigQueryb,
1999 .configQueryi = dri2GalliumConfigQueryi,
2000 .configQueryf = dri2GalliumConfigQueryf,
2001 };
2002
2003 /*
2004 * Backend function init_screen.
2005 */
2006
2007 static const __DRIextension *dri_screen_extensions[] = {
2008 &driTexBufferExtension.base,
2009 &dri2FlushExtension.base,
2010 &dri2ImageExtension.base,
2011 &dri2RendererQueryExtension.base,
2012 &dri2GalliumConfigQueryExtension.base,
2013 &dri2ThrottleExtension.base,
2014 &dri2FenceExtension.base,
2015 &dri2InteropExtension.base,
2016 &dri2NoErrorExtension.base,
2017 NULL
2018 };
2019
2020 static const __DRIextension *dri_robust_screen_extensions[] = {
2021 &driTexBufferExtension.base,
2022 &dri2FlushExtension.base,
2023 &dri2ImageExtension.base,
2024 &dri2RendererQueryExtension.base,
2025 &dri2GalliumConfigQueryExtension.base,
2026 &dri2ThrottleExtension.base,
2027 &dri2FenceExtension.base,
2028 &dri2InteropExtension.base,
2029 &dri2Robustness.base,
2030 &dri2NoErrorExtension.base,
2031 NULL
2032 };
2033
2034 /**
2035 * This is the driver specific part of the createNewScreen entry point.
2036 *
2037 * Returns the struct gl_config supported by this driver.
2038 */
2039 static const __DRIconfig **
dri2_init_screen(__DRIscreen * sPriv)2040 dri2_init_screen(__DRIscreen * sPriv)
2041 {
2042 const __DRIconfig **configs;
2043 struct dri_screen *screen;
2044 struct pipe_screen *pscreen = NULL;
2045 const struct drm_conf_ret *throttle_ret;
2046 const struct drm_conf_ret *dmabuf_ret;
2047 int fd;
2048
2049 screen = CALLOC_STRUCT(dri_screen);
2050 if (!screen)
2051 return NULL;
2052
2053 screen->sPriv = sPriv;
2054 screen->fd = sPriv->fd;
2055 (void) mtx_init(&screen->opencl_func_mutex, mtx_plain);
2056
2057 sPriv->driverPrivate = (void *)screen;
2058
2059 if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0)
2060 goto free_screen;
2061
2062
2063 if (pipe_loader_drm_probe_fd(&screen->dev, fd)) {
2064 dri_init_options(screen);
2065
2066 pscreen = pipe_loader_create_screen(screen->dev);
2067 }
2068
2069 if (!pscreen)
2070 goto release_pipe;
2071
2072 throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE);
2073 dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD);
2074
2075 if (throttle_ret && throttle_ret->val.val_int != -1) {
2076 screen->throttling_enabled = TRUE;
2077 screen->default_throttle_frames = throttle_ret->val.val_int;
2078 }
2079
2080 if (pscreen->resource_create_with_modifiers)
2081 dri2ImageExtension.createImageWithModifiers =
2082 dri2_create_image_with_modifiers;
2083
2084 if (dmabuf_ret && dmabuf_ret->val.val_bool) {
2085 uint64_t cap;
2086
2087 if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
2088 (cap & DRM_PRIME_CAP_IMPORT)) {
2089 dri2ImageExtension.createImageFromFds = dri2_from_fds;
2090 dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
2091 dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
2092 if (pscreen->query_dmabuf_modifiers) {
2093 dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
2094 dri2ImageExtension.queryDmaBufModifiers =
2095 dri2_query_dma_buf_modifiers;
2096 }
2097 }
2098 }
2099
2100 if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) {
2101 sPriv->extensions = dri_robust_screen_extensions;
2102 screen->has_reset_status_query = true;
2103 }
2104 else
2105 sPriv->extensions = dri_screen_extensions;
2106
2107 configs = dri_init_screen_helper(screen, pscreen);
2108 if (!configs)
2109 goto destroy_screen;
2110
2111 screen->can_share_buffer = true;
2112 screen->auto_fake_front = dri_with_format(sPriv);
2113 screen->broken_invalidate = !sPriv->dri2.useInvalidate;
2114 screen->lookup_egl_image = dri2_lookup_egl_image;
2115
2116 return configs;
2117
2118 destroy_screen:
2119 dri_destroy_screen_helper(screen);
2120
2121 release_pipe:
2122 if (screen->dev)
2123 pipe_loader_release(&screen->dev, 1);
2124 else
2125 close(fd);
2126
2127 free_screen:
2128 FREE(screen);
2129 return NULL;
2130 }
2131
2132 /**
2133 * This is the driver specific part of the createNewScreen entry point.
2134 *
2135 * Returns the struct gl_config supported by this driver.
2136 */
2137 static const __DRIconfig **
dri_kms_init_screen(__DRIscreen * sPriv)2138 dri_kms_init_screen(__DRIscreen * sPriv)
2139 {
2140 #if defined(GALLIUM_SOFTPIPE)
2141 const __DRIconfig **configs;
2142 struct dri_screen *screen;
2143 struct pipe_screen *pscreen = NULL;
2144 uint64_t cap;
2145 int fd;
2146
2147 screen = CALLOC_STRUCT(dri_screen);
2148 if (!screen)
2149 return NULL;
2150
2151 screen->sPriv = sPriv;
2152 screen->fd = sPriv->fd;
2153
2154 sPriv->driverPrivate = (void *)screen;
2155
2156 if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0)
2157 goto free_screen;
2158
2159 if (pipe_loader_sw_probe_kms(&screen->dev, fd)) {
2160 dri_init_options(screen);
2161 pscreen = pipe_loader_create_screen(screen->dev);
2162 }
2163
2164 if (!pscreen)
2165 goto release_pipe;
2166
2167 if (pscreen->resource_create_with_modifiers)
2168 dri2ImageExtension.createImageWithModifiers =
2169 dri2_create_image_with_modifiers;
2170
2171 if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
2172 (cap & DRM_PRIME_CAP_IMPORT)) {
2173 dri2ImageExtension.createImageFromFds = dri2_from_fds;
2174 dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
2175 dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
2176 dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
2177 dri2ImageExtension.queryDmaBufModifiers = dri2_query_dma_buf_modifiers;
2178 }
2179
2180 sPriv->extensions = dri_screen_extensions;
2181
2182 configs = dri_init_screen_helper(screen, pscreen);
2183 if (!configs)
2184 goto destroy_screen;
2185
2186 screen->can_share_buffer = false;
2187 screen->auto_fake_front = dri_with_format(sPriv);
2188 screen->broken_invalidate = !sPriv->dri2.useInvalidate;
2189 screen->lookup_egl_image = dri2_lookup_egl_image;
2190
2191 return configs;
2192
2193 destroy_screen:
2194 dri_destroy_screen_helper(screen);
2195
2196 release_pipe:
2197 if (screen->dev)
2198 pipe_loader_release(&screen->dev, 1);
2199 else
2200 close(fd);
2201
2202 free_screen:
2203 FREE(screen);
2204 #endif // GALLIUM_SOFTPIPE
2205 return NULL;
2206 }
2207
2208 static boolean
dri2_create_buffer(__DRIscreen * sPriv,__DRIdrawable * dPriv,const struct gl_config * visual,boolean isPixmap)2209 dri2_create_buffer(__DRIscreen * sPriv,
2210 __DRIdrawable * dPriv,
2211 const struct gl_config * visual, boolean isPixmap)
2212 {
2213 struct dri_drawable *drawable = NULL;
2214
2215 if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
2216 return FALSE;
2217
2218 drawable = dPriv->driverPrivate;
2219
2220 drawable->allocate_textures = dri2_allocate_textures;
2221 drawable->flush_frontbuffer = dri2_flush_frontbuffer;
2222 drawable->update_tex_buffer = dri2_update_tex_buffer;
2223 drawable->flush_swapbuffers = dri2_flush_swapbuffers;
2224
2225 return TRUE;
2226 }
2227
2228 /**
2229 * DRI driver virtual function table.
2230 *
2231 * DRI versions differ in their implementation of init_screen and swap_buffers.
2232 */
2233 const struct __DriverAPIRec galliumdrm_driver_api = {
2234 .InitScreen = dri2_init_screen,
2235 .DestroyScreen = dri_destroy_screen,
2236 .CreateContext = dri_create_context,
2237 .DestroyContext = dri_destroy_context,
2238 .CreateBuffer = dri2_create_buffer,
2239 .DestroyBuffer = dri_destroy_buffer,
2240 .MakeCurrent = dri_make_current,
2241 .UnbindContext = dri_unbind_context,
2242
2243 .AllocateBuffer = dri2_allocate_buffer,
2244 .ReleaseBuffer = dri2_release_buffer,
2245 };
2246
2247 /**
2248 * DRI driver virtual function table.
2249 *
2250 * KMS/DRM version of the DriverAPI above sporting a different InitScreen
2251 * hook. The latter is used to explicitly initialise the kms_swrast driver
2252 * rather than selecting the approapriate driver as suggested by the loader.
2253 */
2254 const struct __DriverAPIRec dri_kms_driver_api = {
2255 .InitScreen = dri_kms_init_screen,
2256 .DestroyScreen = dri_destroy_screen,
2257 .CreateContext = dri_create_context,
2258 .DestroyContext = dri_destroy_context,
2259 .CreateBuffer = dri2_create_buffer,
2260 .DestroyBuffer = dri_destroy_buffer,
2261 .MakeCurrent = dri_make_current,
2262 .UnbindContext = dri_unbind_context,
2263
2264 .AllocateBuffer = dri2_allocate_buffer,
2265 .ReleaseBuffer = dri2_release_buffer,
2266 };
2267
2268 /* This is the table of extensions that the loader will dlsym() for. */
2269 const __DRIextension *galliumdrm_driver_extensions[] = {
2270 &driCoreExtension.base,
2271 &driImageDriverExtension.base,
2272 &driDRI2Extension.base,
2273 &gallium_config_options.base,
2274 NULL
2275 };
2276
2277 /* vim: set sw=3 ts=8 sts=3 expandtab: */
2278