From: Francisco J. <cur...@ri...> - 2010-01-16 21:59:08
|
The current buffer validation approach (AKA the DRI2 glViewport hack) is both incorrect (because a compliant OpenGL application may opt for the identity as viewport transform and work with window coordinates directly) and inefficient (some programs have the habit of calling glViewport several times per frame (e.g. OpenArena), causing many unnecessary roundtrips). This changeset gives DRI2 the ability to report drawable changes in an asynchronous way, but it's a bit intrusive so I expect all sorts of complaints to come. I've tested this with the gallium and classic nouveau drivers, using direct and indirect rendering, with single and double buffered apps, with older X servers, and it seems to work... I'm open to any comments. [dri2proto patch 1/3] Define an event to notify clients about the validity of their buffers. [dri2proto patch 2/3] More useful names for the DRI2_*_COMPLETE tokens. [dri2proto patch 3/3] Bump the package version. [xserver patch 1/6] Add a PreConfigureWindow hook. [xserver patch 2/6] dri2: No need to blit from front on DRI2GetBuffers if they're just being reused. [xserver patch 3/6] dri2: Add a type parameter to SwapBuffers. [xserver patch 4/6] glx: Enforce a 1:1 correspondence between GLX and X11 windows. [xserver patch 5/6] glx/dri2: Notify the driver when its buffers become invalid. [xserver patch 6/6] dri2: Support the DRI2InvalidateBuffers event. [mesa patch 1/3] dri2: Event driven buffer validation. [mesa patch 2/3] dri/nouveau: Use event driven buffer validation. [mesa patch 3/3] st/dri2: Use event-driven buffer validation. |
From: Francisco J. <cur...@ri...> - 2010-01-16 21:59:12
|
Bumps the protocol version. Signed-off-by: Francisco Jerez <cur...@ri...> --- dri2proto.h | 19 +++++++++++++++++-- dri2proto.txt | 31 ++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/dri2proto.h b/dri2proto.h index 43152c2..9708a4a 100644 --- a/dri2proto.h +++ b/dri2proto.h @@ -35,10 +35,10 @@ #define DRI2_NAME "DRI2" #define DRI2_MAJOR 1 -#define DRI2_MINOR 2 +#define DRI2_MINOR 3 #define DRI2NumberErrors 0 -#define DRI2NumberEvents 1 +#define DRI2NumberEvents 2 #define DRI2NumberRequests 13 #define X_DRI2QueryVersion 0 @@ -59,6 +59,7 @@ * Events */ #define DRI2_BufferSwapComplete 0 +#define DRI2_InvalidateBuffers 1 typedef struct { CARD32 attachment B32; @@ -299,4 +300,18 @@ typedef struct { } xDRI2BufferSwapComplete; #define sz_xDRI2BufferSwapComplete 32 +typedef struct { + CARD8 type; + CARD8 pad; + CARD16 sequenceNumber B16; + CARD32 drawable B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xDRI2InvalidateBuffers; +#define sz_xDRI2InvalidateBuffers 32 + #endif diff --git a/dri2proto.txt b/dri2proto.txt index de58289..3d3eec4 100644 --- a/dri2proto.txt +++ b/dri2proto.txt @@ -125,9 +125,12 @@ or by using the OML swap buffers routine. 2.7 Events -DRI2 provides a single event to indicate when a DRI2SwapBuffers request has -been completed. This can be used to throttle drawing on the client side and -tie into application main loops. +DRI2 provides an event to indicate when a DRI2SwapBuffers request has +been completed. This can be used to throttle drawing on the client +side and tie into application main loops. + +Another event is generated when the validity of the requested buffers +changes. â â â â â â @@ -333,10 +336,6 @@ The name of this extension is "DRI2". Returns the swap count value when the swap will actually occur (e.g. the last queued swap count + (pending swap count * swap interval)). - The client should invalidate its render buffers after sending this - request, causing a subsequent GetBuffers request to get updated buffer - info. - This request is only available with protocol version 1.2 or later. @@ -459,6 +458,22 @@ The name of this extension is "DRI2". the swap was performed with a blit, and DRI2_FLIP_COMPLETE, indicating a full page flip was completed. +ââââ + DRI2InvalidateBuffers + â¶ + drawable: CARD32 +ââââ + + This event is generated when the buffers the client had + requested for 'drawable' (with DRI2GetBuffers or + DRI2GetBuffersWithFormat) become inappropriate because they + don't match the drawable dimensions anymore, or a buffer swap + has been performed. + + Note that the server is only required to warn the client once + about this condition, until the client takes care of bringing + them back up-to-date with another GetBuffers request. + â â â â â â 10. Extension Versioning @@ -491,6 +506,8 @@ The DRI2 extension has undergone a number of revisions before 2.2: Approaching perfection. Added requests for swapbuffers, MSC and SBC related requests, and events. + 2.3: Added the DRI2InvalidateBuffers event. + Compatibility up to 2.0 is not preserved, but was also never released. -- 1.6.4.4 |
From: Francisco J. <cur...@ri...> - 2010-01-16 21:59:13
|
The same names could be reused for e.g. GLX_OML_swap_control, and the COMPLETE suffix doesn't make so much sense there. Signed-off-by: Francisco Jerez <cur...@ri...> --- This patch isn't strictly necessary for buffer validation events, but it makes some of the X server code nicer. dri2proto.txt | 6 +++--- dri2tokens.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dri2proto.txt b/dri2proto.txt index 3d3eec4..4e53bea 100644 --- a/dri2proto.txt +++ b/dri2proto.txt @@ -453,9 +453,9 @@ The name of this extension is "DRI2". ââââ This event reports the status of the last DRI2SwapBuffers event to - the client. The event type should be one of DRI2_EXCHANGE_COMPLETE, - indicating a successful buffer exchange, DRI2_BLIT_COMPLETE, indicating - the swap was performed with a blit, and DRI2_FLIP_COMPLETE, indicating + the client. The event type should be one of DRI2_SWAP_EXCHANGE, + indicating a successful buffer exchange, DRI2_SWAP_BLIT, indicating + the swap was performed with a blit, and DRI2_SWAP_FLIP, indicating a full page flip was completed. ââââ diff --git a/dri2tokens.h b/dri2tokens.h index 7804e4d..2b31a1d 100644 --- a/dri2tokens.h +++ b/dri2tokens.h @@ -48,8 +48,8 @@ #define DRI2DriverVDPAU 1 /* Event sub-types for the swap complete event */ -#define DRI2_EXCHANGE_COMPLETE 0x1 -#define DRI2_BLIT_COMPLETE 0x2 -#define DRI2_FLIP_COMPLETE 0x3 +#define DRI2_SWAP_EXCHANGE 0x1 +#define DRI2_SWAP_BLIT 0x2 +#define DRI2_SWAP_FLIP 0x3 #endif -- 1.6.4.4 |
From: Francisco J. <cur...@ri...> - 2010-01-16 21:59:13
|
Signed-off-by: Francisco Jerez <cur...@ri...> --- configure.ac | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/configure.ac b/configure.ac index fc96197..c5affe3 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.57]) -AC_INIT([DRI2Proto], [2.2], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg]) +AC_INIT([DRI2Proto], [2.3], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- 1.6.4.4 |
From: Francisco J. <cur...@ri...> - 2010-01-16 22:00:26
|
Executed from the ConfigureWindow request, right before sending ConfigureNotify to the clients. This commit breaks the ScreenRec ABI. Signed-off-by: Francisco Jerez <cur...@ri...> --- It might be possible to delay the ABI bump, but I'd rather do it this way. The already existing Resize and MoveWindow hooks aren't an option because the client *needs* to get DRI2InvalidateBuffers before ConfigureNotify. dix/window.c | 4 ++++ hw/xfree86/common/xf86Module.h | 6 +++--- include/scrnintstr.h | 10 ++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/dix/window.c b/dix/window.c index caff1cb..d9836e1 100644 --- a/dix/window.c +++ b/dix/window.c @@ -2303,6 +2303,10 @@ ConfigureWindow(WindowPtr pWin, Mask mask, XID *vlist, ClientPtr client) return(Success); ActuallyDoSomething: + if (pWin->drawable.pScreen->PreConfigureWindow) + (*pWin->drawable.pScreen->PreConfigureWindow)(pWin, x, y, + w, h, bw, pSib); + if (SubStrSend(pWin, pParent)) { memset(&event, 0, sizeof(xEvent)); diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h index bbf5786..d61758f 100644 --- a/hw/xfree86/common/xf86Module.h +++ b/hw/xfree86/common/xf86Module.h @@ -82,9 +82,9 @@ typedef enum { * mask is 0xFFFF0000. */ #define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4) -#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(7, 0) -#define ABI_XINPUT_VERSION SET_ABI_VERSION(9, 0) -#define ABI_EXTENSION_VERSION SET_ABI_VERSION(3, 0) +#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(8, 0) +#define ABI_XINPUT_VERSION SET_ABI_VERSION(10, 0) +#define ABI_EXTENSION_VERSION SET_ABI_VERSION(4, 0) #define ABI_FONT_VERSION SET_ABI_VERSION(0, 6) #define MODINFOSTRING1 0xef23fdc5 diff --git a/include/scrnintstr.h b/include/scrnintstr.h index ab50e7a..467b61c 100644 --- a/include/scrnintstr.h +++ b/include/scrnintstr.h @@ -399,6 +399,15 @@ typedef void (* PostChangeSaveUnderProcPtr)( WindowPtr /*pLayerWin*/, WindowPtr /*firstChild*/); +typedef void (* PreConfigureWindowProcPtr)( + WindowPtr /*pWin*/, + int /*x*/, + int /*y*/, + int /*w*/, + int /*h*/, + int /*bw*/, + WindowPtr /*pSib*/); + typedef void (* MoveWindowProcPtr)( WindowPtr /*pWin*/, int /*x*/, @@ -581,6 +590,7 @@ typedef struct _Screen { MarkOverlappedWindowsProcPtr MarkOverlappedWindows; ChangeSaveUnderProcPtr ChangeSaveUnder; PostChangeSaveUnderProcPtr PostChangeSaveUnder; + PreConfigureWindowProcPtr PreConfigureWindow; MoveWindowProcPtr MoveWindow; ResizeWindowProcPtr ResizeWindow; GetLayerWindowProcPtr GetLayerWindow; -- 1.6.4.4 |
From: Francisco J. <cur...@ri...> - 2010-01-16 22:00:27
|
It can be quite an expensive operation, so we're better off not doing it unless it's totally required. Signed-off-by: Francisco Jerez <cur...@ri...> --- hw/xfree86/dri2/dri2.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index 3db826e..3f4ed92 100644 --- a/hw/xfree86/dri2/dri2.c +++ b/hw/xfree86/dri2/dri2.c @@ -212,6 +212,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, int have_fake_front = 0; int front_format = 0; int dimensions_match; + int buffers_changed; int i; if (!pPriv) { @@ -224,6 +225,8 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, dimensions_match = (pDraw->width == pPriv->width) && (pDraw->height == pPriv->height); + buffers_changed = (pPriv->buffers == NULL); + buffers = xalloc((count + 1) * sizeof(buffers[0])); for (i = 0; i < count; i++) { @@ -280,6 +283,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, for (i = 0; i < pPriv->bufferCount; i++) { if (pPriv->buffers[i] != NULL) { (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]); + buffers_changed = 1; } } @@ -298,7 +302,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, * contents of the real front-buffer. This ensures correct operation of * applications that call glXWaitX before calling glDrawBuffer. */ - if (have_fake_front) { + if (have_fake_front && buffers_changed) { BoxRec box; RegionRec region; -- 1.6.4.4 |
From: Francisco J. <cur...@ri...> - 2010-01-16 22:00:29
|
It helps to determine if buffers need to be invalidated or not, and it makes sense for e.g. GLX_OML_swap_control. Note that this patch bumps the DRI2InfoRec version and the minimum required dri2proto version. Signed-off-by: Francisco Jerez <cur...@ri...> --- configure.ac | 2 +- glx/glxdri2.c | 9 +++++---- hw/xfree86/dri2/dri2.c | 10 ++++++---- hw/xfree86/dri2/dri2.h | 7 +++++-- hw/xfree86/dri2/dri2ext.c | 4 ++-- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index 8c1085b..85225ba 100644 --- a/configure.ac +++ b/configure.ac @@ -754,7 +754,7 @@ RECORDPROTO="recordproto >= 1.13.99.1" SCRNSAVERPROTO="scrnsaverproto >= 1.1" RESOURCEPROTO="resourceproto" DRIPROTO="xf86driproto >= 2.1.0" -DRI2PROTO="dri2proto >= 2.2" +DRI2PROTO="dri2proto >= 2.3" XINERAMAPROTO="xineramaproto" BIGFONTPROTO="xf86bigfontproto >= 1.2.0" XCALIBRATEPROTO="xcalibrateproto" diff --git a/glx/glxdri2.c b/glx/glxdri2.c index 69fd39b..c5e7b0b 100644 --- a/glx/glxdri2.c +++ b/glx/glxdri2.c @@ -179,13 +179,13 @@ __glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust, wire.type = __glXEventBase + GLX_BufferSwapComplete; switch (type) { - case DRI2_EXCHANGE_COMPLETE: + case DRI2_SWAP_EXCHANGE: wire.event_type = GLX_EXCHANGE_COMPLETE_INTEL; break; - case DRI2_BLIT_COMPLETE: + case DRI2_SWAP_BLIT: wire.event_type = GLX_BLIT_COMPLETE_INTEL; break; - case DRI2_FLIP_COMPLETE: + case DRI2_SWAP_FLIP: wire.event_type = GLX_FLIP_COMPLETE_INTEL; break; default: @@ -216,11 +216,12 @@ __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable) __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable; __GLXDRIscreen *screen = priv->screen; CARD64 unused; + int type; if (screen->flush) (*screen->flush->flushInvalidate)(priv->driDrawable); - if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused, + if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused, &type, __glXdriSwapEvent, drawable->pDraw) != Success) return FALSE; diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index 3f4ed92..65433e9 100644 --- a/hw/xfree86/dri2/dri2.c +++ b/hw/xfree86/dri2/dri2.c @@ -547,7 +547,7 @@ DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable) int DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc, CARD64 divisor, CARD64 remainder, CARD64 *swap_target, - DRI2SwapEventPtr func, void *data) + int *type, DRI2SwapEventPtr func, void *data) { ScreenPtr pScreen = pDraw->pScreen; DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); @@ -587,9 +587,10 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc, REGION_INIT(pScreen, ®ion, &box, 0); pPriv->swapsPending++; + *type = DRI2_SWAP_BLIT; (*ds->CopyRegion)(pDraw, ®ion, pDestBuffer, pSrcBuffer); - DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE, + DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_SWAP_BLIT, func, data); return Success; } @@ -623,7 +624,8 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc, *swap_target = pPriv->last_swap_target + pPriv->swap_interval; ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer, - swap_target, divisor, remainder, func, data); + swap_target, type, divisor, remainder, func, + data); if (!ret) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[DRI2] %s: driver failed to schedule swap\n", __func__); @@ -826,7 +828,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) ds->DestroyBuffer = info->DestroyBuffer; ds->CopyRegion = info->CopyRegion; - if (info->version >= 4) { + if (info->version >= 5) { ds->ScheduleSwap = info->ScheduleSwap; ds->ScheduleWaitMSC = info->ScheduleWaitMSC; ds->GetMSC = info->GetMSC; diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h index dd59297..c0f82ee 100644 --- a/hw/xfree86/dri2/dri2.h +++ b/hw/xfree86/dri2/dri2.h @@ -85,6 +85,7 @@ typedef void (*DRI2WaitProcPtr)(WindowPtr pWin, * \param pDestBuffer current front buffer * \param pSrcBuffer current back buffer * \param target_msc frame count to wait for + * \param type outputs the kind of swap the DDX has chosen * \param divisor divisor for condition equation * \param remainder remainder for division equation * \param func function to call when the swap completes @@ -95,6 +96,7 @@ typedef int (*DRI2ScheduleSwapProcPtr)(ClientPtr client, DRI2BufferPtr pDestBuffer, DRI2BufferPtr pSrcBuffer, CARD64 *target_msc, + int *type, CARD64 divisor, CARD64 remainder, DRI2SwapEventPtr func, @@ -152,7 +154,7 @@ typedef int (*DRI2ScheduleWaitMSCProcPtr)(ClientPtr client, /** * Version of the DRI2InfoRec structure defined in this header */ -#define DRI2INFOREC_VERSION 4 +#define DRI2INFOREC_VERSION 5 typedef struct { unsigned int version; /**< Version of this struct */ @@ -226,7 +228,8 @@ 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); + int *type, DRI2SwapEventPtr func, + void *data); extern _X_EXPORT Bool DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable); extern _X_EXPORT int DRI2GetMSC(DrawablePtr pDrawable, CARD64 *ust, diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c index 3e6b03e..a4ed2ad 100644 --- a/hw/xfree86/dri2/dri2ext.c +++ b/hw/xfree86/dri2/dri2ext.c @@ -374,7 +374,7 @@ ProcDRI2SwapBuffers(ClientPtr client) xDRI2SwapBuffersReply rep; DrawablePtr pDrawable; CARD64 target_msc, divisor, remainder, swap_target; - int status; + int type, status; REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq); @@ -387,7 +387,7 @@ ProcDRI2SwapBuffers(ClientPtr client) remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi); status = DRI2SwapBuffers(client, pDrawable, target_msc, divisor, remainder, - &swap_target, DRI2SwapEvent, pDrawable); + &swap_target, &type, DRI2SwapEvent, pDrawable); if (status != Success) return BadDrawable; -- 1.6.4.4 |
From: Francisco J. <cur...@ri...> - 2010-01-16 22:00:32
|
The spec says (regarding glXCreateWindow): "If there is already a GLXFBConfig associated with win (as a result of a previous glXCreateWindow call), then a BadAlloc error is generated.". It will also come useful to implement DRI2InvalidateBuffers for the indirect case. Signed-off-by: Francisco Jerez <cur...@ri...> --- glx/glxcmds.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------ glx/glxserver.h | 1 + 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/glx/glxcmds.c b/glx/glxcmds.c index 77afbf4..0e1c89c 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -51,6 +51,15 @@ #include "indirect_table.h" #include "indirect_util.h" +static int glxWindowPrivateKeyIndex; +static DevPrivateKey glxWindowPrivateKey = &glxWindowPrivateKeyIndex; + +__GLXdrawable * +glxGetDrawableFromWindow(WindowPtr pWin) +{ + return dixLookupPrivate(&pWin->devPrivates, glxWindowPrivateKey); +} + static int validGlxScreen(ClientPtr client, int screen, __GLXscreen **pGlxScreen, int *err) { @@ -473,6 +482,7 @@ __glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client, int *error) { DrawablePtr pDraw; + WindowPtr pWin; __GLXdrawable *pGlxDraw; int rc; @@ -499,6 +509,12 @@ __glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client, return NULL; } + pWin = (WindowPtr)pDraw; + + pGlxDraw = glxGetDrawableFromWindow(pWin); + if (pGlxDraw) + return pGlxDraw; + if (pDraw->pScreen != glxc->pGlxScreen->pScreen) { client->errorValue = pDraw->pScreen->myNum; *error = BadMatch; @@ -519,6 +535,8 @@ __glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client, return NULL; } + dixSetPrivate(&pWin->devPrivates, glxWindowPrivateKey, pGlxDraw); + return pGlxDraw; } @@ -1107,9 +1125,10 @@ __glXDrawableRelease(__GLXdrawable *drawable) } } -static int +static int DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config, - DrawablePtr pDraw, XID glxDrawableId, int type) + DrawablePtr pDraw, XID glxDrawableId, int type, + __GLXdrawable **ret) { __GLXdrawable *pGlxDraw; @@ -1128,6 +1147,9 @@ DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *conf return BadAlloc; } + if (ret) + *ret = pGlxDraw; + return Success; } @@ -1149,7 +1171,7 @@ DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config } err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, - glxDrawableId, GLX_DRAWABLE_PIXMAP); + glxDrawableId, GLX_DRAWABLE_PIXMAP, NULL); if (err == Success) ((PixmapPtr) pDraw)->refcnt++; @@ -1305,7 +1327,7 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId, __glXleaveServer(GL_FALSE); return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable, - glxDrawableId, GLX_DRAWABLE_PBUFFER); + glxDrawableId, GLX_DRAWABLE_PBUFFER, NULL); } int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc) @@ -1409,6 +1431,8 @@ int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc) __GLXscreen *pGlxScreen; ClientPtr client = cl->client; DrawablePtr pDraw; + WindowPtr pWin; + __GLXdrawable *pGlxDraw; int err; if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) @@ -1422,11 +1446,26 @@ int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc) return BadWindow; } + pWin = (WindowPtr)pDraw; + + /* Make sure there're no already associated GLX drawables. */ + if (glxGetDrawableFromWindow(pWin)) { + client->errorValue = req->window; + return BadAlloc; + } + if (!validGlxFBConfigForWindow(client, config, pDraw, &err)) return err; - return DoCreateGLXDrawable(client, pGlxScreen, config, - pDraw, req->glxwindow, GLX_DRAWABLE_WINDOW); + err = DoCreateGLXDrawable(client, pGlxScreen, config, + pDraw, req->glxwindow, + GLX_DRAWABLE_WINDOW, &pGlxDraw); + if (err) + return err; + + dixSetPrivate(&pWin->devPrivates, glxWindowPrivateKey, pGlxDraw); + + return Success; } int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc) diff --git a/glx/glxserver.h b/glx/glxserver.h index 1daf977..3c49b5e 100644 --- a/glx/glxserver.h +++ b/glx/glxserver.h @@ -80,6 +80,7 @@ typedef struct __GLXcontext __GLXcontext; extern __GLXscreen *glxGetScreen(ScreenPtr pScreen); extern __GLXclientState *glxGetClient(ClientPtr pClient); +extern __GLXdrawable *glxGetDrawableFromWindow(WindowPtr pWin); /************************************************************************/ -- 1.6.4.4 |
From: Francisco J. <cur...@ri...> - 2010-01-16 22:00:34
|
Signed-off-by: Francisco Jerez <cur...@ri...> --- glx/glxdri2.c | 28 +++++++++++++++++++++++++--- 1 files changed, 25 insertions(+), 3 deletions(-) diff --git a/glx/glxdri2.c b/glx/glxdri2.c index c5e7b0b..0ac6900 100644 --- a/glx/glxdri2.c +++ b/glx/glxdri2.c @@ -67,6 +67,7 @@ struct __GLXDRIscreen { xf86EnterVTProc *enterVT; xf86LeaveVTProc *leaveVT; + PreConfigureWindowProcPtr PreConfigureWindow; const __DRIcoreExtension *core; const __DRIdri2Extension *dri2; @@ -218,13 +219,13 @@ __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable) CARD64 unused; int type; - if (screen->flush) - (*screen->flush->flushInvalidate)(priv->driDrawable); - if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused, &type, __glXdriSwapEvent, drawable->pDraw) != Success) return FALSE; + if (type != DRI2_SWAP_BLIT && screen->flush) + (*screen->flush->invalidate)(priv->driDrawable); + return TRUE; } @@ -608,6 +609,24 @@ glxDRILeaveVT (int index, int flags) } static void +glxDRIPreConfigureWindow(WindowPtr pWin, int x, int y, int w, int h, int bw, + WindowPtr pSib) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + __GLXDRIscreen *screen = (__GLXDRIscreen *)glxGetScreen(pScreen); + __GLXDRIdrawable *draw = (__GLXDRIdrawable *)glxGetDrawableFromWindow(pWin); + + if (screen->PreConfigureWindow) + (*screen->PreConfigureWindow)(pWin, x, y, w, h, bw, pSib); + + if (!draw || (draw->height == h && draw->width == w)) + return; + + if (screen->flush) + screen->flush->invalidate(draw->driDrawable); +} + +static void initializeExtensions(__GLXDRIscreen *screen) { const __DRIextension **extensions; @@ -783,6 +802,9 @@ __glXDRIscreenProbe(ScreenPtr pScreen) screen->leaveVT = pScrn->LeaveVT; pScrn->LeaveVT = glxDRILeaveVT; + screen->PreConfigureWindow = pScreen->PreConfigureWindow; + pScreen->PreConfigureWindow = glxDRIPreConfigureWindow; + LogMessage(X_INFO, "AIGLX: Loaded and initialized %s\n", filename); -- 1.6.4.4 |
From: Francisco J. <cur...@ri...> - 2010-01-16 22:00:37
|
Bumps the supported DRI2 protocol version to 1.3. Signed-off-by: Francisco Jerez <cur...@ri...> --- hw/xfree86/dri2/dri2.c | 82 +++++++++++++++++++++++++++++++++++++++++++ hw/xfree86/dri2/dri2.h | 4 ++ hw/xfree86/dri2/dri2ext.c | 22 +++++++++++ include/protocol-versions.h | 2 +- 4 files changed, 109 insertions(+), 1 deletions(-) diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index 65433e9..783c98f 100644 --- a/hw/xfree86/dri2/dri2.c +++ b/hw/xfree86/dri2/dri2.c @@ -65,6 +65,12 @@ typedef struct _DRI2Drawable { CARD64 target_sbc; /* -1 means no SBC wait outstanding */ CARD64 last_swap_target; /* most recently queued swap target */ int swap_limit; /* for N-buffering */ + + /* Array of clients that want to be notified + * when the drawable dimensions change. */ + ClientPtr *track_clients; + int track_count; + } DRI2DrawableRec, *DRI2DrawablePtr; typedef struct _DRI2Screen *DRI2ScreenPtr; @@ -83,6 +89,8 @@ typedef struct _DRI2Screen { DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC; HandleExposuresProcPtr HandleExposures; + + PreConfigureWindowProcPtr PreConfigureWindow; } DRI2ScreenRec; static DRI2ScreenPtr @@ -142,6 +150,8 @@ DRI2CreateDrawable(DrawablePtr pDraw) pPriv->swap_interval = 1; pPriv->last_swap_target = -1; pPriv->swap_limit = 1; /* default to double buffering */ + pPriv->track_clients = NULL; + pPriv->track_count = 0; if (pDraw->type == DRAWABLE_WINDOW) { @@ -380,6 +390,54 @@ DRI2BlockClient(ClientPtr client, DrawablePtr pDraw) } int +DRI2TrackClient(ClientPtr client, DrawablePtr pDraw) +{ + DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); + ClientPtr *clients; + int i; + + if (pPriv == NULL) + return BadDrawable; + + /* Check if the client is already in. */ + for (i = 0; i < pPriv->track_count; i++) { + if (pPriv->track_clients[i] == client) + return Success; + } + + /* Grow the track_clients array. */ + clients = xrealloc(pPriv->track_clients, + (pPriv->track_count + 1) * sizeof(*clients)); + if (clients == NULL) + return BadAlloc; + + pPriv->track_clients = clients; + pPriv->track_clients[pPriv->track_count++] = client; + + return Success; +} + +void +DRI2InvalidateDrawable(DrawablePtr pDraw) +{ + DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); + int i; + + if (pPriv == NULL) + return; + + for (i = 0; i < pPriv->track_count; i++) + DRI2InvalidateBuffersEvent(pPriv->track_clients[i], pDraw); + + pPriv->track_count = 0; + + if (pPriv->track_clients) { + xfree(pPriv->track_clients); + pPriv->track_clients = NULL; + } +} + +int DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, unsigned int dest, unsigned int src) { @@ -760,6 +818,9 @@ DRI2DestroyDrawable(DrawablePtr pDraw) if (!pPriv->swapsPending) xfree(pPriv); + if (pPriv->track_clients) + xfree(pPriv->track_clients); + if (pDraw->type == DRAWABLE_WINDOW) { pWin = (WindowPtr) pDraw; @@ -802,6 +863,24 @@ DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic) return TRUE; } +static void +DRI2PreConfigureWindow(WindowPtr pWin, int x, int y, int w, int h, int bw, + WindowPtr pSib) +{ + DrawablePtr pDraw = (DrawablePtr)pWin; + ScreenPtr pScreen = pDraw->pScreen; + DRI2ScreenPtr ds = DRI2GetScreen(pScreen); + DRI2DrawablePtr dd = DRI2GetDrawable(pDraw); + + if (ds->PreConfigureWindow) + (*ds->PreConfigureWindow)(pWin, x, y, w, h, bw, pSib); + + if (!dd || (dd->width == w && dd->height == h)) + return; + + DRI2InvalidateDrawable(pDraw); +} + Bool DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) { @@ -836,6 +915,9 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds); + ds->PreConfigureWindow = pScreen->PreConfigureWindow; + pScreen->PreConfigureWindow = DRI2PreConfigureWindow; + xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n"); return TRUE; diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h index c0f82ee..b448e51 100644 --- a/hw/xfree86/dri2/dri2.h +++ b/hw/xfree86/dri2/dri2.h @@ -259,4 +259,8 @@ extern _X_EXPORT void DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame, unsigned int tv_sec, unsigned int tv_usec); +extern _X_EXPORT int DRI2TrackClient(ClientPtr client, DrawablePtr pDraw); +extern _X_EXPORT void DRI2InvalidateBuffersEvent(ClientPtr client, DrawablePtr draw); +extern _X_EXPORT void DRI2InvalidateDrawable(DrawablePtr pDraw); + #endif diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c index a4ed2ad..a41376b 100644 --- a/hw/xfree86/dri2/dri2ext.c +++ b/hw/xfree86/dri2/dri2ext.c @@ -266,6 +266,9 @@ ProcDRI2GetBuffers(ClientPtr client) buffers = DRI2GetBuffers(pDrawable, &width, &height, attachments, stuff->count, &count); + status = DRI2TrackClient(client, pDrawable); + if (status) + return status; send_buffers_reply(client, pDrawable, buffers, count, width, height); @@ -293,6 +296,10 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client) buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height, attachments, stuff->count, &count); + status = DRI2TrackClient(client, pDrawable); + if (status) + return status; + send_buffers_reply(client, pDrawable, buffers, count, width, height); return client->noClientException; @@ -367,6 +374,18 @@ DRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc, WriteEventsToClient(client, 1, (xEvent *)&event); } +void +DRI2InvalidateBuffersEvent(ClientPtr client, DrawablePtr draw) +{ + xDRI2InvalidateBuffers event; + + event.type = DRI2EventBase + DRI2_InvalidateBuffers; + event.sequenceNumber = client->sequence; + event.drawable = draw->id; + + WriteEventsToClient(client, 1, (xEvent *)&event); +} + static int ProcDRI2SwapBuffers(ClientPtr client) { @@ -391,6 +410,9 @@ ProcDRI2SwapBuffers(ClientPtr client) if (status != Success) return BadDrawable; + if (type != DRI2_SWAP_BLIT) + DRI2InvalidateDrawable(pDrawable); + rep.type = X_Reply; rep.length = 0; rep.sequenceNumber = client->sequence; diff --git a/include/protocol-versions.h b/include/protocol-versions.h index c74b7fa..c425eef 100644 --- a/include/protocol-versions.h +++ b/include/protocol-versions.h @@ -53,7 +53,7 @@ /* DRI2 */ #define SERVER_DRI2_MAJOR_VERSION 1 -#define SERVER_DRI2_MINOR_VERSION 2 +#define SERVER_DRI2_MINOR_VERSION 3 /* Generic event extension */ #define SERVER_GE_MAJOR_VERSION 1 -- 1.6.4.4 |
From: Francisco J. <cur...@ri...> - 2010-01-19 17:12:21
|
Bumps the supported DRI2 protocol version to 1.3. Signed-off-by: Francisco Jerez <cur...@ri...> --- v1 was evil because the multiple clients rendering to the same drawable case wasn't handled correctly (sometimes it crashed). Seems to work now. hw/xfree86/dri2/dri2.c | 109 +++++++++++++++++++++++++++++++++++++++++++ hw/xfree86/dri2/dri2.h | 5 ++ hw/xfree86/dri2/dri2ext.c | 36 +++++++++++++-- include/protocol-versions.h | 2 +- 4 files changed, 147 insertions(+), 5 deletions(-) diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index 65433e9..82ecf28 100644 --- a/hw/xfree86/dri2/dri2.c +++ b/hw/xfree86/dri2/dri2.c @@ -52,6 +52,13 @@ static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex; static int dri2PixmapPrivateKeyIndex; static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex; +typedef struct _DRI2ClientRef *DRI2ClientRefPtr; + +struct _DRI2ClientRef { + DRI2ClientRefPtr next; + XID resource; +}; + typedef struct _DRI2Drawable { unsigned int refCount; int width; @@ -65,6 +72,8 @@ typedef struct _DRI2Drawable { CARD64 target_sbc; /* -1 means no SBC wait outstanding */ CARD64 last_swap_target; /* most recently queued swap target */ int swap_limit; /* for N-buffering */ + DRI2ClientRefPtr track_clients; /* Clients to notify on drawable changes. */ + } DRI2DrawableRec, *DRI2DrawablePtr; typedef struct _DRI2Screen *DRI2ScreenPtr; @@ -83,6 +92,8 @@ typedef struct _DRI2Screen { DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC; HandleExposuresProcPtr HandleExposures; + + PreConfigureWindowProcPtr PreConfigureWindow; } DRI2ScreenRec; static DRI2ScreenPtr @@ -142,6 +153,7 @@ DRI2CreateDrawable(DrawablePtr pDraw) pPriv->swap_interval = 1; pPriv->last_swap_target = -1; pPriv->swap_limit = 1; /* default to double buffering */ + pPriv->track_clients = NULL; if (pDraw->type == DRAWABLE_WINDOW) { @@ -379,6 +391,78 @@ DRI2BlockClient(ClientPtr client, DrawablePtr pDraw) } } +extern RESTYPE dri2DrawableRes; + +int +DRI2TrackClient(DrawablePtr pDraw, int id) +{ + DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); + DRI2ClientRefPtr ref; + + if (pPriv == NULL) + return BadDrawable; + + /* Check if the client is already in. */ + for (ref = pPriv->track_clients; ref; ref = ref->next) { + if (CLIENT_ID(ref->resource) == id) + return Success; + } + + /* Allocate a client ref. */ + ref = xalloc(sizeof(*ref)); + if (ref == NULL) + return BadAlloc; + + ref->next = pPriv->track_clients; + pPriv->track_clients = ref; + + /* Allocate a resource for it. */ + ref->resource = FakeClientID(id); + if (!AddResource(ref->resource, dri2DrawableRes, pDraw)) + return BadAlloc; + + return Success; +} + +void +DRI2UntrackClient(DrawablePtr pDraw, int id) +{ + DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); + DRI2ClientRefPtr ref, *prev; + + if (pPriv == NULL) + return; + + prev = &pPriv->track_clients; + + for (ref = *prev; ref; prev = &ref->next, ref = ref->next) { + if (CLIENT_ID(ref->resource) == id) { + *prev = ref->next; + xfree(ref); + break; + } + } +} + +void +DRI2InvalidateDrawable(DrawablePtr pDraw) +{ + DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); + DRI2ClientRefPtr ref; + + if (pPriv == NULL) + return; + + while ((ref = pPriv->track_clients)) { + ClientPtr client = clients[CLIENT_ID(ref->resource)]; + + FreeResource(ref->resource, RT_NONE); + + if (client && !client->clientGone) + DRI2InvalidateBuffersEvent(pDraw, client); + } +} + int DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, unsigned int dest, unsigned int src) @@ -736,6 +820,7 @@ DRI2DestroyDrawable(DrawablePtr pDraw) DRI2DrawablePtr pPriv; WindowPtr pWin; PixmapPtr pPixmap; + DRI2ClientRefPtr ref; pPriv = DRI2GetDrawable(pDraw); if (pPriv == NULL) @@ -754,6 +839,9 @@ DRI2DestroyDrawable(DrawablePtr pDraw) xfree(pPriv->buffers); } + while ((ref = pPriv->track_clients)) + FreeResource(ref->resource, RT_NONE); + /* 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. */ @@ -802,6 +890,24 @@ DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic) return TRUE; } +static void +DRI2PreConfigureWindow(WindowPtr pWin, int x, int y, int w, int h, int bw, + WindowPtr pSib) +{ + DrawablePtr pDraw = (DrawablePtr)pWin; + ScreenPtr pScreen = pDraw->pScreen; + DRI2ScreenPtr ds = DRI2GetScreen(pScreen); + DRI2DrawablePtr dd = DRI2GetDrawable(pDraw); + + if (ds->PreConfigureWindow) + (*ds->PreConfigureWindow)(pWin, x, y, w, h, bw, pSib); + + if (!dd || (dd->width == w && dd->height == h)) + return; + + DRI2InvalidateDrawable(pDraw); +} + Bool DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) { @@ -836,6 +942,9 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds); + ds->PreConfigureWindow = pScreen->PreConfigureWindow; + pScreen->PreConfigureWindow = DRI2PreConfigureWindow; + xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n"); return TRUE; diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h index c0f82ee..4973819 100644 --- a/hw/xfree86/dri2/dri2.h +++ b/hw/xfree86/dri2/dri2.h @@ -259,4 +259,9 @@ extern _X_EXPORT void DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame, unsigned int tv_sec, unsigned int tv_usec); +extern _X_EXPORT int DRI2TrackClient(DrawablePtr pDraw, int id); +extern _X_EXPORT void DRI2UntrackClient(DrawablePtr pDraw, int id); +extern _X_EXPORT void DRI2InvalidateBuffersEvent(DrawablePtr pDraw, ClientPtr client); +extern _X_EXPORT void DRI2InvalidateDrawable(DrawablePtr pDraw); + #endif diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c index a4ed2ad..fadda3b 100644 --- a/hw/xfree86/dri2/dri2ext.c +++ b/hw/xfree86/dri2/dri2ext.c @@ -51,7 +51,7 @@ #include "xf86Module.h" static ExtensionEntry *dri2Extension; -static RESTYPE dri2DrawableRes; +RESTYPE dri2DrawableRes; static Bool validDrawable(ClientPtr client, XID drawable, Mask access_mode, @@ -266,6 +266,9 @@ ProcDRI2GetBuffers(ClientPtr client) buffers = DRI2GetBuffers(pDrawable, &width, &height, attachments, stuff->count, &count); + status = DRI2TrackClient(pDrawable, client->index); + if (status) + return status; send_buffers_reply(client, pDrawable, buffers, count, width, height); @@ -293,6 +296,10 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client) buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height, attachments, stuff->count, &count); + status = DRI2TrackClient(pDrawable, client->index); + if (status) + return status; + send_buffers_reply(client, pDrawable, buffers, count, width, height); return client->noClientException; @@ -367,6 +374,18 @@ DRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc, WriteEventsToClient(client, 1, (xEvent *)&event); } +void +DRI2InvalidateBuffersEvent(DrawablePtr pDraw, ClientPtr client) +{ + xDRI2InvalidateBuffers event; + + event.type = DRI2EventBase + DRI2_InvalidateBuffers; + event.sequenceNumber = client->sequence; + event.drawable = pDraw->id; + + WriteEventsToClient(client, 1, (xEvent *)&event); +} + static int ProcDRI2SwapBuffers(ClientPtr client) { @@ -391,6 +410,9 @@ ProcDRI2SwapBuffers(ClientPtr client) if (status != Success) return BadDrawable; + if (type != DRI2_SWAP_BLIT) + DRI2InvalidateDrawable(pDrawable); + rep.type = X_Reply; rep.length = 0; rep.sequenceNumber = client->sequence; @@ -618,11 +640,17 @@ SProcDRI2Dispatch (ClientPtr client) } } -static int DRI2DrawableGone(pointer p, XID id) +static int +DRI2DrawableGone(pointer p, XID id) { - DrawablePtr pDrawable = p; + DrawablePtr pDraw = p; - DRI2DestroyDrawable(pDrawable); + if (pDraw->id != id) { + /* Secondary reference. */ + DRI2UntrackClient(pDraw, CLIENT_ID(id)); + } else { + DRI2DestroyDrawable(pDraw); + } return Success; } diff --git a/include/protocol-versions.h b/include/protocol-versions.h index c74b7fa..c425eef 100644 --- a/include/protocol-versions.h +++ b/include/protocol-versions.h @@ -53,7 +53,7 @@ /* DRI2 */ #define SERVER_DRI2_MAJOR_VERSION 1 -#define SERVER_DRI2_MINOR_VERSION 2 +#define SERVER_DRI2_MINOR_VERSION 3 /* Generic event extension */ #define SERVER_GE_MAJOR_VERSION 1 -- 1.6.4.4 |
From: Francisco J. <cur...@ri...> - 2010-01-16 22:02:15
|
When a buffer invalidation event is received from the X server, the "invalidate" hook of the DRI2 flush extension is executed: A generic implementation (dri2InvalidateDrawable) is provided that just bumps the "pStamp" sequence number in __DRIdrawableRec. For old servers not supporting buffer invalidation events, the invalidate hook will be called after flushing the fake front/back buffer (that's typically once per frame -- not a lot worse than the situation we were in before). No effort has been made on preserving backwards compatibility with version 2 of the flush extension, but I think it's acceptable because AFAIK no released stack is making use of it. Note that this bumps the required dri2proto version to 2.3. --- configure.ac | 2 +- include/GL/internal/dri_interface.h | 14 +++++------ src/glx/x11/dri2.c | 23 +++++++++++++++--- src/glx/x11/dri2_glx.c | 32 +++++++++++++++++-------- src/glx/x11/glx_pbuffer.c | 4 --- src/glx/x11/glxclient.h | 4 +++ src/glx/x11/glxcmds.c | 4 --- src/mesa/drivers/dri/common/dri_util.c | 15 +++++++++++- src/mesa/drivers/dri/common/dri_util.h | 8 ++++-- src/mesa/drivers/dri/intel/intel_context.c | 1 - src/mesa/drivers/dri/intel/intel_screen.c | 9 +------ src/mesa/drivers/dri/intel/intel_tex_image.c | 4 ++- 12 files changed, 75 insertions(+), 45 deletions(-) diff --git a/configure.ac b/configure.ac index d01d0f1..d334abf 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_CANONICAL_HOST dnl Versions for external dependencies LIBDRM_REQUIRED=2.4.15 LIBDRM_RADEON_REQUIRED=2.4.17 -DRI2PROTO_REQUIRED=2.2 +DRI2PROTO_REQUIRED=2.3 GLPROTO_REQUIRED=1.4.11 dnl Check for progs diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index ec6238f..6399787 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -262,22 +262,20 @@ struct __DRItexBufferExtensionRec { * Used by drivers that implement DRI2 */ #define __DRI2_FLUSH "DRI2_Flush" -#define __DRI2_FLUSH_VERSION 2 +#define __DRI2_FLUSH_VERSION 3 struct __DRI2flushExtensionRec { __DRIextension base; void (*flush)(__DRIdrawable *drawable); /** - * Flush all rendering queue in the driver to the drm and - * invalidate all buffers. The driver will call out to - * getBuffers/getBuffersWithFormat before it starts rendering - * again. + * Ask the driver to call getBuffers/getBuffersWithFormat before + * it starts rendering again. * - * \param drawable the drawable to flush and invalidate + * \param drawable the drawable to invalidate * - * \since 2 + * \since 3 */ - void (*flushInvalidate)(__DRIdrawable *drawable); + void (*invalidate)(__DRIdrawable *drawable); }; diff --git a/src/glx/x11/dri2.c b/src/glx/x11/dri2.c index 2cb5d34..931a90b 100644 --- a/src/glx/x11/dri2.c +++ b/src/glx/x11/dri2.c @@ -81,7 +81,7 @@ static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, dri2Info, dri2ExtensionName, &dri2ExtensionHooks, - 0, NULL) + DRI2NumberEvents, NULL) static Bool DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire) @@ -95,14 +95,15 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire) { GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire; + switch (awire->type) { - case DRI2_EXCHANGE_COMPLETE: + case DRI2_SWAP_EXCHANGE: aevent->event_type = GLX_EXCHANGE_COMPLETE; break; - case DRI2_BLIT_COMPLETE: + case DRI2_SWAP_BLIT: aevent->event_type = GLX_BLIT_COMPLETE; break; - case DRI2_FLIP_COMPLETE: + case DRI2_SWAP_FLIP: aevent->event_type = GLX_FLIP_COMPLETE; break; default: @@ -115,6 +116,20 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire) aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo; return True; } + +#if __DRI2_FLUSH_VERSION >= 3 + case DRI2_InvalidateBuffers: + { + xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire; + __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, awire->drawable, NULL); + + if (draw && draw->psc->f) + draw->psc->f->invalidate(draw->driDrawable); + + return False; + } +#endif + default: /* client doesn't support server event */ break; diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c index 7b0c52b..d787d84 100644 --- a/src/glx/x11/dri2_glx.c +++ b/src/glx/x11/dri2_glx.c @@ -67,6 +67,7 @@ struct __GLXDRIdisplayPrivateRec int driMinor; int driPatch; int swapAvailable; + int invalidateAvailable; }; struct __GLXDRIcontextPrivateRec @@ -310,12 +311,27 @@ dri2WaitGL(__GLXDRIdrawable * pdraw) XFixesDestroyRegion(pdraw->psc->dpy, region); } +static void +dri2LegacyInvalidate(__GLXDRIdrawable *pdraw) +{ +#if __DRI2_FLUSH_VERSION >= 3 + __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *)pdraw; + __GLXdisplayPrivate *dpy = __glXInitialize(priv->base.psc->dpy); + __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)dpy->dri2Display; + + /* Force an invalidate call if the server doesn't + * support buffer invalidation events. */ + + if (!pdp->invalidateAvailable && pdraw->psc->f) + (*pdraw->psc->f->invalidate)(pdraw->driDrawable); +#endif +} static void dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate) { - (void) driDrawable; - dri2WaitGL((__GLXDRIdrawable *) loaderPrivate); + dri2WaitGL(loaderPrivate); + dri2LegacyInvalidate(loaderPrivate); } @@ -378,17 +394,14 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, /* Old servers can't handle swapbuffers */ if (!pdp->swapAvailable) { dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); + dri2LegacyInvalidate(pdraw); + return 0; } DRI2SwapBuffers(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, remainder, &ret); -#if __DRI2_FLUSH_VERSION >= 2 - if (pdraw->psc->f) - (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable); -#endif - return ret; } @@ -640,9 +653,8 @@ dri2CreateDisplay(Display * dpy) } pdp->driPatch = 0; - pdp->swapAvailable = 0; - if (pdp->driMinor >= 2) - pdp->swapAvailable = 1; + pdp->swapAvailable = (pdp->driMinor >= 2); + pdp->invalidateAvailable = (pdp->driMinor >= 3); pdp->base.destroyDisplay = dri2DestroyDisplay; pdp->base.createScreen = dri2CreateScreen; diff --git a/src/glx/x11/glx_pbuffer.c b/src/glx/x11/glx_pbuffer.c index 501500a..15dffed 100644 --- a/src/glx/x11/glx_pbuffer.c +++ b/src/glx/x11/glx_pbuffer.c @@ -188,10 +188,6 @@ DestroyPbuffer(Display * dpy, GLXDrawable drawable) #ifdef GLX_DIRECT_RENDERING -extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy, - GLXDrawable drawable, - int *const scrn_num); - static GLenum determineTextureTarget(const int *attribs, int numAttribs) { diff --git a/src/glx/x11/glxclient.h b/src/glx/x11/glxclient.h index ded4f5a..970cbe0 100644 --- a/src/glx/x11/glxclient.h +++ b/src/glx/x11/glxclient.h @@ -793,6 +793,10 @@ extern GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable, GLboolean __driGetMscRateOML(__DRIdrawable * draw, int32_t * numerator, int32_t * denominator, void *private); + +extern __GLXDRIdrawable * +GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int *const scrn_num); + #endif #endif /* !__GLX_client_h__ */ diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c index c3be974..da0dcf1 100644 --- a/src/glx/x11/glxcmds.c +++ b/src/glx/x11/glxcmds.c @@ -105,10 +105,6 @@ GarbageCollectDRIDrawables(Display * dpy, __GLXscreenConfigs * sc) XSetErrorHandler(oldXErrorHandler); } -extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy, - GLXDrawable drawable, - int *const scrn_num); - /** * Get the __DRIdrawable for the drawable associated with a GLXContext * diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index 3649c29..705681e 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -454,7 +454,6 @@ driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config, pdp->driScreenPriv = psp; pdp->driContextPriv = &psp->dummyContextPriv; - pdp->validBuffers = GL_FALSE; if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes, renderType == GLX_PIXMAP_BIT)) { @@ -488,6 +487,9 @@ dri2CreateNewDrawable(__DRIscreen *screen, pdraw->pClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects); pdraw->pBackClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects); + pdraw->pStamp = _mesa_malloc(sizeof(unsigned int)); + *pdraw->pStamp = pdraw->lastStamp + 1; + return pdraw; } @@ -515,6 +517,11 @@ static void dri_put_drawable(__DRIdrawable *pdp) _mesa_free(pdp->pBackClipRects); pdp->pBackClipRects = NULL; } + if (psp->dri2.enabled && pdp->pStamp) { + _mesa_free(pdp->pStamp); + pdp->pStamp = NULL; + + } _mesa_free(pdp); } } @@ -948,4 +955,10 @@ driCalculateSwapUsage( __DRIdrawable *dPriv, int64_t last_swap_ust, return usage; } +void +dri2InvalidateDrawable(__DRIdrawable *drawable) +{ + (*drawable->pStamp)++; +} + /*@}*/ diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h index 95df702..d473091 100644 --- a/src/mesa/drivers/dri/common/dri_util.h +++ b/src/mesa/drivers/dri/common/dri_util.h @@ -295,7 +295,8 @@ struct __DRIdrawableRec { unsigned int index; /** - * Pointer to the "drawable has changed ID" stamp in the SAREA. + * Pointer to the "drawable has changed ID" stamp in the SAREA (or + * in malloc'ed memory if DRI2 is being used). */ unsigned int *pStamp; @@ -376,8 +377,6 @@ struct __DRIdrawableRec { * GLX_MESA_swap_control. */ unsigned int swap_interval; - - GLboolean validBuffers; }; /** @@ -550,4 +549,7 @@ driCalculateSwapUsage( __DRIdrawable *dPriv, extern GLint driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 ); +extern void +dri2InvalidateDrawable(__DRIdrawable *drawable); + #endif /* _DRI_UTIL_H_ */ diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index 3f6634c..d015540 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -376,7 +376,6 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) } } - drawable->validBuffers = GL_TRUE; driUpdateFramebufferSize(&intel->ctx, drawable); } diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index e240957..4591db8 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -125,17 +125,10 @@ intelDRI2Flush(__DRIdrawable *drawable) intel_batchbuffer_flush(intel->batch); } -static void -intelDRI2FlushInvalidate(__DRIdrawable *drawable) -{ - intelDRI2Flush(drawable); - drawable->validBuffers = GL_FALSE; -} - static const struct __DRI2flushExtensionRec intelFlushExtension = { { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, intelDRI2Flush, - intelDRI2FlushInvalidate, + dri2InvalidateDrawable, }; static const __DRIextension *intelScreenExtensions[] = { diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index 6f41eaf..0ecafab 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -742,8 +742,10 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, if (!intelObj) return; - if (!dPriv->validBuffers) + if (dPriv->lastStamp != *dPriv->pStamp) { + dPriv->lastStamp = *dPriv->pStamp; intel_update_renderbuffers(pDRICtx, dPriv); + } rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); /* If the region isn't set, then intel_update_renderbuffers was unable -- 1.6.4.4 |
From: Michel D. <mi...@da...> - 2010-01-21 22:39:04
|
On Sat, 2010-01-16 at 23:01 +0100, Francisco Jerez wrote: > When a buffer invalidation event is received from the X server, the > "invalidate" hook of the DRI2 flush extension is executed: A generic > implementation (dri2InvalidateDrawable) is provided that just bumps > the "pStamp" sequence number in __DRIdrawableRec. > > For old servers not supporting buffer invalidation events, the > invalidate hook will be called after flushing the fake front/back > buffer (that's typically once per frame -- not a lot worse than the > situation we were in before). When the invalidate event is available, IMO the buffers should also only be invalidated after a buffer swap / front buffer flush, not 'in the middle of a frame'. > No effort has been made on preserving backwards compatibility with > version 2 of the flush extension, but I think it's acceptable because > AFAIK no released stack is making use of it. IIRC it was added for a released but proprietary driver. > @@ -378,17 +394,14 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, > /* Old servers can't handle swapbuffers */ > if (!pdp->swapAvailable) { > dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); > + dri2LegacyInvalidate(pdraw); > + > return 0; > } > Doesn't this also need to call dri2LegacyInvalidate() if (pdp->swapAvailable) but (!pdp->invalidateAvailable)? -- Earthling Michel Dänzer | http://www.vmware.com Libre software enthusiast | Debian, X and DRI developer |
From: Michel D. <mi...@da...> - 2010-01-21 22:45:38
|
On Thu, 2010-01-21 at 23:38 +0100, Michel Dänzer wrote: > On Sat, 2010-01-16 at 23:01 +0100, Francisco Jerez wrote: > > > No effort has been made on preserving backwards compatibility with > > version 2 of the flush extension, but I think it's acceptable because > > AFAIK no released stack is making use of it. > > IIRC it was added for a released but proprietary driver. Never mind, I was thinking of the extension itself, you're right about version 2. -- Earthling Michel Dänzer | http://www.vmware.com Libre software enthusiast | Debian, X and DRI developer |
From: Michel D. <mi...@da...> - 2010-01-22 16:51:22
|
On Fri, 2010-01-22 at 08:40 -0800, Keith Whitwell wrote: > It's a very rare application that can render half a frame to one sized > framebuffer and the other half to another and expect to have a > meaningful result. > > It's also incredibly difficult to write a driver that produces any > sensible result when the render-target size changes halfway through a > frame. There are a bunch of reasons for this, including the fact that > the driver will have unflushed command buffers referring to the old > size that are suddenly invalid when a new size materializes. Right, that's why I was worrying about processing the DRI2 buffer invalidate event in the middle of rendering a frame. But Francisco clarified that it's only processed when the application is actively processing X11 events, which should usually only be the case between rendering frames. > My pet take on this is that we should go one step further and modify > GLX semantics to allow a stretch blit on swapbuffers to scale the > rendered image up/down to the new window size. I think it's better to follow the X11 window gravity than to scale. DRI2 may accidentally already be doing this for the majority of apps which use the default gravity. :) -- Earthling Michel Dänzer | http://www.vmware.com Libre software enthusiast | Debian, X and DRI developer |
From: Jordan C. <jc...@co...> - 2010-01-22 17:18:41
|
Michel Dänzer wrote: > On Fri, 2010-01-22 at 08:40 -0800, Keith Whitwell wrote: >> It's a very rare application that can render half a frame to one sized >> framebuffer and the other half to another and expect to have a >> meaningful result. >> >> It's also incredibly difficult to write a driver that produces any >> sensible result when the render-target size changes halfway through a >> frame. There are a bunch of reasons for this, including the fact that >> the driver will have unflushed command buffers referring to the old >> size that are suddenly invalid when a new size materializes. > > Right, that's why I was worrying about processing the DRI2 buffer > invalidate event in the middle of rendering a frame. But Francisco > clarified that it's only processed when the application is actively > processing X11 events, which should usually only be the case between > rendering frames. > > >> My pet take on this is that we should go one step further and modify >> GLX semantics to allow a stretch blit on swapbuffers to scale the >> rendered image up/down to the new window size. > > I think it's better to follow the X11 window gravity than to scale. DRI2 > may accidentally already be doing this for the majority of apps which > use the default gravity. :) Agreed. It should behave the same as if you had any busy X client that didn't repaint its window after a resize. A stretch blit would be just as jarring to the eye as an unpainted window (though in a different way). Jordan -- Jordan Crouse Qualcomm Innovation Center Qualcomm Innovation Center is a member of Code Aurora Forum |
From: Francisco J. <cur...@ri...> - 2010-01-16 22:02:17
|
--- This driver isn't in master yet, but I thought that maybe this patch could be interesting. src/mesa/drivers/dri/nouveau/nouveau_context.c | 38 +++++++++++++++------- src/mesa/drivers/dri/nouveau/nouveau_context.h | 3 ++ src/mesa/drivers/dri/nouveau/nouveau_driver.c | 1 + src/mesa/drivers/dri/nouveau/nouveau_render_t.c | 2 + src/mesa/drivers/dri/nouveau/nouveau_screen.c | 19 +++++++++++ src/mesa/drivers/dri/nouveau/nouveau_state.c | 2 - src/mesa/drivers/dri/nouveau/nv10_context.c | 2 + 7 files changed, 53 insertions(+), 14 deletions(-) diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c index 9312ec7..e679a6d 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c @@ -127,7 +127,8 @@ nouveau_context_destroy(__DRIcontext *dri_ctx) } static void -nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) +nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable, + unsigned int *stamp) { struct nouveau_context *nctx = context->driverPrivate; GLcontext *ctx = &nctx->base; @@ -137,6 +138,8 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) __DRIbuffer *buffers = NULL; int i = 0, count, ret; + *stamp = *drawable->pStamp; + attachments[i++] = __DRI_BUFFER_FRONT_LEFT; if (fb->Visual.doubleBufferMode) attachments[i++] = __DRI_BUFFER_BACK_LEFT; @@ -217,15 +220,18 @@ nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *dri_draw, struct nouveau_context *nctx = dri_ctx->driverPrivate; GLcontext *ctx = &nctx->base; - if (nctx->screen->context != nctx) { - nctx->screen->context = nctx; - nctx->dirty = ~0; - } + if (nctx->screen->context == nctx) + return GL_TRUE; + + nctx->screen->context = nctx; + nctx->dirty = ~0; /* Ask the X server for new renderbuffers. */ - nouveau_update_renderbuffers(dri_ctx, dri_draw); + nouveau_update_renderbuffers(dri_ctx, dri_draw, + &nctx->drawable_stamp); if (dri_draw != dri_read) - nouveau_update_renderbuffers(dri_ctx, dri_read); + nouveau_update_renderbuffers(dri_ctx, dri_read, + &nctx->readable_stamp); /* Pass it down to mesa. */ _mesa_make_current(ctx, dri_draw->driverPrivate, @@ -260,17 +266,25 @@ nouveau_fallback(GLcontext *ctx, enum nouveau_fallback mode) void nouveau_validate_framebuffer(GLcontext *ctx) { + struct nouveau_context *nctx = to_nouveau_context(ctx); __DRIcontext *dri_ctx = to_nouveau_context(ctx)->dri_context; + __DRIdrawable *dri_draw = dri_ctx->driDrawablePriv; + __DRIdrawable *dri_read = dri_ctx->driReadablePriv; - if (ctx->DrawBuffer->Name) + if ((ctx->DrawBuffer->Name || + nctx->drawable_stamp == *dri_draw->pStamp) && + (dri_draw == dri_read || ctx->ReadBuffer->Name || + nctx->readable_stamp == *dri_read->pStamp)) return; ctx->Driver.Flush(ctx); - /* Make sure our renderbuffers are up-to-date. */ - nouveau_update_renderbuffers(dri_ctx, dri_ctx->driDrawablePriv); - if (dri_ctx->driDrawablePriv != dri_ctx->driReadablePriv) - nouveau_update_renderbuffers(dri_ctx, dri_ctx->driReadablePriv); + /* Ask the X server for new renderbuffers. */ + nouveau_update_renderbuffers(dri_ctx, dri_draw, + &nctx->drawable_stamp); + if (dri_draw != dri_read) + nouveau_update_renderbuffers(dri_ctx, dri_read, + &nctx->readable_stamp); FIRE_RING(context_chan(ctx)); } diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h index 4171249..7382cac 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h @@ -48,6 +48,9 @@ struct nouveau_context { struct nouveau_bo_state bo; struct nouveau_render_state render; + + unsigned int drawable_stamp; + unsigned int readable_stamp; }; #define to_nouveau_context(ctx) ((struct nouveau_context *)(ctx)) diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.c b/src/mesa/drivers/dri/nouveau/nouveau_driver.c index 12df30a..eb259ab 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_driver.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.c @@ -82,6 +82,7 @@ nouveau_clear(GLcontext *ctx, GLbitfield buffers) int x, y, w, h; int i, buf; + nouveau_validate_framebuffer(ctx); get_scissors(fb, &x, &y, &w, &h); for (i = 0; i < BUFFER_COUNT; i++) { diff --git a/src/mesa/drivers/dri/nouveau/nouveau_render_t.c b/src/mesa/drivers/dri/nouveau/nouveau_render_t.c index 8c551de..6fc2668 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_render_t.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_render_t.c @@ -218,6 +218,8 @@ render_prims(GLcontext *ctx, const struct gl_client_array **arrays, { struct nouveau_context *nctx = to_nouveau_context(ctx); + nouveau_validate_framebuffer(ctx); + if (nctx->fallback == HWTNL) TAG(vbo_render_prims)(ctx, arrays, prims, nr_prims, ib, index_bounds_valid, min_index, max_index); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/src/mesa/drivers/dri/nouveau/nouveau_screen.c index fbb0d75..b70d1f3 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_screen.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.c @@ -35,6 +35,8 @@ #include "main/framebuffer.h" #include "main/renderbuffer.h" +static const __DRIextension *nouveau_screen_extensions[]; + static void nouveau_destroy_screen(__DRIscreen *dri_screen); @@ -104,6 +106,7 @@ nouveau_init_screen2(__DRIscreen *dri_screen) return NULL; dri_screen->private = screen; + dri_screen->extensions = nouveau_screen_extensions; screen->dri_screen = dri_screen; /* Open the DRM device. */ @@ -243,6 +246,22 @@ nouveau_destroy_buffer(__DRIdrawable *drawable) (struct gl_framebuffer **)&drawable->driverPrivate, NULL); } +static void +nouveau_drawable_flush(__DRIdrawable *draw) +{ +} + +static const struct __DRI2flushExtensionRec nouveau_flush_extension = { + { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, + nouveau_drawable_flush, + dri2InvalidateDrawable, +}; + +static const __DRIextension *nouveau_screen_extensions[] = { + &nouveau_flush_extension.base, + NULL +}; + const struct __DriverAPIRec driDriverAPI = { .InitScreen2 = nouveau_init_screen2, .DestroyScreen = nouveau_destroy_screen, diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.c b/src/mesa/drivers/dri/nouveau/nouveau_state.c index 01f924c..7c5f7f2 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_state.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_state.c @@ -366,8 +366,6 @@ nouveau_update_state(GLcontext *ctx, GLbitfield new_state) context_dirty(ctx, PROJECTION); if (new_state & _NEW_MODELVIEW) context_dirty(ctx, MODELVIEW); - if (new_state & _NEW_VIEWPORT) - nouveau_validate_framebuffer(ctx); _swrast_InvalidateState(ctx, new_state); _tnl_InvalidateState(ctx, new_state); diff --git a/src/mesa/drivers/dri/nouveau/nv10_context.c b/src/mesa/drivers/dri/nouveau/nv10_context.c index b2ef800..d1afa87 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_context.c +++ b/src/mesa/drivers/dri/nouveau/nv10_context.c @@ -39,6 +39,8 @@ nv10_clear(GLcontext *ctx, GLbitfield buffers) struct nouveau_framebuffer *nfb = to_nouveau_framebuffer( ctx->DrawBuffer); + nouveau_validate_framebuffer(ctx); + /* Clear the LMA depth buffer, if present. */ if ((buffers & BUFFER_BIT_DEPTH) && ctx->Depth.Mask && nfb->lma_bo) { -- 1.6.4.4 |
From: Francisco J. <cur...@ri...> - 2010-01-16 22:02:19
|
--- src/gallium/state_trackers/dri/dri_context.c | 6 +-- src/gallium/state_trackers/dri/dri_drawable.c | 13 ++++++ src/gallium/state_trackers/dri/dri_screen.c | 12 ++++++ src/mesa/SConscript | 1 - src/mesa/sources.mak | 1 - src/mesa/state_tracker/st_atom.c | 7 +++- src/mesa/state_tracker/st_cb_viewport.c | 53 ------------------------- src/mesa/state_tracker/st_cb_viewport.h | 29 ------------- src/mesa/state_tracker/st_context.c | 2 - 9 files changed, 33 insertions(+), 91 deletions(-) delete mode 100644 src/mesa/state_tracker/st_cb_viewport.c delete mode 100644 src/mesa/state_tracker/st_cb_viewport.h diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c index f2e5f3f..f2d0e61 100644 --- a/src/gallium/state_trackers/dri/dri_context.c +++ b/src/gallium/state_trackers/dri/dri_context.c @@ -162,10 +162,8 @@ dri_make_current(__DRIcontext * cPriv, if (__dri1_api_hooks) { dri1_update_drawables(ctx, draw, read); } else { - if (driDrawPriv) - dri_get_buffers(driDrawPriv); - if (driDrawPriv != driReadPriv && driReadPriv) - dri_get_buffers(driReadPriv); + dri_update_buffer(ctx->pipe->screen, + ctx->pipe->priv); } } else { st_make_current(NULL, NULL, NULL); diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c index 0fdfa96..9aaa662 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.c +++ b/src/gallium/state_trackers/dri/dri_drawable.c @@ -273,7 +273,20 @@ dri_update_buffer(struct pipe_screen *screen, void *context_private) { struct dri_context *ctx = (struct dri_context *)context_private; + if (ctx->d_stamp == *ctx->dPriv->pStamp && + ctx->r_stamp == *ctx->rPriv->pStamp) + return; + + ctx->d_stamp = *ctx->dPriv->pStamp; + ctx->r_stamp = *ctx->rPriv->pStamp; + + st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + + /* Ask the X server for new renderbuffers. */ dri_get_buffers(ctx->dPriv); + if (ctx->dPriv != ctx->rPriv) + dri_get_buffers(ctx->rPriv); + } void diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c index 793db08..f981278 100644 --- a/src/gallium/state_trackers/dri/dri_screen.c +++ b/src/gallium/state_trackers/dri/dri_screen.c @@ -63,6 +63,17 @@ static const __DRItexBufferExtension dri2TexBufferExtension = { dri2_set_tex_buffer2, }; +static void +dri2_flush_drawable(__DRIdrawable *draw) +{ +} + +static const __DRI2flushExtension dri2FlushExtension = { + { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, + dri2_flush_drawable, + dri2InvalidateDrawable, +}; + static const __DRIextension *dri_screen_extensions[] = { &driReadDrawableExtension, &driCopySubBufferExtension.base, @@ -70,6 +81,7 @@ static const __DRItexBufferExtension dri2TexBufferExtension = { &driFrameTrackingExtension.base, &driMediaStreamCounterExtension.base, &dri2TexBufferExtension.base, + &dri2FlushExtension.base, NULL }; diff --git a/src/mesa/SConscript b/src/mesa/SConscript index bdcfffe..dc12cbe 100644 --- a/src/mesa/SConscript +++ b/src/mesa/SConscript @@ -174,7 +174,6 @@ if env['platform'] != 'winddk': 'state_tracker/st_cb_readpixels.c', 'state_tracker/st_cb_strings.c', 'state_tracker/st_cb_texture.c', - 'state_tracker/st_cb_viewport.c', 'state_tracker/st_context.c', 'state_tracker/st_debug.c', 'state_tracker/st_draw.c', diff --git a/src/mesa/sources.mak b/src/mesa/sources.mak index a4d09c7..99aca7d 100644 --- a/src/mesa/sources.mak +++ b/src/mesa/sources.mak @@ -203,7 +203,6 @@ STATETRACKER_SOURCES = \ state_tracker/st_cb_readpixels.c \ state_tracker/st_cb_strings.c \ state_tracker/st_cb_texture.c \ - state_tracker/st_cb_viewport.c \ state_tracker/st_context.c \ state_tracker/st_debug.c \ state_tracker/st_draw.c \ diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index 73df44d..6a7ebff 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -35,7 +35,8 @@ #include "st_cb_bitmap.h" #include "st_program.h" - +#include "pipe/p_context.h" + /** * This is used to initialize st->atoms[]. @@ -135,6 +136,10 @@ void st_validate_state( struct st_context *st ) check_program_state( st ); + if (st->pipe->screen->update_buffer) + st->pipe->screen->update_buffer(st->pipe->screen, + st->pipe->priv); + if (state->st == 0) return; diff --git a/src/mesa/state_tracker/st_cb_viewport.c b/src/mesa/state_tracker/st_cb_viewport.c deleted file mode 100644 index ab11c5b..0000000 --- a/src/mesa/state_tracker/st_cb_viewport.c +++ /dev/null @@ -1,53 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "main/glheader.h" -#include "st_context.h" -#include "st_public.h" -#include "st_cb_viewport.h" - -#include "pipe/p_context.h" -#include "pipe/p_inlines.h" -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" - - -static void st_viewport(GLcontext * ctx, GLint x, GLint y, - GLsizei width, GLsizei height) -{ - struct st_context *st = ctx->st; - - if (st->pipe->screen && st->pipe->screen->update_buffer) - st->pipe->screen->update_buffer( st->pipe->screen, - st->pipe->priv ); -} - -void st_init_viewport_functions(struct dd_function_table *functions) -{ - functions->Viewport = st_viewport; -} diff --git a/src/mesa/state_tracker/st_cb_viewport.h b/src/mesa/state_tracker/st_cb_viewport.h deleted file mode 100644 index 44948e5..0000000 --- a/src/mesa/state_tracker/st_cb_viewport.h +++ /dev/null @@ -1,29 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -extern void -st_init_viewport_functions(struct dd_function_table *functions); diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 45bb6b3..8c70f7c 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -61,7 +61,6 @@ #include "st_cb_texture.h" #include "st_cb_flush.h" #include "st_cb_strings.h" -#include "st_cb_viewport.h" #include "st_atom.h" #include "st_draw.h" #include "st_extensions.h" @@ -343,7 +342,6 @@ void st_init_driver_functions(struct dd_function_table *functions) st_init_texture_functions(functions); st_init_flush_functions(functions); st_init_string_functions(functions); - st_init_viewport_functions(functions); functions->UpdateState = st_invalidate_state; } -- 1.6.4.4 |
From: Luca B. <luc...@gm...> - 2010-01-16 22:15:39
|
What are the advantages of the new DRI2 event over the existing ConfigureNotify? Couldn't that be used as a fallback on older servers? |
From: Francisco J. <cur...@ri...> - 2010-01-16 23:11:31
|
Hi, Luca Barbieri <luc...@gm...> writes: > What are the advantages of the new DRI2 event over the existing ConfigureNotify? > Couldn't that be used as a fallback on older servers? ConfigureNotify is a core event, so: * All the methods we have to catch them are nasty hacks (or at least all the methods I can think of). * A client may ask the server to not send them. |
From: Chia-I Wu <ol...@gm...> - 2010-01-17 02:28:43
|
On Sat, Jan 16, 2010 at 10:58:28PM +0100, Francisco Jerez wrote: > The current buffer validation approach (AKA the DRI2 glViewport hack) > is both incorrect (because a compliant OpenGL application may opt for > the identity as viewport transform and work with window coordinates > directly) and inefficient (some programs have the habit of calling > glViewport several times per frame (e.g. OpenArena), causing many > unnecessary roundtrips). > This changeset gives DRI2 the ability to report drawable changes in an > asynchronous way, but it's a bit intrusive so I expect all sorts of > complaints to come. Great work! I am not familiar with X protocol enough to have concrete comments on the code, but I wish it finds its way in soon. -- Regards, olv |
From: Luca B. <luc...@gm...> - 2010-01-17 06:35:11
|
How about just having GLX open another connection to the X server and use that to receive ConfigureNotify? Since we are using direct rendering, we must be on the same machine, so it's just a unix/TCP loopback connection and should always work. Xlib stores the display name in _XDisplay.display_name so that works. Furthermore, we can ask the kernel to send SIGIO for input on that fd, and we wouldn't have to make any system calls at all to detect resizes! It seems quite workable and even advantageous. How about it? |
From: Luca B. <luc...@gm...> - 2010-01-17 06:43:13
|
Using SIGIO would be a problem in a library. However, the kernel can be told to send an arbitrary signal (see F_SETSIG) and glibc can allocate realtime signals with __libc_allocate_rtsig() (pthread uses this for internal signals). |
From: Francisco J. <cur...@ri...> - 2010-01-17 13:03:51
|
Luca Barbieri <luc...@gm...> writes: > How about just having GLX open another connection to the X server and > use that to receive ConfigureNotify? > Since we are using direct rendering, we must be on the same machine, > so it's just a unix/TCP loopback connection and should always work. > Xlib stores the display name in _XDisplay.display_name so that works. > Furthermore, we can ask the kernel to send SIGIO for input on that fd, > and we wouldn't have to make any system calls at all to detect > resizes! > > It seems quite workable and even advantageous. How about it? How do you make sure events are ordered correctly? Say a window is resized and the client receives the ConfigureNotify event before us, and it reacts drawing on the newly exposed areas: we aren't guaranteed to have received our event yet, so it might end up rendered in the old buffers. The semantics of DRI2InvalidateBuffers are not exactly the same as ConfigureNotify, it just means "your buffers are no longer valid", and there are other reasons we may want to send it (SwapBuffers). Besides, I doubt the fd is public Xlib interface, that would complicate things. |
From: Luca B. <luc...@gm...> - 2010-01-17 21:17:59
|
> How do you make sure events are ordered correctly? Say a window is > resized and the client receives the ConfigureNotify event before us, and > it reacts drawing on the newly exposed areas: we aren't guaranteed to > have received our event yet, so it might end up rendered in the old > buffers. OK, more complicated solution: 1. We snoop on events on the user connection using XESetWireToEvent. This avoids the problem you just mentioned. 2. We still do the secondary connection, so that we don't disturb the client X connection, can check for resizes very quickly (ideally with a signal), and things work even if ConfigureWindow is disabled. There is still a race condition if the application is informed of the resize by a third party, which I think is unfixable with the current X server without adding a roundtrip. Your approach seems to avoid this by sending the invalidate event before any other event that would inform clients of a resize: this is a good reason to use it instead/in addition to the hack proposed above. As for the fd, it is in _XDisplay.fd, and anyway it's only needed for the secondary connection, and that can be done with XCB which has xcb_connect_to_fd. The approach you posted is clearly better; this may be an useful addition to it for backwards compatiblity if desired. |