From: Kristian H. <kr...@bi...> - 2010-01-18 02:05:38
|
On Sat, Jan 16, 2010 at 4:58 PM, Francisco Jerez <cur...@ri...> 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. No, it sounds good, I'm happy that you're looking into this. I'll have a closer look tomorrow, but what I've had in mind for this kind of thing was that we could just allocate the new buffers up front in the X server. Then, instead of an invalidate event and a subsequent DRI2GetBuffers, we'll just have a "here are your new buffers event", so we avoid the round trip. Thanks, Kristian |
From: Francisco J. <cur...@ri...> - 2010-01-18 04:19:30
|
Kristian Høgsberg <kr...@bi...> writes: > On Sat, Jan 16, 2010 at 4:58 PM, Francisco Jerez <cur...@ri...> 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. > > No, it sounds good, I'm happy that you're looking into this. I'll > have a closer look tomorrow, but what I've had in mind for this kind > of thing was that we could just allocate the new buffers up front in > the X server. Then, instead of an invalidate event and a subsequent > DRI2GetBuffers, we'll just have a "here are your new buffers event", > so we avoid the round trip. Yeah that's sensible, the only problem I see with doing things that way is that it doesn't give the driver an opportunity to flush its rendering queues before swapping buffers, so some of it could be lost buried in the old buffers. If we killed DRI2GetBuffers, then I think we would want something like a "please keep me informed about this drawable" request and a "i don't care about this drawable anymore" request, because we don't want to bother clients when they aren't actually rendering to the affected drawables. (Resurrecting the old DRI2Create/DestroyDrawable would also do). I'll be happy to rewrite the patches that way if you guys think a somewhat smaller resizing latency is worth the somewhat greater complexity (and you have a solution for the flushing issue). BTW, I suspect there might be some problems with the X server DRI2 code so please don't look at it so closely yet... (or maybe just my usual 5AM paranoia) > > Thanks, > Kristian |
From: Kristian H. <kr...@bi...> - 2010-01-18 18:54:00
|
On Sun, Jan 17, 2010 at 11:18 PM, Francisco Jerez <cur...@ri...> wrote: > Kristian Høgsberg <kr...@bi...> writes: >> No, it sounds good, I'm happy that you're looking into this. I'll >> have a closer look tomorrow, but what I've had in mind for this kind >> of thing was that we could just allocate the new buffers up front in >> the X server. Then, instead of an invalidate event and a subsequent >> DRI2GetBuffers, we'll just have a "here are your new buffers event", >> so we avoid the round trip. > > Yeah that's sensible, the only problem I see with doing things that way > is that it doesn't give the driver an opportunity to flush its rendering > queues before swapping buffers, so some of it could be lost buried in > the old buffers. Right. Another option is to tell the client about new buffers in the DRI2SwapBuffer/DRI2CopyRegion reply instead - or to kill two birds with one stone, make DRI2SwapBuffers/DRI2CopyRegion one-way requests (that is, requests without a reply) and then send an event instead. This lets the client do other things while waiting for the server to reply, and we'll wait for the event to arrive in the GetBuffers callback from the driver if it hasn't already. The event will always be sent in response to either DRI2SwapBuffer or DRI2CopyRegion, which addresses your concern about sending the event to everybody. The client must wait for the event before it starts rendering the next frame since it could receive new buffers and in any case the server needs to submit the back->front blit first (which is the reason DRI2CopyRegion is a round-trip). That would be the ideal solution as far as I know, and if we're changing things, this is what we should go for. cheers, Kristian |
From: Francisco J. <cur...@ri...> - 2010-01-19 04:21:41
|
Kristian Høgsberg <kr...@bi...> writes: > On Sun, Jan 17, 2010 at 11:18 PM, Francisco Jerez <cur...@ri...> wrote: >> Kristian Høgsberg <kr...@bi...> writes: >>> No, it sounds good, I'm happy that you're looking into this. I'll >>> have a closer look tomorrow, but what I've had in mind for this kind >>> of thing was that we could just allocate the new buffers up front in >>> the X server. Then, instead of an invalidate event and a subsequent >>> DRI2GetBuffers, we'll just have a "here are your new buffers event", >>> so we avoid the round trip. >> >> Yeah that's sensible, the only problem I see with doing things that way >> is that it doesn't give the driver an opportunity to flush its rendering >> queues before swapping buffers, so some of it could be lost buried in >> the old buffers. > > Right. Another option is to tell the client about new buffers in the > DRI2SwapBuffer/DRI2CopyRegion reply instead - or to kill two birds > with one stone, make DRI2SwapBuffers/DRI2CopyRegion one-way requests > (that is, requests without a reply) and then send an event instead. > This lets the client do other things while waiting for the server to > reply, and we'll wait for the event to arrive in the GetBuffers > callback from the driver if it hasn't already. The event will always > be sent in response to either DRI2SwapBuffer or DRI2CopyRegion, which > addresses your concern about sending the event to everybody. The > client must wait for the event before it starts rendering the next > frame since it could receive new buffers and in any case the server > needs to submit the back->front blit first (which is the reason > DRI2CopyRegion is a round-trip). > That last proposal has a clear advantage: it needs *zero* protocol changes: It could be implemented sending SwapBuffers and GetBuffers in one go, without waiting for the responses. Instead we handle them asynchronously with some "async handlers". If it hasn't arrived yet by the time we start drawing again, we XSync(). However, IMHO, we still want a DRI2InvalidateBuffers-like event, because: * That solution wouldn't make event-driven GL applications very happy, the succession of events could be something like: 1/ A frame is drawn, the app flushes and then it waits for events. 2/ We get the GetBuffers reply and install our new buffers. 3/ The user attempts a resize and the application reacts redrawing the exposed areas... Helplessly, because we're still on the pre-resize buffers, and they aren't big enough to hold it. * It breaks up when there are several contexts bound to the same drawable, because only the one calling SwapBuffers gets buffer updates. As I see it, forcing a buffer update on each flush or not, asynchronously or not, is somewhat orthogonal with having the server send buffer invalidation events to clients, and we probably want both eventually. > That would be the ideal solution as far as I know, and if we're > changing things, this is what we should go for. > > cheers, > Kristian |
From: Michel D. <mi...@da...> - 2010-01-21 18:14:00
|
On Sat, 2010-01-16 at 23:00 +0100, Francisco Jerez wrote: > 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. 'Needs to' why? If you're worrying about the client side driver being unable to see the DRI2InvalidateBuffers event for the client app's reaction to the ConfigureNotify event, how likely is that to happen, and couldn't it be avoided by other means? If the ABI break is truly unavoidable, it would have been nice to get it into xserver 1.8, which already bumped the ABI versions... -- Earthling Michel Dänzer | http://www.vmware.com Libre software enthusiast | Debian, X and DRI developer |
From: Francisco J. <cur...@ri...> - 2010-01-21 18:50:10
|
Michel Dänzer <mi...@da...> writes: > On Sat, 2010-01-16 at 23:00 +0100, Francisco Jerez wrote: >> 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. > > 'Needs to' why? If you're worrying about the client side driver being > unable to see the DRI2InvalidateBuffers event for the client app's > reaction to the ConfigureNotify event, how likely is that to happen, and > couldn't it be avoided by other means? > Right, that's what I was worried about. It's unlikely, but possible if e.g. the X server output buffer is flushed between both events. I think it could also be done hooking an "event callback" as (IIRC) the record extension used to do, but... it would be slow and ugly. > If the ABI break is truly unavoidable, it would have been nice to get it > into xserver 1.8, which already bumped the ABI versions... |
From: Michel D. <mi...@da...> - 2010-01-21 19:30:09
|
On Sat, 2010-01-16 at 23:00 +0100, Francisco Jerez wrote: > 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; > >From the comment, I think the intention is to do the copy iff there wasn't a fake front before but there is one afterwards. Is that what it does after your change? I'm having a hard time determining that. :} -- Earthling Michel Dänzer | http://www.vmware.com Libre software enthusiast | Debian, X and DRI developer |
From: Francisco J. <cur...@ri...> - 2010-01-21 20:46:34
|
Michel Dänzer <mi...@da...> writes: > On Sat, 2010-01-16 at 23:00 +0100, Francisco Jerez wrote: >> 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; >> > >>From the comment, I think the intention is to do the copy iff there > wasn't a fake front before but there is one afterwards. Is that what it > does after your change? I'm having a hard time determining that. :} I meant to make it do the copy iff it's the initial allocation or it's being reallocated, but I admit this patch legibility could be improved. I think I'll post a nicer one later today. BTW, I'm considering to drop "dri2proto patch2" and "xserver patch3". The plan was to save the subsequent GetBuffers round-trip when the DDX implements SwapBuffers with some kind of blitter, but the DRI driver can be made smart enough to make the slowdown almost unnoticeable (benchmarked on nv17 with an app at ~600FPS, the FPS drop is less than 0.2%, so I guess it isn't worth the DRI2InfoRec ABI break). |
From: Francisco J. <cur...@ri...> - 2010-01-21 23:12:45
|
Michel Dänzer <mi...@da...> writes: > 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'. > Event-driven applications want the new buffers immediately after getting the resize event, otherwise they could try to draw outside the bounds of the old buffers, and that rendering would be lost. Patches 2 and 3 make the affected drivers fabricate a flush before switching buffers, so the previous rendering shouldn't be lost either. > >> 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)? Yeah, I'll fix that one. |
From: Michel D. <mi...@da...> - 2010-01-22 12:11:57
|
On Fri, 2010-01-22 at 00:10 +0100, Francisco Jerez wrote: > Michel Dänzer <mi...@da...> writes: > > > 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'. > > > Event-driven applications want the new buffers immediately after getting > the resize event, otherwise they could try to draw outside the bounds of > the old buffers, and that rendering would be lost. I still don't see any benefit to changing the buffers while the app is rendering a frame, but I guess the problem is that the DRI2 code in libGL doesn't know if that's the case or not... > Patches 2 and 3 make the affected drivers fabricate a flush before > switching buffers, so the previous rendering shouldn't be lost either. That may help for the fake front but not for the back buffer. Then again I guess the worst case is intermittent incomplete frames during a window resize, which may be acceptable. -- Earthling Michel Dänzer | http://www.vmware.com Libre software enthusiast | Debian, X and DRI developer |
From: Francisco J. <cur...@ri...> - 2010-01-22 12:56:53
|
Michel Dänzer <mi...@da...> writes: > On Fri, 2010-01-22 at 00:10 +0100, Francisco Jerez wrote: >> Michel Dänzer <mi...@da...> writes: >> >> > 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'. >> > >> Event-driven applications want the new buffers immediately after getting >> the resize event, otherwise they could try to draw outside the bounds of >> the old buffers, and that rendering would be lost. > > I still don't see any benefit to changing the buffers while the app is > rendering a frame, but I guess the problem is that the DRI2 code in > libGL doesn't know if that's the case or not... > >> Patches 2 and 3 make the affected drivers fabricate a flush before >> switching buffers, so the previous rendering shouldn't be lost either. > > That may help for the fake front but not for the back buffer. Then again > I guess the worst case is intermittent incomplete frames during a window > resize, which may be acceptable. That shouldn't happen, we only get InvalidateBuffers events when the client is actively processing X events: sane clients don't do that "in the middle of a frame" -- and whoever is actually doing that is likely to be prepared to deal with a resize and some invalidated buffers at the same point. |
From: Michel D. <mi...@da...> - 2010-01-22 16:16:32
|
On Fri, 2010-01-22 at 13:33 +0100, Francisco Jerez wrote: > Michel Dänzer <mi...@da...> writes: > > > On Fri, 2010-01-22 at 00:10 +0100, Francisco Jerez wrote: > >> Michel Dänzer <mi...@da...> writes: > >> > >> > 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'. > >> > > >> Event-driven applications want the new buffers immediately after getting > >> the resize event, otherwise they could try to draw outside the bounds of > >> the old buffers, and that rendering would be lost. > > > > I still don't see any benefit to changing the buffers while the app is > > rendering a frame, but I guess the problem is that the DRI2 code in > > libGL doesn't know if that's the case or not... > > > >> Patches 2 and 3 make the affected drivers fabricate a flush before > >> switching buffers, so the previous rendering shouldn't be lost either. > > > > That may help for the fake front but not for the back buffer. Then again > > I guess the worst case is intermittent incomplete frames during a window > > resize, which may be acceptable. > > That shouldn't happen, we only get InvalidateBuffers events when the > client is actively processing X events: sane clients don't do that "in > the middle of a frame" -- and whoever is actually doing that is likely > to be prepared to deal with a resize and some invalidated buffers at the > same point. Ah, I didn't realize that, thanks for the clarification. Sounds good then. -- Earthling Michel Dänzer | http://www.vmware.com Libre software enthusiast | Debian, X and DRI developer |
From: Francisco J. <cur...@ri...> - 2010-01-22 14:26:46
|
Francisco Jerez <cur...@ri...> writes: > 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. > A revised changeset follows. Among other minor fixes, it avoids the DRI2InfoRec ABI breakup, so this version will hopefully be somewhat less intrusive on the X side. This time I've tried to preserve backwards compatibility with flush v2 (sigh), as intel has recently started to make use of it in a non-trivial way. [dri2proto patch v3] Define an event to notify clients about the validity of their buffers. [xserver patch v3 1/5] Add a PreConfigureWindow hook. [xserver patch v3 2/5] dri2: No need to blit from front on DRI2GetBuffers if they're just being reused. [xserver patch v3 3/5] glx: Enforce a 1:1 correspondence between GLX and X11 windows. [xserver patch v3 4/5] glx/dri2: Notify the driver when its buffers become invalid. [xserver patch v3 5/5] dri2: Support the DRI2InvalidateBuffers event. [mesa patch v3 1/3] dri2: Event driven buffer validation. [mesa patch v3 2/3] dri/nouveau: Use event driven buffer validation. [mesa patch v3 3/3] st/dri2: Use event-driven buffer validation. |
From: Francisco J. <cur...@ri...> - 2010-01-22 14:30:07
|
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...> --- 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-22 14:30:07
|
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 | 42 +++++++++++++++++++++++------------------- 1 files changed, 23 insertions(+), 19 deletions(-) diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index 3db826e..02a93ff 100644 --- a/hw/xfree86/dri2/dri2.c +++ b/hw/xfree86/dri2/dri2.c @@ -176,27 +176,25 @@ find_attachment(DRI2DrawablePtr pPriv, unsigned attachment) return -1; } -static DRI2BufferPtr +static Bool allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds, DRI2DrawablePtr pPriv, unsigned int attachment, unsigned int format, - int dimensions_match) + int dimensions_match, DRI2BufferPtr *buffer) { - DRI2BufferPtr buffer; - int old_buf; - - old_buf = find_attachment(pPriv, attachment); + int old_buf = find_attachment(pPriv, attachment); if ((old_buf < 0) || !dimensions_match || (pPriv->buffers[old_buf]->format != format)) { - buffer = (*ds->CreateBuffer)(pDraw, attachment, format); + *buffer = (*ds->CreateBuffer)(pDraw, attachment, format); + return TRUE; + } else { - buffer = pPriv->buffers[old_buf]; + *buffer = pPriv->buffers[old_buf]; pPriv->buffers[old_buf] = NULL; + return FALSE; } - - return buffer; } static DRI2BufferPtr * @@ -212,6 +210,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 = 0; int i; if (!pPriv) { @@ -230,8 +229,10 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, const unsigned attachment = *(attachments++); const unsigned format = (has_format) ? *(attachments++) : 0; - buffers[i] = allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment, - format, dimensions_match); + if (allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment, + format, dimensions_match, + &buffers[i])) + buffers_changed = 1; /* If the drawable is a window and the front-buffer is requested, * silently add the fake front-buffer to the list of requested @@ -261,15 +262,18 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, } if (need_real_front > 0) { - buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv, - DRI2BufferFrontLeft, - front_format, dimensions_match); + if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFrontLeft, + front_format, dimensions_match, + &buffers[i++])) + buffers_changed = 1; } if (need_fake_front > 0) { - buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv, - DRI2BufferFakeFrontLeft, - front_format, dimensions_match); + if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFakeFrontLeft, + front_format, dimensions_match, + &buffers[i++])) + buffers_changed = 1; + have_fake_front = 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-22 14:30:11
|
Signed-off-by: Francisco Jerez <cur...@ri...> --- glx/glxdri2.c | 31 ++++++++++++++++++++++++++++--- 1 files changed, 28 insertions(+), 3 deletions(-) diff --git a/glx/glxdri2.c b/glx/glxdri2.c index 69fd39b..5cb15d9 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; @@ -217,13 +218,16 @@ __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *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; + if (screen->flush) + (*screen->flush->invalidate)(priv->driDrawable); + + if (screen->flush && screen->flush->flushInvalidate) + (*screen->flush->flushInvalidate)(priv->driDrawable); + return TRUE; } @@ -607,6 +611,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; @@ -782,6 +804,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-22 14:30:10
|
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-22 14:30:16
|
Bumps the supported DRI2 protocol version. Signed-off-by: Francisco Jerez <cur...@ri...> --- configure.ac | 2 +- hw/xfree86/dri2/dri2.c | 109 +++++++++++++++++++++++++++++++++++++++++++ hw/xfree86/dri2/dri2.h | 5 ++ hw/xfree86/dri2/dri2ext.c | 35 ++++++++++++-- include/protocol-versions.h | 2 +- 5 files changed, 147 insertions(+), 6 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/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index 02a93ff..90a5879 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) @@ -734,6 +818,7 @@ DRI2DestroyDrawable(DrawablePtr pDraw) DRI2DrawablePtr pPriv; WindowPtr pWin; PixmapPtr pPixmap; + DRI2ClientRefPtr ref; pPriv = DRI2GetDrawable(pDraw); if (pPriv == NULL) @@ -752,6 +837,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. */ @@ -800,6 +888,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) { @@ -834,6 +940,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 dd59297..736cfb6 100644 --- a/hw/xfree86/dri2/dri2.h +++ b/hw/xfree86/dri2/dri2.h @@ -256,4 +256,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 3e6b03e..713c82e 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,8 @@ ProcDRI2SwapBuffers(ClientPtr client) if (status != Success) return BadDrawable; + DRI2InvalidateDrawable(pDrawable); + rep.type = X_Reply; rep.length = 0; rep.sequenceNumber = client->sequence; @@ -618,11 +639,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-22 14:31:19
|
--- src/mesa/drivers/dri/nouveau/nouveau_context.c | 49 ++++++++++++++++------- src/mesa/drivers/dri/nouveau/nouveau_context.h | 7 +++ src/mesa/drivers/dri/nouveau/nouveau_driver.c | 3 + src/mesa/drivers/dri/nouveau/nouveau_render_t.c | 2 + src/mesa/drivers/dri/nouveau/nouveau_screen.c | 20 +++++++++ src/mesa/drivers/dri/nouveau/nouveau_state.c | 2 - src/mesa/drivers/dri/nouveau/nv10_context.c | 2 + 7 files changed, 68 insertions(+), 17 deletions(-) diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c index 9312ec7..e526b6d 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.d_stamp); if (dri_draw != dri_read) - nouveau_update_renderbuffers(dri_ctx, dri_read); + nouveau_update_renderbuffers(dri_ctx, dri_read, + &nctx->drawable.r_stamp); /* Pass it down to mesa. */ _mesa_make_current(ctx, dri_draw->driverPrivate, @@ -260,17 +266,30 @@ 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) - return; + if ((ctx->DrawBuffer->Name == 0 && + nctx->drawable.d_stamp != *dri_draw->pStamp) || + (dri_draw != dri_read && + ctx->ReadBuffer->Name == 0 && + nctx->drawable.r_stamp != *dri_read->pStamp)) { + if (nctx->drawable.dirty) + ctx->Driver.Flush(ctx); - ctx->Driver.Flush(ctx); + /* Ask the X server for new renderbuffers. */ + nouveau_update_renderbuffers(dri_ctx, dri_draw, + &nctx->drawable.d_stamp); + if (dri_draw != dri_read) + nouveau_update_renderbuffers(dri_ctx, dri_read, + &nctx->drawable.r_stamp); - /* 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); + if (nctx->dirty) + FIRE_RING(context_chan(ctx)); + } - FIRE_RING(context_chan(ctx)); + /* Someone's planning to draw something really soon. */ + nctx->drawable.dirty = GL_TRUE; } diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h index 4171249..891fca0 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h @@ -38,6 +38,12 @@ enum nouveau_fallback { SWRAST, }; +struct nouveau_drawable_state { + GLboolean dirty; + unsigned int d_stamp; + unsigned int r_stamp; +}; + struct nouveau_context { GLcontext base; __DRIcontext *dri_context; @@ -48,6 +54,7 @@ struct nouveau_context { struct nouveau_bo_state bo; struct nouveau_render_state render; + struct nouveau_drawable_state drawable; }; #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..bf0e20c 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_driver.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.c @@ -67,6 +67,8 @@ nouveau_flush(GLcontext *ctx) dri2->flushFrontBuffer(drawable, drawable->loaderPrivate); } + + nctx->drawable.dirty = GL_FALSE; } static void @@ -82,6 +84,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..9a19144 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,23 @@ 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, + NULL, + 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-22 14:31:24
|
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). Backwards compatibility should be preserved with version 2 of the flush extension, but the "flushInvalidate" callback has been marked as deprecated. Note that this bumps the required dri2proto version to 2.3. --- configure.ac | 2 +- include/GL/internal/dri_interface.h | 16 ++++++++++- src/glx/x11/dri2.c | 10 ++++++- src/glx/x11/dri2.h | 3 ++ src/glx/x11/dri2_glx.c | 37 ++++++++++++++++++++----- 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 | 2 +- src/mesa/drivers/dri/intel/intel_tex_image.c | 4 ++- 13 files changed, 84 insertions(+), 26 deletions(-) diff --git a/configure.ac b/configure.ac index 6ae526d..0efbeb0 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..e818744 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -262,7 +262,7 @@ 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); @@ -273,11 +273,25 @@ struct __DRI2flushExtensionRec { * getBuffers/getBuffersWithFormat before it starts rendering * again. * + * This function is only called when \c SwapBuffers is the reason + * buffers have become invalid, and it's deprecated in favor of + * \c ::invalidate. + * * \param drawable the drawable to flush and invalidate * * \since 2 */ void (*flushInvalidate)(__DRIdrawable *drawable); + + /** + * Ask the driver to call getBuffers/getBuffersWithFormat before + * it starts rendering again. + * + * \param drawable the drawable to invalidate + * + * \since 3 + */ + void (*invalidate)(__DRIdrawable *drawable); }; diff --git a/src/glx/x11/dri2.c b/src/glx/x11/dri2.c index 2cb5d34..4a84066 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,6 +95,7 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire) { GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire; + switch (awire->type) { case DRI2_EXCHANGE_COMPLETE: aevent->event_type = GLX_EXCHANGE_COMPLETE; @@ -115,6 +116,13 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire) aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo; return True; } + case DRI2_InvalidateBuffers: + { + xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire; + + DRI2InvalidateBuffers(dpy, awire->drawable); + return False; + } default: /* client doesn't support server event */ break; diff --git a/src/glx/x11/dri2.h b/src/glx/x11/dri2.h index 114e9f8..943ac59 100644 --- a/src/glx/x11/dri2.h +++ b/src/glx/x11/dri2.h @@ -103,4 +103,7 @@ DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust, extern void DRI2SwapInterval(Display *dpy, XID drawable, int interval); +extern void +DRI2InvalidateBuffers(Display *dpy, XID drawable); + #endif diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c index 7b0c52b..73f988d 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,18 @@ dri2WaitGL(__GLXDRIdrawable * pdraw) XFixesDestroyRegion(pdraw->psc->dpy, region); } - static void -dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate) +dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) { - (void) driDrawable; - dri2WaitGL((__GLXDRIdrawable *) loaderPrivate); + __GLXDRIdrawablePrivate *pdraw = loaderPrivate; + __GLXdisplayPrivate *priv = __glXInitialize(pdraw->base.psc->dpy); + __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)priv->dri2Display; + + /* Old servers don't send invalidate events */ + if (!pdp->invalidateAvailable) + DRI2InvalidateBuffers(priv->dpy, pdraw->base.xDrawable); + + dri2WaitGL(loaderPrivate); } @@ -375,6 +382,10 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, (*pdraw->psc->f->flush)(pdraw->driDrawable); #endif + /* Old servers don't send invalidate events */ + if (!pdp->invalidateAvailable) + DRI2InvalidateBuffers(dpyPriv->dpy, pdraw->xDrawable); + /* Old servers can't handle swapbuffers */ if (!pdp->swapAvailable) { dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); @@ -385,7 +396,7 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, remainder, &ret); #if __DRI2_FLUSH_VERSION >= 2 - if (pdraw->psc->f) + if (pdraw->psc->f && pdraw->psc->f->flushInvalidate) (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable); #endif @@ -483,6 +494,17 @@ static const __DRIextension *loader_extensions_old[] = { NULL }; +_X_HIDDEN void +DRI2InvalidateBuffers(Display *dpy, XID drawable) +{ + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); + +#if __DRI2_FLUSH_VERSION >= 3 + if (pdraw && pdraw->psc->f) + pdraw->psc->f->invalidate(pdraw->driDrawable); +#endif +} + static __GLXDRIscreen * dri2CreateScreen(__GLXscreenConfigs * psc, int screen, __GLXdisplayPrivate * priv) @@ -640,9 +662,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 d52fe2e..b4891b1 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 6c2cb3b..74a4a13 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -131,7 +131,6 @@ intelDRI2FlushInvalidate(__DRIdrawable *drawable) struct intel_context *intel = drawable->driContextPriv->driverPrivate; intelDRI2Flush(drawable); - drawable->validBuffers = GL_FALSE; /* We're using FlushInvalidate as an indicator that a frame is * done. It's only called immediately after SwapBuffers, so it @@ -157,6 +156,7 @@ 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: Francisco J. <cur...@ri...> - 2010-01-22 14:31:25
|
--- 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 | 13 ++++++ 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, 34 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 d8c0543..a66ab70 100644 --- a/src/gallium/state_trackers/dri/dri_screen.c +++ b/src/gallium/state_trackers/dri/dri_screen.c @@ -63,6 +63,18 @@ 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, + NULL, + dri2InvalidateDrawable, +}; + static const __DRIextension *dri_screen_extensions[] = { &driReadDrawableExtension, &driCopySubBufferExtension.base, @@ -70,6 +82,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 9e6ce30..d37bdc8 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" @@ -348,7 +347,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: Francisco J. <cur...@ri...> - 2010-01-22 14:46:38
|
Bumps the protocol and package versions. Signed-off-by: Francisco Jerez <cur...@ri...> --- configure.ac | 2 +- dri2proto.h | 19 +++++++++++++++++-- dri2proto.txt | 31 ++++++++++++++++++++++++------- 3 files changed, 42 insertions(+), 10 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 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-02-08 19:01:40
|
Francisco Jerez <cur...@ri...> writes: > Francisco Jerez <cur...@ri...> writes: > >> 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. >> > > A revised changeset follows. Among other minor fixes, it avoids the > DRI2InfoRec ABI breakup, so this version will hopefully be somewhat less > intrusive on the X side. > > This time I've tried to preserve backwards compatibility with flush v2 > (sigh), as intel has recently started to make use of it in a non-trivial > way. > > [dri2proto patch v3] Define an event to notify clients about the validity of their buffers. > [xserver patch v3 1/5] Add a PreConfigureWindow hook. > [xserver patch v3 2/5] dri2: No need to blit from front on DRI2GetBuffers if they're just being reused. > [xserver patch v3 3/5] glx: Enforce a 1:1 correspondence between GLX and X11 windows. > [xserver patch v3 4/5] glx/dri2: Notify the driver when its buffers become invalid. > [xserver patch v3 5/5] dri2: Support the DRI2InvalidateBuffers event. > [mesa patch v3 1/3] dri2: Event driven buffer validation. > [mesa patch v3 2/3] dri/nouveau: Use event driven buffer validation. > [mesa patch v3 3/3] st/dri2: Use event-driven buffer validation. I assume everyone is OK with these patches because they've been around for more than three weeks already... The following patch series is roughly the same as v3, but it's rebased over the latest conflicting changes. [dri2proto patch v4] Define an event to notify clients about the validity of their buffers. [xserver patch v4 1/5] Add a PreConfigureWindow hook. [xserver patch v4 2/5] dri2: No need to blit from front on DRI2GetBuffers if they're just being reused. [xserver patch v4 3/5] glx: Enforce a 1:1 correspondence between GLX and X11 windows. [xserver patch v4 4/5] glx/dri2: Notify the driver when its buffers become invalid. [xserver patch v4 5/5] dri2: Support the DRI2InvalidateBuffers event. [mesa patch v4 1/3] dri2: Event driven buffer validation. [mesa patch v4 2/3] dri/nouveau: Use event driven buffer validation. [mesa patch v4 3/3] st/dri2: Use event-driven buffer validation. |
From: Francisco J. <cur...@ri...> - 2010-02-08 18:24:49
|
Bumps the protocol and package versions. Signed-off-by: Francisco Jerez <cur...@ri...> --- configure.ac | 2 +- dri2proto.h | 19 +++++++++++++++++-- dri2proto.txt | 31 ++++++++++++++++++++++++------- 3 files changed, 42 insertions(+), 10 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 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-02-08 18:25:28
|
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 | 42 +++++++++++++++++++++++------------------- 1 files changed, 23 insertions(+), 19 deletions(-) diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index cd69ca0..48618e1 100644 --- a/hw/xfree86/dri2/dri2.c +++ b/hw/xfree86/dri2/dri2.c @@ -202,27 +202,25 @@ find_attachment(DRI2DrawablePtr pPriv, unsigned attachment) return -1; } -static DRI2BufferPtr +static Bool allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds, DRI2DrawablePtr pPriv, unsigned int attachment, unsigned int format, - int dimensions_match) + int dimensions_match, DRI2BufferPtr *buffer) { - DRI2BufferPtr buffer; - int old_buf; - - old_buf = find_attachment(pPriv, attachment); + int old_buf = find_attachment(pPriv, attachment); if ((old_buf < 0) || !dimensions_match || (pPriv->buffers[old_buf]->format != format)) { - buffer = (*ds->CreateBuffer)(pDraw, attachment, format); + *buffer = (*ds->CreateBuffer)(pDraw, attachment, format); + return TRUE; + } else { - buffer = pPriv->buffers[old_buf]; + *buffer = pPriv->buffers[old_buf]; pPriv->buffers[old_buf] = NULL; + return FALSE; } - - return buffer; } static DRI2BufferPtr * @@ -238,6 +236,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 = 0; int i; if (!pPriv) { @@ -256,8 +255,10 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, const unsigned attachment = *(attachments++); const unsigned format = (has_format) ? *(attachments++) : 0; - buffers[i] = allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment, - format, dimensions_match); + if (allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment, + format, dimensions_match, + &buffers[i])) + buffers_changed = 1; /* If the drawable is a window and the front-buffer is requested, * silently add the fake front-buffer to the list of requested @@ -287,15 +288,18 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, } if (need_real_front > 0) { - buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv, - DRI2BufferFrontLeft, - front_format, dimensions_match); + if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFrontLeft, + front_format, dimensions_match, + &buffers[i++])) + buffers_changed = 1; } if (need_fake_front > 0) { - buffers[i++] = allocate_or_reuse_buffer(pDraw, ds, pPriv, - DRI2BufferFakeFrontLeft, - front_format, dimensions_match); + if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFakeFrontLeft, + front_format, dimensions_match, + &buffers[i++])) + buffers_changed = 1; + have_fake_front = 1; } @@ -324,7 +328,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 |