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