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_api.h"
38 #include "dri_screen.h"
39 #include "dri_context.h"
40 #include "dri_drawable.h"
43 #include "GL/internal/dri_interface.h"
46 * DRI2 flush extension.
49 dri2_flush_drawable(__DRIdrawable
*draw
)
54 dri2_invalidate_drawable(__DRIdrawable
*dPriv
)
56 struct dri_drawable
*drawable
= dri_drawable(dPriv
);
57 struct dri_context
*ctx
= dri_context(dPriv
->driContextPriv
);
59 dri2InvalidateDrawable(dPriv
);
60 drawable
->dPriv
->lastStamp
= *drawable
->dPriv
->pStamp
;
63 ctx
->st
->notify_invalid_framebuffer(ctx
->st
, &drawable
->base
);
66 static const __DRI2flushExtension dri2FlushExtension
= {
67 { __DRI2_FLUSH
, __DRI2_FLUSH_VERSION
},
69 dri2_invalidate_drawable
,
73 * These are used for GLX_EXT_texture_from_pixmap
76 dri2_set_tex_buffer2(__DRIcontext
*pDRICtx
, GLint target
,
77 GLint format
, __DRIdrawable
*dPriv
)
79 struct dri_context
*ctx
= dri_context(pDRICtx
);
80 struct dri_drawable
*drawable
= dri_drawable(dPriv
);
81 struct pipe_resource
*pt
;
83 dri_drawable_validate_att(drawable
, ST_ATTACHMENT_FRONT_LEFT
);
85 pt
= drawable
->textures
[ST_ATTACHMENT_FRONT_LEFT
];
88 enum pipe_format internal_format
= pt
->format
;
90 if (format
== __DRI_TEXTURE_FORMAT_RGB
) {
91 /* only need to cover the formats recognized by dri_fill_st_visual */
92 switch (internal_format
) {
93 case PIPE_FORMAT_B8G8R8A8_UNORM
:
94 internal_format
= PIPE_FORMAT_B8G8R8X8_UNORM
;
96 case PIPE_FORMAT_A8R8G8B8_UNORM
:
97 internal_format
= PIPE_FORMAT_X8R8G8B8_UNORM
;
104 ctx
->st
->teximage(ctx
->st
,
105 (target
== GL_TEXTURE_2D
) ? ST_TEXTURE_2D
: ST_TEXTURE_RECT
,
106 0, internal_format
, pt
, FALSE
);
111 dri2_set_tex_buffer(__DRIcontext
*pDRICtx
, GLint target
,
112 __DRIdrawable
*dPriv
)
114 dri2_set_tex_buffer2(pDRICtx
, target
, __DRI_TEXTURE_FORMAT_RGBA
, dPriv
);
117 static const __DRItexBufferExtension dri2TexBufferExtension
= {
118 { __DRI_TEX_BUFFER
, __DRI_TEX_BUFFER_VERSION
},
120 dri2_set_tex_buffer2
,
124 * Get the format and binding of an attachment.
127 dri2_drawable_get_format(struct dri_drawable
*drawable
,
128 enum st_attachment_type statt
,
129 enum pipe_format
*format
,
133 case ST_ATTACHMENT_FRONT_LEFT
:
134 case ST_ATTACHMENT_BACK_LEFT
:
135 case ST_ATTACHMENT_FRONT_RIGHT
:
136 case ST_ATTACHMENT_BACK_RIGHT
:
137 *format
= drawable
->stvis
.color_format
;
138 *bind
= PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
;
140 case ST_ATTACHMENT_DEPTH_STENCIL
:
141 *format
= drawable
->stvis
.depth_stencil_format
;
142 *bind
= PIPE_BIND_DEPTH_STENCIL
; /* XXX sampler? */
145 *format
= PIPE_FORMAT_NONE
;
153 * Retrieve __DRIbuffer from the DRI loader.
156 dri2_drawable_get_buffers(struct dri_drawable
*drawable
,
157 const enum st_attachment_type
*statts
,
160 __DRIdrawable
*dri_drawable
= drawable
->dPriv
;
161 struct __DRIdri2LoaderExtensionRec
*loader
= drawable
->sPriv
->dri2
.loader
;
163 __DRIbuffer
*buffers
;
165 unsigned attachments
[10];
166 unsigned num_attachments
, i
;
169 with_format
= dri_with_format(drawable
->sPriv
);
173 /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
175 attachments
[num_attachments
++] = __DRI_BUFFER_FRONT_LEFT
;
177 for (i
= 0; i
< *count
; i
++) {
178 enum pipe_format format
;
182 dri2_drawable_get_format(drawable
, statts
[i
], &format
, &bind
);
183 if (format
== PIPE_FORMAT_NONE
)
187 case ST_ATTACHMENT_FRONT_LEFT
:
191 att
= __DRI_BUFFER_FRONT_LEFT
;
193 case ST_ATTACHMENT_BACK_LEFT
:
194 att
= __DRI_BUFFER_BACK_LEFT
;
196 case ST_ATTACHMENT_FRONT_RIGHT
:
197 att
= __DRI_BUFFER_FRONT_RIGHT
;
199 case ST_ATTACHMENT_BACK_RIGHT
:
200 att
= __DRI_BUFFER_BACK_RIGHT
;
202 case ST_ATTACHMENT_DEPTH_STENCIL
:
203 att
= __DRI_BUFFER_DEPTH_STENCIL
;
210 bpp
= util_format_get_blocksizebits(format
);
213 attachments
[num_attachments
++] = att
;
215 attachments
[num_attachments
++] = bpp
;
221 num_attachments
/= 2;
222 buffers
= loader
->getBuffersWithFormat(dri_drawable
,
223 &dri_drawable
->w
, &dri_drawable
->h
,
224 attachments
, num_attachments
,
225 &num_buffers
, dri_drawable
->loaderPrivate
);
228 buffers
= loader
->getBuffers(dri_drawable
,
229 &dri_drawable
->w
, &dri_drawable
->h
,
230 attachments
, num_attachments
,
231 &num_buffers
, dri_drawable
->loaderPrivate
);
235 /* set one cliprect to cover the whole dri_drawable */
238 dri_drawable
->backX
= 0;
239 dri_drawable
->backY
= 0;
240 dri_drawable
->numClipRects
= 1;
241 dri_drawable
->pClipRects
[0].x1
= 0;
242 dri_drawable
->pClipRects
[0].y1
= 0;
243 dri_drawable
->pClipRects
[0].x2
= dri_drawable
->w
;
244 dri_drawable
->pClipRects
[0].y2
= dri_drawable
->h
;
245 dri_drawable
->numBackClipRects
= 1;
246 dri_drawable
->pBackClipRects
[0].x1
= 0;
247 dri_drawable
->pBackClipRects
[0].y1
= 0;
248 dri_drawable
->pBackClipRects
[0].x2
= dri_drawable
->w
;
249 dri_drawable
->pBackClipRects
[0].y2
= dri_drawable
->h
;
251 *count
= num_buffers
;
258 * Process __DRIbuffer and convert them into pipe_resources.
261 dri2_drawable_process_buffers(struct dri_drawable
*drawable
,
262 __DRIbuffer
*buffers
, unsigned count
)
264 struct dri_screen
*screen
= dri_screen(drawable
->sPriv
);
265 __DRIdrawable
*dri_drawable
= drawable
->dPriv
;
266 struct pipe_resource templ
;
267 struct winsys_handle whandle
;
268 boolean have_depth
= FALSE
;
271 if (drawable
->old_num
== count
&&
272 drawable
->old_w
== dri_drawable
->w
&&
273 drawable
->old_h
== dri_drawable
->h
&&
274 memcmp(drawable
->old
, buffers
, sizeof(__DRIbuffer
) * count
) == 0)
277 for (i
= 0; i
< ST_ATTACHMENT_COUNT
; i
++)
278 pipe_resource_reference(&drawable
->textures
[i
], NULL
);
280 memset(&templ
, 0, sizeof(templ
));
281 templ
.target
= PIPE_TEXTURE_2D
;
282 templ
.last_level
= 0;
283 templ
.width0
= dri_drawable
->w
;
284 templ
.height0
= dri_drawable
->h
;
287 memset(&whandle
, 0, sizeof(whandle
));
289 for (i
= 0; i
< count
; i
++) {
290 __DRIbuffer
*buf
= &buffers
[i
];
291 enum st_attachment_type statt
;
292 enum pipe_format format
;
294 switch (buf
->attachment
) {
295 case __DRI_BUFFER_FRONT_LEFT
:
296 if (!screen
->auto_fake_front
) {
297 statt
= ST_ATTACHMENT_INVALID
;
301 case __DRI_BUFFER_FAKE_FRONT_LEFT
:
302 statt
= ST_ATTACHMENT_FRONT_LEFT
;
304 case __DRI_BUFFER_BACK_LEFT
:
305 statt
= ST_ATTACHMENT_BACK_LEFT
;
307 case __DRI_BUFFER_DEPTH
:
308 case __DRI_BUFFER_DEPTH_STENCIL
:
309 case __DRI_BUFFER_STENCIL
:
310 /* use only the first depth/stencil buffer */
313 statt
= ST_ATTACHMENT_DEPTH_STENCIL
;
316 statt
= ST_ATTACHMENT_INVALID
;
320 statt
= ST_ATTACHMENT_INVALID
;
324 dri2_drawable_get_format(drawable
, statt
, &format
, &bind
);
325 if (statt
== ST_ATTACHMENT_INVALID
|| format
== PIPE_FORMAT_NONE
)
328 templ
.format
= format
;
330 whandle
.handle
= buf
->name
;
331 whandle
.stride
= buf
->pitch
;
333 drawable
->textures
[statt
] =
334 screen
->base
.screen
->resource_from_handle(screen
->base
.screen
,
338 drawable
->old_num
= count
;
339 drawable
->old_w
= dri_drawable
->w
;
340 drawable
->old_h
= dri_drawable
->h
;
341 memcpy(drawable
->old
, buffers
, sizeof(__DRIbuffer
) * count
);
345 * Backend functions for st_framebuffer interface.
349 dri2_allocate_textures(struct dri_drawable
*drawable
,
350 const enum st_attachment_type
*statts
,
353 __DRIbuffer
*buffers
;
354 unsigned num_buffers
= count
;
356 buffers
= dri2_drawable_get_buffers(drawable
, statts
, &num_buffers
);
357 dri2_drawable_process_buffers(drawable
, buffers
, num_buffers
);
361 dri2_flush_frontbuffer(struct dri_drawable
*drawable
,
362 enum st_attachment_type statt
)
364 __DRIdrawable
*dri_drawable
= drawable
->dPriv
;
365 struct __DRIdri2LoaderExtensionRec
*loader
= drawable
->sPriv
->dri2
.loader
;
367 if (loader
->flushFrontBuffer
== NULL
)
370 if (statt
== ST_ATTACHMENT_FRONT_LEFT
) {
371 loader
->flushFrontBuffer(dri_drawable
, dri_drawable
->loaderPrivate
);
376 dri2_lookup_egl_image(struct dri_context
*ctx
, void *handle
)
378 __DRIimageLookupExtension
*loader
= ctx
->sPriv
->dri2
.image
;
381 if (!loader
->lookupEGLImage
)
384 img
= loader
->lookupEGLImage(ctx
->cPriv
, handle
, ctx
->cPriv
->loaderPrivate
);
390 dri2_create_image_from_name(__DRIcontext
*context
,
391 int width
, int height
, int format
,
392 int name
, int pitch
, void *loaderPrivate
)
394 struct dri_screen
*screen
= dri_screen(context
->driScreenPriv
);
396 struct pipe_resource templ
;
397 struct winsys_handle whandle
;
401 tex_usage
= PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
;
404 case __DRI_IMAGE_FORMAT_RGB565
:
405 pf
= PIPE_FORMAT_B5G6R5_UNORM
;
407 case __DRI_IMAGE_FORMAT_XRGB8888
:
408 pf
= PIPE_FORMAT_B8G8R8X8_UNORM
;
410 case __DRI_IMAGE_FORMAT_ARGB8888
:
411 pf
= PIPE_FORMAT_B8G8R8A8_UNORM
;
414 pf
= PIPE_FORMAT_NONE
;
417 if (pf
== PIPE_FORMAT_NONE
)
420 img
= CALLOC_STRUCT(__DRIimageRec
);
424 memset(&templ
, 0, sizeof(templ
));
425 templ
.bind
= tex_usage
;
427 templ
.target
= PIPE_TEXTURE_2D
;
428 templ
.last_level
= 0;
429 templ
.width0
= width
;
430 templ
.height0
= height
;
433 memset(&whandle
, 0, sizeof(whandle
));
434 whandle
.handle
= name
;
435 whandle
.stride
= pitch
* util_format_get_blocksize(pf
);
437 img
->texture
= screen
->base
.screen
->resource_from_handle(screen
->base
.screen
,
447 img
->loader_private
= loaderPrivate
;
453 dri2_create_image_from_renderbuffer(__DRIcontext
*context
,
454 int renderbuffer
, void *loaderPrivate
)
456 struct dri_context
*ctx
= dri_context(context
->driverPrivate
);
458 if (!ctx
->st
->get_resource_for_egl_image
)
466 dri2_destroy_image(__DRIimage
*img
)
468 pipe_resource_reference(&img
->texture
, NULL
);
472 static struct __DRIimageExtensionRec dri2ImageExtension
= {
473 { __DRI_IMAGE
, __DRI_IMAGE_VERSION
},
474 dri2_create_image_from_name
,
475 dri2_create_image_from_renderbuffer
,
480 * Backend function init_screen.
483 static const __DRIextension
*dri_screen_extensions
[] = {
484 &driReadDrawableExtension
,
485 &driCopySubBufferExtension
.base
,
486 &driSwapControlExtension
.base
,
487 &driFrameTrackingExtension
.base
,
488 &driMediaStreamCounterExtension
.base
,
489 &dri2TexBufferExtension
.base
,
490 &dri2FlushExtension
.base
,
491 &dri2ImageExtension
.base
,
496 * This is the driver specific part of the createNewScreen entry point.
498 * Returns the __GLcontextModes supported by this driver.
501 dri2_init_screen(__DRIscreen
* sPriv
)
503 const __DRIconfig
**configs
;
504 struct dri_screen
*screen
;
505 struct pipe_screen
*pscreen
;
507 screen
= CALLOC_STRUCT(dri_screen
);
511 screen
->api
= drm_api_create();
512 screen
->sPriv
= sPriv
;
513 screen
->fd
= sPriv
->fd
;
514 screen
->lookup_egl_image
= dri2_lookup_egl_image
;
515 screen
->allocate_textures
= dri2_allocate_textures
;
516 screen
->flush_frontbuffer
= dri2_flush_frontbuffer
;
518 sPriv
->private = (void *)screen
;
519 sPriv
->extensions
= dri_screen_extensions
;
521 pscreen
= screen
->api
->create_screen(screen
->api
, screen
->fd
);
522 /* dri_init_screen_helper checks pscreen for us */
524 configs
= dri_init_screen_helper(screen
, pscreen
, 32);
528 screen
->auto_fake_front
= dri_with_format(sPriv
);
529 screen
->broken_invalidate
= !sPriv
->dri2
.useInvalidate
;
533 dri_destroy_screen_helper(screen
);
538 /* This is the table of extensions that the loader will dlsym() for. */
539 PUBLIC
const __DRIextension
*__driDriverExtensions
[] = {
540 &driCoreExtension
.base
,
541 &driLegacyExtension
.base
,
542 &driDRI2Extension
.base
,
546 /* vim: set sw=3 ts=8 sts=3 expandtab: */