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);
443
if (screen->st_api[ST_API_OPENGL])
444
sPriv->api_mask |= 1 << __DRI_API_OPENGL;
445
if (screen->st_api[ST_API_OPENGL_ES1])
446
sPriv->api_mask |= 1 << __DRI_API_GLES;
447
if (screen->st_api[ST_API_OPENGL_ES2])
448
sPriv->api_mask |= 1 << __DRI_API_GLES2;
450
screen->auto_fake_front = dri_with_format(sPriv);
451
screen->broken_invalidate = !sPriv->dri2.useInvalidate;
455
dri_destroy_screen_helper(screen);
461
dri2_create_context(gl_api api, const __GLcontextModes * visual,
462
__DRIcontext * cPriv, void *sharedContextPrivate)
464
struct dri_context *ctx = NULL;
466
if (!dri_create_context(api, visual, cPriv, sharedContextPrivate))
469
ctx = cPriv->driverPrivate;
471
ctx->lookup_egl_image = dri2_lookup_egl_image;
477
dri2_create_buffer(__DRIscreen * sPriv,
478
__DRIdrawable * dPriv,
479
const __GLcontextModes * visual, boolean isPixmap)
481
struct dri_drawable *drawable = NULL;
483
if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
486
drawable = dPriv->driverPrivate;
488
drawable->allocate_textures = dri2_allocate_textures;
489
drawable->flush_frontbuffer = dri2_flush_frontbuffer;
495
* DRI driver virtual function table.
497
* DRI versions differ in their implementation of init_screen and swap_buffers.
499
const struct __DriverAPIRec driDriverAPI = {
501
.InitScreen2 = dri2_init_screen,
502
.DestroyScreen = dri_destroy_screen,
503
.CreateContext = dri2_create_context,
504
.DestroyContext = dri_destroy_context,
505
.CreateBuffer = dri2_create_buffer,
506
.DestroyBuffer = dri_destroy_buffer,
507
.MakeCurrent = dri_make_current,
508
.UnbindContext = dri_unbind_context,
511
.GetDrawableMSC = NULL,
515
.CopySubBuffer = NULL,
518
/* This is the table of extensions that the loader will dlsym() for. */
519
PUBLIC const __DRIextension *__driDriverExtensions[] = {
520
&driCoreExtension.base,
521
&driLegacyExtension.base,
522
&driDRI2Extension.base,
526
/* vim: set sw=3 ts=8 sts=3 expandtab: */