[PATCH 2/6] DRI2: Implement protocol for DRI2GetBuffersWithFormat
Ian Romanick
idr at freedesktop.org
Mon Apr 20 21:06:04 PDT 2009
This change implements the protocol for DRI2GetBuffersWithFormat, but
the bulk of the differences are the changes to the extension / driver
interface to make this function work. The old CreateBuffers and
DeleteBuffers routines are replaced with CreateBuffer and DeleteBuffer
(both singular).
This allows drivers to allocate buffers for a drawable one at a time.
As a result, 3D drivers can now allocate the (fake) front-buffer for a
window only when it is needed. Since 3D drivers only ask for the
front-buffer on demand, the real front-buffer is always created. This
allows CopyRegion impelemenations of SwapBuffers to continue working.
As with previous version of this code, if the client asks for the
front-buffer for a window, we instead give it the fake front-buffer.
Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
configure.ac | 2 +-
glx/glxdri2.c | 59 ++++++++++++--
hw/xfree86/dri2/dri2.c | 195 +++++++++++++++++++++++++++++++++------------
hw/xfree86/dri2/dri2.h | 22 +++++-
hw/xfree86/dri2/dri2ext.c | 88 ++++++++++++++------
5 files changed, 278 insertions(+), 88 deletions(-)
diff --git a/configure.ac b/configure.ac
index ef50627..2a73d8e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -886,7 +886,7 @@ if test "x$DRI" = xyes; then
AC_SUBST(DRIPROTO_CFLAGS)
fi
-PKG_CHECK_MODULES([DRI2PROTO], [dri2proto >= 1.99.3],
+PKG_CHECK_MODULES([DRI2PROTO], [dri2proto >= 2.1],
[HAVE_DRI2PROTO=yes], [HAVE_DRI2PROTO=no])
case "$DRI2,$HAVE_DRI2PROTO" in
yes,no)
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 612defb..529b2df 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -406,7 +406,7 @@ dri2GetBuffers(__DRIdrawable *driDrawable,
int *out_count, void *loaderPrivate)
{
__GLXDRIdrawable *private = loaderPrivate;
- DRI2BufferPtr buffers;
+ DRI2BufferPtr *buffers;
int i;
int j;
@@ -427,15 +427,59 @@ dri2GetBuffers(__DRIdrawable *driDrawable,
/* Do not send the real front buffer of a window to the client.
*/
if ((private->base.pDraw->type == DRAWABLE_WINDOW)
- && (buffers[i].attachment == DRI2BufferFrontLeft)) {
+ && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
continue;
}
- private->buffers[j].attachment = buffers[i].attachment;
- private->buffers[j].name = buffers[i].name;
- private->buffers[j].pitch = buffers[i].pitch;
- private->buffers[j].cpp = buffers[i].cpp;
- private->buffers[j].flags = buffers[i].flags;
+ private->buffers[j].attachment = buffers[i]->attachment;
+ private->buffers[j].name = buffers[i]->name;
+ private->buffers[j].pitch = buffers[i]->pitch;
+ private->buffers[j].cpp = buffers[i]->cpp;
+ private->buffers[j].flags = buffers[i]->flags;
+ j++;
+ }
+
+ *out_count = j;
+ return private->buffers;
+}
+
+static __DRIbuffer *
+dri2GetBuffersWithFormat(__DRIdrawable *driDrawable,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *out_count, void *loaderPrivate)
+{
+ __GLXDRIdrawable *private = loaderPrivate;
+ DRI2BufferPtr *buffers;
+ int i;
+ int j = 0;
+
+ buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
+ width, height, attachments, count,
+ out_count);
+ if (*out_count > MAX_DRAWABLE_BUFFERS) {
+ *out_count = 0;
+ return NULL;
+ }
+
+ private->width = *width;
+ private->height = *height;
+
+ /* This assumes the DRI2 buffer attachment tokens matches the
+ * __DRIbuffer tokens. */
+ for (i = 0; i < *out_count; i++) {
+ /* Do not send the real front buffer of a window to the client.
+ */
+ if ((private->base.pDraw->type == DRAWABLE_WINDOW)
+ && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
+ continue;
+ }
+
+ private->buffers[j].attachment = buffers[i]->attachment;
+ private->buffers[j].name = buffers[i]->name;
+ private->buffers[j].pitch = buffers[i]->pitch;
+ private->buffers[j].cpp = buffers[i]->cpp;
+ private->buffers[j].flags = buffers[i]->flags;
j++;
}
@@ -454,6 +498,7 @@ static const __DRIdri2LoaderExtension loaderExtension = {
{ __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION },
dri2GetBuffers,
dri2FlushFrontBuffer,
+ dri2GetBuffersWithFormat,
};
static const __DRIextension *loader_extensions[] = {
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 0b52a0f..9f9ec9d 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -53,7 +53,7 @@ typedef struct _DRI2Drawable {
unsigned int refCount;
int width;
int height;
- DRI2BufferPtr buffers;
+ DRI2BufferPtr *buffers;
int bufferCount;
unsigned int pendingSequence;
} DRI2DrawableRec, *DRI2DrawablePtr;
@@ -63,8 +63,8 @@ typedef struct _DRI2Screen {
const char *deviceName;
int fd;
unsigned int lastSequence;
- DRI2CreateBuffersProcPtr CreateBuffers;
- DRI2DestroyBuffersProcPtr DestroyBuffers;
+ DRI2CreateBufferProcPtr CreateBuffer;
+ DRI2DestroyBufferProcPtr DestroyBuffer;
DRI2CopyRegionProcPtr CopyRegion;
HandleExposuresProcPtr HandleExposures;
@@ -132,71 +132,130 @@ DRI2CreateDrawable(DrawablePtr pDraw)
return Success;
}
-DRI2BufferPtr
-DRI2GetBuffers(DrawablePtr pDraw, int *width, int *height,
- unsigned int *attachments, int count, int *out_count)
+static int
+find_attachment(DRI2BufferPtr *buffer_list, int count, unsigned attachment)
+{
+ int i;
+
+ if (buffer_list == NULL) {
+ return -1;
+ }
+
+ for (i = 0; i < count; i++) {
+ if ((buffer_list[i] != NULL)
+ && (buffer_list[i]->attachment == attachment)) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static DRI2BufferPtr
+allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds,
+ DRI2DrawablePtr pPriv,
+ unsigned int attachment, unsigned int format,
+ int dimensions_match)
+{
+ DRI2BufferPtr buffer;
+ int old_buf;
+
+ old_buf = find_attachment(pPriv->buffers, pPriv->bufferCount, attachment);
+
+ if ((old_buf < 0)
+ || !dimensions_match
+ || (pPriv->buffers[old_buf]->format != format)) {
+ buffer = (*ds->CreateBuffer)(pDraw, attachment, format);
+ } else {
+ buffer = pPriv->buffers[old_buf];
+ pPriv->buffers[old_buf] = NULL;
+ }
+
+ return buffer;
+}
+
+static DRI2BufferPtr *
+do_get_buffers(DrawablePtr pDraw, int *width, int *height,
+ unsigned int *attachments, int count, int *out_count,
+ int has_format)
{
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
- DRI2BufferPtr buffers;
- unsigned int temp_buf[32];
- unsigned int *temp = temp_buf;
+ DRI2BufferPtr *buffers;
+ int need_real_front = 0;
+ int need_fake_front = 0;
int have_fake_front = 0;
+ int front_format = 0;
+ const int dimensions_match = (pDraw->width == pPriv->width)
+ && (pDraw->height == pPriv->height);
+ int i;
- /* If the drawable is a window and the front-buffer is requested, silently
- * add the fake front-buffer to the list of requested attachments. The
- * counting logic in the loop accounts for the case where the client
- * requests both the fake and real front-buffer.
- */
- if (pDraw->type == DRAWABLE_WINDOW) {
- int need_fake_front = 0;
- int i;
+ buffers = xalloc((count + 1) * sizeof(buffers[0]));
- if ((count + 1) > 32) {
- temp = xalloc((count + 1) * sizeof(temp[0]));
- }
+ for (i = 0; i < count; i++) {
+ const unsigned attachment = *(attachments++);
+ const unsigned format = (has_format) ? *(attachments++) : 0;
+
+ buffers[i] = allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment,
+ format, dimensions_match);
- for (i = 0; i < count; i++) {
- if (attachments[i] == DRI2BufferFrontLeft) {
+
+ /* If the drawable is a window and the front-buffer is requested,
+ * silently add the fake front-buffer to the list of requested
+ * attachments. The counting logic in the loop accounts for the case
+ * where the client requests both the fake and real front-buffer.
+ */
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ if (attachment == DRI2BufferBackLeft) {
+ need_real_front++;
+ front_format = format;
+ }
+
+ if (attachment == DRI2BufferFrontLeft) {
+ need_real_front--;
need_fake_front++;
+ front_format = format;
}
- if (attachments[i] == DRI2BufferFakeFrontLeft) {
+ if (attachment == DRI2BufferFakeFrontLeft) {
need_fake_front--;
have_fake_front = 1;
}
-
- temp[i] = attachments[i];
- }
-
- if (need_fake_front > 0) {
- temp[i] = DRI2BufferFakeFrontLeft;
- count++;
- have_fake_front = 1;
- attachments = temp;
}
}
+ if (need_real_front > 0) {
+ buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv,
+ DRI2BufferFrontLeft,
+ front_format, dimensions_match);
+ }
- if (pPriv->buffers == NULL ||
- pDraw->width != pPriv->width || pDraw->height != pPriv->height)
- {
- buffers = (*ds->CreateBuffers)(pDraw, attachments, count);
- (*ds->DestroyBuffers)(pDraw, pPriv->buffers, pPriv->bufferCount);
- pPriv->buffers = buffers;
- pPriv->bufferCount = count;
- pPriv->width = pDraw->width;
- pPriv->height = pDraw->height;
+ if (need_fake_front > 0) {
+ buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv,
+ DRI2BufferFakeFrontLeft,
+ front_format, dimensions_match);
+ have_fake_front = 1;
}
- if (temp != temp_buf) {
- xfree(temp);
+ *out_count = i;
+
+
+ if (pPriv->buffers != NULL) {
+ for (i = 0; i < pPriv->bufferCount; i++) {
+ if (pPriv->buffers[i] != NULL) {
+ (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
+ }
+ }
+
+ xfree(pPriv->buffers);
}
+
+ pPriv->buffers = buffers;
+ pPriv->bufferCount = *out_count;
*width = pPriv->width;
*height = pPriv->height;
- *out_count = pPriv->bufferCount;
/* If the client is getting a fake front-buffer, pre-fill it with the
@@ -220,6 +279,22 @@ DRI2GetBuffers(DrawablePtr pDraw, int *width, int *height,
return pPriv->buffers;
}
+DRI2BufferPtr *
+DRI2GetBuffers(DrawablePtr pDraw, int *width, int *height,
+ unsigned int *attachments, int count, int *out_count)
+{
+ return do_get_buffers(pDraw, width, height, attachments, count,
+ out_count, FALSE);
+}
+
+DRI2BufferPtr *
+DRI2GetBuffersWithFormat(DrawablePtr pDraw, int *width, int *height,
+ unsigned int *attachments, int count, int *out_count)
+{
+ return do_get_buffers(pDraw, width, height, attachments, count,
+ out_count, TRUE);
+}
+
int
DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
unsigned int dest, unsigned int src)
@@ -237,10 +312,10 @@ DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
pSrcBuffer = NULL;
for (i = 0; i < pPriv->bufferCount; i++)
{
- if (pPriv->buffers[i].attachment == dest)
- pDestBuffer = &pPriv->buffers[i];
- if (pPriv->buffers[i].attachment == src)
- pSrcBuffer = &pPriv->buffers[i];
+ if (pPriv->buffers[i]->attachment == dest)
+ pDestBuffer = pPriv->buffers[i];
+ if (pPriv->buffers[i]->attachment == src)
+ pSrcBuffer = pPriv->buffers[i];
}
if (pSrcBuffer == NULL || pDestBuffer == NULL)
return BadValue;
@@ -266,7 +341,16 @@ DRI2DestroyDrawable(DrawablePtr pDraw)
if (pPriv->refCount > 0)
return;
- (*ds->DestroyBuffers)(pDraw, pPriv->buffers, pPriv->bufferCount);
+ if (pPriv->buffers != NULL) {
+ int i;
+
+ for (i = 0; i < pPriv->bufferCount; i++) {
+ (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
+ }
+
+ xfree(pPriv->buffers);
+ }
+
xfree(pPriv);
if (pDraw->type == DRAWABLE_WINDOW)
@@ -320,11 +404,18 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
if (!ds)
return FALSE;
+ if ((info->version < 2)
+ || (info->CreateBuffer == NULL)
+ || (info->DestroyBuffer == NULL)) {
+ return FALSE;
+ }
+
+
ds->fd = info->fd;
ds->driverName = info->driverName;
ds->deviceName = info->deviceName;
- ds->CreateBuffers = info->CreateBuffers;
- ds->DestroyBuffers = info->DestroyBuffers;
+ ds->CreateBuffer = info->CreateBuffer;
+ ds->DestroyBuffer = info->DestroyBuffer;
ds->CopyRegion = info->CopyRegion;
dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
@@ -371,7 +462,7 @@ static XF86ModuleVersionInfo DRI2VersRec =
MODINFOSTRING1,
MODINFOSTRING2,
XORG_VERSION_CURRENT,
- 1, 0, 0,
+ 1, 1, 0,
ABI_CLASS_EXTENSION,
ABI_EXTENSION_VERSION,
MOD_CLASS_NONE,
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index 847e57c..53fe888 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -41,6 +41,7 @@ typedef struct {
unsigned int pitch;
unsigned int cpp;
unsigned int flags;
+ unsigned int format;
void *driverPrivate;
} DRI2BufferRec, *DRI2BufferPtr;
@@ -58,8 +59,19 @@ typedef void (*DRI2CopyRegionProcPtr)(DrawablePtr pDraw,
typedef void (*DRI2WaitProcPtr)(WindowPtr pWin,
unsigned int sequence);
+typedef DRI2BufferPtr (*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
+ unsigned int attachment,
+ unsigned int format);
+typedef void (*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
+ DRI2BufferPtr buffer);
+
+/**
+ * Version of the DRI2InfoRec structure defined in this header
+ */
+#define DRI2INFOREC_VERSION 2
+
typedef struct {
- unsigned int version; /* Version of this struct */
+ unsigned int version; /**< Version of this struct */
int fd;
const char *driverName;
const char *deviceName;
@@ -68,6 +80,8 @@ typedef struct {
DRI2DestroyBuffersProcPtr DestroyBuffers;
DRI2CopyRegionProcPtr CopyRegion;
DRI2WaitProcPtr Wait;
+ DRI2CreateBufferProcPtr CreateBuffer;
+ DRI2DestroyBufferProcPtr DestroyBuffer;
} DRI2InfoRec, *DRI2InfoPtr;
@@ -88,7 +102,7 @@ extern _X_EXPORT int DRI2CreateDrawable(DrawablePtr pDraw);
extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw);
-extern _X_EXPORT DRI2BufferPtr DRI2GetBuffers(DrawablePtr pDraw,
+extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffers(DrawablePtr pDraw,
int *width,
int *height,
unsigned int *attachments,
@@ -100,4 +114,8 @@ extern _X_EXPORT int DRI2CopyRegion(DrawablePtr pDraw,
unsigned int dest,
unsigned int src);
+extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
+ int *width, int *height, unsigned int *attachments, int count,
+ int *out_count);
+
#endif
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index 23f3121..029dce8 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -80,7 +80,7 @@ ProcDRI2QueryVersion(ClientPtr client)
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.majorVersion = 1;
- rep.minorVersion = 0;
+ rep.minorVersion = 1;
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
@@ -192,32 +192,20 @@ ProcDRI2DestroyDrawable(ClientPtr client)
return client->noClientException;
}
-static int
-ProcDRI2GetBuffers(ClientPtr client)
+
+static void
+send_buffers_reply(ClientPtr client, DrawablePtr pDrawable,
+ DRI2BufferPtr *buffers, int count, int width, int height)
{
- REQUEST(xDRI2GetBuffersReq);
xDRI2GetBuffersReply rep;
- DrawablePtr pDrawable;
- DRI2BufferPtr buffers;
- int i, status, width, height, count;
- unsigned int *attachments;
- xDRI2Buffer buffer;
- int skip;
+ int skip = 0;
+ int i;
- REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * 4);
- if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
- return status;
-
- attachments = (unsigned int *) &stuff[1];
- buffers = DRI2GetBuffers(pDrawable, &width, &height,
- attachments, stuff->count, &count);
-
- skip = 0;
if (pDrawable->type == DRAWABLE_WINDOW) {
for (i = 0; i < count; i++) {
/* Do not send the real front buffer of a window to the client.
*/
- if (buffers[i].attachment == DRI2BufferFrontLeft) {
+ if (buffers[i]->attachment == DRI2BufferFrontLeft) {
skip++;
continue;
}
@@ -233,20 +221,66 @@ ProcDRI2GetBuffers(ClientPtr client)
WriteToClient(client, sizeof(xDRI2GetBuffersReply), &rep);
for (i = 0; i < count; i++) {
+ xDRI2Buffer buffer;
+
/* Do not send the real front buffer of a window to the client.
*/
if ((pDrawable->type == DRAWABLE_WINDOW)
- && (buffers[i].attachment == DRI2BufferFrontLeft)) {
+ && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
continue;
}
- buffer.attachment = buffers[i].attachment;
- buffer.name = buffers[i].name;
- buffer.pitch = buffers[i].pitch;
- buffer.cpp = buffers[i].cpp;
- buffer.flags = buffers[i].flags;
+ buffer.attachment = buffers[i]->attachment;
+ buffer.name = buffers[i]->name;
+ buffer.pitch = buffers[i]->pitch;
+ buffer.cpp = buffers[i]->cpp;
+ buffer.flags = buffers[i]->flags;
WriteToClient(client, sizeof(xDRI2Buffer), &buffer);
}
+}
+
+
+static int
+ProcDRI2GetBuffers(ClientPtr client)
+{
+ REQUEST(xDRI2GetBuffersReq);
+ DrawablePtr pDrawable;
+ DRI2BufferPtr *buffers;
+ int status, width, height, count;
+ unsigned int *attachments;
+
+ REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * 4);
+ if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
+ return status;
+
+ attachments = (unsigned int *) &stuff[1];
+ buffers = DRI2GetBuffers(pDrawable, &width, &height,
+ attachments, stuff->count, &count);
+
+
+ send_buffers_reply(client, pDrawable, buffers, count, width, height);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2GetBuffersWithFormat(ClientPtr client)
+{
+ REQUEST(xDRI2GetBuffersReq);
+ DrawablePtr pDrawable;
+ DRI2BufferPtr *buffers;
+ int status, width, height, count;
+ unsigned int *attachments;
+
+ REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * (2 * 4));
+ if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
+ return status;
+
+ attachments = (unsigned int *) &stuff[1];
+ buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
+ attachments, stuff->count, &count);
+
+ send_buffers_reply(client, pDrawable, buffers, count, width, height);
return client->noClientException;
}
@@ -313,6 +347,8 @@ ProcDRI2Dispatch (ClientPtr client)
return ProcDRI2GetBuffers(client);
case X_DRI2CopyRegion:
return ProcDRI2CopyRegion(client);
+ case X_DRI2GetBuffersWithFormat:
+ return ProcDRI2GetBuffersWithFormat(client);
default:
return BadRequest;
}
--
1.6.0.6
More information about the xorg-devel
mailing list