Merge remote branch 'jbarnes/master'
This commit is contained in:
commit
44f9c3d16c
|
@ -754,12 +754,12 @@ RECORDPROTO="recordproto >= 1.13.99.1"
|
||||||
SCRNSAVERPROTO="scrnsaverproto >= 1.1"
|
SCRNSAVERPROTO="scrnsaverproto >= 1.1"
|
||||||
RESOURCEPROTO="resourceproto"
|
RESOURCEPROTO="resourceproto"
|
||||||
DRIPROTO="xf86driproto >= 2.1.0"
|
DRIPROTO="xf86driproto >= 2.1.0"
|
||||||
DRI2PROTO="dri2proto >= 2.1"
|
DRI2PROTO="dri2proto >= 2.2"
|
||||||
XINERAMAPROTO="xineramaproto"
|
XINERAMAPROTO="xineramaproto"
|
||||||
BIGFONTPROTO="xf86bigfontproto >= 1.2.0"
|
BIGFONTPROTO="xf86bigfontproto >= 1.2.0"
|
||||||
XCALIBRATEPROTO="xcalibrateproto"
|
XCALIBRATEPROTO="xcalibrateproto"
|
||||||
DGAPROTO="xf86dgaproto >= 2.0.99.1"
|
DGAPROTO="xf86dgaproto >= 2.0.99.1"
|
||||||
GLPROTO="glproto >= 1.4.9"
|
GLPROTO="glproto >= 1.4.10"
|
||||||
DMXPROTO="dmxproto >= 2.2.99.1"
|
DMXPROTO="dmxproto >= 2.2.99.1"
|
||||||
VIDMODEPROTO="xf86vidmodeproto >= 2.2.99.1"
|
VIDMODEPROTO="xf86vidmodeproto >= 2.2.99.1"
|
||||||
WINDOWSWMPROTO="windowswmproto"
|
WINDOWSWMPROTO="windowswmproto"
|
||||||
|
|
|
@ -82,6 +82,7 @@ static const struct extension_info known_glx_extensions[] = {
|
||||||
{ GLX(SGIX_fbconfig), VER(1,3), Y, },
|
{ GLX(SGIX_fbconfig), VER(1,3), Y, },
|
||||||
{ GLX(SGIX_pbuffer), VER(1,3), Y, },
|
{ GLX(SGIX_pbuffer), VER(1,3), Y, },
|
||||||
{ GLX(SGIX_visual_select_group), VER(0,0), Y, },
|
{ GLX(SGIX_visual_select_group), VER(0,0), Y, },
|
||||||
|
{ GLX(INTEL_swap_event), VER(1,4), N, },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ enum {
|
||||||
SGIX_fbconfig_bit,
|
SGIX_fbconfig_bit,
|
||||||
SGIX_pbuffer_bit,
|
SGIX_pbuffer_bit,
|
||||||
SGIX_visual_select_group_bit,
|
SGIX_visual_select_group_bit,
|
||||||
|
INTEL_swap_event_bit,
|
||||||
__NUM_GLX_EXTS,
|
__NUM_GLX_EXTS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1481,7 +1481,7 @@ int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (pGlxDraw->type == DRAWABLE_WINDOW &&
|
if (pGlxDraw->type == DRAWABLE_WINDOW &&
|
||||||
(*pGlxDraw->swapBuffers)(pGlxDraw) == GL_FALSE)
|
(*pGlxDraw->swapBuffers)(cl->client, pGlxDraw) == GL_FALSE)
|
||||||
return __glXError(GLXBadDrawable);
|
return __glXError(GLXBadDrawable);
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
|
|
|
@ -55,6 +55,10 @@ struct __GLXcontext {
|
||||||
unsigned long mask);
|
unsigned long mask);
|
||||||
int (*forceCurrent) (__GLXcontext *context);
|
int (*forceCurrent) (__GLXcontext *context);
|
||||||
|
|
||||||
|
Bool (*wait) (__GLXcontext *context,
|
||||||
|
__GLXclientState *cl,
|
||||||
|
int *error);
|
||||||
|
|
||||||
__GLXtextureFromPixmap *textureFromPixmap;
|
__GLXtextureFromPixmap *textureFromPixmap;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -45,7 +45,7 @@ enum {
|
||||||
|
|
||||||
struct __GLXdrawable {
|
struct __GLXdrawable {
|
||||||
void (*destroy)(__GLXdrawable *private);
|
void (*destroy)(__GLXdrawable *private);
|
||||||
GLboolean (*swapBuffers)(__GLXdrawable *);
|
GLboolean (*swapBuffers)(ClientPtr client, __GLXdrawable *);
|
||||||
void (*copySubBuffer)(__GLXdrawable *drawable,
|
void (*copySubBuffer)(__GLXdrawable *drawable,
|
||||||
int x, int y, int w, int h);
|
int x, int y, int w, int h);
|
||||||
void (*waitX)(__GLXdrawable *);
|
void (*waitX)(__GLXdrawable *);
|
||||||
|
|
|
@ -245,7 +245,7 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLboolean
|
static GLboolean
|
||||||
__glXDRIdrawableSwapBuffers(__GLXdrawable *basePrivate)
|
__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *basePrivate)
|
||||||
{
|
{
|
||||||
__GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
|
__GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
|
||||||
__GLXDRIscreen *screen =
|
__GLXDRIscreen *screen =
|
||||||
|
|
102
glx/glxdri2.c
102
glx/glxdri2.c
|
@ -70,6 +70,7 @@ struct __GLXDRIscreen {
|
||||||
|
|
||||||
const __DRIcoreExtension *core;
|
const __DRIcoreExtension *core;
|
||||||
const __DRIdri2Extension *dri2;
|
const __DRIdri2Extension *dri2;
|
||||||
|
const __DRI2flushExtension *flush;
|
||||||
const __DRIcopySubBufferExtension *copySubBuffer;
|
const __DRIcopySubBufferExtension *copySubBuffer;
|
||||||
const __DRIswapControlExtension *swapControl;
|
const __DRIswapControlExtension *swapControl;
|
||||||
const __DRItexBufferExtension *texBuffer;
|
const __DRItexBufferExtension *texBuffer;
|
||||||
|
@ -132,17 +133,6 @@ __glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable,
|
||||||
DRI2BufferFrontLeft, DRI2BufferBackLeft);
|
DRI2BufferFrontLeft, DRI2BufferBackLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLboolean
|
|
||||||
__glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
|
|
||||||
{
|
|
||||||
__GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
|
|
||||||
|
|
||||||
__glXDRIdrawableCopySubBuffer(drawable, 0, 0,
|
|
||||||
private->width, private->height);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
__glXDRIdrawableWaitX(__GLXdrawable *drawable)
|
__glXDRIdrawableWaitX(__GLXdrawable *drawable)
|
||||||
{
|
{
|
||||||
|
@ -177,9 +167,74 @@ __glXDRIdrawableWaitGL(__GLXdrawable *drawable)
|
||||||
DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
|
DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
__glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
|
||||||
|
CARD64 msc, CARD64 sbc)
|
||||||
|
{
|
||||||
|
__GLXdrawable *drawable = data;
|
||||||
|
xGLXBufferSwapComplete wire;
|
||||||
|
|
||||||
|
if (!drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wire.type = __glXEventBase + GLX_BufferSwapComplete;
|
||||||
|
switch (type) {
|
||||||
|
case DRI2_EXCHANGE_COMPLETE:
|
||||||
|
wire.event_type = GLX_EXCHANGE_COMPLETE_INTEL;
|
||||||
|
break;
|
||||||
|
case DRI2_BLIT_COMPLETE:
|
||||||
|
wire.event_type = GLX_BLIT_COMPLETE_INTEL;
|
||||||
|
break;
|
||||||
|
case DRI2_FLIP_COMPLETE:
|
||||||
|
wire.event_type = GLX_FLIP_COMPLETE_INTEL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* unknown swap completion type */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wire.sequenceNumber = client->sequence;
|
||||||
|
wire.drawable = drawable->drawId;
|
||||||
|
wire.ust_hi = ust >> 32;
|
||||||
|
wire.ust_lo = ust & 0xffffffff;
|
||||||
|
wire.msc_hi = msc >> 32;
|
||||||
|
wire.msc_lo = msc & 0xffffffff;
|
||||||
|
wire.sbc_hi = sbc >> 32;
|
||||||
|
wire.sbc_lo = sbc & 0xffffffff;
|
||||||
|
|
||||||
|
WriteEventsToClient(client, 1, (xEvent *) &wire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy or flip back to front, honoring the swap interval if possible.
|
||||||
|
*
|
||||||
|
* If the kernel supports it, we request an event for the frame when the
|
||||||
|
* swap should happen, then perform the copy when we receive it.
|
||||||
|
*/
|
||||||
|
static GLboolean
|
||||||
|
__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
|
||||||
|
{
|
||||||
|
__GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
|
||||||
|
__GLXDRIscreen *screen = priv->screen;
|
||||||
|
CARD64 unused;
|
||||||
|
|
||||||
|
if (screen->flush)
|
||||||
|
(*screen->flush->flushInvalidate)(priv->driDrawable);
|
||||||
|
|
||||||
|
if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
|
||||||
|
__glXdriSwapEvent, drawable->pDraw) != Success)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
__glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval)
|
__glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval)
|
||||||
{
|
{
|
||||||
|
if (interval <= 0) /* || interval > BIGNUM? */
|
||||||
|
return GLX_BAD_VALUE;
|
||||||
|
|
||||||
|
DRI2SwapInterval(drawable->pDraw, interval);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,6 +296,18 @@ __glXDRIcontextForceCurrent(__GLXcontext *baseContext)
|
||||||
read->driDrawable);
|
read->driDrawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
__glXDRIcontextWait(__GLXcontext *baseContext,
|
||||||
|
__GLXclientState *cl, int *error)
|
||||||
|
{
|
||||||
|
if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) {
|
||||||
|
*error = cl->client->noClientException;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __DRI_TEX_BUFFER
|
#ifdef __DRI_TEX_BUFFER
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -346,6 +413,7 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
|
||||||
context->base.copy = __glXDRIcontextCopy;
|
context->base.copy = __glXDRIcontextCopy;
|
||||||
context->base.forceCurrent = __glXDRIcontextForceCurrent;
|
context->base.forceCurrent = __glXDRIcontextForceCurrent;
|
||||||
context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
|
context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
|
||||||
|
context->base.wait = __glXDRIcontextWait;
|
||||||
|
|
||||||
context->driContext =
|
context->driContext =
|
||||||
(*screen->dri2->createNewContext)(screen->driScreen,
|
(*screen->dri2->createNewContext)(screen->driScreen,
|
||||||
|
@ -550,6 +618,10 @@ initializeExtensions(__GLXDRIscreen *screen)
|
||||||
"GLX_MESA_copy_sub_buffer");
|
"GLX_MESA_copy_sub_buffer");
|
||||||
LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
|
LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
|
||||||
|
|
||||||
|
/* FIXME: only if DDX supports it */
|
||||||
|
__glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
|
||||||
|
LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
|
||||||
|
|
||||||
for (i = 0; extensions[i]; i++) {
|
for (i = 0; extensions[i]; i++) {
|
||||||
#ifdef __DRI_READ_DRAWABLE
|
#ifdef __DRI_READ_DRAWABLE
|
||||||
if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
|
if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
|
||||||
|
@ -581,6 +653,14 @@ initializeExtensions(__GLXDRIscreen *screen)
|
||||||
LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
|
LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __DRI2_FLUSH
|
||||||
|
if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
|
||||||
|
extensions[i]->version >= __DRI2_FLUSH_VERSION) {
|
||||||
|
screen->flush = (__DRI2flushExtension *) extensions[i];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Ignore unknown extensions */
|
/* Ignore unknown extensions */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLboolean
|
static GLboolean
|
||||||
__glXDRIdrawableSwapBuffers(__GLXdrawable *drawable)
|
__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
|
||||||
{
|
{
|
||||||
__GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
|
__GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
|
||||||
const __DRIcoreExtension *core = private->screen->core;
|
const __DRIcoreExtension *core = private->screen->core;
|
||||||
|
|
|
@ -267,6 +267,7 @@ GLboolean __glXErrorOccured(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __glXErrorBase;
|
static int __glXErrorBase;
|
||||||
|
int __glXEventBase;
|
||||||
|
|
||||||
int __glXError(int error)
|
int __glXError(int error)
|
||||||
{
|
{
|
||||||
|
@ -403,6 +404,7 @@ void GlxExtensionInit(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
__glXErrorBase = extEntry->errorBase;
|
__glXErrorBase = extEntry->errorBase;
|
||||||
|
__glXEventBase = extEntry->eventBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -446,6 +448,9 @@ __GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cx->wait && (*cx->wait)(cx, cl, error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (cx == __glXLastContext) {
|
if (cx == __glXLastContext) {
|
||||||
/* No need to re-bind */
|
/* No need to re-bind */
|
||||||
return cx;
|
return cx;
|
||||||
|
|
|
@ -181,6 +181,7 @@ static char GLXServerExtensions[] =
|
||||||
"GLX_SGIX_fbconfig "
|
"GLX_SGIX_fbconfig "
|
||||||
"GLX_SGIX_pbuffer "
|
"GLX_SGIX_pbuffer "
|
||||||
"GLX_MESA_copy_sub_buffer "
|
"GLX_MESA_copy_sub_buffer "
|
||||||
|
"GLX_INTEL_swap_event"
|
||||||
;
|
;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -56,7 +56,14 @@
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <GL/glxproto.h>
|
#include <GL/glxproto.h>
|
||||||
|
|
||||||
/* For glxscreens.h */
|
/*
|
||||||
|
** GLX resources.
|
||||||
|
*/
|
||||||
|
typedef XID GLXContextID;
|
||||||
|
typedef XID GLXPixmap;
|
||||||
|
typedef XID GLXDrawable;
|
||||||
|
|
||||||
|
typedef struct __GLXclientStateRec __GLXclientState;
|
||||||
typedef struct __GLXdrawable __GLXdrawable;
|
typedef struct __GLXdrawable __GLXdrawable;
|
||||||
typedef struct __GLXcontext __GLXcontext;
|
typedef struct __GLXcontext __GLXcontext;
|
||||||
|
|
||||||
|
@ -71,15 +78,6 @@ typedef struct __GLXcontext __GLXcontext;
|
||||||
#define False 0
|
#define False 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
** GLX resources.
|
|
||||||
*/
|
|
||||||
typedef XID GLXContextID;
|
|
||||||
typedef XID GLXPixmap;
|
|
||||||
typedef XID GLXDrawable;
|
|
||||||
|
|
||||||
typedef struct __GLXclientStateRec __GLXclientState;
|
|
||||||
|
|
||||||
extern __GLXscreen *glxGetScreen(ScreenPtr pScreen);
|
extern __GLXscreen *glxGetScreen(ScreenPtr pScreen);
|
||||||
extern __GLXclientState *glxGetClient(ClientPtr pClient);
|
extern __GLXclientState *glxGetClient(ClientPtr pClient);
|
||||||
|
|
||||||
|
@ -251,4 +249,6 @@ extern int __glXImageSize(GLenum format, GLenum type,
|
||||||
extern unsigned glxMajorVersion;
|
extern unsigned glxMajorVersion;
|
||||||
extern unsigned glxMinorVersion;
|
extern unsigned glxMinorVersion;
|
||||||
|
|
||||||
|
extern int __glXEventBase;
|
||||||
|
|
||||||
#endif /* !__GLX_server_h__ */
|
#endif /* !__GLX_server_h__ */
|
||||||
|
|
|
@ -53,8 +53,6 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap)
|
||||||
|
|
||||||
cx = __glXLookupContextByTag(cl, tag);
|
cx = __glXLookupContextByTag(cl, tag);
|
||||||
|
|
||||||
LogMessage(X_ERROR, "%s: cx = %p, GLX screen = %p\n", __func__,
|
|
||||||
cx, (cx == NULL) ? NULL : cx->pGlxScreen);
|
|
||||||
if ((cx == NULL) || (cx->pGlxScreen == NULL)) {
|
if ((cx == NULL) || (cx->pGlxScreen == NULL)) {
|
||||||
client->errorValue = tag;
|
client->errorValue = tag;
|
||||||
return __glXError(GLXBadContext);
|
return __glXError(GLXBadContext);
|
||||||
|
@ -68,7 +66,7 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap)
|
||||||
|
|
||||||
if (cx->drawPriv == NULL) {
|
if (cx->drawPriv == NULL) {
|
||||||
client->errorValue = tag;
|
client->errorValue = tag;
|
||||||
return __glXError(GLXBadDrawable);
|
return BadValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pc += __GLX_VENDPRIV_HDR_SIZE;
|
pc += __GLX_VENDPRIV_HDR_SIZE;
|
||||||
|
@ -76,6 +74,9 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap)
|
||||||
? bswap_32(*(int *)(pc + 0))
|
? bswap_32(*(int *)(pc + 0))
|
||||||
: *(int *)(pc + 0);
|
: *(int *)(pc + 0);
|
||||||
|
|
||||||
|
if (interval <= 0)
|
||||||
|
return BadValue;
|
||||||
|
|
||||||
(void) (*cx->pGlxScreen->swapInterval)(cx->drawPriv, interval);
|
(void) (*cx->pGlxScreen->swapInterval)(cx->drawPriv, interval);
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,12 @@
|
||||||
#include <xorg-config.h>
|
#include <xorg-config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
#include "xf86Module.h"
|
#include "xf86Module.h"
|
||||||
#include "scrnintstr.h"
|
#include "scrnintstr.h"
|
||||||
#include "windowstr.h"
|
#include "windowstr.h"
|
||||||
|
#include "dixstruct.h"
|
||||||
#include "dri2.h"
|
#include "dri2.h"
|
||||||
#include "xf86VGAarbiter.h"
|
#include "xf86VGAarbiter.h"
|
||||||
|
|
||||||
|
@ -56,9 +58,17 @@ typedef struct _DRI2Drawable {
|
||||||
int height;
|
int height;
|
||||||
DRI2BufferPtr *buffers;
|
DRI2BufferPtr *buffers;
|
||||||
int bufferCount;
|
int bufferCount;
|
||||||
unsigned int pendingSequence;
|
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;
|
} DRI2DrawableRec, *DRI2DrawablePtr;
|
||||||
|
|
||||||
|
typedef struct _DRI2Screen *DRI2ScreenPtr;
|
||||||
|
|
||||||
typedef struct _DRI2Screen {
|
typedef struct _DRI2Screen {
|
||||||
const char *driverName;
|
const char *driverName;
|
||||||
const char *deviceName;
|
const char *deviceName;
|
||||||
|
@ -68,9 +78,12 @@ typedef struct _DRI2Screen {
|
||||||
DRI2CreateBufferProcPtr CreateBuffer;
|
DRI2CreateBufferProcPtr CreateBuffer;
|
||||||
DRI2DestroyBufferProcPtr DestroyBuffer;
|
DRI2DestroyBufferProcPtr DestroyBuffer;
|
||||||
DRI2CopyRegionProcPtr CopyRegion;
|
DRI2CopyRegionProcPtr CopyRegion;
|
||||||
|
DRI2ScheduleSwapProcPtr ScheduleSwap;
|
||||||
|
DRI2GetMSCProcPtr GetMSC;
|
||||||
|
DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC;
|
||||||
|
|
||||||
HandleExposuresProcPtr HandleExposures;
|
HandleExposuresProcPtr HandleExposures;
|
||||||
} DRI2ScreenRec, *DRI2ScreenPtr;
|
} DRI2ScreenRec;
|
||||||
|
|
||||||
static DRI2ScreenPtr
|
static DRI2ScreenPtr
|
||||||
DRI2GetScreen(ScreenPtr pScreen)
|
DRI2GetScreen(ScreenPtr pScreen)
|
||||||
|
@ -84,6 +97,9 @@ DRI2GetDrawable(DrawablePtr pDraw)
|
||||||
WindowPtr pWin;
|
WindowPtr pWin;
|
||||||
PixmapPtr pPixmap;
|
PixmapPtr pPixmap;
|
||||||
|
|
||||||
|
if (!pDraw)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (pDraw->type == DRAWABLE_WINDOW)
|
if (pDraw->type == DRAWABLE_WINDOW)
|
||||||
{
|
{
|
||||||
pWin = (WindowPtr) pDraw;
|
pWin = (WindowPtr) pDraw;
|
||||||
|
@ -119,6 +135,13 @@ DRI2CreateDrawable(DrawablePtr pDraw)
|
||||||
pPriv->height = pDraw->height;
|
pPriv->height = pDraw->height;
|
||||||
pPriv->buffers = NULL;
|
pPriv->buffers = NULL;
|
||||||
pPriv->bufferCount = 0;
|
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)
|
if (pDraw->type == DRAWABLE_WINDOW)
|
||||||
{
|
{
|
||||||
|
@ -308,6 +331,50 @@ DRI2GetBuffersWithFormat(DrawablePtr pDraw, int *width, int *height,
|
||||||
out_count, TRUE);
|
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
|
int
|
||||||
DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
|
DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
|
||||||
unsigned int dest, unsigned int src)
|
unsigned int dest, unsigned int src)
|
||||||
|
@ -338,6 +405,324 @@ DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
|
||||||
return Success;
|
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, ®ion, &box, 0);
|
||||||
|
|
||||||
|
pPriv->swapsPending++;
|
||||||
|
|
||||||
|
(*ds->CopyRegion)(pDraw, ®ion, 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
|
void
|
||||||
DRI2DestroyDrawable(DrawablePtr pDraw)
|
DRI2DestroyDrawable(DrawablePtr pDraw)
|
||||||
{
|
{
|
||||||
|
@ -363,7 +748,11 @@ DRI2DestroyDrawable(DrawablePtr pDraw)
|
||||||
xfree(pPriv->buffers);
|
xfree(pPriv->buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
xfree(pPriv);
|
/* 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)
|
if (pDraw->type == DRAWABLE_WINDOW)
|
||||||
{
|
{
|
||||||
|
@ -421,7 +810,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ds = xalloc(sizeof *ds);
|
ds = xcalloc(1, sizeof *ds);
|
||||||
if (!ds)
|
if (!ds)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -433,6 +822,12 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
|
||||||
ds->DestroyBuffer = info->DestroyBuffer;
|
ds->DestroyBuffer = info->DestroyBuffer;
|
||||||
ds->CopyRegion = info->CopyRegion;
|
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);
|
dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds);
|
||||||
|
|
||||||
xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
|
xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
|
||||||
|
|
|
@ -47,6 +47,9 @@ typedef struct {
|
||||||
} DRI2BufferRec, *DRI2BufferPtr;
|
} DRI2BufferRec, *DRI2BufferPtr;
|
||||||
|
|
||||||
typedef DRI2BufferRec DRI2Buffer2Rec, *DRI2Buffer2Ptr;
|
typedef DRI2BufferRec DRI2Buffer2Rec, *DRI2Buffer2Ptr;
|
||||||
|
typedef void (*DRI2SwapEventPtr)(ClientPtr client, void *data, int type,
|
||||||
|
CARD64 ust, CARD64 msc, CARD64 sbc);
|
||||||
|
|
||||||
|
|
||||||
typedef DRI2BufferPtr (*DRI2CreateBuffersProcPtr)(DrawablePtr pDraw,
|
typedef DRI2BufferPtr (*DRI2CreateBuffersProcPtr)(DrawablePtr pDraw,
|
||||||
unsigned int *attachments,
|
unsigned int *attachments,
|
||||||
|
@ -58,20 +61,98 @@ typedef void (*DRI2CopyRegionProcPtr)(DrawablePtr pDraw,
|
||||||
RegionPtr pRegion,
|
RegionPtr pRegion,
|
||||||
DRI2BufferPtr pDestBuffer,
|
DRI2BufferPtr pDestBuffer,
|
||||||
DRI2BufferPtr pSrcBuffer);
|
DRI2BufferPtr pSrcBuffer);
|
||||||
|
|
||||||
typedef void (*DRI2WaitProcPtr)(WindowPtr pWin,
|
typedef void (*DRI2WaitProcPtr)(WindowPtr pWin,
|
||||||
unsigned int sequence);
|
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,
|
typedef DRI2BufferPtr (*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
|
||||||
unsigned int attachment,
|
unsigned int attachment,
|
||||||
unsigned int format);
|
unsigned int format);
|
||||||
typedef void (*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
|
typedef void (*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
|
||||||
DRI2BufferPtr buffer);
|
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
|
* Version of the DRI2InfoRec structure defined in this header
|
||||||
*/
|
*/
|
||||||
#define DRI2INFOREC_VERSION 3
|
#define DRI2INFOREC_VERSION 4
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int version; /**< Version of this struct */
|
unsigned int version; /**< Version of this struct */
|
||||||
|
@ -83,9 +164,13 @@ typedef struct {
|
||||||
DRI2DestroyBufferProcPtr DestroyBuffer;
|
DRI2DestroyBufferProcPtr DestroyBuffer;
|
||||||
DRI2CopyRegionProcPtr CopyRegion;
|
DRI2CopyRegionProcPtr CopyRegion;
|
||||||
DRI2WaitProcPtr Wait;
|
DRI2WaitProcPtr Wait;
|
||||||
|
DRI2ScheduleSwapProcPtr ScheduleSwap;
|
||||||
|
DRI2GetMSCProcPtr GetMSC;
|
||||||
|
DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC;
|
||||||
} DRI2InfoRec, *DRI2InfoPtr;
|
} DRI2InfoRec, *DRI2InfoPtr;
|
||||||
|
|
||||||
|
extern _X_EXPORT int DRI2EventBase;
|
||||||
|
|
||||||
extern _X_EXPORT Bool DRI2ScreenInit(ScreenPtr pScreen,
|
extern _X_EXPORT Bool DRI2ScreenInit(ScreenPtr pScreen,
|
||||||
DRI2InfoPtr info);
|
DRI2InfoPtr info);
|
||||||
|
|
||||||
|
@ -137,4 +222,38 @@ extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
|
||||||
int *width, int *height, unsigned int *attachments, int count,
|
int *width, int *height, unsigned int *attachments, int count,
|
||||||
int *out_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
|
#endif
|
||||||
|
|
|
@ -259,6 +259,9 @@ ProcDRI2GetBuffers(ClientPtr client)
|
||||||
&pDrawable, &status))
|
&pDrawable, &status))
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
if (DRI2ThrottleClient(client, pDrawable))
|
||||||
|
return client->noClientException;
|
||||||
|
|
||||||
attachments = (unsigned int *) &stuff[1];
|
attachments = (unsigned int *) &stuff[1];
|
||||||
buffers = DRI2GetBuffers(pDrawable, &width, &height,
|
buffers = DRI2GetBuffers(pDrawable, &width, &height,
|
||||||
attachments, stuff->count, &count);
|
attachments, stuff->count, &count);
|
||||||
|
@ -283,6 +286,9 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client)
|
||||||
&pDrawable, &status))
|
&pDrawable, &status))
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
if (DRI2ThrottleClient(client, pDrawable))
|
||||||
|
return client->noClientException;
|
||||||
|
|
||||||
attachments = (unsigned int *) &stuff[1];
|
attachments = (unsigned int *) &stuff[1];
|
||||||
buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
|
buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
|
||||||
attachments, stuff->count, &count);
|
attachments, stuff->count, &count);
|
||||||
|
@ -329,6 +335,204 @@ ProcDRI2CopyRegion(ClientPtr client)
|
||||||
return client->noClientException;
|
return client->noClientException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_swap_reply(xDRI2SwapBuffersReply *rep, CARD64 sbc)
|
||||||
|
{
|
||||||
|
rep->swap_hi = sbc >> 32;
|
||||||
|
rep->swap_lo = sbc & 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CARD64
|
||||||
|
vals_to_card64(CARD32 lo, CARD32 hi)
|
||||||
|
{
|
||||||
|
return (CARD64)hi << 32 | lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc,
|
||||||
|
CARD64 sbc)
|
||||||
|
{
|
||||||
|
xDRI2BufferSwapComplete event;
|
||||||
|
|
||||||
|
event.type = DRI2EventBase + DRI2_BufferSwapComplete;
|
||||||
|
event.sequenceNumber = client->sequence;
|
||||||
|
event.event_type = type;
|
||||||
|
event.ust_hi = (CARD64)ust >> 32;
|
||||||
|
event.ust_lo = ust & 0xffffffff;
|
||||||
|
event.msc_hi = (CARD64)msc >> 32;
|
||||||
|
event.msc_lo = msc & 0xffffffff;
|
||||||
|
event.sbc_hi = (CARD64)sbc >> 32;
|
||||||
|
event.sbc_lo = sbc & 0xffffffff;
|
||||||
|
|
||||||
|
WriteEventsToClient(client, 1, (xEvent *)&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ProcDRI2SwapBuffers(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xDRI2SwapBuffersReq);
|
||||||
|
xDRI2SwapBuffersReply rep;
|
||||||
|
DrawablePtr pDrawable;
|
||||||
|
CARD64 target_msc, divisor, remainder, swap_target;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq);
|
||||||
|
|
||||||
|
if (!validDrawable(client, stuff->drawable,
|
||||||
|
DixReadAccess | DixWriteAccess, &pDrawable, &status))
|
||||||
|
return status;
|
||||||
|
|
||||||
|
target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
|
||||||
|
divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
|
||||||
|
remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
|
||||||
|
|
||||||
|
status = DRI2SwapBuffers(client, pDrawable, target_msc, divisor, remainder,
|
||||||
|
&swap_target, DRI2SwapEvent, pDrawable);
|
||||||
|
if (status != Success)
|
||||||
|
return BadDrawable;
|
||||||
|
|
||||||
|
rep.type = X_Reply;
|
||||||
|
rep.length = 0;
|
||||||
|
rep.sequenceNumber = client->sequence;
|
||||||
|
load_swap_reply(&rep, swap_target);
|
||||||
|
|
||||||
|
WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep);
|
||||||
|
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_msc_reply(xDRI2MSCReply *rep, CARD64 ust, CARD64 msc, CARD64 sbc)
|
||||||
|
{
|
||||||
|
rep->ust_hi = ust >> 32;
|
||||||
|
rep->ust_lo = ust & 0xffffffff;
|
||||||
|
rep->msc_hi = msc >> 32;
|
||||||
|
rep->msc_lo = msc & 0xffffffff;
|
||||||
|
rep->sbc_hi = sbc >> 32;
|
||||||
|
rep->sbc_lo = sbc & 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ProcDRI2GetMSC(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xDRI2GetMSCReq);
|
||||||
|
xDRI2MSCReply rep;
|
||||||
|
DrawablePtr pDrawable;
|
||||||
|
CARD64 ust, msc, sbc;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xDRI2GetMSCReq);
|
||||||
|
|
||||||
|
if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
|
||||||
|
&status))
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = DRI2GetMSC(pDrawable, &ust, &msc, &sbc);
|
||||||
|
if (status != Success)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
rep.type = X_Reply;
|
||||||
|
rep.length = 0;
|
||||||
|
rep.sequenceNumber = client->sequence;
|
||||||
|
load_msc_reply(&rep, ust, msc, sbc);
|
||||||
|
|
||||||
|
WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
|
||||||
|
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ProcDRI2WaitMSC(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xDRI2WaitMSCReq);
|
||||||
|
DrawablePtr pDrawable;
|
||||||
|
CARD64 target, divisor, remainder;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/* FIXME: in restart case, client may be gone at this point */
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xDRI2WaitMSCReq);
|
||||||
|
|
||||||
|
if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
|
||||||
|
&status))
|
||||||
|
return status;
|
||||||
|
|
||||||
|
target = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
|
||||||
|
divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
|
||||||
|
remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
|
||||||
|
|
||||||
|
status = DRI2WaitMSC(client, pDrawable, target, divisor, remainder);
|
||||||
|
if (status != Success)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust, CARD64 msc, CARD64 sbc)
|
||||||
|
{
|
||||||
|
xDRI2MSCReply rep;
|
||||||
|
|
||||||
|
rep.type = X_Reply;
|
||||||
|
rep.length = 0;
|
||||||
|
rep.sequenceNumber = client->sequence;
|
||||||
|
load_msc_reply(&rep, ust, msc, sbc);
|
||||||
|
|
||||||
|
WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
|
||||||
|
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ProcDRI2SwapInterval(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xDRI2SwapIntervalReq);
|
||||||
|
DrawablePtr pDrawable;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/* FIXME: in restart case, client may be gone at this point */
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xDRI2SwapIntervalReq);
|
||||||
|
|
||||||
|
if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
|
||||||
|
&pDrawable, &status))
|
||||||
|
return status;
|
||||||
|
|
||||||
|
DRI2SwapInterval(pDrawable, stuff->interval);
|
||||||
|
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ProcDRI2WaitSBC(ClientPtr client)
|
||||||
|
{
|
||||||
|
REQUEST(xDRI2WaitSBCReq);
|
||||||
|
xDRI2MSCReply rep;
|
||||||
|
DrawablePtr pDrawable;
|
||||||
|
CARD64 target, ust, msc, sbc;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
REQUEST_SIZE_MATCH(xDRI2WaitSBCReq);
|
||||||
|
|
||||||
|
if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
|
||||||
|
&status))
|
||||||
|
return status;
|
||||||
|
|
||||||
|
target = vals_to_card64(stuff->target_sbc_lo, stuff->target_sbc_hi);
|
||||||
|
status = DRI2WaitSBC(client, pDrawable, target, &ust, &msc, &sbc);
|
||||||
|
if (status != Success)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
rep.type = X_Reply;
|
||||||
|
rep.length = 0;
|
||||||
|
rep.sequenceNumber = client->sequence;
|
||||||
|
load_msc_reply(&rep, ust, msc, sbc);
|
||||||
|
|
||||||
|
WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
|
||||||
|
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ProcDRI2Dispatch (ClientPtr client)
|
ProcDRI2Dispatch (ClientPtr client)
|
||||||
{
|
{
|
||||||
|
@ -357,6 +561,16 @@ ProcDRI2Dispatch (ClientPtr client)
|
||||||
return ProcDRI2CopyRegion(client);
|
return ProcDRI2CopyRegion(client);
|
||||||
case X_DRI2GetBuffersWithFormat:
|
case X_DRI2GetBuffersWithFormat:
|
||||||
return ProcDRI2GetBuffersWithFormat(client);
|
return ProcDRI2GetBuffersWithFormat(client);
|
||||||
|
case X_DRI2SwapBuffers:
|
||||||
|
return ProcDRI2SwapBuffers(client);
|
||||||
|
case X_DRI2GetMSC:
|
||||||
|
return ProcDRI2GetMSC(client);
|
||||||
|
case X_DRI2WaitMSC:
|
||||||
|
return ProcDRI2WaitMSC(client);
|
||||||
|
case X_DRI2WaitSBC:
|
||||||
|
return ProcDRI2WaitSBC(client);
|
||||||
|
case X_DRI2SwapInterval:
|
||||||
|
return ProcDRI2SwapInterval(client);
|
||||||
default:
|
default:
|
||||||
return BadRequest;
|
return BadRequest;
|
||||||
}
|
}
|
||||||
|
@ -413,6 +627,8 @@ static int DRI2DrawableGone(pointer p, XID id)
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DRI2EventBase;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DRI2ExtensionInit(void)
|
DRI2ExtensionInit(void)
|
||||||
{
|
{
|
||||||
|
@ -429,6 +645,7 @@ DRI2ExtensionInit(void)
|
||||||
NULL,
|
NULL,
|
||||||
StandardMinorOpcode);
|
StandardMinorOpcode);
|
||||||
|
|
||||||
|
DRI2EventBase = dri2Extension->eventBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern Bool noDRI2Extension;
|
extern Bool noDRI2Extension;
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
|
|
||||||
/* DRI2 */
|
/* DRI2 */
|
||||||
#define SERVER_DRI2_MAJOR_VERSION 1
|
#define SERVER_DRI2_MAJOR_VERSION 1
|
||||||
#define SERVER_DRI2_MINOR_VERSION 1
|
#define SERVER_DRI2_MINOR_VERSION 2
|
||||||
|
|
||||||
/* Generic event extension */
|
/* Generic event extension */
|
||||||
#define SERVER_GE_MAJOR_VERSION 1
|
#define SERVER_GE_MAJOR_VERSION 1
|
||||||
|
|
Loading…
Reference in New Issue
Block a user