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