aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xfree86/dri2
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xfree86/dri2')
-rw-r--r--xorg-server/hw/xfree86/dri2/dri2.c1826
-rw-r--r--xorg-server/hw/xfree86/dri2/dri2.h527
2 files changed, 1202 insertions, 1151 deletions
diff --git a/xorg-server/hw/xfree86/dri2/dri2.c b/xorg-server/hw/xfree86/dri2/dri2.c
index 3db826e91..787544c20 100644
--- a/xorg-server/hw/xfree86/dri2/dri2.c
+++ b/xorg-server/hw/xfree86/dri2/dri2.c
@@ -1,892 +1,934 @@
-/*
- * Copyright © 2007, 2008 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Soft-
- * ware"), to deal in the Software without restriction, including without
- * limitation the rights to use, copy, modify, merge, publish, distribute,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, provided that the above copyright
- * notice(s) and this permission notice appear in all copies of the Soft-
- * ware and that both the above copyright notice(s) and this permission
- * notice appear in supporting documentation.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
- * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
- * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
- * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
- * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
- * MANCE OF THIS SOFTWARE.
- *
- * Except as contained in this notice, the name of a copyright holder shall
- * not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization of
- * the copyright holder.
- *
- * Authors:
- * Kristian Høgsberg (krh@redhat.com)
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <errno.h>
-#include <xf86drm.h>
-#include "xf86Module.h"
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include "dixstruct.h"
-#include "dri2.h"
-#include "xf86VGAarbiter.h"
-
-#include "xf86.h"
-
-static int dri2ScreenPrivateKeyIndex;
-static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
-static int dri2WindowPrivateKeyIndex;
-static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
-static int dri2PixmapPrivateKeyIndex;
-static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
-
-typedef struct _DRI2Drawable {
- unsigned int refCount;
- int width;
- int height;
- DRI2BufferPtr *buffers;
- int bufferCount;
- unsigned int swapsPending;
- ClientPtr blockedClient;
- int swap_interval;
- CARD64 swap_count;
- CARD64 target_sbc; /* -1 means no SBC wait outstanding */
- CARD64 last_swap_target; /* most recently queued swap target */
- int swap_limit; /* for N-buffering */
-} DRI2DrawableRec, *DRI2DrawablePtr;
-
-typedef struct _DRI2Screen *DRI2ScreenPtr;
-
-typedef struct _DRI2Screen {
- const char *driverName;
- const char *deviceName;
- int fd;
- unsigned int lastSequence;
-
- DRI2CreateBufferProcPtr CreateBuffer;
- DRI2DestroyBufferProcPtr DestroyBuffer;
- DRI2CopyRegionProcPtr CopyRegion;
- DRI2ScheduleSwapProcPtr ScheduleSwap;
- DRI2GetMSCProcPtr GetMSC;
- DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC;
-
- HandleExposuresProcPtr HandleExposures;
-} DRI2ScreenRec;
-
-static DRI2ScreenPtr
-DRI2GetScreen(ScreenPtr pScreen)
-{
- return dixLookupPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey);
-}
-
-static DRI2DrawablePtr
-DRI2GetDrawable(DrawablePtr pDraw)
-{
- WindowPtr pWin;
- PixmapPtr pPixmap;
-
- if (!pDraw)
- return NULL;
-
- if (pDraw->type == DRAWABLE_WINDOW)
- {
- pWin = (WindowPtr) pDraw;
- return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
- }
- else
- {
- pPixmap = (PixmapPtr) pDraw;
- return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
- }
-}
-
-int
-DRI2CreateDrawable(DrawablePtr pDraw)
-{
- WindowPtr pWin;
- PixmapPtr pPixmap;
- DRI2DrawablePtr pPriv;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv != NULL)
- {
- pPriv->refCount++;
- return Success;
- }
-
- pPriv = xalloc(sizeof *pPriv);
- if (pPriv == NULL)
- return BadAlloc;
-
- pPriv->refCount = 1;
- pPriv->width = pDraw->width;
- pPriv->height = pDraw->height;
- pPriv->buffers = NULL;
- pPriv->bufferCount = 0;
- pPriv->swapsPending = 0;
- pPriv->blockedClient = NULL;
- pPriv->swap_count = 0;
- pPriv->target_sbc = -1;
- pPriv->swap_interval = 1;
- pPriv->last_swap_target = -1;
- pPriv->swap_limit = 1; /* default to double buffering */
-
- if (pDraw->type == DRAWABLE_WINDOW)
- {
- pWin = (WindowPtr) pDraw;
- dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
- }
- else
- {
- pPixmap = (PixmapPtr) pDraw;
- dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
- }
-
- return Success;
-}
-
-static int
-find_attachment(DRI2DrawablePtr pPriv, unsigned attachment)
-{
- int i;
-
- if (pPriv->buffers == NULL) {
- return -1;
- }
-
- for (i = 0; i < pPriv->bufferCount; i++) {
- if ((pPriv->buffers[i] != NULL)
- && (pPriv->buffers[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, 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;
- int need_real_front = 0;
- int need_fake_front = 0;
- int have_fake_front = 0;
- int front_format = 0;
- int dimensions_match;
- int i;
-
- if (!pPriv) {
- *width = pDraw->width;
- *height = pDraw->height;
- *out_count = 0;
- return NULL;
- }
-
- dimensions_match = (pDraw->width == pPriv->width)
- && (pDraw->height == pPriv->height);
-
- buffers = xalloc((count + 1) * sizeof(buffers[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);
-
- /* 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 (attachment == DRI2BufferBackLeft) {
- need_real_front++;
- front_format = format;
- }
-
- if (attachment == DRI2BufferFrontLeft) {
- need_real_front--;
- front_format = format;
-
- if (pDraw->type == DRAWABLE_WINDOW) {
- need_fake_front++;
- }
- }
-
- if (pDraw->type == DRAWABLE_WINDOW) {
- if (attachment == DRI2BufferFakeFrontLeft) {
- need_fake_front--;
- have_fake_front = 1;
- }
- }
- }
-
- if (need_real_front > 0) {
- buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv,
- DRI2BufferFrontLeft,
- front_format, dimensions_match);
- }
-
- if (need_fake_front > 0) {
- buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv,
- DRI2BufferFakeFrontLeft,
- front_format, dimensions_match);
- have_fake_front = 1;
- }
-
- *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;
- pPriv->width = pDraw->width;
- pPriv->height = pDraw->height;
- *width = pPriv->width;
- *height = pPriv->height;
-
-
- /* If the client is getting a fake front-buffer, pre-fill it with the
- * contents of the real front-buffer. This ensures correct operation of
- * applications that call glXWaitX before calling glDrawBuffer.
- */
- if (have_fake_front) {
- BoxRec box;
- RegionRec region;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pPriv->width;
- box.y2 = pPriv->height;
- REGION_INIT(pDraw->pScreen, &region, &box, 0);
-
- DRI2CopyRegion(pDraw, &region, DRI2BufferFakeFrontLeft,
- DRI2BufferFrontLeft);
- }
-
- 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);
-}
-
-/*
- * In the direct rendered case, we throttle the clients that have more
- * than their share of outstanding swaps (and thus busy buffers) when a
- * new GetBuffers request is received. In the AIGLX case, we allow the
- * client to get the new buffers, but throttle when the next GLX request
- * comes in (see __glXDRIcontextWait()).
- */
-Bool
-DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw)
-{
- DRI2DrawablePtr pPriv;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return FALSE;
-
- /* Throttle to swap limit */
- if ((pPriv->swapsPending >= pPriv->swap_limit) &&
- !pPriv->blockedClient) {
- ResetCurrentRequest(client);
- client->sequence--;
- IgnoreClient(client);
- pPriv->blockedClient = client;
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
-{
- DRI2DrawablePtr pPriv;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return;
-
- if (pPriv->blockedClient == NULL) {
- IgnoreClient(client);
- pPriv->blockedClient = client;
- }
-}
-
-int
-DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
- unsigned int dest, unsigned int src)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
- DRI2DrawablePtr pPriv;
- DRI2BufferPtr pDestBuffer, pSrcBuffer;
- int i;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return BadDrawable;
-
- pDestBuffer = NULL;
- pSrcBuffer = NULL;
- for (i = 0; i < pPriv->bufferCount; i++)
- {
- if (pPriv->buffers[i]->attachment == dest)
- pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
- if (pPriv->buffers[i]->attachment == src)
- pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
- }
- if (pSrcBuffer == NULL || pDestBuffer == NULL)
- return BadValue;
-
- (*ds->CopyRegion)(pDraw, pRegion, pDestBuffer, pSrcBuffer);
-
- return Success;
-}
-
-/* Can this drawable be page flipped? */
-Bool
-DRI2CanFlip(DrawablePtr pDraw)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- WindowPtr pWin, pRoot;
- PixmapPtr pWinPixmap, pRootPixmap;
-
- if (pDraw->type == DRAWABLE_PIXMAP)
- return TRUE;
-
- pRoot = WindowTable[pScreen->myNum];
- pRootPixmap = pScreen->GetWindowPixmap(pRoot);
-
- pWin = (WindowPtr) pDraw;
- pWinPixmap = pScreen->GetWindowPixmap(pWin);
- if (pRootPixmap != pWinPixmap)
- return FALSE;
- if (!REGION_EQUAL(pScreen, &pWin->clipList, &pRoot->winSize))
- return FALSE;
-
- return TRUE;
-}
-
-/* Can we do a pixmap exchange instead of a blit? */
-Bool
-DRI2CanExchange(DrawablePtr pDraw)
-{
- return FALSE;
-}
-
-void
-DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
- unsigned int tv_sec, unsigned int tv_usec)
-{
- DRI2DrawablePtr pPriv;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return;
-
- ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
- frame, pPriv->swap_count);
-
- if (pPriv->blockedClient)
- AttendClient(pPriv->blockedClient);
-
- pPriv->blockedClient = NULL;
-}
-
-static void
-DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
- unsigned int tv_sec, unsigned int tv_usec)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- DRI2DrawablePtr pPriv;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: bad drawable\n", __func__);
- return;
- }
-
- /*
- * Swap completed. Either wake up an SBC waiter or a client that was
- * blocked due to GLX activity during a swap.
- */
- if (pPriv->target_sbc != -1 &&
- pPriv->target_sbc >= pPriv->swap_count) {
- ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
- frame, pPriv->swap_count);
- pPriv->target_sbc = -1;
-
- AttendClient(pPriv->blockedClient);
- pPriv->blockedClient = NULL;
- } else if (pPriv->target_sbc == -1) {
- if (pPriv->blockedClient)
- AttendClient(pPriv->blockedClient);
- pPriv->blockedClient = NULL;
- }
-}
-
-void
-DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
- unsigned int tv_sec, unsigned int tv_usec, int type,
- DRI2SwapEventPtr swap_complete, void *swap_data)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- DRI2DrawablePtr pPriv;
- CARD64 ust = 0;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: bad drawable\n", __func__);
- return;
- }
-
- if (pPriv->refCount == 0) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: bad drawable refcount\n", __func__);
- xfree(pPriv);
- return;
- }
-
- ust = ((CARD64)tv_sec * 1000000) + tv_usec;
- if (swap_complete)
- swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count);
-
- pPriv->swapsPending--;
- pPriv->swap_count++;
-
- DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
-}
-
-Bool
-DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
-{
- DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
-
- /* If we're currently waiting for a swap on this drawable, reset
- * the request and suspend the client. We only support one
- * blocked client per drawable. */
- if ((pPriv->swapsPending) &&
- pPriv->blockedClient == NULL) {
- ResetCurrentRequest(client);
- client->sequence--;
- DRI2BlockClient(client, pDrawable);
- return TRUE;
- }
-
- return FALSE;
-}
-
-int
-DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
- CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
- DRI2SwapEventPtr func, void *data)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
- DRI2DrawablePtr pPriv;
- DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
- CARD64 ust;
- int ret, i;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: bad drawable\n", __func__);
- return BadDrawable;
- }
-
- for (i = 0; i < pPriv->bufferCount; i++) {
- if (pPriv->buffers[i]->attachment == DRI2BufferFrontLeft)
- pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
- if (pPriv->buffers[i]->attachment == DRI2BufferBackLeft)
- pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
- }
- if (pSrcBuffer == NULL || pDestBuffer == NULL) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: drawable has no back or front?\n", __func__);
- return BadDrawable;
- }
-
- /* Old DDX, just blit */
- if (!ds->ScheduleSwap) {
- BoxRec box;
- RegionRec region;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pDraw->width;
- box.y2 = pDraw->height;
- REGION_INIT(pScreen, &region, &box, 0);
-
- pPriv->swapsPending++;
-
- (*ds->CopyRegion)(pDraw, &region, pDestBuffer, pSrcBuffer);
- DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
- func, data);
- return Success;
- }
-
- /*
- * In the simple glXSwapBuffers case, all params will be 0, and we just
- * need to schedule a swap for the last swap target + the swap interval.
- * If the last swap target hasn't been set yet, call into the driver
- * to get the current count.
- */
- if (target_msc == 0 && divisor == 0 && remainder == 0 &&
- pPriv->last_swap_target < 0) {
- ret = (*ds->GetMSC)(pDraw, &ust, &target_msc);
- if (!ret) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: driver failed to return current MSC\n",
- __func__);
- return BadDrawable;
- }
- }
-
- /* First swap needs to initialize last_swap_target */
- if (pPriv->last_swap_target < 0)
- pPriv->last_swap_target = target_msc;
-
- /*
- * Swap target for this swap is last swap target + swap interval since
- * we have to account for the current swap count, interval, and the
- * number of pending swaps.
- */
- *swap_target = pPriv->last_swap_target + pPriv->swap_interval;
-
- ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer,
- swap_target, divisor, remainder, func, data);
- if (!ret) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: driver failed to schedule swap\n", __func__);
- return BadDrawable;
- }
-
- pPriv->swapsPending++;
- pPriv->last_swap_target = *swap_target;
-
- return Success;
-}
-
-void
-DRI2SwapInterval(DrawablePtr pDrawable, int interval)
-{
- DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
-
- /* fixme: check against arbitrary max? */
-
- pPriv->swap_interval = interval;
-}
-
-int
-DRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
- DRI2DrawablePtr pPriv;
- Bool ret;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL) {
- xf86DrvMsg(pScreen->myNum, X_ERROR,
- "[DRI2] %s: bad drawable\n", __func__);
- return BadDrawable;
- }
-
- if (!ds->GetMSC) {
- *ust = 0;
- *msc = 0;
- *sbc = pPriv->swap_count;
- return Success;
- }
-
- /*
- * Spec needs to be updated to include unmapped or redirected
- * drawables
- */
-
- ret = (*ds->GetMSC)(pDraw, ust, msc);
- if (!ret)
- return BadDrawable;
-
- *sbc = pPriv->swap_count;
-
- return Success;
-}
-
-int
-DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
- CARD64 divisor, CARD64 remainder)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
- DRI2DrawablePtr pPriv;
- Bool ret;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return BadDrawable;
-
- /* Old DDX just completes immediately */
- if (!ds->ScheduleWaitMSC) {
- DRI2WaitMSCComplete(client, pDraw, target_msc, 0, 0);
-
- return Success;
- }
-
- ret = (*ds->ScheduleWaitMSC)(client, pDraw, target_msc, divisor, remainder);
- if (!ret)
- return BadDrawable;
-
- return Success;
-}
-
-int
-DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
- CARD64 *ust, CARD64 *msc, CARD64 *sbc)
-{
- DRI2DrawablePtr pPriv;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return BadDrawable;
-
- if (pPriv->swap_count >= target_sbc)
- return Success;
-
- pPriv->target_sbc = target_sbc;
- DRI2BlockClient(client, pDraw);
-
- return Success;
-}
-
-void
-DRI2DestroyDrawable(DrawablePtr pDraw)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
- DRI2DrawablePtr pPriv;
- WindowPtr pWin;
- PixmapPtr pPixmap;
-
- pPriv = DRI2GetDrawable(pDraw);
- if (pPriv == NULL)
- return;
-
- pPriv->refCount--;
- if (pPriv->refCount > 0)
- return;
-
- if (pPriv->buffers != NULL) {
- int i;
-
- for (i = 0; i < pPriv->bufferCount; i++)
- (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
-
- xfree(pPriv->buffers);
- }
-
- /* If the window is destroyed while we have a swap pending, don't
- * actually free the priv yet. We'll need it in the DRI2SwapComplete()
- * callback and we'll free it there once we're done. */
- if (!pPriv->swapsPending)
- xfree(pPriv);
-
- if (pDraw->type == DRAWABLE_WINDOW)
- {
- pWin = (WindowPtr) pDraw;
- dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
- }
- else
- {
- pPixmap = (PixmapPtr) pDraw;
- dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
- }
-}
-
-Bool
-DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
- const char **driverName, const char **deviceName)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
-
- if (ds == NULL)
- return FALSE;
-
- if (driverType != DRI2DriverDRI)
- return BadValue;
-
- *fd = ds->fd;
- *driverName = ds->driverName;
- *deviceName = ds->deviceName;
-
- return TRUE;
-}
-
-Bool
-DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
-
- if (ds == NULL || drmAuthMagic(ds->fd, magic))
- return FALSE;
-
- return TRUE;
-}
-
-Bool
-DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
-{
- DRI2ScreenPtr ds;
-
- if (info->version < 3)
- return FALSE;
-
- if (!xf86VGAarbiterAllowDRI(pScreen)) {
- xf86DrvMsg(pScreen->myNum, X_WARNING,
- "[DRI2] Direct rendering is not supported when VGA arb is necessary for the device\n");
- return FALSE;
- }
-
- ds = xcalloc(1, sizeof *ds);
- if (!ds)
- return FALSE;
-
- ds->fd = info->fd;
- ds->driverName = info->driverName;
- ds->deviceName = info->deviceName;
-
- ds->CreateBuffer = info->CreateBuffer;
- ds->DestroyBuffer = info->DestroyBuffer;
- ds->CopyRegion = info->CopyRegion;
-
- if (info->version >= 4) {
- ds->ScheduleSwap = info->ScheduleSwap;
- ds->ScheduleWaitMSC = info->ScheduleWaitMSC;
- ds->GetMSC = info->GetMSC;
- }
-
- dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
-
- xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
-
- return TRUE;
-}
-
-void
-DRI2CloseScreen(ScreenPtr pScreen)
-{
- DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
-
- xfree(ds);
- dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL);
-}
-
-extern ExtensionModule dri2ExtensionModule;
-
-static pointer
-DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
-{
- static Bool setupDone = FALSE;
-
- if (!setupDone)
- {
- setupDone = TRUE;
- LoadExtension(&dri2ExtensionModule, FALSE);
- }
- else
- {
- if (errmaj)
- *errmaj = LDR_ONCEONLY;
- }
-
- return (pointer) 1;
-}
-
-static XF86ModuleVersionInfo DRI2VersRec =
-{
- "dri2",
- MODULEVENDORSTRING,
- MODINFOSTRING1,
- MODINFOSTRING2,
- XORG_VERSION_CURRENT,
- 1, 1, 0,
- ABI_CLASS_EXTENSION,
- ABI_EXTENSION_VERSION,
- MOD_CLASS_NONE,
- { 0, 0, 0, 0 }
-};
-
-_X_EXPORT XF86ModuleData dri2ModuleData = { &DRI2VersRec, DRI2Setup, NULL };
-
-void
-DRI2Version(int *major, int *minor)
-{
- if (major != NULL)
- *major = DRI2VersRec.majorversion;
-
- if (minor != NULL)
- *minor = DRI2VersRec.minorversion;
-}
+/*
+ * Copyright © 2007, 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ * Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <errno.h>
+#include <xf86drm.h>
+#include "xf86Module.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "dixstruct.h"
+#include "dri2.h"
+#include "xf86VGAarbiter.h"
+
+#include "xf86.h"
+
+static int dri2ScreenPrivateKeyIndex;
+static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
+static int dri2WindowPrivateKeyIndex;
+static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
+static int dri2PixmapPrivateKeyIndex;
+static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
+
+typedef struct _DRI2Drawable {
+ unsigned int refCount;
+ int width;
+ int height;
+ DRI2BufferPtr *buffers;
+ int bufferCount;
+ unsigned int swapsPending;
+ ClientPtr blockedClient;
+ int swap_interval;
+ CARD64 swap_count;
+ CARD64 target_sbc; /* -1 means no SBC wait outstanding */
+ CARD64 last_swap_target; /* most recently queued swap target */
+ int swap_limit; /* for N-buffering */
+} DRI2DrawableRec, *DRI2DrawablePtr;
+
+typedef struct _DRI2Screen *DRI2ScreenPtr;
+
+typedef struct _DRI2Screen {
+ unsigned int numDrivers;
+ const char **driverNames;
+ const char *deviceName;
+ int fd;
+ unsigned int lastSequence;
+
+ DRI2CreateBufferProcPtr CreateBuffer;
+ DRI2DestroyBufferProcPtr DestroyBuffer;
+ DRI2CopyRegionProcPtr CopyRegion;
+ DRI2ScheduleSwapProcPtr ScheduleSwap;
+ DRI2GetMSCProcPtr GetMSC;
+ DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC;
+
+ HandleExposuresProcPtr HandleExposures;
+} DRI2ScreenRec;
+
+static DRI2ScreenPtr
+DRI2GetScreen(ScreenPtr pScreen)
+{
+ return dixLookupPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey);
+}
+
+static DRI2DrawablePtr
+DRI2GetDrawable(DrawablePtr pDraw)
+{
+ WindowPtr pWin;
+ PixmapPtr pPixmap;
+
+ if (!pDraw)
+ return NULL;
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ {
+ pWin = (WindowPtr) pDraw;
+ return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
+ }
+ else
+ {
+ pPixmap = (PixmapPtr) pDraw;
+ return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
+ }
+}
+
+int
+DRI2CreateDrawable(DrawablePtr pDraw)
+{
+ WindowPtr pWin;
+ PixmapPtr pPixmap;
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv != NULL)
+ {
+ pPriv->refCount++;
+ return Success;
+ }
+
+ pPriv = xalloc(sizeof *pPriv);
+ if (pPriv == NULL)
+ return BadAlloc;
+
+ pPriv->refCount = 1;
+ pPriv->width = pDraw->width;
+ pPriv->height = pDraw->height;
+ pPriv->buffers = NULL;
+ pPriv->bufferCount = 0;
+ pPriv->swapsPending = 0;
+ pPriv->blockedClient = NULL;
+ pPriv->swap_count = 0;
+ pPriv->target_sbc = -1;
+ pPriv->swap_interval = 1;
+ pPriv->last_swap_target = -1;
+ pPriv->swap_limit = 1; /* default to double buffering */
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ {
+ pWin = (WindowPtr) pDraw;
+ dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
+ }
+ else
+ {
+ pPixmap = (PixmapPtr) pDraw;
+ dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
+ }
+
+ return Success;
+}
+
+static void
+DRI2FreeDrawable(DrawablePtr pDraw)
+{
+ DRI2DrawablePtr pPriv;
+ WindowPtr pWin;
+ PixmapPtr pPixmap;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return;
+
+ xfree(pPriv);
+
+ if (pDraw->type == DRAWABLE_WINDOW)
+ {
+ pWin = (WindowPtr) pDraw;
+ dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
+ }
+ else
+ {
+ pPixmap = (PixmapPtr) pDraw;
+ dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
+ }
+}
+
+static int
+find_attachment(DRI2DrawablePtr pPriv, unsigned attachment)
+{
+ int i;
+
+ if (pPriv->buffers == NULL) {
+ return -1;
+ }
+
+ for (i = 0; i < pPriv->bufferCount; i++) {
+ if ((pPriv->buffers[i] != NULL)
+ && (pPriv->buffers[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, 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;
+ int need_real_front = 0;
+ int need_fake_front = 0;
+ int have_fake_front = 0;
+ int front_format = 0;
+ int dimensions_match;
+ int i;
+
+ if (!pPriv) {
+ *width = pDraw->width;
+ *height = pDraw->height;
+ *out_count = 0;
+ return NULL;
+ }
+
+ dimensions_match = (pDraw->width == pPriv->width)
+ && (pDraw->height == pPriv->height);
+
+ buffers = xalloc((count + 1) * sizeof(buffers[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);
+
+ /* 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 (attachment == DRI2BufferBackLeft) {
+ need_real_front++;
+ front_format = format;
+ }
+
+ if (attachment == DRI2BufferFrontLeft) {
+ need_real_front--;
+ front_format = format;
+
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ need_fake_front++;
+ }
+ }
+
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ if (attachment == DRI2BufferFakeFrontLeft) {
+ need_fake_front--;
+ have_fake_front = 1;
+ }
+ }
+ }
+
+ if (need_real_front > 0) {
+ buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv,
+ DRI2BufferFrontLeft,
+ front_format, dimensions_match);
+ }
+
+ if (need_fake_front > 0) {
+ buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv,
+ DRI2BufferFakeFrontLeft,
+ front_format, dimensions_match);
+ have_fake_front = 1;
+ }
+
+ *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;
+ pPriv->width = pDraw->width;
+ pPriv->height = pDraw->height;
+ *width = pPriv->width;
+ *height = pPriv->height;
+
+
+ /* If the client is getting a fake front-buffer, pre-fill it with the
+ * contents of the real front-buffer. This ensures correct operation of
+ * applications that call glXWaitX before calling glDrawBuffer.
+ */
+ if (have_fake_front) {
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pPriv->width;
+ box.y2 = pPriv->height;
+ REGION_INIT(pDraw->pScreen, &region, &box, 0);
+
+ DRI2CopyRegion(pDraw, &region, DRI2BufferFakeFrontLeft,
+ DRI2BufferFrontLeft);
+ }
+
+ 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);
+}
+
+/*
+ * In the direct rendered case, we throttle the clients that have more
+ * than their share of outstanding swaps (and thus busy buffers) when a
+ * new GetBuffers request is received. In the AIGLX case, we allow the
+ * client to get the new buffers, but throttle when the next GLX request
+ * comes in (see __glXDRIcontextWait()).
+ */
+Bool
+DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw)
+{
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return FALSE;
+
+ /* Throttle to swap limit */
+ if ((pPriv->swapsPending >= pPriv->swap_limit) &&
+ !pPriv->blockedClient) {
+ ResetCurrentRequest(client);
+ client->sequence--;
+ IgnoreClient(client);
+ pPriv->blockedClient = client;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
+{
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return;
+
+ if (pPriv->blockedClient == NULL) {
+ IgnoreClient(client);
+ pPriv->blockedClient = client;
+ }
+}
+
+int
+DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
+ unsigned int dest, unsigned int src)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+ DRI2DrawablePtr pPriv;
+ DRI2BufferPtr pDestBuffer, pSrcBuffer;
+ int i;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return BadDrawable;
+
+ pDestBuffer = NULL;
+ pSrcBuffer = NULL;
+ for (i = 0; i < pPriv->bufferCount; i++)
+ {
+ if (pPriv->buffers[i]->attachment == dest)
+ pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+ if (pPriv->buffers[i]->attachment == src)
+ pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+ }
+ if (pSrcBuffer == NULL || pDestBuffer == NULL)
+ return BadValue;
+
+ (*ds->CopyRegion)(pDraw, pRegion, pDestBuffer, pSrcBuffer);
+
+ return Success;
+}
+
+/* Can this drawable be page flipped? */
+Bool
+DRI2CanFlip(DrawablePtr pDraw)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ WindowPtr pWin, pRoot;
+ PixmapPtr pWinPixmap, pRootPixmap;
+
+ if (pDraw->type == DRAWABLE_PIXMAP)
+ return TRUE;
+
+ pRoot = WindowTable[pScreen->myNum];
+ pRootPixmap = pScreen->GetWindowPixmap(pRoot);
+
+ pWin = (WindowPtr) pDraw;
+ pWinPixmap = pScreen->GetWindowPixmap(pWin);
+ if (pRootPixmap != pWinPixmap)
+ return FALSE;
+ if (!REGION_EQUAL(pScreen, &pWin->clipList, &pRoot->winSize))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Can we do a pixmap exchange instead of a blit? */
+Bool
+DRI2CanExchange(DrawablePtr pDraw)
+{
+ return FALSE;
+}
+
+void
+DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
+ unsigned int tv_sec, unsigned int tv_usec)
+{
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return;
+
+ ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
+ frame, pPriv->swap_count);
+
+ if (pPriv->blockedClient)
+ AttendClient(pPriv->blockedClient);
+
+ pPriv->blockedClient = NULL;
+}
+
+static void
+DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
+ unsigned int tv_sec, unsigned int tv_usec)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: bad drawable\n", __func__);
+ return;
+ }
+
+ /*
+ * Swap completed. Either wake up an SBC waiter or a client that was
+ * blocked due to GLX activity during a swap.
+ */
+ if (pPriv->target_sbc != -1 &&
+ pPriv->target_sbc >= pPriv->swap_count) {
+ ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
+ frame, pPriv->swap_count);
+ pPriv->target_sbc = -1;
+
+ AttendClient(pPriv->blockedClient);
+ pPriv->blockedClient = NULL;
+ } else if (pPriv->target_sbc == -1) {
+ if (pPriv->blockedClient)
+ AttendClient(pPriv->blockedClient);
+ pPriv->blockedClient = NULL;
+ }
+}
+
+void
+DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
+ unsigned int tv_sec, unsigned int tv_usec, int type,
+ DRI2SwapEventPtr swap_complete, void *swap_data)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ DRI2DrawablePtr pPriv;
+ CARD64 ust = 0;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: bad drawable\n", __func__);
+ return;
+ }
+
+ if (pPriv->refCount == 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: bad drawable refcount\n", __func__);
+ DRI2FreeDrawable(pDraw);
+ return;
+ }
+
+ ust = ((CARD64)tv_sec * 1000000) + tv_usec;
+ if (swap_complete)
+ swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count);
+
+ pPriv->swapsPending--;
+ pPriv->swap_count++;
+
+ DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
+}
+
+Bool
+DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
+{
+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
+
+ /* If we're currently waiting for a swap on this drawable, reset
+ * the request and suspend the client. We only support one
+ * blocked client per drawable. */
+ if ((pPriv->swapsPending) &&
+ pPriv->blockedClient == NULL) {
+ ResetCurrentRequest(client);
+ client->sequence--;
+ DRI2BlockClient(client, pDrawable);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int
+DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
+ CARD64 divisor, CARD64 remainder, CARD64 *swap_target,
+ DRI2SwapEventPtr func, void *data)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+ DRI2DrawablePtr pPriv;
+ DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
+ CARD64 ust;
+ int ret, i;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: bad drawable\n", __func__);
+ return BadDrawable;
+ }
+
+ for (i = 0; i < pPriv->bufferCount; i++) {
+ if (pPriv->buffers[i]->attachment == DRI2BufferFrontLeft)
+ pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+ if (pPriv->buffers[i]->attachment == DRI2BufferBackLeft)
+ pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i];
+ }
+ if (pSrcBuffer == NULL || pDestBuffer == NULL) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: drawable has no back or front?\n", __func__);
+ return BadDrawable;
+ }
+
+ /* Old DDX, just blit */
+ if (!ds->ScheduleSwap) {
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pDraw->width;
+ box.y2 = pDraw->height;
+ REGION_INIT(pScreen, &region, &box, 0);
+
+ pPriv->swapsPending++;
+
+ (*ds->CopyRegion)(pDraw, &region, pDestBuffer, pSrcBuffer);
+ DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE,
+ func, data);
+ return Success;
+ }
+
+ /*
+ * In the simple glXSwapBuffers case, all params will be 0, and we just
+ * need to schedule a swap for the last swap target + the swap interval.
+ * If the last swap target hasn't been set yet, call into the driver
+ * to get the current count.
+ */
+ if (target_msc == 0 && divisor == 0 && remainder == 0 &&
+ pPriv->last_swap_target < 0) {
+ ret = (*ds->GetMSC)(pDraw, &ust, &target_msc);
+ if (!ret) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: driver failed to return current MSC\n",
+ __func__);
+ return BadDrawable;
+ }
+ }
+
+ /* First swap needs to initialize last_swap_target */
+ if (pPriv->last_swap_target < 0)
+ pPriv->last_swap_target = target_msc;
+
+ /*
+ * Swap target for this swap is last swap target + swap interval since
+ * we have to account for the current swap count, interval, and the
+ * number of pending swaps.
+ */
+ *swap_target = pPriv->last_swap_target + pPriv->swap_interval;
+
+ ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer,
+ swap_target, divisor, remainder, func, data);
+ if (!ret) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: driver failed to schedule swap\n", __func__);
+ return BadDrawable;
+ }
+
+ pPriv->swapsPending++;
+ pPriv->last_swap_target = *swap_target;
+
+ return Success;
+}
+
+void
+DRI2SwapInterval(DrawablePtr pDrawable, int interval)
+{
+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
+
+ /* fixme: check against arbitrary max? */
+
+ pPriv->swap_interval = interval;
+}
+
+int
+DRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+ DRI2DrawablePtr pPriv;
+ Bool ret;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[DRI2] %s: bad drawable\n", __func__);
+ return BadDrawable;
+ }
+
+ if (!ds->GetMSC) {
+ *ust = 0;
+ *msc = 0;
+ *sbc = pPriv->swap_count;
+ return Success;
+ }
+
+ /*
+ * Spec needs to be updated to include unmapped or redirected
+ * drawables
+ */
+
+ ret = (*ds->GetMSC)(pDraw, ust, msc);
+ if (!ret)
+ return BadDrawable;
+
+ *sbc = pPriv->swap_count;
+
+ return Success;
+}
+
+int
+DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
+ CARD64 divisor, CARD64 remainder)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+ DRI2DrawablePtr pPriv;
+ Bool ret;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return BadDrawable;
+
+ /* Old DDX just completes immediately */
+ if (!ds->ScheduleWaitMSC) {
+ DRI2WaitMSCComplete(client, pDraw, target_msc, 0, 0);
+
+ return Success;
+ }
+
+ ret = (*ds->ScheduleWaitMSC)(client, pDraw, target_msc, divisor, remainder);
+ if (!ret)
+ return BadDrawable;
+
+ return Success;
+}
+
+int
+DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
+ CARD64 *ust, CARD64 *msc, CARD64 *sbc)
+{
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return BadDrawable;
+
+ if (pPriv->swap_count >= target_sbc)
+ return Success;
+
+ pPriv->target_sbc = target_sbc;
+ DRI2BlockClient(client, pDraw);
+
+ return Success;
+}
+
+void
+DRI2DestroyDrawable(DrawablePtr pDraw)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+ DRI2DrawablePtr pPriv;
+
+ pPriv = DRI2GetDrawable(pDraw);
+ if (pPriv == NULL)
+ return;
+
+ pPriv->refCount--;
+ if (pPriv->refCount > 0)
+ return;
+
+ if (pPriv->buffers != NULL) {
+ int i;
+
+ for (i = 0; i < pPriv->bufferCount; i++)
+ (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
+
+ xfree(pPriv->buffers);
+ }
+
+ /* If the window is destroyed while we have a swap pending, don't
+ * actually free the priv yet. We'll need it in the DRI2SwapComplete()
+ * callback and we'll free it there once we're done. */
+ if (!pPriv->swapsPending)
+ DRI2FreeDrawable(pDraw);
+}
+
+Bool
+DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
+ const char **driverName, const char **deviceName)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+
+ if (ds == NULL || driverType >= ds->numDrivers ||
+ !ds->driverNames[driverType])
+ return FALSE;
+
+ *fd = ds->fd;
+ *driverName = ds->driverNames[driverType];
+ *deviceName = ds->deviceName;
+
+ return TRUE;
+}
+
+Bool
+DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+
+ if (ds == NULL || drmAuthMagic(ds->fd, magic))
+ return FALSE;
+
+ return TRUE;
+}
+
+Bool
+DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
+{
+ DRI2ScreenPtr ds;
+ const char* driverTypeNames[] = {
+ "DRI", /* DRI2DriverDRI */
+ "VDPAU", /* DRI2DriverVDPAU */
+ };
+ unsigned int i;
+
+ if (info->version < 3)
+ return FALSE;
+
+ if (!xf86VGAarbiterAllowDRI(pScreen)) {
+ xf86DrvMsg(pScreen->myNum, X_WARNING,
+ "[DRI2] Direct rendering is not supported when VGA arb is necessary for the device\n");
+ return FALSE;
+ }
+
+ ds = xcalloc(1, sizeof *ds);
+ if (!ds)
+ return FALSE;
+
+ ds->fd = info->fd;
+ ds->deviceName = info->deviceName;
+
+ ds->CreateBuffer = info->CreateBuffer;
+ ds->DestroyBuffer = info->DestroyBuffer;
+ ds->CopyRegion = info->CopyRegion;
+
+ if (info->version >= 4) {
+ ds->ScheduleSwap = info->ScheduleSwap;
+ ds->ScheduleWaitMSC = info->ScheduleWaitMSC;
+ ds->GetMSC = info->GetMSC;
+ }
+
+ if (info->version == 3 || info->numDrivers == 0) {
+ /* Driver too old: use the old-style driverName field */
+ ds->numDrivers = 1;
+ ds->driverNames = xalloc(sizeof(*ds->driverNames));
+ if (!ds->driverNames) {
+ xfree(ds);
+ return FALSE;
+ }
+ ds->driverNames[0] = info->driverName;
+ } else {
+ ds->numDrivers = info->numDrivers;
+ ds->driverNames = xalloc(info->numDrivers * sizeof(*ds->driverNames));
+ if (!ds->driverNames) {
+ xfree(ds);
+ return FALSE;
+ }
+ memcpy(ds->driverNames, info->driverNames,
+ info->numDrivers * sizeof(*ds->driverNames));
+ }
+
+ dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
+
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
+ for (i = 0; i < sizeof(driverTypeNames) / sizeof(driverTypeNames[0]); i++) {
+ if (i < ds->numDrivers && ds->driverNames[i]) {
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] %s driver: %s\n",
+ driverTypeNames[i], ds->driverNames[i]);
+ }
+ }
+
+ return TRUE;
+}
+
+void
+DRI2CloseScreen(ScreenPtr pScreen)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+
+ xfree(ds->driverNames);
+ xfree(ds);
+ dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL);
+}
+
+extern ExtensionModule dri2ExtensionModule;
+
+static pointer
+DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = FALSE;
+
+ if (!setupDone)
+ {
+ setupDone = TRUE;
+ LoadExtension(&dri2ExtensionModule, FALSE);
+ }
+ else
+ {
+ if (errmaj)
+ *errmaj = LDR_ONCEONLY;
+ }
+
+ return (pointer) 1;
+}
+
+static XF86ModuleVersionInfo DRI2VersRec =
+{
+ "dri2",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 1, 2, 0,
+ ABI_CLASS_EXTENSION,
+ ABI_EXTENSION_VERSION,
+ MOD_CLASS_NONE,
+ { 0, 0, 0, 0 }
+};
+
+_X_EXPORT XF86ModuleData dri2ModuleData = { &DRI2VersRec, DRI2Setup, NULL };
+
+void
+DRI2Version(int *major, int *minor)
+{
+ if (major != NULL)
+ *major = DRI2VersRec.majorversion;
+
+ if (minor != NULL)
+ *minor = DRI2VersRec.minorversion;
+}
diff --git a/xorg-server/hw/xfree86/dri2/dri2.h b/xorg-server/hw/xfree86/dri2/dri2.h
index dd59297df..cb818f898 100644
--- a/xorg-server/hw/xfree86/dri2/dri2.h
+++ b/xorg-server/hw/xfree86/dri2/dri2.h
@@ -1,259 +1,268 @@
-/*
- * Copyright © 2007 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Soft-
- * ware"), to deal in the Software without restriction, including without
- * limitation the rights to use, copy, modify, merge, publish, distribute,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, provided that the above copyright
- * notice(s) and this permission notice appear in all copies of the Soft-
- * ware and that both the above copyright notice(s) and this permission
- * notice appear in supporting documentation.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
- * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
- * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
- * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
- * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
- * MANCE OF THIS SOFTWARE.
- *
- * Except as contained in this notice, the name of a copyright holder shall
- * not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization of
- * the copyright holder.
- *
- * Authors:
- * Kristian Høgsberg (krh@redhat.com)
- */
-
-#ifndef _DRI2_H_
-#define _DRI2_H_
-
-#include <X11/extensions/dri2tokens.h>
-
-/* Version 2 structure (with format at the end) */
-typedef struct {
- unsigned int attachment;
- unsigned int name;
- unsigned int pitch;
- unsigned int cpp;
- unsigned int flags;
- unsigned int format;
- void *driverPrivate;
-} DRI2BufferRec, *DRI2BufferPtr;
-
-typedef DRI2BufferRec DRI2Buffer2Rec, *DRI2Buffer2Ptr;
-typedef void (*DRI2SwapEventPtr)(ClientPtr client, void *data, int type,
- CARD64 ust, CARD64 msc, CARD64 sbc);
-
-
-typedef DRI2BufferPtr (*DRI2CreateBuffersProcPtr)(DrawablePtr pDraw,
- unsigned int *attachments,
- int count);
-typedef void (*DRI2DestroyBuffersProcPtr)(DrawablePtr pDraw,
- DRI2BufferPtr buffers,
- int count);
-typedef void (*DRI2CopyRegionProcPtr)(DrawablePtr pDraw,
- RegionPtr pRegion,
- DRI2BufferPtr pDestBuffer,
- DRI2BufferPtr pSrcBuffer);
-typedef void (*DRI2WaitProcPtr)(WindowPtr pWin,
- unsigned int sequence);
-/**
- * Schedule a buffer swap
- *
- * This callback is used to support glXSwapBuffers and the OML_sync_control
- * extension (see it for a description of the params).
- *
- * Drivers should queue an event for the frame count that satisfies the
- * parameters passed in. If the event is in the future (i.e. the conditions
- * aren't currently satisfied), the server may block the client at the next
- * GLX request using DRI2WaitSwap. When the event arrives, drivers should call
- * \c DRI2SwapComplete, which will handle waking the client and returning
- * the appropriate data.
- *
- * The DDX is responsible for doing a flip, exchange, or blit of the swap
- * when the corresponding event arrives. The \c DRI2CanFlip and
- * \c DRI2CanExchange functions can be used as helpers for this purpose.
- *
- * \param client client pointer (used for block/unblock)
- * \param pDraw drawable whose count we want
- * \param pDestBuffer current front buffer
- * \param pSrcBuffer current back buffer
- * \param target_msc frame count to wait for
- * \param divisor divisor for condition equation
- * \param remainder remainder for division equation
- * \param func function to call when the swap completes
- * \param data data for the callback \p func.
- */
-typedef int (*DRI2ScheduleSwapProcPtr)(ClientPtr client,
- DrawablePtr pDraw,
- DRI2BufferPtr pDestBuffer,
- DRI2BufferPtr pSrcBuffer,
- CARD64 *target_msc,
- CARD64 divisor,
- CARD64 remainder,
- DRI2SwapEventPtr func,
- void *data);
-typedef DRI2BufferPtr (*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
- unsigned int attachment,
- unsigned int format);
-typedef void (*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
- DRI2BufferPtr buffer);
-/**
- * Get current media stamp counter values
- *
- * This callback is used to support the SGI_video_sync and OML_sync_control
- * extensions.
- *
- * Drivers should return the current frame counter and the timestamp from
- * when the returned frame count was last incremented.
- *
- * The count should correspond to the screen where the drawable is currently
- * visible. If the drawable isn't visible (e.g. redirected), the server
- * should return BadDrawable to the client, pending GLX spec updates to
- * define this behavior.
- *
- * \param pDraw drawable whose count we want
- * \param ust timestamp from when the count was last incremented.
- * \param mst current frame count
- */
-typedef int (*DRI2GetMSCProcPtr)(DrawablePtr pDraw, CARD64 *ust,
- CARD64 *msc);
-/**
- * Schedule a frame count related wait
- *
- * This callback is used to support the SGI_video_sync and OML_sync_control
- * extensions. See those specifications for details on how to handle
- * the divisor and remainder parameters.
- *
- * Drivers should queue an event for the frame count that satisfies the
- * parameters passed in. If the event is in the future (i.e. the conditions
- * aren't currently satisfied), the driver should block the client using
- * \c DRI2BlockClient. When the event arrives, drivers should call
- * \c DRI2WaitMSCComplete, which will handle waking the client and returning
- * the appropriate data.
- *
- * \param client client pointer (used for block/unblock)
- * \param pDraw drawable whose count we want
- * \param target_msc frame count to wait for
- * \param divisor divisor for condition equation
- * \param remainder remainder for division equation
- */
-typedef int (*DRI2ScheduleWaitMSCProcPtr)(ClientPtr client,
- DrawablePtr pDraw,
- CARD64 target_msc,
- CARD64 divisor,
- CARD64 remainder);
-/**
- * Version of the DRI2InfoRec structure defined in this header
- */
-#define DRI2INFOREC_VERSION 4
-
-typedef struct {
- unsigned int version; /**< Version of this struct */
- int fd;
- const char *driverName;
- const char *deviceName;
-
- DRI2CreateBufferProcPtr CreateBuffer;
- DRI2DestroyBufferProcPtr DestroyBuffer;
- DRI2CopyRegionProcPtr CopyRegion;
- DRI2WaitProcPtr Wait;
- DRI2ScheduleSwapProcPtr ScheduleSwap;
- DRI2GetMSCProcPtr GetMSC;
- DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC;
-} DRI2InfoRec, *DRI2InfoPtr;
-
-extern _X_EXPORT int DRI2EventBase;
-
-extern _X_EXPORT Bool DRI2ScreenInit(ScreenPtr pScreen,
- DRI2InfoPtr info);
-
-extern _X_EXPORT void DRI2CloseScreen(ScreenPtr pScreen);
-
-extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
- unsigned int driverType,
- int *fd,
- const char **driverName,
- const char **deviceName);
-
-extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic);
-
-extern _X_EXPORT int DRI2CreateDrawable(DrawablePtr pDraw);
-
-extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw);
-
-extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffers(DrawablePtr pDraw,
- int *width,
- int *height,
- unsigned int *attachments,
- int count,
- int *out_count);
-
-extern _X_EXPORT int DRI2CopyRegion(DrawablePtr pDraw,
- RegionPtr pRegion,
- unsigned int dest,
- unsigned int src);
-
-/**
- * Determine the major and minor version of the DRI2 extension.
- *
- * Provides a mechanism to other modules (e.g., 2D drivers) to determine the
- * version of the DRI2 extension. While it is possible to peek directly at
- * the \c XF86ModuleData from a layered module, such a module will fail to
- * load (due to an unresolved symbol) if the DRI2 extension is not loaded.
- *
- * \param major Location to store the major verion of the DRI2 extension
- * \param minor Location to store the minor verion of the DRI2 extension
- *
- * \note
- * This interface was added some time after the initial release of the DRI2
- * module. Layered modules that wish to use this interface must first test
- * its existance by calling \c xf86LoaderCheckSymbol.
- */
-extern _X_EXPORT void DRI2Version(int *major, int *minor);
-
-extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
- int *width, int *height, unsigned int *attachments, int count,
- int *out_count);
-
-extern _X_EXPORT void DRI2SwapInterval(DrawablePtr pDrawable, int interval);
-extern _X_EXPORT int DRI2SwapBuffers(ClientPtr client, DrawablePtr pDrawable,
- CARD64 target_msc, CARD64 divisor,
- CARD64 remainder, CARD64 *swap_target,
- DRI2SwapEventPtr func, void *data);
-extern _X_EXPORT Bool DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable);
-
-extern _X_EXPORT int DRI2GetMSC(DrawablePtr pDrawable, CARD64 *ust,
- CARD64 *msc, CARD64 *sbc);
-extern _X_EXPORT int DRI2WaitMSC(ClientPtr client, DrawablePtr pDrawable,
- CARD64 target_msc, CARD64 divisor,
- CARD64 remainder);
-extern _X_EXPORT int ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust,
- CARD64 msc, CARD64 sbc);
-extern _X_EXPORT int DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw,
- CARD64 target_sbc, CARD64 *ust, CARD64 *msc,
- CARD64 *sbc);
-extern _X_EXPORT Bool DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw);
-
-extern _X_EXPORT Bool DRI2CanFlip(DrawablePtr pDraw);
-
-extern _X_EXPORT Bool DRI2CanExchange(DrawablePtr pDraw);
-
-extern _X_EXPORT void DRI2BlockClient(ClientPtr client, DrawablePtr pDraw);
-
-extern _X_EXPORT void DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw,
- int frame, unsigned int tv_sec,
- unsigned int tv_usec, int type,
- DRI2SwapEventPtr swap_complete,
- void *swap_data);
-extern _X_EXPORT void DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw,
- int frame, unsigned int tv_sec,
- unsigned int tv_usec);
-
-#endif
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ * Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifndef _DRI2_H_
+#define _DRI2_H_
+
+#include <X11/extensions/dri2tokens.h>
+
+/* Version 2 structure (with format at the end) */
+typedef struct {
+ unsigned int attachment;
+ unsigned int name;
+ unsigned int pitch;
+ unsigned int cpp;
+ unsigned int flags;
+ unsigned int format;
+ void *driverPrivate;
+} DRI2BufferRec, *DRI2BufferPtr;
+
+typedef DRI2BufferRec DRI2Buffer2Rec, *DRI2Buffer2Ptr;
+typedef void (*DRI2SwapEventPtr)(ClientPtr client, void *data, int type,
+ CARD64 ust, CARD64 msc, CARD64 sbc);
+
+
+typedef DRI2BufferPtr (*DRI2CreateBuffersProcPtr)(DrawablePtr pDraw,
+ unsigned int *attachments,
+ int count);
+typedef void (*DRI2DestroyBuffersProcPtr)(DrawablePtr pDraw,
+ DRI2BufferPtr buffers,
+ int count);
+typedef void (*DRI2CopyRegionProcPtr)(DrawablePtr pDraw,
+ RegionPtr pRegion,
+ DRI2BufferPtr pDestBuffer,
+ DRI2BufferPtr pSrcBuffer);
+typedef void (*DRI2WaitProcPtr)(WindowPtr pWin,
+ unsigned int sequence);
+/**
+ * Schedule a buffer swap
+ *
+ * This callback is used to support glXSwapBuffers and the OML_sync_control
+ * extension (see it for a description of the params).
+ *
+ * Drivers should queue an event for the frame count that satisfies the
+ * parameters passed in. If the event is in the future (i.e. the conditions
+ * aren't currently satisfied), the server may block the client at the next
+ * GLX request using DRI2WaitSwap. When the event arrives, drivers should call
+ * \c DRI2SwapComplete, which will handle waking the client and returning
+ * the appropriate data.
+ *
+ * The DDX is responsible for doing a flip, exchange, or blit of the swap
+ * when the corresponding event arrives. The \c DRI2CanFlip and
+ * \c DRI2CanExchange functions can be used as helpers for this purpose.
+ *
+ * \param client client pointer (used for block/unblock)
+ * \param pDraw drawable whose count we want
+ * \param pDestBuffer current front buffer
+ * \param pSrcBuffer current back buffer
+ * \param target_msc frame count to wait for
+ * \param divisor divisor for condition equation
+ * \param remainder remainder for division equation
+ * \param func function to call when the swap completes
+ * \param data data for the callback \p func.
+ */
+typedef int (*DRI2ScheduleSwapProcPtr)(ClientPtr client,
+ DrawablePtr pDraw,
+ DRI2BufferPtr pDestBuffer,
+ DRI2BufferPtr pSrcBuffer,
+ CARD64 *target_msc,
+ CARD64 divisor,
+ CARD64 remainder,
+ DRI2SwapEventPtr func,
+ void *data);
+typedef DRI2BufferPtr (*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
+ unsigned int attachment,
+ unsigned int format);
+typedef void (*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
+ DRI2BufferPtr buffer);
+/**
+ * Get current media stamp counter values
+ *
+ * This callback is used to support the SGI_video_sync and OML_sync_control
+ * extensions.
+ *
+ * Drivers should return the current frame counter and the timestamp from
+ * when the returned frame count was last incremented.
+ *
+ * The count should correspond to the screen where the drawable is currently
+ * visible. If the drawable isn't visible (e.g. redirected), the server
+ * should return BadDrawable to the client, pending GLX spec updates to
+ * define this behavior.
+ *
+ * \param pDraw drawable whose count we want
+ * \param ust timestamp from when the count was last incremented.
+ * \param mst current frame count
+ */
+typedef int (*DRI2GetMSCProcPtr)(DrawablePtr pDraw, CARD64 *ust,
+ CARD64 *msc);
+/**
+ * Schedule a frame count related wait
+ *
+ * This callback is used to support the SGI_video_sync and OML_sync_control
+ * extensions. See those specifications for details on how to handle
+ * the divisor and remainder parameters.
+ *
+ * Drivers should queue an event for the frame count that satisfies the
+ * parameters passed in. If the event is in the future (i.e. the conditions
+ * aren't currently satisfied), the driver should block the client using
+ * \c DRI2BlockClient. When the event arrives, drivers should call
+ * \c DRI2WaitMSCComplete, which will handle waking the client and returning
+ * the appropriate data.
+ *
+ * \param client client pointer (used for block/unblock)
+ * \param pDraw drawable whose count we want
+ * \param target_msc frame count to wait for
+ * \param divisor divisor for condition equation
+ * \param remainder remainder for division equation
+ */
+typedef int (*DRI2ScheduleWaitMSCProcPtr)(ClientPtr client,
+ DrawablePtr pDraw,
+ CARD64 target_msc,
+ CARD64 divisor,
+ CARD64 remainder);
+/**
+ * Version of the DRI2InfoRec structure defined in this header
+ */
+#define DRI2INFOREC_VERSION 4
+
+typedef struct {
+ unsigned int version; /**< Version of this struct */
+ int fd;
+ const char *driverName;
+ const char *deviceName;
+
+ DRI2CreateBufferProcPtr CreateBuffer;
+ DRI2DestroyBufferProcPtr DestroyBuffer;
+ DRI2CopyRegionProcPtr CopyRegion;
+ DRI2WaitProcPtr Wait;
+
+ /* added in version 4 */
+
+ DRI2ScheduleSwapProcPtr ScheduleSwap;
+ DRI2GetMSCProcPtr GetMSC;
+ DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC;
+
+ /* number of drivers in the driverNames array */
+ unsigned int numDrivers;
+ /* array of driver names, indexed by DRI2Driver* driver types */
+ /* a name of NULL means that driver is not supported */
+ const char * const *driverNames;
+} DRI2InfoRec, *DRI2InfoPtr;
+
+extern _X_EXPORT int DRI2EventBase;
+
+extern _X_EXPORT Bool DRI2ScreenInit(ScreenPtr pScreen,
+ DRI2InfoPtr info);
+
+extern _X_EXPORT void DRI2CloseScreen(ScreenPtr pScreen);
+
+extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
+ unsigned int driverType,
+ int *fd,
+ const char **driverName,
+ const char **deviceName);
+
+extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic);
+
+extern _X_EXPORT int DRI2CreateDrawable(DrawablePtr pDraw);
+
+extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw);
+
+extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffers(DrawablePtr pDraw,
+ int *width,
+ int *height,
+ unsigned int *attachments,
+ int count,
+ int *out_count);
+
+extern _X_EXPORT int DRI2CopyRegion(DrawablePtr pDraw,
+ RegionPtr pRegion,
+ unsigned int dest,
+ unsigned int src);
+
+/**
+ * Determine the major and minor version of the DRI2 extension.
+ *
+ * Provides a mechanism to other modules (e.g., 2D drivers) to determine the
+ * version of the DRI2 extension. While it is possible to peek directly at
+ * the \c XF86ModuleData from a layered module, such a module will fail to
+ * load (due to an unresolved symbol) if the DRI2 extension is not loaded.
+ *
+ * \param major Location to store the major verion of the DRI2 extension
+ * \param minor Location to store the minor verion of the DRI2 extension
+ *
+ * \note
+ * This interface was added some time after the initial release of the DRI2
+ * module. Layered modules that wish to use this interface must first test
+ * its existance by calling \c xf86LoaderCheckSymbol.
+ */
+extern _X_EXPORT void DRI2Version(int *major, int *minor);
+
+extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
+ int *width, int *height, unsigned int *attachments, int count,
+ int *out_count);
+
+extern _X_EXPORT void DRI2SwapInterval(DrawablePtr pDrawable, int interval);
+extern _X_EXPORT int DRI2SwapBuffers(ClientPtr client, DrawablePtr pDrawable,
+ CARD64 target_msc, CARD64 divisor,
+ CARD64 remainder, CARD64 *swap_target,
+ DRI2SwapEventPtr func, void *data);
+extern _X_EXPORT Bool DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable);
+
+extern _X_EXPORT int DRI2GetMSC(DrawablePtr pDrawable, CARD64 *ust,
+ CARD64 *msc, CARD64 *sbc);
+extern _X_EXPORT int DRI2WaitMSC(ClientPtr client, DrawablePtr pDrawable,
+ CARD64 target_msc, CARD64 divisor,
+ CARD64 remainder);
+extern _X_EXPORT int ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust,
+ CARD64 msc, CARD64 sbc);
+extern _X_EXPORT int DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw,
+ CARD64 target_sbc, CARD64 *ust, CARD64 *msc,
+ CARD64 *sbc);
+extern _X_EXPORT Bool DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw);
+
+extern _X_EXPORT Bool DRI2CanFlip(DrawablePtr pDraw);
+
+extern _X_EXPORT Bool DRI2CanExchange(DrawablePtr pDraw);
+
+extern _X_EXPORT void DRI2BlockClient(ClientPtr client, DrawablePtr pDraw);
+
+extern _X_EXPORT void DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw,
+ int frame, unsigned int tv_sec,
+ unsigned int tv_usec, int type,
+ DRI2SwapEventPtr swap_complete,
+ void *swap_data);
+extern _X_EXPORT void DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw,
+ int frame, unsigned int tv_sec,
+ unsigned int tv_usec);
+
+#endif