diff options
25 files changed, 1164 insertions, 69 deletions
diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index e0ddd48f2..8c1085b29 100644 --- a/xorg-server/configure.ac +++ b/xorg-server/configure.ac @@ -754,12 +754,12 @@ RECORDPROTO="recordproto >= 1.13.99.1" SCRNSAVERPROTO="scrnsaverproto >= 1.1" RESOURCEPROTO="resourceproto" DRIPROTO="xf86driproto >= 2.1.0" -DRI2PROTO="dri2proto >= 2.1" +DRI2PROTO="dri2proto >= 2.2" XINERAMAPROTO="xineramaproto" BIGFONTPROTO="xf86bigfontproto >= 1.2.0" XCALIBRATEPROTO="xcalibrateproto" DGAPROTO="xf86dgaproto >= 2.0.99.1" -GLPROTO="glproto >= 1.4.9" +GLPROTO="glproto >= 1.4.10" DMXPROTO="dmxproto >= 2.2.99.1" VIDMODEPROTO="xf86vidmodeproto >= 2.2.99.1" WINDOWSWMPROTO="windowswmproto" @@ -2112,9 +2112,9 @@ AC_TRY_COMPILE([ AC_DEFINE_DIR(PROJECTROOT, prefix, [Overall prefix]) -BUILD_DATE="$(date +'%Y%m%d')" +BUILD_DATE="`date +'%Y%m%d'`" AC_SUBST([BUILD_DATE]) -BUILD_TIME="$(date +'1%H%M%S')" +BUILD_TIME="`date +'1%H%M%S'`" AC_SUBST([BUILD_TIME]) DIX_CFLAGS="-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS" diff --git a/xorg-server/glx/extension_string.c b/xorg-server/glx/extension_string.c index 9d110cf98..7721cb056 100644 --- a/xorg-server/glx/extension_string.c +++ b/xorg-server/glx/extension_string.c @@ -82,6 +82,7 @@ static const struct extension_info known_glx_extensions[] = { { GLX(SGIX_fbconfig), VER(1,3), Y, }, { GLX(SGIX_pbuffer), VER(1,3), Y, }, { GLX(SGIX_visual_select_group), VER(0,0), Y, }, + { GLX(INTEL_swap_event), VER(1,4), N, }, { NULL } }; diff --git a/xorg-server/glx/extension_string.h b/xorg-server/glx/extension_string.h index 98e91bc18..912534a04 100644 --- a/xorg-server/glx/extension_string.h +++ b/xorg-server/glx/extension_string.h @@ -50,6 +50,7 @@ enum { SGIX_fbconfig_bit, SGIX_pbuffer_bit, SGIX_visual_select_group_bit, + INTEL_swap_event_bit, __NUM_GLX_EXTS, }; diff --git a/xorg-server/glx/glxcmds.c b/xorg-server/glx/glxcmds.c index eedab652f..77afbf4b1 100644 --- a/xorg-server/glx/glxcmds.c +++ b/xorg-server/glx/glxcmds.c @@ -1481,7 +1481,7 @@ int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc) return error; if (pGlxDraw->type == DRAWABLE_WINDOW && - (*pGlxDraw->swapBuffers)(pGlxDraw) == GL_FALSE) + (*pGlxDraw->swapBuffers)(cl->client, pGlxDraw) == GL_FALSE) return __glXError(GLXBadDrawable); return Success; diff --git a/xorg-server/glx/glxcontext.h b/xorg-server/glx/glxcontext.h index 70a14115d..79bc083a8 100644 --- a/xorg-server/glx/glxcontext.h +++ b/xorg-server/glx/glxcontext.h @@ -55,6 +55,10 @@ struct __GLXcontext { unsigned long mask); int (*forceCurrent) (__GLXcontext *context); + Bool (*wait) (__GLXcontext *context, + __GLXclientState *cl, + int *error); + __GLXtextureFromPixmap *textureFromPixmap; /* diff --git a/xorg-server/glx/glxdrawable.h b/xorg-server/glx/glxdrawable.h index 3f165ed4f..2a365c505 100644 --- a/xorg-server/glx/glxdrawable.h +++ b/xorg-server/glx/glxdrawable.h @@ -45,7 +45,7 @@ enum { struct __GLXdrawable { void (*destroy)(__GLXdrawable *private); - GLboolean (*swapBuffers)(__GLXdrawable *); + GLboolean (*swapBuffers)(ClientPtr client, __GLXdrawable *); void (*copySubBuffer)(__GLXdrawable *drawable, int x, int y, int w, int h); void (*waitX)(__GLXdrawable *); diff --git a/xorg-server/glx/glxdri.c b/xorg-server/glx/glxdri.c index 6122653b0..21e44d12d 100644 --- a/xorg-server/glx/glxdri.c +++ b/xorg-server/glx/glxdri.c @@ -245,7 +245,7 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable) } static GLboolean -__glXDRIdrawableSwapBuffers(__GLXdrawable *basePrivate) +__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *basePrivate) { __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate; __GLXDRIscreen *screen = diff --git a/xorg-server/glx/glxdri2.c b/xorg-server/glx/glxdri2.c index ed7dc80ba..69fd39b3b 100644 --- a/xorg-server/glx/glxdri2.c +++ b/xorg-server/glx/glxdri2.c @@ -70,6 +70,7 @@ struct __GLXDRIscreen { const __DRIcoreExtension *core; const __DRIdri2Extension *dri2; + const __DRI2flushExtension *flush; const __DRIcopySubBufferExtension *copySubBuffer; const __DRIswapControlExtension *swapControl; const __DRItexBufferExtension *texBuffer; @@ -132,17 +133,6 @@ __glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable, DRI2BufferFrontLeft, DRI2BufferBackLeft); } -static GLboolean -__glXDRIdrawableSwapBuffers(__GLXdrawable *drawable) -{ - __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; - - __glXDRIdrawableCopySubBuffer(drawable, 0, 0, - private->width, private->height); - - return TRUE; -} - static void __glXDRIdrawableWaitX(__GLXdrawable *drawable) { @@ -177,9 +167,74 @@ __glXDRIdrawableWaitGL(__GLXdrawable *drawable) 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 __glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval) { + if (interval <= 0) /* || interval > BIGNUM? */ + return GLX_BAD_VALUE; + + DRI2SwapInterval(drawable->pDraw, interval); + return 0; } @@ -241,6 +296,18 @@ __glXDRIcontextForceCurrent(__GLXcontext *baseContext) 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 static int @@ -346,6 +413,7 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen, context->base.copy = __glXDRIcontextCopy; context->base.forceCurrent = __glXDRIcontextForceCurrent; context->base.textureFromPixmap = &__glXDRItextureFromPixmap; + context->base.wait = __glXDRIcontextWait; context->driContext = (*screen->dri2->createNewContext)(screen->driScreen, @@ -550,6 +618,10 @@ initializeExtensions(__GLXDRIscreen *screen) "GLX_MESA_copy_sub_buffer"); 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++) { #ifdef __DRI_READ_DRAWABLE 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"); } #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 */ } } diff --git a/xorg-server/glx/glxdriswrast.c b/xorg-server/glx/glxdriswrast.c index 20f9f90d6..c647d83ca 100644 --- a/xorg-server/glx/glxdriswrast.c +++ b/xorg-server/glx/glxdriswrast.c @@ -108,7 +108,7 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable) } static GLboolean -__glXDRIdrawableSwapBuffers(__GLXdrawable *drawable) +__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable) { __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; const __DRIcoreExtension *core = private->screen->core; diff --git a/xorg-server/glx/glxext.c b/xorg-server/glx/glxext.c index 751ea7297..59bcfbed2 100644 --- a/xorg-server/glx/glxext.c +++ b/xorg-server/glx/glxext.c @@ -267,6 +267,7 @@ GLboolean __glXErrorOccured(void) } static int __glXErrorBase; +int __glXEventBase; int __glXError(int error) { @@ -403,6 +404,7 @@ void GlxExtensionInit(void) } __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) { /* No need to re-bind */ return cx; diff --git a/xorg-server/glx/glxscreens.c b/xorg-server/glx/glxscreens.c index 674e2c681..58d8ee0b4 100644 --- a/xorg-server/glx/glxscreens.c +++ b/xorg-server/glx/glxscreens.c @@ -181,6 +181,7 @@ static char GLXServerExtensions[] = "GLX_SGIX_fbconfig " "GLX_SGIX_pbuffer " "GLX_MESA_copy_sub_buffer " + "GLX_INTEL_swap_event" ; /* diff --git a/xorg-server/glx/glxserver.h b/xorg-server/glx/glxserver.h index 80f1b28f9..1daf97758 100644 --- a/xorg-server/glx/glxserver.h +++ b/xorg-server/glx/glxserver.h @@ -56,7 +56,14 @@ #include <GL/gl.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 __GLXcontext __GLXcontext; @@ -71,15 +78,6 @@ typedef struct __GLXcontext __GLXcontext; #define False 0 #endif -/* -** GLX resources. -*/ -typedef XID GLXContextID; -typedef XID GLXPixmap; -typedef XID GLXDrawable; - -typedef struct __GLXclientStateRec __GLXclientState; - extern __GLXscreen *glxGetScreen(ScreenPtr pScreen); extern __GLXclientState *glxGetClient(ClientPtr pClient); @@ -251,4 +249,6 @@ extern int __glXImageSize(GLenum format, GLenum type, extern unsigned glxMajorVersion; extern unsigned glxMinorVersion; +extern int __glXEventBase; + #endif /* !__GLX_server_h__ */ diff --git a/xorg-server/glx/swap_interval.c b/xorg-server/glx/swap_interval.c index 3a5242022..0bae3247e 100644 --- a/xorg-server/glx/swap_interval.c +++ b/xorg-server/glx/swap_interval.c @@ -53,8 +53,6 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap) 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)) { client->errorValue = tag; return __glXError(GLXBadContext); @@ -68,7 +66,7 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap) if (cx->drawPriv == NULL) { client->errorValue = tag; - return __glXError(GLXBadDrawable); + return BadValue; } pc += __GLX_VENDPRIV_HDR_SIZE; @@ -76,6 +74,9 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap) ? bswap_32(*(int *)(pc + 0)) : *(int *)(pc + 0); + if (interval <= 0) + return BadValue; + (void) (*cx->pGlxScreen->swapInterval)(cx->drawPriv, interval); return Success; } diff --git a/xorg-server/hw/kdrive/linux/Makefile.am b/xorg-server/hw/kdrive/linux/Makefile.am index fe4a3d183..93e5d2f9f 100644 --- a/xorg-server/hw/kdrive/linux/Makefile.am +++ b/xorg-server/hw/kdrive/linux/Makefile.am @@ -8,7 +8,7 @@ noinst_LTLIBRARIES = liblinux.la liblinux_la_SOURCES = -liblinux_la_SOURCES += linux.c klinux.h +liblinux_la_SOURCES += linux.c if KDRIVE_KBD liblinux_la_SOURCES += keyboard.c diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.c b/xorg-server/hw/xfree86/common/xf86Xinput.c index 57db056d8..df774a155 100644 --- a/xorg-server/hw/xfree86/common/xf86Xinput.c +++ b/xorg-server/hw/xfree86/common/xf86Xinput.c @@ -121,7 +121,7 @@ ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, /* common settings (available via device properties) */ tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); - if(tempf > 1.0){ + if (tempf > 1.0) { xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", devname, tempf); prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); @@ -130,7 +130,7 @@ ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, } tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); - if(tempf > 1.0){ + if (tempf > 1.0) { xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", devname, tempf); prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); @@ -144,8 +144,7 @@ ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, - PropModeReplace, 1, &tempi, FALSE) == Success) - { + PropModeReplace, 1, &tempi, FALSE) == Success) { xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, tempi); } else { @@ -156,20 +155,19 @@ ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, /* set scaling */ tempf = xf86SetRealOption(list, "ExpectedRate", 0); prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); - if(tempf > 0){ + if (tempf > 0) { tempf = 1000.0 / tempf; XIChangeDeviceProperty(pDev, prop, float_prop, 32, PropModeReplace, 1, &tempf, FALSE); - }else{ + } else { tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); XIChangeDeviceProperty(pDev, prop, float_prop, 32, PropModeReplace, 1, &tempf, FALSE); } tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); - if(tempi > 1){ + if (tempi > 1) InitTrackers(s, tempi); - } s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", s->initial_range); @@ -177,7 +175,7 @@ ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); - if(tempf >= 0){ + if (tempf >= 0) { xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", devname, tempf*100.0); s->max_rel_diff = tempf; @@ -198,40 +196,40 @@ ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, static void ApplyAccelerationSettings(DeviceIntPtr dev){ - int scheme; + int scheme, i; DeviceVelocityPtr pVel; LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; char* schemeStr; - if(dev->valuator){ + if (dev->valuator && dev->ptrfeed) { schemeStr = xf86SetStrOption(local->options, "AccelerationScheme", ""); scheme = dev->valuator->accelScheme.number; - if(!xf86NameCmp(schemeStr, "predictable")) + if (!xf86NameCmp(schemeStr, "predictable")) scheme = PtrAccelPredictable; - if(!xf86NameCmp(schemeStr, "lightweight")) + if (!xf86NameCmp(schemeStr, "lightweight")) scheme = PtrAccelLightweight; - if(!xf86NameCmp(schemeStr, "none")) + if (!xf86NameCmp(schemeStr, "none")) scheme = PtrAccelNoOp; /* reinit scheme if needed */ - if(dev->valuator->accelScheme.number != scheme){ - if(dev->valuator->accelScheme.AccelCleanupProc){ + if (dev->valuator->accelScheme.number != scheme) { + if (dev->valuator->accelScheme.AccelCleanupProc) { dev->valuator->accelScheme.AccelCleanupProc(dev); } - if(InitPointerAccelerationScheme(dev, scheme)){ + if (InitPointerAccelerationScheme(dev, scheme)) { xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", local->name, schemeStr, scheme); - }else{ + } else { xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", local->name, schemeStr); scheme = dev->valuator->accelScheme.number; } - }else{ + } else { xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", local->name, scheme); } @@ -239,13 +237,37 @@ ApplyAccelerationSettings(DeviceIntPtr dev){ xfree(schemeStr); /* process special configuration */ - switch(scheme){ + switch (scheme) { case PtrAccelPredictable: pVel = GetDevicePredictableAccelData(dev); ProcessVelocityConfiguration (dev, local->name, local->options, pVel); break; } + + i = xf86SetIntOption(local->options, "AccelerationNumerator", + dev->ptrfeed->ctrl.num); + if (i >= 0) + dev->ptrfeed->ctrl.num = i; + + i = xf86SetIntOption(local->options, "AccelerationDenominator", + dev->ptrfeed->ctrl.den); + if (i > 0) + dev->ptrfeed->ctrl.den = i; + + i = xf86SetIntOption(local->options, "AccelerationThreshold", + dev->ptrfeed->ctrl.threshold); + if (i >= 0) + dev->ptrfeed->ctrl.threshold = i; + + /* mostly a no-op anyway */ + (*dev->ptrfeed->CtrlProc)(dev, &dev->ptrfeed->ctrl); + + xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", + local->name, ((float)dev->ptrfeed->ctrl.num)/ + ((float)dev->ptrfeed->ctrl.den)); + xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", + local->name, dev->ptrfeed->ctrl.threshold); } } diff --git a/xorg-server/hw/xfree86/doc/man/xorg.conf.man.pre b/xorg-server/hw/xfree86/doc/man/xorg.conf.man.pre index 5b98bda63..222530b41 100644 --- a/xorg-server/hw/xfree86/doc/man/xorg.conf.man.pre +++ b/xorg-server/hw/xfree86/doc/man/xorg.conf.man.pre @@ -914,7 +914,72 @@ X Input extension. This option controls the startup behavior only, a device may be reattached or set floating at runtime. .TP 7 .BI "Option \*qSendDragEvents\*q \*q" boolean \*q -??? +Send core events while dragging. Enabled by default. +.PP +For pointing devices, the following options control how the pointer +is accelerated or decelerated with respect to physical device motion. Most of +these can be adjusted at runtime, see the xinput(1) man page for details. Only +the most important acceleration options are discussed here. +.TP 7 +.BI "Option \*qAccelerationProfile\*q \*q" integer \*q +Select the profile. In layman's terms, the profile constitutes the "feeling" of +the acceleration. More formally, it defines how the transfer function (actual +acceleration as a function of current device velocity and acceleration controls) +is constructed. This is mainly a matter of personal preference. +.PP +.RS 6 +.nf +.B " 0 classic (mostly compatible)" +.B "-1 none (only constant deceleration is applied)" +.B " 1 device-dependent" +.B " 2 polynomial (polynomial function)" +.B " 3 smooth linear (soft knee, then linear)" +.B " 4 simple (normal when slow, otherwise accelerated)" +.B " 5 power (power function)" +.B " 6 linear (more speed, more acceleration)" +.B " 7 limited (like linear, but maxes out at threshold)" +.fi +.RE +.TP 7 +.BI "Option \*qConstantDeceleration\*q \*q" real \*q +Makes the pointer go +.B deceleration +times slower than normal. Most useful for high-resolution devices. +.TP 7 +.BI "Option \*qAdaptiveDeceleration\*q \*q" real \*q +Allows to actually decelerate the pointer when going slow. At most, it will be +.B adaptive deceleration +times slower. Enables precise pointer placement without sacrificing speed. +.TP 7 +.BI "Option \*qAccelerationScheme\*q \*q" string \*q +Selects the scheme, which is the underlying algorithm. +.PP +.RS 7 +.nf +.B "predictable default algorithm (behaving more predictable)" +.B "lightweight old acceleration code (as specified in the X protocol spec)" +.B "none no acceleration or deceleration" +.fi +.RE +.TP 7 +.BI "Option \*qAccelerationNumerator\*q \*q" integer \*q +.TP 7 +.BI "Option \*qAccelerationDenominator\*q \*q" integer \*q +Set numerator and denominator of the acceleration factor. The acceleration +factor is a rational which, together with threshold, can be used to tweak +profiles to suit the users needs. The +.B simple +and +.B limited +profiles use it directly (i.e. they accelerate by the factor), for other +profiles it should hold that a higher acceleration factor leads to a faster +pointer. Typically, 1 is unaccelerated and values up to 5 are sensible. +.TP 7 +.BI "Option \*qAccelerationThreshold\*q \*q" integer \*q +Set the threshold, which is roughly the velocity (usually device units per 10 +ms) required for acceleration to become effective. The precise effect varies +with the profile however. + .SH "INPUTCLASS SECTION" The config file may have multiple .B InputClass diff --git a/xorg-server/hw/xfree86/dri2/dri2.c b/xorg-server/hw/xfree86/dri2/dri2.c index d15ced112..3db826e91 100644 --- a/xorg-server/hw/xfree86/dri2/dri2.c +++ b/xorg-server/hw/xfree86/dri2/dri2.c @@ -34,10 +34,12 @@ #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" @@ -56,9 +58,17 @@ typedef struct _DRI2Drawable { int height; DRI2BufferPtr *buffers; 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; +typedef struct _DRI2Screen *DRI2ScreenPtr; + typedef struct _DRI2Screen { const char *driverName; const char *deviceName; @@ -68,9 +78,12 @@ typedef struct _DRI2Screen { DRI2CreateBufferProcPtr CreateBuffer; DRI2DestroyBufferProcPtr DestroyBuffer; DRI2CopyRegionProcPtr CopyRegion; + DRI2ScheduleSwapProcPtr ScheduleSwap; + DRI2GetMSCProcPtr GetMSC; + DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC; HandleExposuresProcPtr HandleExposures; -} DRI2ScreenRec, *DRI2ScreenPtr; +} DRI2ScreenRec; static DRI2ScreenPtr DRI2GetScreen(ScreenPtr pScreen) @@ -84,6 +97,9 @@ DRI2GetDrawable(DrawablePtr pDraw) WindowPtr pWin; PixmapPtr pPixmap; + if (!pDraw) + return NULL; + if (pDraw->type == DRAWABLE_WINDOW) { pWin = (WindowPtr) pDraw; @@ -119,6 +135,13 @@ DRI2CreateDrawable(DrawablePtr pDraw) 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) { @@ -308,6 +331,50 @@ DRI2GetBuffersWithFormat(DrawablePtr pDraw, int *width, int *height, 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) @@ -338,6 +405,324 @@ DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, 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 DRI2DestroyDrawable(DrawablePtr pDraw) { @@ -363,7 +748,11 @@ DRI2DestroyDrawable(DrawablePtr pDraw) 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) { @@ -421,7 +810,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) return FALSE; } - ds = xalloc(sizeof *ds); + ds = xcalloc(1, sizeof *ds); if (!ds) return FALSE; @@ -433,6 +822,12 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) 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"); diff --git a/xorg-server/hw/xfree86/dri2/dri2.h b/xorg-server/hw/xfree86/dri2/dri2.h index 175471aae..dd59297df 100644 --- a/xorg-server/hw/xfree86/dri2/dri2.h +++ b/xorg-server/hw/xfree86/dri2/dri2.h @@ -47,6 +47,9 @@ typedef struct { } 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, @@ -58,20 +61,98 @@ 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 3 +#define DRI2INFOREC_VERSION 4 typedef struct { unsigned int version; /**< Version of this struct */ @@ -83,9 +164,13 @@ typedef struct { 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); @@ -137,4 +222,38 @@ 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 diff --git a/xorg-server/hw/xfree86/dri2/dri2ext.c b/xorg-server/hw/xfree86/dri2/dri2ext.c index 7d6064acb..3e6b03e4e 100644 --- a/xorg-server/hw/xfree86/dri2/dri2ext.c +++ b/xorg-server/hw/xfree86/dri2/dri2ext.c @@ -259,6 +259,9 @@ ProcDRI2GetBuffers(ClientPtr client) &pDrawable, &status)) return status; + if (DRI2ThrottleClient(client, pDrawable)) + return client->noClientException; + attachments = (unsigned int *) &stuff[1]; buffers = DRI2GetBuffers(pDrawable, &width, &height, attachments, stuff->count, &count); @@ -283,6 +286,9 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client) &pDrawable, &status)) return status; + if (DRI2ThrottleClient(client, pDrawable)) + return client->noClientException; + attachments = (unsigned int *) &stuff[1]; buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height, attachments, stuff->count, &count); @@ -329,6 +335,204 @@ ProcDRI2CopyRegion(ClientPtr client) 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 ProcDRI2Dispatch (ClientPtr client) { @@ -357,6 +561,16 @@ ProcDRI2Dispatch (ClientPtr client) return ProcDRI2CopyRegion(client); case X_DRI2GetBuffersWithFormat: 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: return BadRequest; } @@ -413,6 +627,8 @@ static int DRI2DrawableGone(pointer p, XID id) return Success; } +int DRI2EventBase; + static void DRI2ExtensionInit(void) { @@ -429,6 +645,7 @@ DRI2ExtensionInit(void) NULL, StandardMinorOpcode); + DRI2EventBase = dri2Extension->eventBase; } extern Bool noDRI2Extension; diff --git a/xorg-server/hw/xfree86/x86emu/Makefile.am b/xorg-server/hw/xfree86/x86emu/Makefile.am index e7368f531..df9697767 100644 --- a/xorg-server/hw/xfree86/x86emu/Makefile.am +++ b/xorg-server/hw/xfree86/x86emu/Makefile.am @@ -11,7 +11,7 @@ libx86emu_la_SOURCES = debug.c \ sys.c \ x86emu.h -INCLUDES = $(XORG_INCS) +INCLUDES = AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) diff --git a/xorg-server/hw/xfree86/x86emu/sys.c b/xorg-server/hw/xfree86/x86emu/sys.c index 2ebf6f157..e15fb0931 100644 --- a/xorg-server/hw/xfree86/x86emu/sys.c +++ b/xorg-server/hw/xfree86/x86emu/sys.c @@ -48,13 +48,168 @@ #ifndef NO_SYS_HEADERS #include <string.h> #endif -#include "compiler.h" /* for unaligned access functions */ /*------------------------- Global Variables ------------------------------*/ X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */ X86EMU_intrFuncs _X86EMU_intrTab[256]; /*----------------------------- Implementation ----------------------------*/ +#if defined(__alpha__) || defined(__alpha) +/* to cope with broken egcs-1.1.2 :-(((( */ + +#define ALPHA_UALOADS +/* + * inline functions to do unaligned accesses + * from linux/include/asm-alpha/unaligned.h + */ + +/* + * EGCS 1.1 knows about arbitrary unaligned loads. Define some + * packed structures to talk about such things with. + */ + +#if defined(__GNUC__) +struct __una_u64 { unsigned long x __attribute__((packed)); }; +struct __una_u32 { unsigned int x __attribute__((packed)); }; +struct __una_u16 { unsigned short x __attribute__((packed)); }; +#endif + +static __inline__ unsigned long ldq_u(unsigned long * r11) +{ +#if defined(__GNUC__) + const struct __una_u64 *ptr = (const struct __una_u64 *) r11; + return ptr->x; +#else + unsigned long r1,r2; + __asm__("ldq_u %0,%3\n\t" + "ldq_u %1,%4\n\t" + "extql %0,%2,%0\n\t" + "extqh %1,%2,%1" + :"=&r" (r1), "=&r" (r2) + :"r" (r11), + "m" (*r11), + "m" (*(const unsigned long *)(7+(char *) r11))); + return r1 | r2; +#endif +} + +static __inline__ unsigned long ldl_u(unsigned int * r11) +{ +#if defined(__GNUC__) + const struct __una_u32 *ptr = (const struct __una_u32 *) r11; + return ptr->x; +#else + unsigned long r1,r2; + __asm__("ldq_u %0,%3\n\t" + "ldq_u %1,%4\n\t" + "extll %0,%2,%0\n\t" + "extlh %1,%2,%1" + :"=&r" (r1), "=&r" (r2) + :"r" (r11), + "m" (*r11), + "m" (*(const unsigned long *)(3+(char *) r11))); + return r1 | r2; +#endif +} + +static __inline__ unsigned long ldw_u(unsigned short * r11) +{ +#if defined(__GNUC__) + const struct __una_u16 *ptr = (const struct __una_u16 *) r11; + return ptr->x; +#else + unsigned long r1,r2; + __asm__("ldq_u %0,%3\n\t" + "ldq_u %1,%4\n\t" + "extwl %0,%2,%0\n\t" + "extwh %1,%2,%1" + :"=&r" (r1), "=&r" (r2) + :"r" (r11), + "m" (*r11), + "m" (*(const unsigned long *)(1+(char *) r11))); + return r1 | r2; +#endif +} + +/* + * Elemental unaligned stores + */ + +static __inline__ void stq_u(unsigned long r5, unsigned long * r11) +{ +#if defined(__GNUC__) + struct __una_u64 *ptr = (struct __una_u64 *) r11; + ptr->x = r5; +#else + unsigned long r1,r2,r3,r4; + + __asm__("ldq_u %3,%1\n\t" + "ldq_u %2,%0\n\t" + "insqh %6,%7,%5\n\t" + "insql %6,%7,%4\n\t" + "mskqh %3,%7,%3\n\t" + "mskql %2,%7,%2\n\t" + "bis %3,%5,%3\n\t" + "bis %2,%4,%2\n\t" + "stq_u %3,%1\n\t" + "stq_u %2,%0" + :"=m" (*r11), + "=m" (*(unsigned long *)(7+(char *) r11)), + "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4) + :"r" (r5), "r" (r11)); +#endif +} + +static __inline__ void stl_u(unsigned long r5, unsigned int * r11) +{ +#if defined(__GNUC__) + struct __una_u32 *ptr = (struct __una_u32 *) r11; + ptr->x = r5; +#else + unsigned long r1,r2,r3,r4; + + __asm__("ldq_u %3,%1\n\t" + "ldq_u %2,%0\n\t" + "inslh %6,%7,%5\n\t" + "insll %6,%7,%4\n\t" + "msklh %3,%7,%3\n\t" + "mskll %2,%7,%2\n\t" + "bis %3,%5,%3\n\t" + "bis %2,%4,%2\n\t" + "stq_u %3,%1\n\t" + "stq_u %2,%0" + :"=m" (*r11), + "=m" (*(unsigned long *)(3+(char *) r11)), + "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4) + :"r" (r5), "r" (r11)); +#endif +} + +static __inline__ void stw_u(unsigned long r5, unsigned short * r11) +{ +#if defined(__GNUC__) + struct __una_u16 *ptr = (struct __una_u16 *) r11; + ptr->x = r5; +#else + unsigned long r1,r2,r3,r4; + + __asm__("ldq_u %3,%1\n\t" + "ldq_u %2,%0\n\t" + "inswh %6,%7,%5\n\t" + "inswl %6,%7,%4\n\t" + "mskwh %3,%7,%3\n\t" + "mskwl %2,%7,%2\n\t" + "bis %3,%5,%3\n\t" + "bis %2,%4,%2\n\t" + "stq_u %3,%1\n\t" + "stq_u %2,%0" + :"=m" (*r11), + "=m" (*(unsigned long *)(1+(char *) r11)), + "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4) + :"r" (r5), "r" (r11)); +#endif +} +#endif /**************************************************************************** PARAMETERS: @@ -107,7 +262,13 @@ u16 X86API rdw( } else #endif +#if defined(ALPHA_UALOADS) val = ldw_u((u16*)(M.mem_base + addr)); +#elif defined(IA64_UALOADS) + val = uldw((u16*)(M.mem_base + addr)); +#else + val = *(u16*)(M.mem_base + addr); +#endif DB( if (DEBUG_MEM_TRACE()) printk("%#08x 2 -> %#x\n", addr, val);) return val; @@ -140,7 +301,13 @@ u32 X86API rdl( } else #endif +#if defined(ALPHA_UALOADS) val = ldl_u((u32*)(M.mem_base + addr)); +#elif defined(IA64_UALOADS) + val = uldl((u32*)(M.mem_base + addr)); +#else + val = *(u32*)(M.mem_base + addr); +#endif DB( if (DEBUG_MEM_TRACE()) printk("%#08x 4 -> %#x\n", addr, val);) return val; @@ -192,7 +359,13 @@ DB( if (DEBUG_MEM_TRACE()) } else #endif +#if defined(ALPHA_UALOADS) stw_u(val,(u16*)(M.mem_base + addr)); +#elif defined(IA64_UALOADS) + ustw(val,(u16*)(M.mem_base + addr)); +#else + *(u16*)(M.mem_base + addr) = val; +#endif } /**************************************************************************** @@ -222,7 +395,13 @@ DB( if (DEBUG_MEM_TRACE()) } else #endif +#if defined(ALPHA_UALOADS) stl_u(val,(u32*)(M.mem_base + addr)); +#elif defined(IA64_UALOADS) + ustl(val,(u32*)(M.mem_base + addr)); +#else + *(u32*)(M.mem_base + addr) = val; +#endif } /**************************************************************************** diff --git a/xorg-server/hw/xquartz/bundle/Info.plist.cpp b/xorg-server/hw/xquartz/bundle/Info.plist.cpp index 87214f456..e89d985f4 100644 --- a/xorg-server/hw/xquartz/bundle/Info.plist.cpp +++ b/xorg-server/hw/xquartz/bundle/Info.plist.cpp @@ -35,9 +35,9 @@ <string>http://xquartz.macosforge.org/downloads/sparkle/release.xml</string> #endif <key>NSHumanReadableCopyright</key> - <string>© 2003-2009 Apple Inc. + <string>© 2003-2010 Apple Inc. © 2003 XFree86 Project, Inc. -© 2003-2009 X.org Foundation, Inc. +© 2003-2010 X.org Foundation, Inc. </string> <key>NSMainNibFile</key> <string>main</string> diff --git a/xorg-server/hw/xquartz/quartzKeyboard.c b/xorg-server/hw/xquartz/quartzKeyboard.c index 62b2ebbdf..96b5fa5b6 100644 --- a/xorg-server/hw/xquartz/quartzKeyboard.c +++ b/xorg-server/hw/xquartz/quartzKeyboard.c @@ -260,6 +260,7 @@ static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) { break; case XK_Mode_switch: + ErrorF("DarwinBuildModifierMaps: XK_Mode_switch encountered, unable to determine side.\n"); info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; #ifdef NX_MODIFIERKEY_RALTERNATE info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i; @@ -388,7 +389,6 @@ void DarwinKeyboardReloadHandler(void) { pthread_mutex_lock(&keyInfo_mutex); { /* Initialize our keySyms */ - DarwinBuildModifierMaps(&keyInfo); keySyms.map = keyInfo.keyMap; keySyms.mapWidth = GLYPHS_PER_KEY; keySyms.minKeyCode = MIN_KEYCODE; @@ -808,5 +808,7 @@ Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) { } } + DarwinBuildModifierMaps(info); + return TRUE; } diff --git a/xorg-server/hw/xquartz/xpr/x-hook.c b/xorg-server/hw/xquartz/xpr/x-hook.c index 03e7f8553..5b850fe88 100644 --- a/xorg-server/hw/xquartz/xpr/x-hook.c +++ b/xorg-server/hw/xquartz/xpr/x-hook.c @@ -79,6 +79,9 @@ X_PFX (hook_run) (x_list *lst, void *arg) void **data; int length, i; + if(!lst) + return; + length = X_PFX (list_length) (lst); fun = xalloc (sizeof (x_hook_function *) * length); data = xalloc (sizeof (void *) * length); diff --git a/xorg-server/include/protocol-versions.h b/xorg-server/include/protocol-versions.h index d688c66b5..c74b7faf0 100644 --- a/xorg-server/include/protocol-versions.h +++ b/xorg-server/include/protocol-versions.h @@ -53,7 +53,7 @@ /* DRI2 */ #define SERVER_DRI2_MAJOR_VERSION 1 -#define SERVER_DRI2_MINOR_VERSION 1 +#define SERVER_DRI2_MINOR_VERSION 2 /* Generic event extension */ #define SERVER_GE_MAJOR_VERSION 1 |