diff options
author | Maarten Maathuis <madman2003@gmail.com> | 2008-08-30 00:37:11 +0200 |
---|---|---|
committer | Maarten Maathuis <madman2003@gmail.com> | 2008-08-30 00:37:11 +0200 |
commit | 974db58f5b730c3770ee461665a02dd4334d1dea (patch) | |
tree | e4a6598a25e173474745dce4bccc73b7cd4822ef | |
parent | 454cb0802eec3c2c2cdbcc17971bced868462b83 (diff) |
damage: initial attempt at a damage marker mechanism
- This should allow drivers to recieve post submission events for X<->opengl synchronisation.
- Lacking a testcase, i'm open to suggestion how to do it better.
- The idea is:
- driver recieves event
- driver creates personal identification and inserts marker into X fifo.
- when something wants to use an X pixmap, it checks if something is pending.
- If so, it synchronizes the 2nd fifo using the initial identification.
- Driver is not required to use interrupt based systems (price too high).
- Lower latency is ofcource better.
- If this is somehow unusable for you, then come up with improvements.
- For that reason i wouldn't consider the api fixed for the moment.
-rwxr-xr-x | miext/damage/damage.c | 103 | ||||
-rwxr-xr-x | miext/damage/damage.h | 11 | ||||
-rwxr-xr-x | miext/damage/damagestr.h | 5 |
3 files changed, 107 insertions, 12 deletions
diff --git a/miext/damage/damage.c b/miext/damage/damage.c index 60acdca87..a90ee08fe 100755 --- a/miext/damage/damage.c +++ b/miext/damage/damage.c @@ -168,6 +168,48 @@ damageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion) } } +static void +damageReportDamagePostRendering (DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pDamageRegion) +{ + BoxRec tmpBox; + RegionRec tmpRegion, newDamage; + Bool was_empty; + + REGION_UNION(pScreem, &newDamage, pOldDamage, pDamageRegion); + + switch (pDamage->damageLevel) { + case DamageReportRawRegion: + (*pDamage->damageReportPostRendering) (pDamage, pDamageRegion, pDamage->closure); + break; + case DamageReportDeltaRegion: + REGION_NULL (pScreen, &tmpRegion); + REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, pOldDamage); + if (REGION_NOTEMPTY (pScreen, &tmpRegion)) { + (*pDamage->damageReportPostRendering) (pDamage, &tmpRegion, pDamage->closure); + } + REGION_UNINIT(pScreen, &tmpRegion); + break; + case DamageReportBoundingBox: + tmpBox = *REGION_EXTENTS (pScreen, pOldDamage); + if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &newDamage))) { + (*pDamage->damageReportPostRendering) (pDamage, &newDamage, + pDamage->closure); + } + break; + case DamageReportNonEmpty: + was_empty = !REGION_NOTEMPTY(pScreen, pOldDamage); + if (was_empty && REGION_NOTEMPTY(pScreen, &newDamage)) { + (*pDamage->damageReportPostRendering) (pDamage, &newDamage, + pDamage->closure); + } + break; + case DamageReportNone: + break; + } + + REGION_UNINIT(pScreen, &newDamage); +} + #if DAMAGE_DEBUG_ENABLE static void _damageRegionPending (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where) @@ -306,15 +348,22 @@ damageRegionPending (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, if (draw_x || draw_y) REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y); - /* If the damage rec has been flagged to report damage after the op has - * completed, then union it into the delayed damage region, which will - * be used for reporting after calling down, and skip the reporting - */ - if (!pDamage->reportAfter) { - damageReportDamage (pDamage, pDamageRegion); - } else { + /* Store damage region if needed after submission. */ + if (pDamage->reportAfter || pDamage->damageMarker) REGION_UNION(pScreen, &pDamage->pendingDamage, &pDamage->pendingDamage, pDamageRegion); + + /* Duplicate current damage if needed. */ + if (pDamage->damageMarker) + REGION_COPY(pScreen, &pDamage->backupDamage, &pDamage->damage); + + /* Report damage now, if desired. */ + if (!pDamage->reportAfter) { + if (pDamage->damageReport) + damageReportDamage (pDamage, pDamageRegion); + else + REGION_UNION(pScreen, &pDamage->damage, + &pDamage->damage, pDamageRegion); } /* @@ -338,10 +387,22 @@ damageRegionSubmitted (DrawablePtr pDrawable) for (; pDamage != NULL; pDamage = pDamage->pNext) { + /* submit damage marker whenever possible. */ + if (pDamage->damageMarker) + (*pDamage->damageMarker) (pDrawable, pDamage, &pDamage->backupDamage, &pDamage->pendingDamage, pDamage->closure); if (pDamage->reportAfter) { - damageReportDamage (pDamage, &pDamage->pendingDamage); - REGION_EMPTY (pScreen, &pDamage->pendingDamage); + /* It's possible that there is only interest in postRendering reporting. */ + if (pDamage->damageReport) + damageReportDamage (pDamage, &pDamage->pendingDamage); + else + REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, + &pDamage->pendingDamage); } + + if (pDamage->reportAfter || pDamage->damageMarker) + REGION_EMPTY (pScreen, &pDamage->pendingDamage); + if (pDamage->damageMarker) + REGION_EMPTY (pScreen, &pDamage->backupDamage); } } @@ -1810,7 +1871,9 @@ DamageCreate (DamageReportFunc damageReport, pDamage->reportAfter = FALSE; pDamage->damageReport = damageReport; + pDamage->damageReportPostRendering = NULL; pDamage->damageDestroy = damageDestroy; + pDamage->damageMarker = NULL; return pDamage; } @@ -1934,7 +1997,7 @@ DamageEmpty (DamagePtr pDamage) REGION_EMPTY (pDamage->pDrawable->pScreen, &pDamage->damage); } -RegionPtr +_X_EXPORT RegionPtr DamageRegion (DamagePtr pDamage) { return &pDamage->damage; @@ -1958,6 +2021,16 @@ DamageRegionSubmitted (DrawablePtr pDrawable) damageRegionSubmitted (pDrawable); } +/* If a damage marker is provided, then this function must be called after rendering is done. */ +/* Please do call back so any future enhancements can assume this function is called. */ +/* There are no strict timing requirements for calling this function, just as soon as (is cheaply) possible. */ +_X_EXPORT void +DamageRegionRendered (DrawablePtr pDrawable, DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pRegion) +{ + if (pDamage->damageReportPostRendering) + damageReportDamagePostRendering (pDamage, pOldDamage, pRegion); +} + /* This call is very odd, i'm leaving it intact for API sake, but please don't use it. */ _X_EXPORT void DamageDamageRegion (DrawablePtr pDrawable, @@ -1972,8 +2045,16 @@ DamageDamageRegion (DrawablePtr pDrawable, damageRegionSubmitted (pDrawable); } -void +_X_EXPORT void DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter) { pDamage->reportAfter = reportAfter; } + +_X_EXPORT void +DamageSetPostRenderingFunctions(DamagePtr pDamage, DamageReportFunc damageReportPostRendering, + DamageMarkerFunc damageMarker) +{ + pDamage->damageReportPostRendering = damageReportPostRendering; + pDamage->damageMarker = damageMarker; +} diff --git a/miext/damage/damage.h b/miext/damage/damage.h index ad9ab4c0d..c20a250b3 100755 --- a/miext/damage/damage.h +++ b/miext/damage/damage.h @@ -39,6 +39,9 @@ typedef enum _damageReportLevel { typedef void (*DamageReportFunc) (DamagePtr pDamage, RegionPtr pRegion, void *closure); typedef void (*DamageDestroyFunc) (DamagePtr pDamage, void *closure); +/* It's the responsibility of the driver to duplicate both regions. */ +/* At some point DamageRegionRendered() must be called. */ +typedef void (*DamageMarkerFunc) (DrawablePtr pDrawable, DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pRegion, void *closure); Bool DamageSetup (ScreenPtr pScreen); @@ -86,6 +89,10 @@ DamageRegionPending (DrawablePtr pDrawable, RegionPtr pRegion); void DamageRegionSubmitted (DrawablePtr pDrawable); +/* Call this some time after rendering is done, only relevant when a damageMarker is provided. */ +void +DamageRegionRendered (DrawablePtr pDrawable, DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pRegion); + /* Avoid using this call, it only exists for API compatibility. */ void DamageDamageRegion (DrawablePtr pDrawable, @@ -94,4 +101,8 @@ DamageDamageRegion (DrawablePtr pDrawable, void DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter); +void +DamageSetPostRenderingFunctions(DamagePtr pDamage, DamageReportFunc damageReportPostRendering, + DamageMarkerFunc damageMarker); + #endif /* _DAMAGE_H_ */ diff --git a/miext/damage/damagestr.h b/miext/damage/damagestr.h index 2f6d53844..f5e0ab9e9 100755 --- a/miext/damage/damagestr.h +++ b/miext/damage/damagestr.h @@ -46,10 +46,13 @@ typedef struct _damage { DrawablePtr pDrawable; DamageReportFunc damageReport; + DamageReportFunc damageReportPostRendering; DamageDestroyFunc damageDestroy; + DamageMarkerFunc damageMarker; Bool reportAfter; - RegionRec pendingDamage; + RegionRec pendingDamage; /* will be flushed post submission at the latest */ + RegionRec backupDamage; /* for use with damageMarker */ } DamageRec; typedef struct _damageScrPriv { |