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"
43 * DRI2 flush extension.
46 dri2_flush_drawable(__DRIdrawable
*draw
)
51 dri2_invalidate_drawable(__DRIdrawable
*dPriv
)
53 struct dri_drawable
*drawable
= dri_drawable(dPriv
);
54 struct dri_context
*ctx
= dri_context(dPriv
->driContextPriv
);
56 dri2InvalidateDrawable(dPriv
);
57 drawable
->dPriv
->lastStamp
= *drawable
->dPriv
->pStamp
;
60 ctx
->st
->notify_invalid_framebuffer(ctx
->st
, &drawable
->base
);
63 static const __DRI2flushExtension dri2FlushExtension
= {
64 { __DRI2_FLUSH
, __DRI2_FLUSH_VERSION
},
66 dri2_invalidate_drawable
,
70 * Retrieve __DRIbuffer from the DRI loader.
73 dri2_drawable_get_buffers(struct dri_drawable
*drawable
,
74 const enum st_attachment_type
*statts
,
77 __DRIdrawable
*dri_drawable
= drawable
->dPriv
;
78 struct __DRIdri2LoaderExtensionRec
*loader
= drawable
->sPriv
->dri2
.loader
;
82 unsigned attachments
[10];
83 unsigned num_attachments
, i
;
86 with_format
= dri_with_format(drawable
->sPriv
);
90 /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
92 attachments
[num_attachments
++] = __DRI_BUFFER_FRONT_LEFT
;
94 for (i
= 0; i
< *count
; i
++) {
95 enum pipe_format format
;
99 dri_drawable_get_format(drawable
, statts
[i
], &format
, &bind
);
100 if (format
== PIPE_FORMAT_NONE
)
104 case ST_ATTACHMENT_FRONT_LEFT
:
108 att
= __DRI_BUFFER_FRONT_LEFT
;
110 case ST_ATTACHMENT_BACK_LEFT
:
111 att
= __DRI_BUFFER_BACK_LEFT
;
113 case ST_ATTACHMENT_FRONT_RIGHT
:
114 att
= __DRI_BUFFER_FRONT_RIGHT
;
116 case ST_ATTACHMENT_BACK_RIGHT
:
117 att
= __DRI_BUFFER_BACK_RIGHT
;
119 case ST_ATTACHMENT_DEPTH_STENCIL
:
120 att
= __DRI_BUFFER_DEPTH_STENCIL
;
127 bpp
= util_format_get_blocksizebits(format
);
130 attachments
[num_attachments
++] = att
;
132 attachments
[num_attachments
++] = bpp
;
138 num_attachments
/= 2;
139 buffers
= loader
->getBuffersWithFormat(dri_drawable
,
140 &dri_drawable
->w
, &dri_drawable
->h
,
141 attachments
, num_attachments
,
142 &num_buffers
, dri_drawable
->loaderPrivate
);
145 buffers
= loader
->getBuffers(dri_drawable
,
146 &dri_drawable
->w
, &dri_drawable
->h
,
147 attachments
, num_attachments
,
148 &num_buffers
, dri_drawable
->loaderPrivate
);
152 /* set one cliprect to cover the whole dri_drawable */
155 dri_drawable
->backX
= 0;
156 dri_drawable
->backY
= 0;
157 dri_drawable
->numClipRects
= 1;
158 dri_drawable
->pClipRects
[0].x1
= 0;
159 dri_drawable
->pClipRects
[0].y1
= 0;
160 dri_drawable
->pClipRects
[0].x2
= dri_drawable
->w
;
161 dri_drawable
->pClipRects
[0].y2
= dri_drawable
->h
;
162 dri_drawable
->numBackClipRects
= 1;
163 dri_drawable
->pBackClipRects
[0].x1
= 0;
164 dri_drawable
->pBackClipRects
[0].y1
= 0;
165 dri_drawable
->pBackClipRects
[0].x2
= dri_drawable
->w
;
166 dri_drawable
->pBackClipRects
[0].y2
= dri_drawable
->h
;
168 *count
= num_buffers
;
175 * Process __DRIbuffer and convert them into pipe_resources.
178 dri2_drawable_process_buffers(struct dri_drawable
*drawable
,
179 __DRIbuffer
*buffers
, unsigned count
)
181 struct dri_screen
*screen
= dri_screen(drawable
->sPriv
);
182 __DRIdrawable
*dri_drawable
= drawable
->dPriv
;
183 struct pipe_resource templ
;
184 struct winsys_handle whandle
;
185 boolean have_depth
= FALSE
;
188 if (drawable
->old_num
== count
&&
189 drawable
->old_w
== dri_drawable
->w
&&
190 drawable
->old_h
== dri_drawable
->h
&&
191 memcmp(drawable
->old
, buffers
, sizeof(__DRIbuffer
) * count
) == 0)
194 for (i
= 0; i
< ST_ATTACHMENT_COUNT
; i
++)
195 pipe_resource_reference(&drawable
->textures
[i
], NULL
);
197 memset(&templ
, 0, sizeof(templ
));
198 templ
.target
= screen
->target
;
199 templ
.last_level
= 0;
200 templ
.width0
= dri_drawable
->w
;
201 templ
.height0
= dri_drawable
->h
;
204 memset(&whandle
, 0, sizeof(whandle
));
206 for (i
= 0; i
< count
; i
++) {
207 __DRIbuffer
*buf
= &buffers
[i
];
208 enum st_attachment_type statt
;
209 enum pipe_format format
;
211 switch (buf
->attachment
) {
212 case __DRI_BUFFER_FRONT_LEFT
:
213 if (!screen
->auto_fake_front
) {
214 statt
= ST_ATTACHMENT_INVALID
;
218 case __DRI_BUFFER_FAKE_FRONT_LEFT
:
219 statt
= ST_ATTACHMENT_FRONT_LEFT
;
221 case __DRI_BUFFER_BACK_LEFT
:
222 statt
= ST_ATTACHMENT_BACK_LEFT
;
224 case __DRI_BUFFER_DEPTH
:
225 case __DRI_BUFFER_DEPTH_STENCIL
:
226 case __DRI_BUFFER_STENCIL
:
227 /* use only the first depth/stencil buffer */
230 statt
= ST_ATTACHMENT_DEPTH_STENCIL
;
233 statt
= ST_ATTACHMENT_INVALID
;
237 statt
= ST_ATTACHMENT_INVALID
;
241 dri_drawable_get_format(drawable
, statt
, &format
, &bind
);
242 if (statt
== ST_ATTACHMENT_INVALID
|| format
== PIPE_FORMAT_NONE
)
245 templ
.format
= format
;
247 whandle
.handle
= buf
->name
;
248 whandle
.stride
= buf
->pitch
;
250 drawable
->textures
[statt
] =
251 screen
->base
.screen
->resource_from_handle(screen
->base
.screen
,
255 drawable
->old_num
= count
;
256 drawable
->old_w
= dri_drawable
->w
;
257 drawable
->old_h
= dri_drawable
->h
;
258 memcpy(drawable
->old
, buffers
, sizeof(__DRIbuffer
) * count
);
262 * Backend functions for st_framebuffer interface.
266 dri2_allocate_textures(struct dri_drawable
*drawable
,
267 const enum st_attachment_type
*statts
,
270 __DRIbuffer
*buffers
;
271 unsigned num_buffers
= count
;
273 buffers
= dri2_drawable_get_buffers(drawable
, statts
, &num_buffers
);
275 dri2_drawable_process_buffers(drawable
, buffers
, num_buffers
);
279 dri2_flush_frontbuffer(struct dri_drawable
*drawable
,
280 enum st_attachment_type statt
)
282 __DRIdrawable
*dri_drawable
= drawable
->dPriv
;
283 struct __DRIdri2LoaderExtensionRec
*loader
= drawable
->sPriv
->dri2
.loader
;
285 if (loader
->flushFrontBuffer
== NULL
)
288 if (statt
== ST_ATTACHMENT_FRONT_LEFT
) {
289 loader
->flushFrontBuffer(dri_drawable
, dri_drawable
->loaderPrivate
);
294 dri2_lookup_egl_image(struct dri_context
*ctx
, void *handle
)
296 __DRIimageLookupExtension
*loader
= ctx
->sPriv
->dri2
.image
;
299 if (!loader
->lookupEGLImage
)
302 img
= loader
->lookupEGLImage(ctx
->cPriv
, handle
, ctx
->cPriv
->loaderPrivate
);
308 dri2_create_image_from_name(__DRIcontext
*context
,
309 int width
, int height
, int format
,
310 int name
, int pitch
, void *loaderPrivate
)
312 struct dri_screen
*screen
= dri_screen(context
->driScreenPriv
);
314 struct pipe_resource templ
;
315 struct winsys_handle whandle
;
319 tex_usage
= PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
;
322 case __DRI_IMAGE_FORMAT_RGB565
:
323 pf
= PIPE_FORMAT_B5G6R5_UNORM
;
325 case __DRI_IMAGE_FORMAT_XRGB8888
:
326 pf
= PIPE_FORMAT_B8G8R8X8_UNORM
;
328 case __DRI_IMAGE_FORMAT_ARGB8888
:
329 pf
= PIPE_FORMAT_B8G8R8A8_UNORM
;
332 pf
= PIPE_FORMAT_NONE
;
335 if (pf
== PIPE_FORMAT_NONE
)
338 img
= CALLOC_STRUCT(__DRIimageRec
);
342 memset(&templ
, 0, sizeof(templ
));
343 templ
.bind
= tex_usage
;
345 templ
.target
= screen
->target
;
346 templ
.last_level
= 0;
347 templ
.width0
= width
;
348 templ
.height0
= height
;
351 memset(&whandle
, 0, sizeof(whandle
));
352 whandle
.handle
= name
;
353 whandle
.stride
= pitch
* util_format_get_blocksize(pf
);
355 img
->texture
= screen
->base
.screen
->resource_from_handle(screen
->base
.screen
,
365 img
->loader_private
= loaderPrivate
;
371 dri2_create_image_from_renderbuffer(__DRIcontext
*context
,
372 int renderbuffer
, void *loaderPrivate
)
374 struct dri_context
*ctx
= dri_context(context
->driverPrivate
);
376 if (!ctx
->st
->get_resource_for_egl_image
)
384 dri2_destroy_image(__DRIimage
*img
)
386 pipe_resource_reference(&img
->texture
, NULL
);
390 static struct __DRIimageExtensionRec dri2ImageExtension
= {
391 { __DRI_IMAGE
, __DRI_IMAGE_VERSION
},
392 dri2_create_image_from_name
,
393 dri2_create_image_from_renderbuffer
,
398 * Backend function init_screen.
401 static const __DRIextension
*dri_screen_extensions
[] = {
402 &driReadDrawableExtension
,
403 &driCopySubBufferExtension
.base
,
404 &driSwapControlExtension
.base
,
405 &driMediaStreamCounterExtension
.base
,
406 &driTexBufferExtension
.base
,
407 &dri2FlushExtension
.base
,
408 &dri2ImageExtension
.base
,
409 &dri2ConfigQueryExtension
.base
,
414 * This is the driver specific part of the createNewScreen entry point.
416 * Returns the __GLcontextModes supported by this driver.
418 static const __DRIconfig
**
419 dri2_init_screen(__DRIscreen
* sPriv
)
421 const __DRIconfig
**configs
;
422 struct dri_screen
*screen
;
423 struct pipe_screen
*pscreen
;
425 screen
= CALLOC_STRUCT(dri_screen
);
429 screen
->sPriv
= sPriv
;
430 screen
->fd
= sPriv
->fd
;
432 sPriv
->private = (void *)screen
;
433 sPriv
->extensions
= dri_screen_extensions
;
435 pscreen
= driver_descriptor
.create_screen(screen
->fd
);
436 /* dri_init_screen_helper checks pscreen for us */
438 configs
= dri_init_screen_helper(screen
, pscreen
, 32);
442 screen
->auto_fake_front
= dri_with_format(sPriv
);
443 screen
->broken_invalidate
= !sPriv
->dri2
.useInvalidate
;
447 dri_destroy_screen_helper(screen
);
453 dri2_create_context(gl_api api
, const __GLcontextModes
* visual
,
454 __DRIcontext
* cPriv
, void *sharedContextPrivate
)
456 struct dri_context
*ctx
= NULL
;
458 if (!dri_create_context(api
, visual
, cPriv
, sharedContextPrivate
))
461 ctx
= cPriv
->driverPrivate
;
463 ctx
->lookup_egl_image
= dri2_lookup_egl_image
;
469 dri2_create_buffer(__DRIscreen
* sPriv
,
470 __DRIdrawable
* dPriv
,
471 const __GLcontextModes
* visual
, boolean isPixmap
)
473 struct dri_drawable
*drawable
= NULL
;
475 if (!dri_create_buffer(sPriv
, dPriv
, visual
, isPixmap
))
478 drawable
= dPriv
->driverPrivate
;
480 drawable
->allocate_textures
= dri2_allocate_textures
;
481 drawable
->flush_frontbuffer
= dri2_flush_frontbuffer
;
487 * DRI driver virtual function table.
489 * DRI versions differ in their implementation of init_screen and swap_buffers.
491 const struct __DriverAPIRec driDriverAPI
= {
493 .InitScreen2
= dri2_init_screen
,
494 .DestroyScreen
= dri_destroy_screen
,
495 .CreateContext
= dri2_create_context
,
496 .DestroyContext
= dri_destroy_context
,
497 .CreateBuffer
= dri2_create_buffer
,
498 .DestroyBuffer
= dri_destroy_buffer
,
499 .MakeCurrent
= dri_make_current
,
500 .UnbindContext
= dri_unbind_context
,
503 .GetDrawableMSC
= NULL
,
507 .CopySubBuffer
= NULL
,
510 /* This is the table of extensions that the loader will dlsym() for. */
511 PUBLIC
const __DRIextension
*__driDriverExtensions
[] = {
512 &driCoreExtension
.base
,
513 &driLegacyExtension
.base
,
514 &driDRI2Extension
.base
,
518 /* vim: set sw=3 ts=8 sts=3 expandtab: */