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