gallium: add INTERP_* opcodes to support interpolateAt*
[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 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
326 screen->base.screen->resource_get_handle(screen->base.screen,
327 buffer->resource, &whandle);
328
329 buffer->base.attachment = attachment;
330 buffer->base.name = whandle.handle;
331 buffer->base.cpp = util_format_get_blocksize(pf);
332 buffer->base.pitch = whandle.stride;
333
334 return &buffer->base;
335 }
336
337 static void
338 dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
339 {
340 struct dri2_buffer *buffer = dri2_buffer(bPriv);
341
342 pipe_resource_reference(&buffer->resource, NULL);
343 FREE(buffer);
344 }
345
346 /*
347 * Backend functions for st_framebuffer interface.
348 */
349
350 static void
351 dri2_allocate_textures(struct dri_context *ctx,
352 struct dri_drawable *drawable,
353 const enum st_attachment_type *statts,
354 unsigned statts_count)
355 {
356 __DRIscreen *sPriv = drawable->sPriv;
357 __DRIdrawable *dri_drawable = drawable->dPriv;
358 struct dri_screen *screen = dri_screen(sPriv);
359 struct pipe_resource templ;
360 boolean alloc_depthstencil = FALSE;
361 unsigned i, j, bind;
362 const __DRIimageLoaderExtension *image = sPriv->image.loader;
363 /* Image specific variables */
364 struct __DRIimageList images;
365 /* Dri2 specific variables */
366 __DRIbuffer *buffers;
367 struct winsys_handle whandle;
368 unsigned num_buffers = statts_count;
369
370 /* First get the buffers from the loader */
371 if (image) {
372 if (!dri_image_drawable_get_buffers(drawable, &images,
373 statts, statts_count))
374 return;
375 }
376 else {
377 buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
378 if (!buffers || (drawable->old_num == num_buffers &&
379 drawable->old_w == dri_drawable->w &&
380 drawable->old_h == dri_drawable->h &&
381 memcmp(drawable->old, buffers,
382 sizeof(__DRIbuffer) * num_buffers) == 0))
383 return;
384 }
385
386 /* Second clean useless resources*/
387
388 /* See if we need a depth-stencil buffer. */
389 for (i = 0; i < statts_count; i++) {
390 if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
391 alloc_depthstencil = TRUE;
392 break;
393 }
394 }
395
396 /* Delete the resources we won't need. */
397 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
398 /* Don't delete the depth-stencil buffer, we can reuse it. */
399 if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
400 continue;
401
402 /* Flush the texture before unreferencing, so that other clients can
403 * see what the driver has rendered.
404 */
405 if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {
406 struct pipe_context *pipe = ctx->st->pipe;
407 pipe->flush_resource(pipe, drawable->textures[i]);
408 }
409
410 pipe_resource_reference(&drawable->textures[i], NULL);
411 }
412
413 if (drawable->stvis.samples > 1) {
414 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
415 boolean del = TRUE;
416
417 /* Don't delete MSAA resources for the attachments which are enabled,
418 * we can reuse them. */
419 for (j = 0; j < statts_count; j++) {
420 if (i == statts[j]) {
421 del = FALSE;
422 break;
423 }
424 }
425
426 if (del) {
427 pipe_resource_reference(&drawable->msaa_textures[i], NULL);
428 }
429 }
430 }
431
432 /* Third use the buffers retrieved to fill the drawable info */
433
434 memset(&templ, 0, sizeof(templ));
435 templ.target = screen->target;
436 templ.last_level = 0;
437 templ.depth0 = 1;
438 templ.array_size = 1;
439
440 if (image) {
441 if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
442 struct pipe_resource **buf =
443 &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
444 struct pipe_resource *texture = images.front->texture;
445
446 dri_drawable->w = texture->width0;
447 dri_drawable->h = texture->height0;
448
449 pipe_resource_reference(buf, texture);
450 }
451
452 if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
453 struct pipe_resource **buf =
454 &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
455 struct pipe_resource *texture = images.back->texture;
456
457 dri_drawable->w = texture->width0;
458 dri_drawable->h = texture->height0;
459
460 pipe_resource_reference(buf, texture);
461 }
462
463 /* Note: if there is both a back and a front buffer,
464 * then they have the same size.
465 */
466 templ.width0 = dri_drawable->w;
467 templ.height0 = dri_drawable->h;
468 }
469 else {
470 memset(&whandle, 0, sizeof(whandle));
471
472 /* Process DRI-provided buffers and get pipe_resources. */
473 for (i = 0; i < num_buffers; i++) {
474 __DRIbuffer *buf = &buffers[i];
475 enum st_attachment_type statt;
476 enum pipe_format format;
477
478 switch (buf->attachment) {
479 case __DRI_BUFFER_FRONT_LEFT:
480 if (!screen->auto_fake_front) {
481 continue; /* invalid attachment */
482 }
483 /* fallthrough */
484 case __DRI_BUFFER_FAKE_FRONT_LEFT:
485 statt = ST_ATTACHMENT_FRONT_LEFT;
486 break;
487 case __DRI_BUFFER_BACK_LEFT:
488 statt = ST_ATTACHMENT_BACK_LEFT;
489 break;
490 default:
491 continue; /* invalid attachment */
492 }
493
494 dri_drawable_get_format(drawable, statt, &format, &bind);
495 if (format == PIPE_FORMAT_NONE)
496 continue;
497
498 /* dri2_drawable_get_buffers has already filled dri_drawable->w
499 * and dri_drawable->h */
500 templ.width0 = dri_drawable->w;
501 templ.height0 = dri_drawable->h;
502 templ.format = format;
503 templ.bind = bind;
504 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
505 whandle.handle = buf->name;
506 whandle.stride = buf->pitch;
507
508 drawable->textures[statt] =
509 screen->base.screen->resource_from_handle(screen->base.screen,
510 &templ, &whandle);
511 assert(drawable->textures[statt]);
512 }
513 }
514
515 /* Allocate private MSAA colorbuffers. */
516 if (drawable->stvis.samples > 1) {
517 for (i = 0; i < statts_count; i++) {
518 enum st_attachment_type statt = statts[i];
519
520 if (statt == ST_ATTACHMENT_DEPTH_STENCIL)
521 continue;
522
523 if (drawable->textures[statt]) {
524 templ.format = drawable->textures[statt]->format;
525 templ.bind = drawable->textures[statt]->bind;
526 templ.nr_samples = drawable->stvis.samples;
527
528 /* Try to reuse the resource.
529 * (the other resource parameters should be constant)
530 */
531 if (!drawable->msaa_textures[statt] ||
532 drawable->msaa_textures[statt]->width0 != templ.width0 ||
533 drawable->msaa_textures[statt]->height0 != templ.height0) {
534 /* Allocate a new one. */
535 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
536
537 drawable->msaa_textures[statt] =
538 screen->base.screen->resource_create(screen->base.screen,
539 &templ);
540 assert(drawable->msaa_textures[statt]);
541
542 /* If there are any MSAA resources, we should initialize them
543 * such that they contain the same data as the single-sample
544 * resources we just got from the X server.
545 *
546 * The reason for this is that the state tracker (and
547 * therefore the app) can access the MSAA resources only.
548 * The single-sample resources are not exposed
549 * to the state tracker.
550 *
551 */
552 dri_pipe_blit(ctx->st->pipe,
553 drawable->msaa_textures[statt],
554 drawable->textures[statt]);
555 }
556 }
557 else {
558 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
559 }
560 }
561 }
562
563 /* Allocate a private depth-stencil buffer. */
564 if (alloc_depthstencil) {
565 enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;
566 struct pipe_resource **zsbuf;
567 enum pipe_format format;
568 unsigned bind;
569
570 dri_drawable_get_format(drawable, statt, &format, &bind);
571
572 if (format) {
573 templ.format = format;
574 templ.bind = bind;
575
576 if (drawable->stvis.samples > 1) {
577 templ.nr_samples = drawable->stvis.samples;
578 zsbuf = &drawable->msaa_textures[statt];
579 }
580 else {
581 templ.nr_samples = 0;
582 zsbuf = &drawable->textures[statt];
583 }
584
585 /* Try to reuse the resource.
586 * (the other resource parameters should be constant)
587 */
588 if (!*zsbuf ||
589 (*zsbuf)->width0 != templ.width0 ||
590 (*zsbuf)->height0 != templ.height0) {
591 /* Allocate a new one. */
592 pipe_resource_reference(zsbuf, NULL);
593 *zsbuf = screen->base.screen->resource_create(screen->base.screen,
594 &templ);
595 assert(*zsbuf);
596 }
597 }
598 else {
599 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
600 pipe_resource_reference(&drawable->textures[statt], NULL);
601 }
602 }
603
604 /* For DRI2, we may get the same buffers again from the server.
605 * To prevent useless imports of gem names, drawable->old* is used
606 * to bypass the import if we get the same buffers. This doesn't apply
607 * to DRI3/Wayland, users of image.loader, since the buffer is managed
608 * by the client (no import), and the back buffer is going to change
609 * at every redraw.
610 */
611 if (!image) {
612 drawable->old_num = num_buffers;
613 drawable->old_w = dri_drawable->w;
614 drawable->old_h = dri_drawable->h;
615 memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);
616 }
617 }
618
619 static void
620 dri2_flush_frontbuffer(struct dri_context *ctx,
621 struct dri_drawable *drawable,
622 enum st_attachment_type statt)
623 {
624 __DRIdrawable *dri_drawable = drawable->dPriv;
625 const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
626 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
627 struct pipe_context *pipe = ctx->st->pipe;
628
629 if (statt != ST_ATTACHMENT_FRONT_LEFT)
630 return;
631
632 if (drawable->stvis.samples > 1) {
633 /* Resolve the front buffer. */
634 dri_pipe_blit(ctx->st->pipe,
635 drawable->textures[ST_ATTACHMENT_FRONT_LEFT],
636 drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]);
637 }
638
639 if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) {
640 pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]);
641 }
642
643 pipe->flush(pipe, NULL, 0);
644
645 if (image) {
646 image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
647 }
648 else if (loader->flushFrontBuffer) {
649 loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
650 }
651 }
652
653 static void
654 dri2_update_tex_buffer(struct dri_drawable *drawable,
655 struct dri_context *ctx,
656 struct pipe_resource *res)
657 {
658 /* no-op */
659 }
660
661 static __DRIimage *
662 dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
663 {
664 const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
665 __DRIimage *img;
666
667 if (!loader->lookupEGLImage)
668 return NULL;
669
670 img = loader->lookupEGLImage(screen->sPriv,
671 handle, screen->sPriv->loaderPrivate);
672
673 return img;
674 }
675
676 static __DRIimage *
677 dri2_create_image_from_winsys(__DRIscreen *_screen,
678 int width, int height, int format,
679 struct winsys_handle *whandle, int pitch,
680 void *loaderPrivate)
681 {
682 struct dri_screen *screen = dri_screen(_screen);
683 __DRIimage *img;
684 struct pipe_resource templ;
685 unsigned tex_usage;
686 enum pipe_format pf;
687
688 tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
689
690 switch (format) {
691 case __DRI_IMAGE_FORMAT_RGB565:
692 pf = PIPE_FORMAT_B5G6R5_UNORM;
693 break;
694 case __DRI_IMAGE_FORMAT_XRGB8888:
695 pf = PIPE_FORMAT_B8G8R8X8_UNORM;
696 break;
697 case __DRI_IMAGE_FORMAT_ARGB8888:
698 pf = PIPE_FORMAT_B8G8R8A8_UNORM;
699 break;
700 case __DRI_IMAGE_FORMAT_ABGR8888:
701 pf = PIPE_FORMAT_R8G8B8A8_UNORM;
702 break;
703 default:
704 pf = PIPE_FORMAT_NONE;
705 break;
706 }
707 if (pf == PIPE_FORMAT_NONE)
708 return NULL;
709
710 img = CALLOC_STRUCT(__DRIimageRec);
711 if (!img)
712 return NULL;
713
714 memset(&templ, 0, sizeof(templ));
715 templ.bind = tex_usage;
716 templ.format = pf;
717 templ.target = screen->target;
718 templ.last_level = 0;
719 templ.width0 = width;
720 templ.height0 = height;
721 templ.depth0 = 1;
722 templ.array_size = 1;
723
724 whandle->stride = pitch * util_format_get_blocksize(pf);
725
726 img->texture = screen->base.screen->resource_from_handle(screen->base.screen,
727 &templ, whandle);
728 if (!img->texture) {
729 FREE(img);
730 return NULL;
731 }
732
733 img->level = 0;
734 img->layer = 0;
735 img->dri_format = format;
736 img->loader_private = loaderPrivate;
737
738 return img;
739 }
740
741 static __DRIimage *
742 dri2_create_image_from_name(__DRIscreen *_screen,
743 int width, int height, int format,
744 int name, int pitch, void *loaderPrivate)
745 {
746 struct winsys_handle whandle;
747
748 memset(&whandle, 0, sizeof(whandle));
749 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
750 whandle.handle = name;
751
752 return dri2_create_image_from_winsys(_screen, width, height, format,
753 &whandle, pitch, loaderPrivate);
754 }
755
756 static __DRIimage *
757 dri2_create_image_from_fd(__DRIscreen *_screen,
758 int width, int height, int format,
759 int fd, int pitch, void *loaderPrivate)
760 {
761 struct winsys_handle whandle;
762
763 if (fd < 0)
764 return NULL;
765
766 memset(&whandle, 0, sizeof(whandle));
767 whandle.type = DRM_API_HANDLE_TYPE_FD;
768 whandle.handle = (unsigned)fd;
769
770 return dri2_create_image_from_winsys(_screen, width, height, format,
771 &whandle, pitch, loaderPrivate);
772 }
773
774 static __DRIimage *
775 dri2_create_image_from_renderbuffer(__DRIcontext *context,
776 int renderbuffer, void *loaderPrivate)
777 {
778 struct dri_context *ctx = dri_context(context);
779
780 if (!ctx->st->get_resource_for_egl_image)
781 return NULL;
782
783 /* TODO */
784 return NULL;
785 }
786
787 static __DRIimage *
788 dri2_create_image(__DRIscreen *_screen,
789 int width, int height, int format,
790 unsigned int use, void *loaderPrivate)
791 {
792 struct dri_screen *screen = dri_screen(_screen);
793 __DRIimage *img;
794 struct pipe_resource templ;
795 unsigned tex_usage;
796 enum pipe_format pf;
797
798 tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
799 if (use & __DRI_IMAGE_USE_SCANOUT)
800 tex_usage |= PIPE_BIND_SCANOUT;
801 if (use & __DRI_IMAGE_USE_SHARE)
802 tex_usage |= PIPE_BIND_SHARED;
803 if (use & __DRI_IMAGE_USE_LINEAR)
804 tex_usage |= PIPE_BIND_LINEAR;
805 if (use & __DRI_IMAGE_USE_CURSOR) {
806 if (width != 64 || height != 64)
807 return NULL;
808 tex_usage |= PIPE_BIND_CURSOR;
809 }
810
811 switch (format) {
812 case __DRI_IMAGE_FORMAT_RGB565:
813 pf = PIPE_FORMAT_B5G6R5_UNORM;
814 break;
815 case __DRI_IMAGE_FORMAT_XRGB8888:
816 pf = PIPE_FORMAT_B8G8R8X8_UNORM;
817 break;
818 case __DRI_IMAGE_FORMAT_ARGB8888:
819 pf = PIPE_FORMAT_B8G8R8A8_UNORM;
820 break;
821 case __DRI_IMAGE_FORMAT_ABGR8888:
822 pf = PIPE_FORMAT_R8G8B8A8_UNORM;
823 break;
824 default:
825 pf = PIPE_FORMAT_NONE;
826 break;
827 }
828 if (pf == PIPE_FORMAT_NONE)
829 return NULL;
830
831 img = CALLOC_STRUCT(__DRIimageRec);
832 if (!img)
833 return NULL;
834
835 memset(&templ, 0, sizeof(templ));
836 templ.bind = tex_usage;
837 templ.format = pf;
838 templ.target = PIPE_TEXTURE_2D;
839 templ.last_level = 0;
840 templ.width0 = width;
841 templ.height0 = height;
842 templ.depth0 = 1;
843 templ.array_size = 1;
844
845 img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
846 if (!img->texture) {
847 FREE(img);
848 return NULL;
849 }
850
851 img->level = 0;
852 img->layer = 0;
853 img->dri_format = format;
854 img->dri_components = 0;
855
856 img->loader_private = loaderPrivate;
857 return img;
858 }
859
860 static GLboolean
861 dri2_query_image(__DRIimage *image, int attrib, int *value)
862 {
863 struct winsys_handle whandle;
864 memset(&whandle, 0, sizeof(whandle));
865
866 switch (attrib) {
867 case __DRI_IMAGE_ATTRIB_STRIDE:
868 whandle.type = DRM_API_HANDLE_TYPE_KMS;
869 image->texture->screen->resource_get_handle(image->texture->screen,
870 image->texture, &whandle);
871 *value = whandle.stride;
872 return GL_TRUE;
873 case __DRI_IMAGE_ATTRIB_HANDLE:
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.handle;
878 return GL_TRUE;
879 case __DRI_IMAGE_ATTRIB_NAME:
880 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
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_FD:
886 whandle.type= DRM_API_HANDLE_TYPE_FD;
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_FORMAT:
892 *value = image->dri_format;
893 return GL_TRUE;
894 case __DRI_IMAGE_ATTRIB_WIDTH:
895 *value = image->texture->width0;
896 return GL_TRUE;
897 case __DRI_IMAGE_ATTRIB_HEIGHT:
898 *value = image->texture->height0;
899 return GL_TRUE;
900 case __DRI_IMAGE_ATTRIB_COMPONENTS:
901 if (image->dri_components == 0)
902 return GL_FALSE;
903 *value = image->dri_components;
904 return GL_TRUE;
905 default:
906 return GL_FALSE;
907 }
908 }
909
910 static __DRIimage *
911 dri2_dup_image(__DRIimage *image, void *loaderPrivate)
912 {
913 __DRIimage *img;
914
915 img = CALLOC_STRUCT(__DRIimageRec);
916 if (!img)
917 return NULL;
918
919 img->texture = NULL;
920 pipe_resource_reference(&img->texture, image->texture);
921 img->level = image->level;
922 img->layer = image->layer;
923 img->dri_format = image->dri_format;
924 /* This should be 0 for sub images, but dup is also used for base images. */
925 img->dri_components = image->dri_components;
926 img->loader_private = loaderPrivate;
927
928 return img;
929 }
930
931 static GLboolean
932 dri2_validate_usage(__DRIimage *image, unsigned int use)
933 {
934 /*
935 * Gallium drivers are bad at adding usages to the resources
936 * once opened again in another process, which is the main use
937 * case for this, so we have to lie.
938 */
939 if (image != NULL)
940 return GL_TRUE;
941 else
942 return GL_FALSE;
943 }
944
945 static __DRIimage *
946 dri2_from_names(__DRIscreen *screen, int width, int height, int format,
947 int *names, int num_names, int *strides, int *offsets,
948 void *loaderPrivate)
949 {
950 __DRIimage *img;
951 int stride, dri_components;
952
953 if (num_names != 1)
954 return NULL;
955 if (offsets[0] != 0)
956 return NULL;
957
958 format = convert_fourcc(format, &dri_components);
959 if (format == -1)
960 return NULL;
961
962 /* Strides are in bytes not pixels. */
963 stride = strides[0] /4;
964
965 img = dri2_create_image_from_name(screen, width, height, format,
966 names[0], stride, loaderPrivate);
967 if (img == NULL)
968 return NULL;
969
970 img->dri_components = dri_components;
971 return img;
972 }
973
974 static __DRIimage *
975 dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
976 {
977 __DRIimage *img;
978
979 if (plane != 0)
980 return NULL;
981
982 if (image->dri_components == 0)
983 return NULL;
984
985 img = dri2_dup_image(image, loaderPrivate);
986 if (img == NULL)
987 return NULL;
988
989 /* set this to 0 for sub images. */
990 img->dri_components = 0;
991 return img;
992 }
993
994 static __DRIimage *
995 dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
996 int depth, int level, unsigned *error,
997 void *loaderPrivate)
998 {
999 __DRIimage *img;
1000 struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
1001 struct gl_texture_object *obj;
1002 struct pipe_resource *tex;
1003 GLuint face = 0;
1004
1005 obj = _mesa_lookup_texture(ctx, texture);
1006 if (!obj || obj->Target != target) {
1007 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1008 return NULL;
1009 }
1010
1011 tex = st_get_texobj_resource(obj);
1012 if (!tex) {
1013 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1014 return NULL;
1015 }
1016
1017 if (target == GL_TEXTURE_CUBE_MAP)
1018 face = depth;
1019
1020 _mesa_test_texobj_completeness(ctx, obj);
1021 if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
1022 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1023 return NULL;
1024 }
1025
1026 if (level < obj->BaseLevel || level > obj->_MaxLevel) {
1027 *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1028 return NULL;
1029 }
1030
1031 if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
1032 *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1033 return NULL;
1034 }
1035
1036 img = CALLOC_STRUCT(__DRIimageRec);
1037 if (!img) {
1038 *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
1039 return NULL;
1040 }
1041
1042 img->level = level;
1043 img->layer = depth;
1044 img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
1045
1046 img->loader_private = loaderPrivate;
1047
1048 if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
1049 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1050 free(img);
1051 return NULL;
1052 }
1053
1054 pipe_resource_reference(&img->texture, tex);
1055
1056 *error = __DRI_IMAGE_ERROR_SUCCESS;
1057 return img;
1058 }
1059
1060 static __DRIimage *
1061 dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
1062 int *fds, int num_fds, int *strides, int *offsets,
1063 void *loaderPrivate)
1064 {
1065 __DRIimage *img;
1066 int format, stride, dri_components;
1067
1068 if (num_fds != 1)
1069 return NULL;
1070 if (offsets[0] != 0)
1071 return NULL;
1072
1073 format = convert_fourcc(fourcc, &dri_components);
1074 if (format == -1)
1075 return NULL;
1076
1077 /* Strides are in bytes not pixels. */
1078 stride = strides[0] /4;
1079
1080 img = dri2_create_image_from_fd(screen, width, height, format,
1081 fds[0], stride, loaderPrivate);
1082 if (img == NULL)
1083 return NULL;
1084
1085 img->dri_components = dri_components;
1086 return img;
1087 }
1088
1089 static __DRIimage *
1090 dri2_from_dma_bufs(__DRIscreen *screen,
1091 int width, int height, int fourcc,
1092 int *fds, int num_fds,
1093 int *strides, int *offsets,
1094 enum __DRIYUVColorSpace yuv_color_space,
1095 enum __DRISampleRange sample_range,
1096 enum __DRIChromaSiting horizontal_siting,
1097 enum __DRIChromaSiting vertical_siting,
1098 unsigned *error,
1099 void *loaderPrivate)
1100 {
1101 __DRIimage *img;
1102 int format, stride, dri_components;
1103
1104 if (num_fds != 1 || offsets[0] != 0) {
1105 *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1106 return NULL;
1107 }
1108
1109 format = convert_fourcc(fourcc, &dri_components);
1110 if (format == -1) {
1111 *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1112 return NULL;
1113 }
1114
1115 /* Strides are in bytes not pixels. */
1116 stride = strides[0] /4;
1117
1118 img = dri2_create_image_from_fd(screen, width, height, format,
1119 fds[0], stride, loaderPrivate);
1120 if (img == NULL) {
1121 *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
1122 return NULL;
1123 }
1124
1125 img->yuv_color_space = yuv_color_space;
1126 img->sample_range = sample_range;
1127 img->horizontal_siting = horizontal_siting;
1128 img->vertical_siting = vertical_siting;
1129 img->dri_components = dri_components;
1130
1131 *error = __DRI_IMAGE_ERROR_SUCCESS;
1132 return img;
1133 }
1134
1135 static void
1136 dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
1137 int dstx0, int dsty0, int dstwidth, int dstheight,
1138 int srcx0, int srcy0, int srcwidth, int srcheight,
1139 int flush_flag)
1140 {
1141 struct dri_context *ctx = dri_context(context);
1142 struct pipe_context *pipe = ctx->st->pipe;
1143 struct pipe_screen *screen;
1144 struct pipe_fence_handle *fence;
1145 struct pipe_blit_info blit;
1146
1147 if (!dst || !src)
1148 return;
1149
1150 memset(&blit, 0, sizeof(blit));
1151 blit.dst.resource = dst->texture;
1152 blit.dst.box.x = dstx0;
1153 blit.dst.box.y = dsty0;
1154 blit.dst.box.width = dstwidth;
1155 blit.dst.box.height = dstheight;
1156 blit.dst.box.depth = 1;
1157 blit.dst.format = dst->texture->format;
1158 blit.src.resource = src->texture;
1159 blit.src.box.x = srcx0;
1160 blit.src.box.y = srcy0;
1161 blit.src.box.width = srcwidth;
1162 blit.src.box.height = srcheight;
1163 blit.src.box.depth = 1;
1164 blit.src.format = src->texture->format;
1165 blit.mask = PIPE_MASK_RGBA;
1166 blit.filter = PIPE_TEX_FILTER_NEAREST;
1167
1168 pipe->blit(pipe, &blit);
1169
1170 if (flush_flag == __BLIT_FLAG_FLUSH) {
1171 pipe->flush_resource(pipe, dst->texture);
1172 ctx->st->flush(ctx->st, 0, NULL);
1173 } else if (flush_flag == __BLIT_FLAG_FINISH) {
1174 screen = dri_screen(ctx->sPriv)->base.screen;
1175 pipe->flush_resource(pipe, dst->texture);
1176 ctx->st->flush(ctx->st, 0, &fence);
1177 (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
1178 screen->fence_reference(screen, &fence, NULL);
1179 }
1180 }
1181
1182 static void
1183 dri2_destroy_image(__DRIimage *img)
1184 {
1185 pipe_resource_reference(&img->texture, NULL);
1186 FREE(img);
1187 }
1188
1189 /* The extension is modified during runtime if DRI_PRIME is detected */
1190 static __DRIimageExtension dri2ImageExtension = {
1191 .base = { __DRI_IMAGE, 9 },
1192
1193 .createImageFromName = dri2_create_image_from_name,
1194 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
1195 .destroyImage = dri2_destroy_image,
1196 .createImage = dri2_create_image,
1197 .queryImage = dri2_query_image,
1198 .dupImage = dri2_dup_image,
1199 .validateUsage = dri2_validate_usage,
1200 .createImageFromNames = dri2_from_names,
1201 .fromPlanar = dri2_from_planar,
1202 .createImageFromTexture = dri2_create_from_texture,
1203 .createImageFromFds = NULL,
1204 .createImageFromDmaBufs = NULL,
1205 .blitImage = dri2_blit_image,
1206 };
1207
1208 /*
1209 * Backend function init_screen.
1210 */
1211
1212 static const __DRIextension *dri_screen_extensions[] = {
1213 &driTexBufferExtension.base,
1214 &dri2FlushExtension.base,
1215 &dri2ImageExtension.base,
1216 &dri2ConfigQueryExtension.base,
1217 &dri2ThrottleExtension.base,
1218 NULL
1219 };
1220
1221 /**
1222 * This is the driver specific part of the createNewScreen entry point.
1223 *
1224 * Returns the struct gl_config supported by this driver.
1225 */
1226 static const __DRIconfig **
1227 dri2_init_screen(__DRIscreen * sPriv)
1228 {
1229 const __DRIconfig **configs;
1230 struct dri_screen *screen;
1231 struct pipe_screen *pscreen = NULL;
1232 const struct drm_conf_ret *throttle_ret = NULL;
1233 const struct drm_conf_ret *dmabuf_ret = NULL;
1234
1235 screen = CALLOC_STRUCT(dri_screen);
1236 if (!screen)
1237 return NULL;
1238
1239 screen->sPriv = sPriv;
1240 screen->fd = sPriv->fd;
1241
1242 sPriv->driverPrivate = (void *)screen;
1243
1244 #if GALLIUM_STATIC_TARGETS
1245 pscreen = dd_create_screen(screen->fd);
1246
1247 throttle_ret = dd_configuration(DRM_CONF_THROTTLE);
1248 dmabuf_ret = dd_configuration(DRM_CONF_SHARE_FD);
1249 #else
1250 if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd, true)) {
1251 pscreen = pipe_loader_create_screen(screen->dev, PIPE_SEARCH_DIR);
1252
1253 throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE);
1254 dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD);
1255 }
1256 #endif // GALLIUM_STATIC_TARGETS
1257
1258 if (throttle_ret && throttle_ret->val.val_int != -1) {
1259 screen->throttling_enabled = TRUE;
1260 screen->default_throttle_frames = throttle_ret->val.val_int;
1261 }
1262
1263 if (dmabuf_ret && dmabuf_ret->val.val_bool) {
1264 uint64_t cap;
1265
1266 if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
1267 (cap & DRM_PRIME_CAP_IMPORT)) {
1268 dri2ImageExtension.createImageFromFds = dri2_from_fds;
1269 dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
1270 }
1271 }
1272
1273 sPriv->extensions = dri_screen_extensions;
1274
1275 /* dri_init_screen_helper checks pscreen for us */
1276
1277 #if GALLIUM_STATIC_TARGETS
1278 configs = dri_init_screen_helper(screen, pscreen, dd_driver_name());
1279 #else
1280 configs = dri_init_screen_helper(screen, pscreen, screen->dev->driver_name);
1281 #endif // GALLIUM_STATIC_TARGETS
1282 if (!configs)
1283 goto fail;
1284
1285 screen->auto_fake_front = dri_with_format(sPriv);
1286 screen->broken_invalidate = !sPriv->dri2.useInvalidate;
1287 screen->lookup_egl_image = dri2_lookup_egl_image;
1288
1289 return configs;
1290 fail:
1291 dri_destroy_screen_helper(screen);
1292 #if !GALLIUM_STATIC_TARGETS
1293 if (screen->dev)
1294 pipe_loader_release(&screen->dev, 1);
1295 #endif // !GALLIUM_STATIC_TARGETS
1296 FREE(screen);
1297 return NULL;
1298 }
1299
1300 static boolean
1301 dri2_create_buffer(__DRIscreen * sPriv,
1302 __DRIdrawable * dPriv,
1303 const struct gl_config * visual, boolean isPixmap)
1304 {
1305 struct dri_drawable *drawable = NULL;
1306
1307 if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
1308 return FALSE;
1309
1310 drawable = dPriv->driverPrivate;
1311
1312 drawable->allocate_textures = dri2_allocate_textures;
1313 drawable->flush_frontbuffer = dri2_flush_frontbuffer;
1314 drawable->update_tex_buffer = dri2_update_tex_buffer;
1315
1316 return TRUE;
1317 }
1318
1319 /**
1320 * DRI driver virtual function table.
1321 *
1322 * DRI versions differ in their implementation of init_screen and swap_buffers.
1323 */
1324 const struct __DriverAPIRec galliumdrm_driver_api = {
1325 .InitScreen = dri2_init_screen,
1326 .DestroyScreen = dri_destroy_screen,
1327 .CreateContext = dri_create_context,
1328 .DestroyContext = dri_destroy_context,
1329 .CreateBuffer = dri2_create_buffer,
1330 .DestroyBuffer = dri_destroy_buffer,
1331 .MakeCurrent = dri_make_current,
1332 .UnbindContext = dri_unbind_context,
1333
1334 .AllocateBuffer = dri2_allocate_buffer,
1335 .ReleaseBuffer = dri2_release_buffer,
1336 };
1337
1338 /* This is the table of extensions that the loader will dlsym() for. */
1339 const __DRIextension *galliumdrm_driver_extensions[] = {
1340 &driCoreExtension.base,
1341 &driImageDriverExtension.base,
1342 &driDRI2Extension.base,
1343 &gallium_config_options.base,
1344 NULL
1345 };
1346
1347 /* vim: set sw=3 ts=8 sts=3 expandtab: */