dri: Add a new capabilities for drivers that can't share buffers
[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 "util/u_memory.h"
33 #include "util/u_inlines.h"
34 #include "util/u_format.h"
35 #include "util/u_debug.h"
36 #include "state_tracker/drm_driver.h"
37 #include "state_tracker/st_texture.h"
38 #include "state_tracker/st_context.h"
39 #include "pipe-loader/pipe_loader.h"
40 #include "main/texobj.h"
41
42 #include "dri_screen.h"
43 #include "dri_context.h"
44 #include "dri_drawable.h"
45 #include "dri2_buffer.h"
46
47 static int convert_fourcc(int format, int *dri_components_p)
48 {
49 int dri_components;
50 switch(format) {
51 case __DRI_IMAGE_FOURCC_RGB565:
52 format = __DRI_IMAGE_FORMAT_RGB565;
53 dri_components = __DRI_IMAGE_COMPONENTS_RGB;
54 break;
55 case __DRI_IMAGE_FOURCC_ARGB8888:
56 format = __DRI_IMAGE_FORMAT_ARGB8888;
57 dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
58 break;
59 case __DRI_IMAGE_FOURCC_XRGB8888:
60 format = __DRI_IMAGE_FORMAT_XRGB8888;
61 dri_components = __DRI_IMAGE_COMPONENTS_RGB;
62 break;
63 case __DRI_IMAGE_FOURCC_ABGR8888:
64 format = __DRI_IMAGE_FORMAT_ABGR8888;
65 dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
66 break;
67 case __DRI_IMAGE_FOURCC_XBGR8888:
68 format = __DRI_IMAGE_FORMAT_XBGR8888;
69 dri_components = __DRI_IMAGE_COMPONENTS_RGB;
70 break;
71 default:
72 return -1;
73 }
74 *dri_components_p = dri_components;
75 return format;
76 }
77
78 /**
79 * DRI2 flush extension.
80 */
81 static void
82 dri2_flush_drawable(__DRIdrawable *dPriv)
83 {
84 dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);
85 }
86
87 static void
88 dri2_invalidate_drawable(__DRIdrawable *dPriv)
89 {
90 struct dri_drawable *drawable = dri_drawable(dPriv);
91
92 dri2InvalidateDrawable(dPriv);
93 drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
94
95 p_atomic_inc(&drawable->base.stamp);
96 }
97
98 static const __DRI2flushExtension dri2FlushExtension = {
99 .base = { __DRI2_FLUSH, 4 },
100
101 .flush = dri2_flush_drawable,
102 .invalidate = dri2_invalidate_drawable,
103 .flush_with_flags = dri_flush,
104 };
105
106 /**
107 * Retrieve __DRIbuffer from the DRI loader.
108 */
109 static __DRIbuffer *
110 dri2_drawable_get_buffers(struct dri_drawable *drawable,
111 const enum st_attachment_type *atts,
112 unsigned *count)
113 {
114 __DRIdrawable *dri_drawable = drawable->dPriv;
115 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
116 boolean with_format;
117 __DRIbuffer *buffers;
118 int num_buffers;
119 unsigned attachments[10];
120 unsigned num_attachments, i;
121
122 assert(loader);
123 with_format = dri_with_format(drawable->sPriv);
124
125 num_attachments = 0;
126
127 /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
128 if (!with_format)
129 attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
130
131 for (i = 0; i < *count; i++) {
132 enum pipe_format format;
133 unsigned bind;
134 int att, depth;
135
136 dri_drawable_get_format(drawable, atts[i], &format, &bind);
137 if (format == PIPE_FORMAT_NONE)
138 continue;
139
140 switch (atts[i]) {
141 case ST_ATTACHMENT_FRONT_LEFT:
142 /* already added */
143 if (!with_format)
144 continue;
145 att = __DRI_BUFFER_FRONT_LEFT;
146 break;
147 case ST_ATTACHMENT_BACK_LEFT:
148 att = __DRI_BUFFER_BACK_LEFT;
149 break;
150 case ST_ATTACHMENT_FRONT_RIGHT:
151 att = __DRI_BUFFER_FRONT_RIGHT;
152 break;
153 case ST_ATTACHMENT_BACK_RIGHT:
154 att = __DRI_BUFFER_BACK_RIGHT;
155 break;
156 default:
157 continue;
158 }
159
160 /*
161 * In this switch statement we must support all formats that
162 * may occur as the stvis->color_format.
163 */
164 switch(format) {
165 case PIPE_FORMAT_B8G8R8A8_UNORM:
166 depth = 32;
167 break;
168 case PIPE_FORMAT_B8G8R8X8_UNORM:
169 depth = 24;
170 break;
171 case PIPE_FORMAT_B5G6R5_UNORM:
172 depth = 16;
173 break;
174 default:
175 depth = util_format_get_blocksizebits(format);
176 assert(!"Unexpected format in dri2_drawable_get_buffers()");
177 }
178
179 attachments[num_attachments++] = att;
180 if (with_format) {
181 attachments[num_attachments++] = depth;
182 }
183 }
184
185 if (with_format) {
186 num_attachments /= 2;
187 buffers = loader->getBuffersWithFormat(dri_drawable,
188 &dri_drawable->w, &dri_drawable->h,
189 attachments, num_attachments,
190 &num_buffers, dri_drawable->loaderPrivate);
191 }
192 else {
193 buffers = loader->getBuffers(dri_drawable,
194 &dri_drawable->w, &dri_drawable->h,
195 attachments, num_attachments,
196 &num_buffers, dri_drawable->loaderPrivate);
197 }
198
199 if (buffers)
200 *count = num_buffers;
201
202 return buffers;
203 }
204
205 static bool
206 dri_image_drawable_get_buffers(struct dri_drawable *drawable,
207 struct __DRIimageList *images,
208 const enum st_attachment_type *statts,
209 unsigned statts_count)
210 {
211 __DRIdrawable *dPriv = drawable->dPriv;
212 __DRIscreen *sPriv = drawable->sPriv;
213 unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;
214 enum pipe_format pf;
215 uint32_t buffer_mask = 0;
216 unsigned i, bind;
217
218 for (i = 0; i < statts_count; i++) {
219 dri_drawable_get_format(drawable, statts[i], &pf, &bind);
220 if (pf == PIPE_FORMAT_NONE)
221 continue;
222
223 switch (statts[i]) {
224 case ST_ATTACHMENT_FRONT_LEFT:
225 buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
226 break;
227 case ST_ATTACHMENT_BACK_LEFT:
228 buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
229 break;
230 default:
231 continue;
232 }
233
234 switch (pf) {
235 case PIPE_FORMAT_B5G6R5_UNORM:
236 image_format = __DRI_IMAGE_FORMAT_RGB565;
237 break;
238 case PIPE_FORMAT_B8G8R8X8_UNORM:
239 image_format = __DRI_IMAGE_FORMAT_XRGB8888;
240 break;
241 case PIPE_FORMAT_B8G8R8A8_UNORM:
242 image_format = __DRI_IMAGE_FORMAT_ARGB8888;
243 break;
244 case PIPE_FORMAT_R8G8B8A8_UNORM:
245 image_format = __DRI_IMAGE_FORMAT_ABGR8888;
246 break;
247 default:
248 image_format = __DRI_IMAGE_FORMAT_NONE;
249 break;
250 }
251 }
252
253 return (*sPriv->image.loader->getBuffers) (dPriv, image_format,
254 (uint32_t *) &drawable->base.stamp,
255 dPriv->loaderPrivate, buffer_mask,
256 images);
257 }
258
259 static __DRIbuffer *
260 dri2_allocate_buffer(__DRIscreen *sPriv,
261 unsigned attachment, unsigned format,
262 int width, int height)
263 {
264 struct dri_screen *screen = dri_screen(sPriv);
265 struct dri2_buffer *buffer;
266 struct pipe_resource templ;
267 enum pipe_format pf;
268 unsigned bind = 0;
269 struct winsys_handle whandle;
270
271 switch (attachment) {
272 case __DRI_BUFFER_FRONT_LEFT:
273 case __DRI_BUFFER_FAKE_FRONT_LEFT:
274 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
275 break;
276 case __DRI_BUFFER_BACK_LEFT:
277 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
278 break;
279 case __DRI_BUFFER_DEPTH:
280 case __DRI_BUFFER_DEPTH_STENCIL:
281 case __DRI_BUFFER_STENCIL:
282 bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
283 break;
284 }
285
286 /* because we get the handle and stride */
287 bind |= PIPE_BIND_SHARED;
288
289 switch (format) {
290 case 32:
291 pf = PIPE_FORMAT_B8G8R8A8_UNORM;
292 break;
293 case 24:
294 pf = PIPE_FORMAT_B8G8R8X8_UNORM;
295 break;
296 case 16:
297 pf = PIPE_FORMAT_Z16_UNORM;
298 break;
299 default:
300 return NULL;
301 }
302
303 buffer = CALLOC_STRUCT(dri2_buffer);
304 if (!buffer)
305 return NULL;
306
307 memset(&templ, 0, sizeof(templ));
308 templ.bind = bind;
309 templ.format = pf;
310 templ.target = PIPE_TEXTURE_2D;
311 templ.last_level = 0;
312 templ.width0 = width;
313 templ.height0 = height;
314 templ.depth0 = 1;
315 templ.array_size = 1;
316
317 buffer->resource =
318 screen->base.screen->resource_create(screen->base.screen, &templ);
319 if (!buffer->resource) {
320 FREE(buffer);
321 return NULL;
322 }
323
324 memset(&whandle, 0, sizeof(whandle));
325 if (screen->can_share_buffer)
326 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
327 else
328 whandle.type = DRM_API_HANDLE_TYPE_KMS;
329
330 screen->base.screen->resource_get_handle(screen->base.screen,
331 buffer->resource, &whandle);
332
333 buffer->base.attachment = attachment;
334 buffer->base.name = whandle.handle;
335 buffer->base.cpp = util_format_get_blocksize(pf);
336 buffer->base.pitch = whandle.stride;
337
338 return &buffer->base;
339 }
340
341 static void
342 dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
343 {
344 struct dri2_buffer *buffer = dri2_buffer(bPriv);
345
346 pipe_resource_reference(&buffer->resource, NULL);
347 FREE(buffer);
348 }
349
350 /*
351 * Backend functions for st_framebuffer interface.
352 */
353
354 static void
355 dri2_allocate_textures(struct dri_context *ctx,
356 struct dri_drawable *drawable,
357 const enum st_attachment_type *statts,
358 unsigned statts_count)
359 {
360 __DRIscreen *sPriv = drawable->sPriv;
361 __DRIdrawable *dri_drawable = drawable->dPriv;
362 struct dri_screen *screen = dri_screen(sPriv);
363 struct pipe_resource templ;
364 boolean alloc_depthstencil = FALSE;
365 unsigned i, j, bind;
366 const __DRIimageLoaderExtension *image = sPriv->image.loader;
367 /* Image specific variables */
368 struct __DRIimageList images;
369 /* Dri2 specific variables */
370 __DRIbuffer *buffers;
371 struct winsys_handle whandle;
372 unsigned num_buffers = statts_count;
373
374 /* First get the buffers from the loader */
375 if (image) {
376 if (!dri_image_drawable_get_buffers(drawable, &images,
377 statts, statts_count))
378 return;
379 }
380 else {
381 buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
382 if (!buffers || (drawable->old_num == num_buffers &&
383 drawable->old_w == dri_drawable->w &&
384 drawable->old_h == dri_drawable->h &&
385 memcmp(drawable->old, buffers,
386 sizeof(__DRIbuffer) * num_buffers) == 0))
387 return;
388 }
389
390 /* Second clean useless resources*/
391
392 /* See if we need a depth-stencil buffer. */
393 for (i = 0; i < statts_count; i++) {
394 if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
395 alloc_depthstencil = TRUE;
396 break;
397 }
398 }
399
400 /* Delete the resources we won't need. */
401 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
402 /* Don't delete the depth-stencil buffer, we can reuse it. */
403 if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
404 continue;
405
406 /* Flush the texture before unreferencing, so that other clients can
407 * see what the driver has rendered.
408 */
409 if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {
410 struct pipe_context *pipe = ctx->st->pipe;
411 pipe->flush_resource(pipe, drawable->textures[i]);
412 }
413
414 pipe_resource_reference(&drawable->textures[i], NULL);
415 }
416
417 if (drawable->stvis.samples > 1) {
418 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
419 boolean del = TRUE;
420
421 /* Don't delete MSAA resources for the attachments which are enabled,
422 * we can reuse them. */
423 for (j = 0; j < statts_count; j++) {
424 if (i == statts[j]) {
425 del = FALSE;
426 break;
427 }
428 }
429
430 if (del) {
431 pipe_resource_reference(&drawable->msaa_textures[i], NULL);
432 }
433 }
434 }
435
436 /* Third use the buffers retrieved to fill the drawable info */
437
438 memset(&templ, 0, sizeof(templ));
439 templ.target = screen->target;
440 templ.last_level = 0;
441 templ.depth0 = 1;
442 templ.array_size = 1;
443
444 if (image) {
445 if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
446 struct pipe_resource **buf =
447 &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
448 struct pipe_resource *texture = images.front->texture;
449
450 dri_drawable->w = texture->width0;
451 dri_drawable->h = texture->height0;
452
453 pipe_resource_reference(buf, texture);
454 }
455
456 if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
457 struct pipe_resource **buf =
458 &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
459 struct pipe_resource *texture = images.back->texture;
460
461 dri_drawable->w = texture->width0;
462 dri_drawable->h = texture->height0;
463
464 pipe_resource_reference(buf, texture);
465 }
466
467 /* Note: if there is both a back and a front buffer,
468 * then they have the same size.
469 */
470 templ.width0 = dri_drawable->w;
471 templ.height0 = dri_drawable->h;
472 }
473 else {
474 memset(&whandle, 0, sizeof(whandle));
475
476 /* Process DRI-provided buffers and get pipe_resources. */
477 for (i = 0; i < num_buffers; i++) {
478 __DRIbuffer *buf = &buffers[i];
479 enum st_attachment_type statt;
480 enum pipe_format format;
481
482 switch (buf->attachment) {
483 case __DRI_BUFFER_FRONT_LEFT:
484 if (!screen->auto_fake_front) {
485 continue; /* invalid attachment */
486 }
487 /* fallthrough */
488 case __DRI_BUFFER_FAKE_FRONT_LEFT:
489 statt = ST_ATTACHMENT_FRONT_LEFT;
490 break;
491 case __DRI_BUFFER_BACK_LEFT:
492 statt = ST_ATTACHMENT_BACK_LEFT;
493 break;
494 default:
495 continue; /* invalid attachment */
496 }
497
498 dri_drawable_get_format(drawable, statt, &format, &bind);
499 if (format == PIPE_FORMAT_NONE)
500 continue;
501
502 /* dri2_drawable_get_buffers has already filled dri_drawable->w
503 * and dri_drawable->h */
504 templ.width0 = dri_drawable->w;
505 templ.height0 = dri_drawable->h;
506 templ.format = format;
507 templ.bind = bind;
508 whandle.handle = buf->name;
509 whandle.stride = buf->pitch;
510 if (screen->can_share_buffer)
511 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
512 else
513 whandle.type = DRM_API_HANDLE_TYPE_KMS;
514 drawable->textures[statt] =
515 screen->base.screen->resource_from_handle(screen->base.screen,
516 &templ, &whandle);
517 assert(drawable->textures[statt]);
518 }
519 }
520
521 /* Allocate private MSAA colorbuffers. */
522 if (drawable->stvis.samples > 1) {
523 for (i = 0; i < statts_count; i++) {
524 enum st_attachment_type statt = statts[i];
525
526 if (statt == ST_ATTACHMENT_DEPTH_STENCIL)
527 continue;
528
529 if (drawable->textures[statt]) {
530 templ.format = drawable->textures[statt]->format;
531 templ.bind = drawable->textures[statt]->bind;
532 templ.nr_samples = drawable->stvis.samples;
533
534 /* Try to reuse the resource.
535 * (the other resource parameters should be constant)
536 */
537 if (!drawable->msaa_textures[statt] ||
538 drawable->msaa_textures[statt]->width0 != templ.width0 ||
539 drawable->msaa_textures[statt]->height0 != templ.height0) {
540 /* Allocate a new one. */
541 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
542
543 drawable->msaa_textures[statt] =
544 screen->base.screen->resource_create(screen->base.screen,
545 &templ);
546 assert(drawable->msaa_textures[statt]);
547
548 /* If there are any MSAA resources, we should initialize them
549 * such that they contain the same data as the single-sample
550 * resources we just got from the X server.
551 *
552 * The reason for this is that the state tracker (and
553 * therefore the app) can access the MSAA resources only.
554 * The single-sample resources are not exposed
555 * to the state tracker.
556 *
557 */
558 dri_pipe_blit(ctx->st->pipe,
559 drawable->msaa_textures[statt],
560 drawable->textures[statt]);
561 }
562 }
563 else {
564 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
565 }
566 }
567 }
568
569 /* Allocate a private depth-stencil buffer. */
570 if (alloc_depthstencil) {
571 enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;
572 struct pipe_resource **zsbuf;
573 enum pipe_format format;
574 unsigned bind;
575
576 dri_drawable_get_format(drawable, statt, &format, &bind);
577
578 if (format) {
579 templ.format = format;
580 templ.bind = bind;
581
582 if (drawable->stvis.samples > 1) {
583 templ.nr_samples = drawable->stvis.samples;
584 zsbuf = &drawable->msaa_textures[statt];
585 }
586 else {
587 templ.nr_samples = 0;
588 zsbuf = &drawable->textures[statt];
589 }
590
591 /* Try to reuse the resource.
592 * (the other resource parameters should be constant)
593 */
594 if (!*zsbuf ||
595 (*zsbuf)->width0 != templ.width0 ||
596 (*zsbuf)->height0 != templ.height0) {
597 /* Allocate a new one. */
598 pipe_resource_reference(zsbuf, NULL);
599 *zsbuf = screen->base.screen->resource_create(screen->base.screen,
600 &templ);
601 assert(*zsbuf);
602 }
603 }
604 else {
605 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
606 pipe_resource_reference(&drawable->textures[statt], NULL);
607 }
608 }
609
610 /* For DRI2, we may get the same buffers again from the server.
611 * To prevent useless imports of gem names, drawable->old* is used
612 * to bypass the import if we get the same buffers. This doesn't apply
613 * to DRI3/Wayland, users of image.loader, since the buffer is managed
614 * by the client (no import), and the back buffer is going to change
615 * at every redraw.
616 */
617 if (!image) {
618 drawable->old_num = num_buffers;
619 drawable->old_w = dri_drawable->w;
620 drawable->old_h = dri_drawable->h;
621 memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);
622 }
623 }
624
625 static void
626 dri2_flush_frontbuffer(struct dri_context *ctx,
627 struct dri_drawable *drawable,
628 enum st_attachment_type statt)
629 {
630 __DRIdrawable *dri_drawable = drawable->dPriv;
631 const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
632 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
633 struct pipe_context *pipe = ctx->st->pipe;
634
635 if (statt != ST_ATTACHMENT_FRONT_LEFT)
636 return;
637
638 if (drawable->stvis.samples > 1) {
639 /* Resolve the front buffer. */
640 dri_pipe_blit(ctx->st->pipe,
641 drawable->textures[ST_ATTACHMENT_FRONT_LEFT],
642 drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]);
643 }
644
645 if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) {
646 pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]);
647 }
648
649 pipe->flush(pipe, NULL, 0);
650
651 if (image) {
652 image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
653 }
654 else if (loader->flushFrontBuffer) {
655 loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
656 }
657 }
658
659 static void
660 dri2_update_tex_buffer(struct dri_drawable *drawable,
661 struct dri_context *ctx,
662 struct pipe_resource *res)
663 {
664 /* no-op */
665 }
666
667 static __DRIimage *
668 dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
669 {
670 const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
671 __DRIimage *img;
672
673 if (!loader->lookupEGLImage)
674 return NULL;
675
676 img = loader->lookupEGLImage(screen->sPriv,
677 handle, screen->sPriv->loaderPrivate);
678
679 return img;
680 }
681
682 static __DRIimage *
683 dri2_create_image_from_winsys(__DRIscreen *_screen,
684 int width, int height, int format,
685 struct winsys_handle *whandle, int pitch,
686 void *loaderPrivate)
687 {
688 struct dri_screen *screen = dri_screen(_screen);
689 __DRIimage *img;
690 struct pipe_resource templ;
691 unsigned tex_usage;
692 enum pipe_format pf;
693
694 tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
695
696 switch (format) {
697 case __DRI_IMAGE_FORMAT_RGB565:
698 pf = PIPE_FORMAT_B5G6R5_UNORM;
699 break;
700 case __DRI_IMAGE_FORMAT_XRGB8888:
701 pf = PIPE_FORMAT_B8G8R8X8_UNORM;
702 break;
703 case __DRI_IMAGE_FORMAT_ARGB8888:
704 pf = PIPE_FORMAT_B8G8R8A8_UNORM;
705 break;
706 case __DRI_IMAGE_FORMAT_ABGR8888:
707 pf = PIPE_FORMAT_R8G8B8A8_UNORM;
708 break;
709 default:
710 pf = PIPE_FORMAT_NONE;
711 break;
712 }
713 if (pf == PIPE_FORMAT_NONE)
714 return NULL;
715
716 img = CALLOC_STRUCT(__DRIimageRec);
717 if (!img)
718 return NULL;
719
720 memset(&templ, 0, sizeof(templ));
721 templ.bind = tex_usage;
722 templ.format = pf;
723 templ.target = screen->target;
724 templ.last_level = 0;
725 templ.width0 = width;
726 templ.height0 = height;
727 templ.depth0 = 1;
728 templ.array_size = 1;
729
730 whandle->stride = pitch * util_format_get_blocksize(pf);
731
732 img->texture = screen->base.screen->resource_from_handle(screen->base.screen,
733 &templ, whandle);
734 if (!img->texture) {
735 FREE(img);
736 return NULL;
737 }
738
739 img->level = 0;
740 img->layer = 0;
741 img->dri_format = format;
742 img->loader_private = loaderPrivate;
743
744 return img;
745 }
746
747 static __DRIimage *
748 dri2_create_image_from_name(__DRIscreen *_screen,
749 int width, int height, int format,
750 int name, int pitch, void *loaderPrivate)
751 {
752 struct winsys_handle whandle;
753
754 memset(&whandle, 0, sizeof(whandle));
755 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
756 whandle.handle = name;
757
758 return dri2_create_image_from_winsys(_screen, width, height, format,
759 &whandle, pitch, loaderPrivate);
760 }
761
762 static __DRIimage *
763 dri2_create_image_from_fd(__DRIscreen *_screen,
764 int width, int height, int format,
765 int fd, int pitch, void *loaderPrivate)
766 {
767 struct winsys_handle whandle;
768
769 if (fd < 0)
770 return NULL;
771
772 memset(&whandle, 0, sizeof(whandle));
773 whandle.type = DRM_API_HANDLE_TYPE_FD;
774 whandle.handle = (unsigned)fd;
775
776 return dri2_create_image_from_winsys(_screen, width, height, format,
777 &whandle, pitch, loaderPrivate);
778 }
779
780 static __DRIimage *
781 dri2_create_image_from_renderbuffer(__DRIcontext *context,
782 int renderbuffer, void *loaderPrivate)
783 {
784 struct dri_context *ctx = dri_context(context);
785
786 if (!ctx->st->get_resource_for_egl_image)
787 return NULL;
788
789 /* TODO */
790 return NULL;
791 }
792
793 static __DRIimage *
794 dri2_create_image(__DRIscreen *_screen,
795 int width, int height, int format,
796 unsigned int use, void *loaderPrivate)
797 {
798 struct dri_screen *screen = dri_screen(_screen);
799 __DRIimage *img;
800 struct pipe_resource templ;
801 unsigned tex_usage;
802 enum pipe_format pf;
803
804 tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
805 if (use & __DRI_IMAGE_USE_SCANOUT)
806 tex_usage |= PIPE_BIND_SCANOUT;
807 if (use & __DRI_IMAGE_USE_SHARE)
808 tex_usage |= PIPE_BIND_SHARED;
809 if (use & __DRI_IMAGE_USE_LINEAR)
810 tex_usage |= PIPE_BIND_LINEAR;
811 if (use & __DRI_IMAGE_USE_CURSOR) {
812 if (width != 64 || height != 64)
813 return NULL;
814 tex_usage |= PIPE_BIND_CURSOR;
815 }
816
817 switch (format) {
818 case __DRI_IMAGE_FORMAT_RGB565:
819 pf = PIPE_FORMAT_B5G6R5_UNORM;
820 break;
821 case __DRI_IMAGE_FORMAT_XRGB8888:
822 pf = PIPE_FORMAT_B8G8R8X8_UNORM;
823 break;
824 case __DRI_IMAGE_FORMAT_ARGB8888:
825 pf = PIPE_FORMAT_B8G8R8A8_UNORM;
826 break;
827 case __DRI_IMAGE_FORMAT_ABGR8888:
828 pf = PIPE_FORMAT_R8G8B8A8_UNORM;
829 break;
830 default:
831 pf = PIPE_FORMAT_NONE;
832 break;
833 }
834 if (pf == PIPE_FORMAT_NONE)
835 return NULL;
836
837 img = CALLOC_STRUCT(__DRIimageRec);
838 if (!img)
839 return NULL;
840
841 memset(&templ, 0, sizeof(templ));
842 templ.bind = tex_usage;
843 templ.format = pf;
844 templ.target = PIPE_TEXTURE_2D;
845 templ.last_level = 0;
846 templ.width0 = width;
847 templ.height0 = height;
848 templ.depth0 = 1;
849 templ.array_size = 1;
850
851 img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
852 if (!img->texture) {
853 FREE(img);
854 return NULL;
855 }
856
857 img->level = 0;
858 img->layer = 0;
859 img->dri_format = format;
860 img->dri_components = 0;
861
862 img->loader_private = loaderPrivate;
863 return img;
864 }
865
866 static GLboolean
867 dri2_query_image(__DRIimage *image, int attrib, int *value)
868 {
869 struct winsys_handle whandle;
870 memset(&whandle, 0, sizeof(whandle));
871
872 switch (attrib) {
873 case __DRI_IMAGE_ATTRIB_STRIDE:
874 whandle.type = DRM_API_HANDLE_TYPE_KMS;
875 image->texture->screen->resource_get_handle(image->texture->screen,
876 image->texture, &whandle);
877 *value = whandle.stride;
878 return GL_TRUE;
879 case __DRI_IMAGE_ATTRIB_HANDLE:
880 whandle.type = DRM_API_HANDLE_TYPE_KMS;
881 image->texture->screen->resource_get_handle(image->texture->screen,
882 image->texture, &whandle);
883 *value = whandle.handle;
884 return GL_TRUE;
885 case __DRI_IMAGE_ATTRIB_NAME:
886 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
887 image->texture->screen->resource_get_handle(image->texture->screen,
888 image->texture, &whandle);
889 *value = whandle.handle;
890 return GL_TRUE;
891 case __DRI_IMAGE_ATTRIB_FD:
892 whandle.type= DRM_API_HANDLE_TYPE_FD;
893 image->texture->screen->resource_get_handle(image->texture->screen,
894 image->texture, &whandle);
895 *value = whandle.handle;
896 return GL_TRUE;
897 case __DRI_IMAGE_ATTRIB_FORMAT:
898 *value = image->dri_format;
899 return GL_TRUE;
900 case __DRI_IMAGE_ATTRIB_WIDTH:
901 *value = image->texture->width0;
902 return GL_TRUE;
903 case __DRI_IMAGE_ATTRIB_HEIGHT:
904 *value = image->texture->height0;
905 return GL_TRUE;
906 case __DRI_IMAGE_ATTRIB_COMPONENTS:
907 if (image->dri_components == 0)
908 return GL_FALSE;
909 *value = image->dri_components;
910 return GL_TRUE;
911 default:
912 return GL_FALSE;
913 }
914 }
915
916 static __DRIimage *
917 dri2_dup_image(__DRIimage *image, void *loaderPrivate)
918 {
919 __DRIimage *img;
920
921 img = CALLOC_STRUCT(__DRIimageRec);
922 if (!img)
923 return NULL;
924
925 img->texture = NULL;
926 pipe_resource_reference(&img->texture, image->texture);
927 img->level = image->level;
928 img->layer = image->layer;
929 img->dri_format = image->dri_format;
930 /* This should be 0 for sub images, but dup is also used for base images. */
931 img->dri_components = image->dri_components;
932 img->loader_private = loaderPrivate;
933
934 return img;
935 }
936
937 static GLboolean
938 dri2_validate_usage(__DRIimage *image, unsigned int use)
939 {
940 /*
941 * Gallium drivers are bad at adding usages to the resources
942 * once opened again in another process, which is the main use
943 * case for this, so we have to lie.
944 */
945 if (image != NULL)
946 return GL_TRUE;
947 else
948 return GL_FALSE;
949 }
950
951 static __DRIimage *
952 dri2_from_names(__DRIscreen *screen, int width, int height, int format,
953 int *names, int num_names, int *strides, int *offsets,
954 void *loaderPrivate)
955 {
956 __DRIimage *img;
957 int stride, dri_components;
958
959 if (num_names != 1)
960 return NULL;
961 if (offsets[0] != 0)
962 return NULL;
963
964 format = convert_fourcc(format, &dri_components);
965 if (format == -1)
966 return NULL;
967
968 /* Strides are in bytes not pixels. */
969 stride = strides[0] /4;
970
971 img = dri2_create_image_from_name(screen, width, height, format,
972 names[0], stride, loaderPrivate);
973 if (img == NULL)
974 return NULL;
975
976 img->dri_components = dri_components;
977 return img;
978 }
979
980 static __DRIimage *
981 dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
982 {
983 __DRIimage *img;
984
985 if (plane != 0)
986 return NULL;
987
988 if (image->dri_components == 0)
989 return NULL;
990
991 img = dri2_dup_image(image, loaderPrivate);
992 if (img == NULL)
993 return NULL;
994
995 /* set this to 0 for sub images. */
996 img->dri_components = 0;
997 return img;
998 }
999
1000 static __DRIimage *
1001 dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
1002 int depth, int level, unsigned *error,
1003 void *loaderPrivate)
1004 {
1005 __DRIimage *img;
1006 struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
1007 struct gl_texture_object *obj;
1008 struct pipe_resource *tex;
1009 GLuint face = 0;
1010
1011 obj = _mesa_lookup_texture(ctx, texture);
1012 if (!obj || obj->Target != target) {
1013 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1014 return NULL;
1015 }
1016
1017 tex = st_get_texobj_resource(obj);
1018 if (!tex) {
1019 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1020 return NULL;
1021 }
1022
1023 if (target == GL_TEXTURE_CUBE_MAP)
1024 face = depth;
1025
1026 _mesa_test_texobj_completeness(ctx, obj);
1027 if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
1028 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1029 return NULL;
1030 }
1031
1032 if (level < obj->BaseLevel || level > obj->_MaxLevel) {
1033 *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1034 return NULL;
1035 }
1036
1037 if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
1038 *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1039 return NULL;
1040 }
1041
1042 img = CALLOC_STRUCT(__DRIimageRec);
1043 if (!img) {
1044 *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
1045 return NULL;
1046 }
1047
1048 img->level = level;
1049 img->layer = depth;
1050 img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
1051
1052 img->loader_private = loaderPrivate;
1053
1054 if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
1055 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1056 free(img);
1057 return NULL;
1058 }
1059
1060 pipe_resource_reference(&img->texture, tex);
1061
1062 *error = __DRI_IMAGE_ERROR_SUCCESS;
1063 return img;
1064 }
1065
1066 static __DRIimage *
1067 dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
1068 int *fds, int num_fds, int *strides, int *offsets,
1069 void *loaderPrivate)
1070 {
1071 __DRIimage *img;
1072 int format, stride, dri_components;
1073
1074 if (num_fds != 1)
1075 return NULL;
1076 if (offsets[0] != 0)
1077 return NULL;
1078
1079 format = convert_fourcc(fourcc, &dri_components);
1080 if (format == -1)
1081 return NULL;
1082
1083 /* Strides are in bytes not pixels. */
1084 stride = strides[0] /4;
1085
1086 img = dri2_create_image_from_fd(screen, width, height, format,
1087 fds[0], stride, loaderPrivate);
1088 if (img == NULL)
1089 return NULL;
1090
1091 img->dri_components = dri_components;
1092 return img;
1093 }
1094
1095 static __DRIimage *
1096 dri2_from_dma_bufs(__DRIscreen *screen,
1097 int width, int height, int fourcc,
1098 int *fds, int num_fds,
1099 int *strides, int *offsets,
1100 enum __DRIYUVColorSpace yuv_color_space,
1101 enum __DRISampleRange sample_range,
1102 enum __DRIChromaSiting horizontal_siting,
1103 enum __DRIChromaSiting vertical_siting,
1104 unsigned *error,
1105 void *loaderPrivate)
1106 {
1107 __DRIimage *img;
1108 int format, stride, dri_components;
1109
1110 if (num_fds != 1 || offsets[0] != 0) {
1111 *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1112 return NULL;
1113 }
1114
1115 format = convert_fourcc(fourcc, &dri_components);
1116 if (format == -1) {
1117 *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1118 return NULL;
1119 }
1120
1121 /* Strides are in bytes not pixels. */
1122 stride = strides[0] /4;
1123
1124 img = dri2_create_image_from_fd(screen, width, height, format,
1125 fds[0], stride, loaderPrivate);
1126 if (img == NULL) {
1127 *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
1128 return NULL;
1129 }
1130
1131 img->yuv_color_space = yuv_color_space;
1132 img->sample_range = sample_range;
1133 img->horizontal_siting = horizontal_siting;
1134 img->vertical_siting = vertical_siting;
1135 img->dri_components = dri_components;
1136
1137 *error = __DRI_IMAGE_ERROR_SUCCESS;
1138 return img;
1139 }
1140
1141 static void
1142 dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
1143 int dstx0, int dsty0, int dstwidth, int dstheight,
1144 int srcx0, int srcy0, int srcwidth, int srcheight,
1145 int flush_flag)
1146 {
1147 struct dri_context *ctx = dri_context(context);
1148 struct pipe_context *pipe = ctx->st->pipe;
1149 struct pipe_screen *screen;
1150 struct pipe_fence_handle *fence;
1151 struct pipe_blit_info blit;
1152
1153 if (!dst || !src)
1154 return;
1155
1156 memset(&blit, 0, sizeof(blit));
1157 blit.dst.resource = dst->texture;
1158 blit.dst.box.x = dstx0;
1159 blit.dst.box.y = dsty0;
1160 blit.dst.box.width = dstwidth;
1161 blit.dst.box.height = dstheight;
1162 blit.dst.box.depth = 1;
1163 blit.dst.format = dst->texture->format;
1164 blit.src.resource = src->texture;
1165 blit.src.box.x = srcx0;
1166 blit.src.box.y = srcy0;
1167 blit.src.box.width = srcwidth;
1168 blit.src.box.height = srcheight;
1169 blit.src.box.depth = 1;
1170 blit.src.format = src->texture->format;
1171 blit.mask = PIPE_MASK_RGBA;
1172 blit.filter = PIPE_TEX_FILTER_NEAREST;
1173
1174 pipe->blit(pipe, &blit);
1175
1176 if (flush_flag == __BLIT_FLAG_FLUSH) {
1177 pipe->flush_resource(pipe, dst->texture);
1178 ctx->st->flush(ctx->st, 0, NULL);
1179 } else if (flush_flag == __BLIT_FLAG_FINISH) {
1180 screen = dri_screen(ctx->sPriv)->base.screen;
1181 pipe->flush_resource(pipe, dst->texture);
1182 ctx->st->flush(ctx->st, 0, &fence);
1183 (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
1184 screen->fence_reference(screen, &fence, NULL);
1185 }
1186 }
1187
1188 static void
1189 dri2_destroy_image(__DRIimage *img)
1190 {
1191 pipe_resource_reference(&img->texture, NULL);
1192 FREE(img);
1193 }
1194
1195 static int
1196 dri2_get_capabilities(__DRIscreen *_screen)
1197 {
1198 struct dri_screen *screen = dri_screen(_screen);
1199
1200 return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
1201 }
1202
1203 /* The extension is modified during runtime if DRI_PRIME is detected */
1204 static __DRIimageExtension dri2ImageExtension = {
1205 .base = { __DRI_IMAGE, 10 },
1206
1207 .createImageFromName = dri2_create_image_from_name,
1208 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
1209 .destroyImage = dri2_destroy_image,
1210 .createImage = dri2_create_image,
1211 .queryImage = dri2_query_image,
1212 .dupImage = dri2_dup_image,
1213 .validateUsage = dri2_validate_usage,
1214 .createImageFromNames = dri2_from_names,
1215 .fromPlanar = dri2_from_planar,
1216 .createImageFromTexture = dri2_create_from_texture,
1217 .createImageFromFds = NULL,
1218 .createImageFromDmaBufs = NULL,
1219 .blitImage = dri2_blit_image,
1220 .getCapabilities = dri2_get_capabilities,
1221 };
1222
1223 /*
1224 * Backend function init_screen.
1225 */
1226
1227 static const __DRIextension *dri_screen_extensions[] = {
1228 &driTexBufferExtension.base,
1229 &dri2FlushExtension.base,
1230 &dri2ImageExtension.base,
1231 &dri2ConfigQueryExtension.base,
1232 &dri2ThrottleExtension.base,
1233 NULL
1234 };
1235
1236 /**
1237 * This is the driver specific part of the createNewScreen entry point.
1238 *
1239 * Returns the struct gl_config supported by this driver.
1240 */
1241 static const __DRIconfig **
1242 dri2_init_screen(__DRIscreen * sPriv)
1243 {
1244 const __DRIconfig **configs;
1245 struct dri_screen *screen;
1246 struct pipe_screen *pscreen = NULL;
1247 const struct drm_conf_ret *throttle_ret = NULL;
1248 const struct drm_conf_ret *dmabuf_ret = NULL;
1249
1250 screen = CALLOC_STRUCT(dri_screen);
1251 if (!screen)
1252 return NULL;
1253
1254 screen->sPriv = sPriv;
1255 screen->fd = sPriv->fd;
1256
1257 sPriv->driverPrivate = (void *)screen;
1258
1259 #if GALLIUM_STATIC_TARGETS
1260 pscreen = dd_create_screen(screen->fd);
1261
1262 throttle_ret = dd_configuration(DRM_CONF_THROTTLE);
1263 dmabuf_ret = dd_configuration(DRM_CONF_SHARE_FD);
1264 #else
1265 if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd, true)) {
1266 pscreen = pipe_loader_create_screen(screen->dev, PIPE_SEARCH_DIR);
1267
1268 throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE);
1269 dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD);
1270 }
1271 #endif // GALLIUM_STATIC_TARGETS
1272
1273 if (throttle_ret && throttle_ret->val.val_int != -1) {
1274 screen->throttling_enabled = TRUE;
1275 screen->default_throttle_frames = throttle_ret->val.val_int;
1276 }
1277
1278 if (dmabuf_ret && dmabuf_ret->val.val_bool) {
1279 uint64_t cap;
1280
1281 if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
1282 (cap & DRM_PRIME_CAP_IMPORT)) {
1283 dri2ImageExtension.createImageFromFds = dri2_from_fds;
1284 dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
1285 }
1286 }
1287
1288 sPriv->extensions = dri_screen_extensions;
1289
1290 /* dri_init_screen_helper checks pscreen for us */
1291
1292 #if GALLIUM_STATIC_TARGETS
1293 configs = dri_init_screen_helper(screen, pscreen, dd_driver_name());
1294 #else
1295 configs = dri_init_screen_helper(screen, pscreen, screen->dev->driver_name);
1296 #endif // GALLIUM_STATIC_TARGETS
1297 if (!configs)
1298 goto fail;
1299
1300 screen->can_share_buffer = true;
1301 screen->auto_fake_front = dri_with_format(sPriv);
1302 screen->broken_invalidate = !sPriv->dri2.useInvalidate;
1303 screen->lookup_egl_image = dri2_lookup_egl_image;
1304
1305 return configs;
1306 fail:
1307 dri_destroy_screen_helper(screen);
1308 #if !GALLIUM_STATIC_TARGETS
1309 if (screen->dev)
1310 pipe_loader_release(&screen->dev, 1);
1311 #endif // !GALLIUM_STATIC_TARGETS
1312 FREE(screen);
1313 return NULL;
1314 }
1315
1316 /**
1317 * This is the driver specific part of the createNewScreen entry point.
1318 *
1319 * Returns the struct gl_config supported by this driver.
1320 */
1321 static const __DRIconfig **
1322 dri_kms_init_screen(__DRIscreen * sPriv)
1323 {
1324 #if GALLIUM_STATIC_TARGETS
1325 const __DRIconfig **configs;
1326 struct dri_screen *screen;
1327 struct pipe_screen *pscreen = NULL;
1328
1329 screen = CALLOC_STRUCT(dri_screen);
1330 if (!screen)
1331 return NULL;
1332
1333 screen->sPriv = sPriv;
1334 screen->fd = sPriv->fd;
1335
1336 sPriv->driverPrivate = (void *)screen;
1337
1338 pscreen = kms_swrast_create_screen(screen->fd);
1339 sPriv->extensions = dri_screen_extensions;
1340
1341 /* dri_init_screen_helper checks pscreen for us */
1342 configs = dri_init_screen_helper(screen, pscreen, "swrast");
1343 if (!configs)
1344 goto fail;
1345
1346 screen->can_share_buffer = false;
1347 screen->auto_fake_front = dri_with_format(sPriv);
1348 screen->broken_invalidate = !sPriv->dri2.useInvalidate;
1349 screen->lookup_egl_image = dri2_lookup_egl_image;
1350
1351 return configs;
1352 fail:
1353 dri_destroy_screen_helper(screen);
1354 FREE(screen);
1355 #endif // GALLIUM_STATIC_TARGETS
1356 return NULL;
1357 }
1358
1359 static boolean
1360 dri2_create_buffer(__DRIscreen * sPriv,
1361 __DRIdrawable * dPriv,
1362 const struct gl_config * visual, boolean isPixmap)
1363 {
1364 struct dri_drawable *drawable = NULL;
1365
1366 if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
1367 return FALSE;
1368
1369 drawable = dPriv->driverPrivate;
1370
1371 drawable->allocate_textures = dri2_allocate_textures;
1372 drawable->flush_frontbuffer = dri2_flush_frontbuffer;
1373 drawable->update_tex_buffer = dri2_update_tex_buffer;
1374
1375 return TRUE;
1376 }
1377
1378 /**
1379 * DRI driver virtual function table.
1380 *
1381 * DRI versions differ in their implementation of init_screen and swap_buffers.
1382 */
1383 const struct __DriverAPIRec galliumdrm_driver_api = {
1384 .InitScreen = dri2_init_screen,
1385 .DestroyScreen = dri_destroy_screen,
1386 .CreateContext = dri_create_context,
1387 .DestroyContext = dri_destroy_context,
1388 .CreateBuffer = dri2_create_buffer,
1389 .DestroyBuffer = dri_destroy_buffer,
1390 .MakeCurrent = dri_make_current,
1391 .UnbindContext = dri_unbind_context,
1392
1393 .AllocateBuffer = dri2_allocate_buffer,
1394 .ReleaseBuffer = dri2_release_buffer,
1395 };
1396
1397 /**
1398 * DRI driver virtual function table.
1399 *
1400 * KMS/DRM version of the DriverAPI above sporting a different InitScreen
1401 * hook. The latter is used to explicitly initialise the kms_swrast driver
1402 * rather than selecting the approapriate driver as suggested by the loader.
1403 */
1404 const struct __DriverAPIRec dri_kms_driver_api = {
1405 .InitScreen = dri_kms_init_screen,
1406 .DestroyScreen = dri_destroy_screen,
1407 .CreateContext = dri_create_context,
1408 .DestroyContext = dri_destroy_context,
1409 .CreateBuffer = dri2_create_buffer,
1410 .DestroyBuffer = dri_destroy_buffer,
1411 .MakeCurrent = dri_make_current,
1412 .UnbindContext = dri_unbind_context,
1413
1414 .AllocateBuffer = dri2_allocate_buffer,
1415 .ReleaseBuffer = dri2_release_buffer,
1416 };
1417
1418 /* This is the table of extensions that the loader will dlsym() for. */
1419 const __DRIextension *galliumdrm_driver_extensions[] = {
1420 &driCoreExtension.base,
1421 &driImageDriverExtension.base,
1422 &driDRI2Extension.base,
1423 &gallium_config_options.base,
1424 NULL
1425 };
1426
1427 /* vim: set sw=3 ts=8 sts=3 expandtab: */