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"
41 #include "dri_st_api.h"
45 * DRI2 flush extension.
48 dri2_flush_drawable(__DRIdrawable
*draw
)
53 dri2_invalidate_drawable(__DRIdrawable
*dPriv
)
55 struct dri_drawable
*drawable
= dri_drawable(dPriv
);
56 struct dri_context
*ctx
= dri_context(dPriv
->driContextPriv
);
58 dri2InvalidateDrawable(dPriv
);
59 drawable
->dPriv
->lastStamp
= *drawable
->dPriv
->pStamp
;
62 ctx
->st
->notify_invalid_framebuffer(ctx
->st
, drawable
->stfb
);
65 static const __DRI2flushExtension dri2FlushExtension
= {
66 { __DRI2_FLUSH
, __DRI2_FLUSH_VERSION
},
68 dri2_invalidate_drawable
,
72 * These are used for GLX_EXT_texture_from_pixmap
75 dri2_set_tex_buffer2(__DRIcontext
*pDRICtx
, GLint target
,
76 GLint format
, __DRIdrawable
*dPriv
)
78 struct dri_context
*ctx
= dri_context(pDRICtx
);
79 struct dri_drawable
*drawable
= dri_drawable(dPriv
);
80 struct pipe_texture
*pt
;
82 dri_st_framebuffer_validate_att(drawable
->stfb
, ST_ATTACHMENT_FRONT_LEFT
);
84 pt
= drawable
->textures
[ST_ATTACHMENT_FRONT_LEFT
];
87 ctx
->st
->teximage(ctx
->st
,
88 (target
== GL_TEXTURE_2D
) ? ST_TEXTURE_2D
: ST_TEXTURE_RECT
,
89 0, drawable
->stvis
.color_format
, pt
, FALSE
);
94 dri2_set_tex_buffer(__DRIcontext
*pDRICtx
, GLint target
,
97 dri2_set_tex_buffer2(pDRICtx
, target
, __DRI_TEXTURE_FORMAT_RGBA
, dPriv
);
100 static const __DRItexBufferExtension dri2TexBufferExtension
= {
101 { __DRI_TEX_BUFFER
, __DRI_TEX_BUFFER_VERSION
},
103 dri2_set_tex_buffer2
,
107 * Get the format of an attachment.
109 static INLINE
enum pipe_format
110 dri2_drawable_get_format(struct dri_drawable
*drawable
,
111 enum st_attachment_type statt
)
113 enum pipe_format format
;
116 case ST_ATTACHMENT_FRONT_LEFT
:
117 case ST_ATTACHMENT_BACK_LEFT
:
118 case ST_ATTACHMENT_FRONT_RIGHT
:
119 case ST_ATTACHMENT_BACK_RIGHT
:
120 format
= drawable
->stvis
.color_format
;
122 case ST_ATTACHMENT_DEPTH_STENCIL
:
123 format
= drawable
->stvis
.depth_stencil_format
;
126 format
= PIPE_FORMAT_NONE
;
134 * Retrieve __DRIbuffer from the DRI loader.
137 dri2_drawable_get_buffers(struct dri_drawable
*drawable
,
138 const enum st_attachment_type
*statts
,
141 __DRIdrawable
*dri_drawable
= drawable
->dPriv
;
142 struct __DRIdri2LoaderExtensionRec
*loader
= drawable
->sPriv
->dri2
.loader
;
144 __DRIbuffer
*buffers
;
146 unsigned attachments
[10];
147 unsigned num_attachments
, i
;
150 with_format
= dri_with_format(drawable
->sPriv
);
154 /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
156 attachments
[num_attachments
++] = __DRI_BUFFER_FRONT_LEFT
;
158 for (i
= 0; i
< *count
; i
++) {
159 enum pipe_format format
;
162 format
= dri2_drawable_get_format(drawable
, statts
[i
]);
163 if (format
== PIPE_FORMAT_NONE
)
167 case ST_ATTACHMENT_FRONT_LEFT
:
171 att
= __DRI_BUFFER_FRONT_LEFT
;
173 case ST_ATTACHMENT_BACK_LEFT
:
174 att
= __DRI_BUFFER_BACK_LEFT
;
176 case ST_ATTACHMENT_FRONT_RIGHT
:
177 att
= __DRI_BUFFER_FRONT_RIGHT
;
179 case ST_ATTACHMENT_BACK_RIGHT
:
180 att
= __DRI_BUFFER_BACK_RIGHT
;
182 case ST_ATTACHMENT_DEPTH_STENCIL
:
183 att
= __DRI_BUFFER_DEPTH_STENCIL
;
190 bpp
= util_format_get_blocksizebits(format
);
193 attachments
[num_attachments
++] = att
;
195 attachments
[num_attachments
++] = bpp
;
201 num_attachments
/= 2;
202 buffers
= loader
->getBuffersWithFormat(dri_drawable
,
203 &dri_drawable
->w
, &dri_drawable
->h
,
204 attachments
, num_attachments
,
205 &num_buffers
, dri_drawable
->loaderPrivate
);
208 buffers
= loader
->getBuffers(dri_drawable
,
209 &dri_drawable
->w
, &dri_drawable
->h
,
210 attachments
, num_attachments
,
211 &num_buffers
, dri_drawable
->loaderPrivate
);
215 /* set one cliprect to cover the whole dri_drawable */
218 dri_drawable
->backX
= 0;
219 dri_drawable
->backY
= 0;
220 dri_drawable
->numClipRects
= 1;
221 dri_drawable
->pClipRects
[0].x1
= 0;
222 dri_drawable
->pClipRects
[0].y1
= 0;
223 dri_drawable
->pClipRects
[0].x2
= dri_drawable
->w
;
224 dri_drawable
->pClipRects
[0].y2
= dri_drawable
->h
;
225 dri_drawable
->numBackClipRects
= 1;
226 dri_drawable
->pBackClipRects
[0].x1
= 0;
227 dri_drawable
->pBackClipRects
[0].y1
= 0;
228 dri_drawable
->pBackClipRects
[0].x2
= dri_drawable
->w
;
229 dri_drawable
->pBackClipRects
[0].y2
= dri_drawable
->h
;
231 *count
= num_buffers
;
238 * Process __DRIbuffer and convert them into pipe_textures.
241 dri2_drawable_process_buffers(struct dri_drawable
*drawable
,
242 __DRIbuffer
*buffers
, unsigned count
)
244 struct dri_screen
*screen
= dri_screen(drawable
->sPriv
);
245 __DRIdrawable
*dri_drawable
= drawable
->dPriv
;
246 struct pipe_texture templ
;
247 struct winsys_handle whandle
;
248 boolean have_depth
= FALSE
;
251 if (drawable
->old_num
== count
&&
252 drawable
->old_w
== dri_drawable
->w
&&
253 drawable
->old_h
== dri_drawable
->h
&&
254 memcmp(drawable
->old
, buffers
, sizeof(__DRIbuffer
) * count
) == 0)
257 for (i
= 0; i
< ST_ATTACHMENT_COUNT
; i
++)
258 pipe_texture_reference(&drawable
->textures
[i
], NULL
);
260 memset(&templ
, 0, sizeof(templ
));
261 templ
.tex_usage
= PIPE_TEXTURE_USAGE_RENDER_TARGET
;
262 templ
.target
= PIPE_TEXTURE_2D
;
263 templ
.last_level
= 0;
264 templ
.width0
= dri_drawable
->w
;
265 templ
.height0
= dri_drawable
->h
;
268 memset(&whandle
, 0, sizeof(whandle
));
270 for (i
= 0; i
< count
; i
++) {
271 __DRIbuffer
*buf
= &buffers
[i
];
272 enum st_attachment_type statt
;
273 enum pipe_format format
;
275 switch (buf
->attachment
) {
276 case __DRI_BUFFER_FRONT_LEFT
:
277 if (!screen
->auto_fake_front
) {
278 statt
= ST_ATTACHMENT_INVALID
;
282 case __DRI_BUFFER_FAKE_FRONT_LEFT
:
283 statt
= ST_ATTACHMENT_FRONT_LEFT
;
285 case __DRI_BUFFER_BACK_LEFT
:
286 statt
= ST_ATTACHMENT_BACK_LEFT
;
288 case __DRI_BUFFER_DEPTH
:
289 case __DRI_BUFFER_DEPTH_STENCIL
:
290 case __DRI_BUFFER_STENCIL
:
291 /* use only the first depth/stencil buffer */
294 statt
= ST_ATTACHMENT_DEPTH_STENCIL
;
297 statt
= ST_ATTACHMENT_INVALID
;
301 statt
= ST_ATTACHMENT_INVALID
;
305 format
= dri2_drawable_get_format(drawable
, statt
);
306 if (statt
== ST_ATTACHMENT_INVALID
|| format
== PIPE_FORMAT_NONE
)
309 templ
.format
= format
;
310 whandle
.handle
= buf
->name
;
311 whandle
.stride
= buf
->pitch
;
313 drawable
->textures
[statt
] =
314 screen
->pipe_screen
->texture_from_handle(screen
->pipe_screen
,
318 drawable
->old_num
= count
;
319 drawable
->old_w
= dri_drawable
->w
;
320 drawable
->old_h
= dri_drawable
->h
;
321 memcpy(drawable
->old
, buffers
, sizeof(__DRIbuffer
) * count
);
325 * Backend functions for st_framebuffer interface.
329 dri2_allocate_textures(struct dri_drawable
*drawable
,
330 const enum st_attachment_type
*statts
,
333 __DRIbuffer
*buffers
;
334 unsigned num_buffers
= count
;
336 buffers
= dri2_drawable_get_buffers(drawable
, statts
, &num_buffers
);
337 dri2_drawable_process_buffers(drawable
, buffers
, num_buffers
);
341 dri2_flush_frontbuffer(struct dri_drawable
*drawable
,
342 enum st_attachment_type statt
)
344 __DRIdrawable
*dri_drawable
= drawable
->dPriv
;
345 struct __DRIdri2LoaderExtensionRec
*loader
= drawable
->sPriv
->dri2
.loader
;
347 if (loader
->flushFrontBuffer
== NULL
)
350 if (statt
== ST_ATTACHMENT_FRONT_LEFT
) {
351 loader
->flushFrontBuffer(dri_drawable
, dri_drawable
->loaderPrivate
);
356 * Backend function init_screen.
359 static const __DRIextension
*dri_screen_extensions
[] = {
360 &driReadDrawableExtension
,
361 &driCopySubBufferExtension
.base
,
362 &driSwapControlExtension
.base
,
363 &driFrameTrackingExtension
.base
,
364 &driMediaStreamCounterExtension
.base
,
365 &dri2TexBufferExtension
.base
,
366 &dri2FlushExtension
.base
,
371 * This is the driver specific part of the createNewScreen entry point.
373 * Returns the __GLcontextModes supported by this driver.
376 dri2_init_screen(__DRIscreen
* sPriv
)
378 struct dri_screen
*screen
;
379 struct drm_create_screen_arg arg
;
381 screen
= CALLOC_STRUCT(dri_screen
);
385 screen
->api
= drm_api_create();
386 screen
->sPriv
= sPriv
;
387 screen
->fd
= sPriv
->fd
;
388 sPriv
->private = (void *)screen
;
389 sPriv
->extensions
= dri_screen_extensions
;
390 arg
.mode
= DRM_CREATE_NORMAL
;
392 screen
->pipe_screen
= screen
->api
->create_screen(screen
->api
, screen
->fd
, &arg
);
393 if (!screen
->pipe_screen
) {
394 debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__
);
398 screen
->smapi
= dri_create_st_manager(screen
);
402 driParseOptionInfo(&screen
->optionCache
,
403 __driConfigOptions
, __driNConfigOptions
);
405 screen
->auto_fake_front
= dri_with_format(sPriv
);
407 return dri_fill_in_modes(screen
, 32);
409 dri_destroy_screen(sPriv
);
413 /* This is the table of extensions that the loader will dlsym() for. */
414 PUBLIC
const __DRIextension
*__driDriverExtensions
[] = {
415 &driCoreExtension
.base
,
416 &driLegacyExtension
.base
,
417 &driDRI2Extension
.base
,
421 /* vim: set sw=3 ts=8 sts=3 expandtab: */