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