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