2 * Mesa 3-D graphics library
5 * Copyright 2009, VMware, Inc.
7 * Copyright (C) 2010 LunarG Inc.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Keith Whitwell <keithw@vmware.com>
28 * Jakob Bornecrantz <wallbraker@gmail.com>
29 * Chia-I Wu <olv@lunarg.com>
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"
38 #include "dri_screen.h"
39 #include "dri_context.h"
40 #include "dri_drawable.h"
41 #include "dri2_buffer.h"
44 * DRI2 flush extension.
47 dri2_flush_drawable(__DRIdrawable
*draw
)
52 dri2_invalidate_drawable(__DRIdrawable
*dPriv
)
54 struct dri_drawable
*drawable
= dri_drawable(dPriv
);
55 struct dri_context
*ctx
= drawable
->context
;
57 dri2InvalidateDrawable(dPriv
);
58 drawable
->dPriv
->lastStamp
= *drawable
->dPriv
->pStamp
;
61 ctx
->st
->notify_invalid_framebuffer(ctx
->st
, &drawable
->base
);
64 static const __DRI2flushExtension dri2FlushExtension
= {
65 { __DRI2_FLUSH
, __DRI2_FLUSH_VERSION
},
67 dri2_invalidate_drawable
,
71 * Retrieve __DRIbuffer from the DRI loader.
74 dri2_drawable_get_buffers(struct dri_drawable
*drawable
,
75 const enum st_attachment_type
*statts
,
78 __DRIdrawable
*dri_drawable
= drawable
->dPriv
;
79 struct __DRIdri2LoaderExtensionRec
*loader
= drawable
->sPriv
->dri2
.loader
;
83 unsigned attachments
[10];
84 unsigned num_attachments
, i
;
87 with_format
= dri_with_format(drawable
->sPriv
);
91 /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
93 attachments
[num_attachments
++] = __DRI_BUFFER_FRONT_LEFT
;
95 for (i
= 0; i
< *count
; i
++) {
96 enum pipe_format format
;
100 dri_drawable_get_format(drawable
, statts
[i
], &format
, &bind
);
101 if (format
== PIPE_FORMAT_NONE
)
105 case ST_ATTACHMENT_FRONT_LEFT
:
109 att
= __DRI_BUFFER_FRONT_LEFT
;
111 case ST_ATTACHMENT_BACK_LEFT
:
112 att
= __DRI_BUFFER_BACK_LEFT
;
114 case ST_ATTACHMENT_FRONT_RIGHT
:
115 att
= __DRI_BUFFER_FRONT_RIGHT
;
117 case ST_ATTACHMENT_BACK_RIGHT
:
118 att
= __DRI_BUFFER_BACK_RIGHT
;
120 case ST_ATTACHMENT_DEPTH_STENCIL
:
121 att
= __DRI_BUFFER_DEPTH_STENCIL
;
128 bpp
= util_format_get_blocksizebits(format
);
131 attachments
[num_attachments
++] = att
;
133 attachments
[num_attachments
++] = bpp
;
139 num_attachments
/= 2;
140 buffers
= loader
->getBuffersWithFormat(dri_drawable
,
141 &dri_drawable
->w
, &dri_drawable
->h
,
142 attachments
, num_attachments
,
143 &num_buffers
, dri_drawable
->loaderPrivate
);
146 buffers
= loader
->getBuffers(dri_drawable
,
147 &dri_drawable
->w
, &dri_drawable
->h
,
148 attachments
, num_attachments
,
149 &num_buffers
, dri_drawable
->loaderPrivate
);
153 /* set one cliprect to cover the whole dri_drawable */
156 dri_drawable
->backX
= 0;
157 dri_drawable
->backY
= 0;
158 dri_drawable
->numClipRects
= 1;
159 dri_drawable
->pClipRects
[0].x1
= 0;
160 dri_drawable
->pClipRects
[0].y1
= 0;
161 dri_drawable
->pClipRects
[0].x2
= dri_drawable
->w
;
162 dri_drawable
->pClipRects
[0].y2
= dri_drawable
->h
;
163 dri_drawable
->numBackClipRects
= 1;
164 dri_drawable
->pBackClipRects
[0].x1
= 0;
165 dri_drawable
->pBackClipRects
[0].y1
= 0;
166 dri_drawable
->pBackClipRects
[0].x2
= dri_drawable
->w
;
167 dri_drawable
->pBackClipRects
[0].y2
= dri_drawable
->h
;
169 *count
= num_buffers
;
176 * Process __DRIbuffer and convert them into pipe_resources.
179 dri2_drawable_process_buffers(struct dri_drawable
*drawable
,
180 __DRIbuffer
*buffers
, unsigned count
)
182 struct dri_screen
*screen
= dri_screen(drawable
->sPriv
);
183 __DRIdrawable
*dri_drawable
= drawable
->dPriv
;
184 struct pipe_resource templ
;
185 struct winsys_handle whandle
;
186 boolean have_depth
= FALSE
;
189 if (drawable
->old_num
== count
&&
190 drawable
->old_w
== dri_drawable
->w
&&
191 drawable
->old_h
== dri_drawable
->h
&&
192 memcmp(drawable
->old
, buffers
, sizeof(__DRIbuffer
) * count
) == 0)
195 for (i
= 0; i
< ST_ATTACHMENT_COUNT
; i
++)
196 pipe_resource_reference(&drawable
->textures
[i
], NULL
);
198 memset(&templ
, 0, sizeof(templ
));
199 templ
.target
= screen
->target
;
200 templ
.last_level
= 0;
201 templ
.width0
= dri_drawable
->w
;
202 templ
.height0
= dri_drawable
->h
;
204 templ
.array_size
= 1;
206 memset(&whandle
, 0, sizeof(whandle
));
208 for (i
= 0; i
< count
; i
++) {
209 __DRIbuffer
*buf
= &buffers
[i
];
210 enum st_attachment_type statt
;
211 enum pipe_format format
;
213 switch (buf
->attachment
) {
214 case __DRI_BUFFER_FRONT_LEFT
:
215 if (!screen
->auto_fake_front
) {
216 statt
= ST_ATTACHMENT_INVALID
;
220 case __DRI_BUFFER_FAKE_FRONT_LEFT
:
221 statt
= ST_ATTACHMENT_FRONT_LEFT
;
223 case __DRI_BUFFER_BACK_LEFT
:
224 statt
= ST_ATTACHMENT_BACK_LEFT
;
226 case __DRI_BUFFER_DEPTH
:
227 case __DRI_BUFFER_DEPTH_STENCIL
:
228 case __DRI_BUFFER_STENCIL
:
229 /* use only the first depth/stencil buffer */
232 statt
= ST_ATTACHMENT_DEPTH_STENCIL
;
235 statt
= ST_ATTACHMENT_INVALID
;
239 statt
= ST_ATTACHMENT_INVALID
;
243 dri_drawable_get_format(drawable
, statt
, &format
, &bind
);
244 if (statt
== ST_ATTACHMENT_INVALID
|| format
== PIPE_FORMAT_NONE
)
247 templ
.format
= format
;
249 whandle
.handle
= buf
->name
;
250 whandle
.stride
= buf
->pitch
;
252 drawable
->textures
[statt
] =
253 screen
->base
.screen
->resource_from_handle(screen
->base
.screen
,
257 drawable
->old_num
= count
;
258 drawable
->old_w
= dri_drawable
->w
;
259 drawable
->old_h
= dri_drawable
->h
;
260 memcpy(drawable
->old
, buffers
, sizeof(__DRIbuffer
) * count
);
264 dri2_allocate_buffer(__DRIscreen
*sPriv
,
265 unsigned attachment
, unsigned format
,
266 int width
, int height
)
268 struct dri_screen
*screen
= dri_screen(sPriv
);
269 struct dri2_buffer
*buffer
;
270 struct pipe_resource templ
;
271 enum st_attachment_type statt
;
274 struct winsys_handle whandle
;
276 switch (attachment
) {
277 case __DRI_BUFFER_FRONT_LEFT
:
278 case __DRI_BUFFER_FAKE_FRONT_LEFT
:
279 statt
= ST_ATTACHMENT_FRONT_LEFT
;
280 bind
= PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
;
282 case __DRI_BUFFER_BACK_LEFT
:
283 statt
= ST_ATTACHMENT_BACK_LEFT
;
284 bind
= PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
;
286 case __DRI_BUFFER_DEPTH
:
287 case __DRI_BUFFER_DEPTH_STENCIL
:
288 case __DRI_BUFFER_STENCIL
:
289 statt
= ST_ATTACHMENT_DEPTH_STENCIL
;
290 bind
= PIPE_BIND_DEPTH_STENCIL
; /* XXX sampler? */
293 statt
= ST_ATTACHMENT_INVALID
;
299 pf
= PIPE_FORMAT_B8G8R8X8_UNORM
;
302 pf
= PIPE_FORMAT_Z16_UNORM
;
308 buffer
= CALLOC_STRUCT(dri2_buffer
);
312 memset(&templ
, 0, sizeof(templ
));
315 templ
.target
= PIPE_TEXTURE_2D
;
316 templ
.last_level
= 0;
317 templ
.width0
= width
;
318 templ
.height0
= height
;
320 templ
.array_size
= 1;
323 screen
->base
.screen
->resource_create(screen
->base
.screen
, &templ
);
324 if (!buffer
->resource
)
327 memset(&whandle
, 0, sizeof(whandle
));
328 whandle
.type
= DRM_API_HANDLE_TYPE_SHARED
;
329 screen
->base
.screen
->resource_get_handle(screen
->base
.screen
,
330 buffer
->resource
, &whandle
);
332 buffer
->base
.attachment
= attachment
;
333 buffer
->base
.name
= whandle
.handle
;
334 buffer
->base
.cpp
= util_format_get_blocksize(pf
);
335 buffer
->base
.pitch
= whandle
.stride
;
337 return &buffer
->base
;
341 dri2_release_buffer(__DRIscreen
*sPriv
, __DRIbuffer
*bPriv
)
343 struct dri2_buffer
*buffer
= dri2_buffer(bPriv
);
345 pipe_resource_reference(&buffer
->resource
, NULL
);
350 * Backend functions for st_framebuffer interface.
354 dri2_allocate_textures(struct dri_drawable
*drawable
,
355 const enum st_attachment_type
*statts
,
358 __DRIbuffer
*buffers
;
359 unsigned num_buffers
= count
;
361 buffers
= dri2_drawable_get_buffers(drawable
, statts
, &num_buffers
);
363 dri2_drawable_process_buffers(drawable
, buffers
, num_buffers
);
367 dri2_flush_frontbuffer(struct dri_drawable
*drawable
,
368 enum st_attachment_type statt
)
370 __DRIdrawable
*dri_drawable
= drawable
->dPriv
;
371 struct __DRIdri2LoaderExtensionRec
*loader
= drawable
->sPriv
->dri2
.loader
;
373 if (loader
->flushFrontBuffer
== NULL
)
376 if (statt
== ST_ATTACHMENT_FRONT_LEFT
) {
377 loader
->flushFrontBuffer(dri_drawable
, dri_drawable
->loaderPrivate
);
382 dri2_lookup_egl_image(struct dri_screen
*screen
, void *handle
)
384 __DRIimageLookupExtension
*loader
= screen
->sPriv
->dri2
.image
;
387 if (!loader
->lookupEGLImage
)
390 img
= loader
->lookupEGLImage(screen
->sPriv
,
391 handle
, screen
->sPriv
->loaderPrivate
);
397 dri2_create_image_from_name(__DRIscreen
*_screen
,
398 int width
, int height
, int format
,
399 int name
, int pitch
, void *loaderPrivate
)
401 struct dri_screen
*screen
= dri_screen(_screen
);
403 struct pipe_resource templ
;
404 struct winsys_handle whandle
;
408 tex_usage
= PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
;
411 case __DRI_IMAGE_FORMAT_RGB565
:
412 pf
= PIPE_FORMAT_B5G6R5_UNORM
;
414 case __DRI_IMAGE_FORMAT_XRGB8888
:
415 pf
= PIPE_FORMAT_B8G8R8X8_UNORM
;
417 case __DRI_IMAGE_FORMAT_ARGB8888
:
418 pf
= PIPE_FORMAT_B8G8R8A8_UNORM
;
421 pf
= PIPE_FORMAT_NONE
;
424 if (pf
== PIPE_FORMAT_NONE
)
427 img
= CALLOC_STRUCT(__DRIimageRec
);
431 memset(&templ
, 0, sizeof(templ
));
432 templ
.bind
= tex_usage
;
434 templ
.target
= screen
->target
;
435 templ
.last_level
= 0;
436 templ
.width0
= width
;
437 templ
.height0
= height
;
439 templ
.array_size
= 1;
441 memset(&whandle
, 0, sizeof(whandle
));
442 whandle
.handle
= name
;
443 whandle
.stride
= pitch
* util_format_get_blocksize(pf
);
445 img
->texture
= screen
->base
.screen
->resource_from_handle(screen
->base
.screen
,
454 img
->loader_private
= loaderPrivate
;
460 dri2_create_image_from_renderbuffer(__DRIcontext
*context
,
461 int renderbuffer
, void *loaderPrivate
)
463 struct dri_context
*ctx
= dri_context(context
);
465 if (!ctx
->st
->get_resource_for_egl_image
)
473 dri2_create_image(__DRIscreen
*_screen
,
474 int width
, int height
, int format
,
475 unsigned int use
, void *loaderPrivate
)
477 struct dri_screen
*screen
= dri_screen(_screen
);
479 struct pipe_resource templ
;
483 tex_usage
= PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
;
484 if (use
& __DRI_IMAGE_USE_SCANOUT
)
485 tex_usage
|= PIPE_BIND_SCANOUT
;
486 if (use
& __DRI_IMAGE_USE_SHARE
)
487 tex_usage
|= PIPE_BIND_SHARED
;
488 if (use
& __DRI_IMAGE_USE_CURSOR
) {
489 if (width
!= 64 || height
!= 64)
491 tex_usage
|= PIPE_BIND_CURSOR
;
495 case __DRI_IMAGE_FORMAT_RGB565
:
496 pf
= PIPE_FORMAT_B5G6R5_UNORM
;
498 case __DRI_IMAGE_FORMAT_XRGB8888
:
499 pf
= PIPE_FORMAT_B8G8R8X8_UNORM
;
501 case __DRI_IMAGE_FORMAT_ARGB8888
:
502 pf
= PIPE_FORMAT_B8G8R8A8_UNORM
;
505 pf
= PIPE_FORMAT_NONE
;
508 if (pf
== PIPE_FORMAT_NONE
)
511 img
= CALLOC_STRUCT(__DRIimageRec
);
515 memset(&templ
, 0, sizeof(templ
));
516 templ
.bind
= tex_usage
;
518 templ
.target
= PIPE_TEXTURE_2D
;
519 templ
.last_level
= 0;
520 templ
.width0
= width
;
521 templ
.height0
= height
;
523 templ
.array_size
= 1;
525 img
->texture
= screen
->base
.screen
->resource_create(screen
->base
.screen
, &templ
);
534 img
->loader_private
= loaderPrivate
;
539 dri2_query_image(__DRIimage
*image
, int attrib
, int *value
)
541 struct winsys_handle whandle
;
542 memset(&whandle
, 0, sizeof(whandle
));
545 case __DRI_IMAGE_ATTRIB_STRIDE
:
546 image
->texture
->screen
->resource_get_handle(image
->texture
->screen
,
547 image
->texture
, &whandle
);
548 *value
= whandle
.stride
;
550 case __DRI_IMAGE_ATTRIB_HANDLE
:
551 whandle
.type
= DRM_API_HANDLE_TYPE_KMS
;
552 image
->texture
->screen
->resource_get_handle(image
->texture
->screen
,
553 image
->texture
, &whandle
);
554 *value
= whandle
.handle
;
556 case __DRI_IMAGE_ATTRIB_NAME
:
557 whandle
.type
= DRM_API_HANDLE_TYPE_SHARED
;
558 image
->texture
->screen
->resource_get_handle(image
->texture
->screen
,
559 image
->texture
, &whandle
);
560 *value
= whandle
.handle
;
568 dri2_dup_image(__DRIimage
*image
, void *loaderPrivate
)
572 img
= CALLOC_STRUCT(__DRIimageRec
);
577 pipe_resource_reference(&img
->texture
, image
->texture
);
578 img
->level
= image
->level
;
579 img
->layer
= image
->layer
;
580 img
->loader_private
= loaderPrivate
;
586 dri2_destroy_image(__DRIimage
*img
)
588 pipe_resource_reference(&img
->texture
, NULL
);
592 static struct __DRIimageExtensionRec dri2ImageExtension
= {
593 { __DRI_IMAGE
, __DRI_IMAGE_VERSION
},
594 dri2_create_image_from_name
,
595 dri2_create_image_from_renderbuffer
,
603 * Backend function init_screen.
606 static const __DRIextension
*dri_screen_extensions
[] = {
607 &driReadDrawableExtension
,
608 &driCopySubBufferExtension
.base
,
609 &driSwapControlExtension
.base
,
610 &driMediaStreamCounterExtension
.base
,
611 &driTexBufferExtension
.base
,
612 &dri2FlushExtension
.base
,
613 &dri2ImageExtension
.base
,
614 &dri2ConfigQueryExtension
.base
,
619 * This is the driver specific part of the createNewScreen entry point.
621 * Returns the struct gl_config supported by this driver.
623 static const __DRIconfig
**
624 dri2_init_screen(__DRIscreen
* sPriv
)
626 const __DRIconfig
**configs
;
627 struct dri_screen
*screen
;
628 struct pipe_screen
*pscreen
;
630 screen
= CALLOC_STRUCT(dri_screen
);
634 screen
->sPriv
= sPriv
;
635 screen
->fd
= sPriv
->fd
;
637 sPriv
->private = (void *)screen
;
638 sPriv
->extensions
= dri_screen_extensions
;
640 pscreen
= driver_descriptor
.create_screen(screen
->fd
);
641 /* dri_init_screen_helper checks pscreen for us */
643 configs
= dri_init_screen_helper(screen
, pscreen
, 32);
648 if (screen
->st_api
->profile_mask
& ST_PROFILE_DEFAULT_MASK
)
649 sPriv
->api_mask
|= 1 << __DRI_API_OPENGL
;
650 if (screen
->st_api
->profile_mask
& ST_PROFILE_OPENGL_ES1_MASK
)
651 sPriv
->api_mask
|= 1 << __DRI_API_GLES
;
652 if (screen
->st_api
->profile_mask
& ST_PROFILE_OPENGL_ES2_MASK
)
653 sPriv
->api_mask
|= 1 << __DRI_API_GLES2
;
655 screen
->auto_fake_front
= dri_with_format(sPriv
);
656 screen
->broken_invalidate
= !sPriv
->dri2
.useInvalidate
;
657 screen
->lookup_egl_image
= dri2_lookup_egl_image
;
661 dri_destroy_screen_helper(screen
);
667 dri2_create_context(gl_api api
, const struct gl_config
* visual
,
668 __DRIcontext
* cPriv
, void *sharedContextPrivate
)
670 struct dri_context
*ctx
= NULL
;
672 if (!dri_create_context(api
, visual
, cPriv
, sharedContextPrivate
))
675 ctx
= cPriv
->driverPrivate
;
681 dri2_create_buffer(__DRIscreen
* sPriv
,
682 __DRIdrawable
* dPriv
,
683 const struct gl_config
* visual
, boolean isPixmap
)
685 struct dri_drawable
*drawable
= NULL
;
687 if (!dri_create_buffer(sPriv
, dPriv
, visual
, isPixmap
))
690 drawable
= dPriv
->driverPrivate
;
692 drawable
->allocate_textures
= dri2_allocate_textures
;
693 drawable
->flush_frontbuffer
= dri2_flush_frontbuffer
;
699 * DRI driver virtual function table.
701 * DRI versions differ in their implementation of init_screen and swap_buffers.
703 const struct __DriverAPIRec driDriverAPI
= {
705 .InitScreen2
= dri2_init_screen
,
706 .DestroyScreen
= dri_destroy_screen
,
707 .CreateContext
= dri2_create_context
,
708 .DestroyContext
= dri_destroy_context
,
709 .CreateBuffer
= dri2_create_buffer
,
710 .DestroyBuffer
= dri_destroy_buffer
,
711 .MakeCurrent
= dri_make_current
,
712 .UnbindContext
= dri_unbind_context
,
715 .GetDrawableMSC
= NULL
,
719 .CopySubBuffer
= NULL
,
721 .AllocateBuffer
= dri2_allocate_buffer
,
722 .ReleaseBuffer
= dri2_release_buffer
,
725 /* This is the table of extensions that the loader will dlsym() for. */
726 PUBLIC
const __DRIextension
*__driDriverExtensions
[] = {
727 &driCoreExtension
.base
,
728 &driLegacyExtension
.base
,
729 &driDRI2Extension
.base
,
733 /* vim: set sw=3 ts=8 sts=3 expandtab: */