summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaarten Maathuis <madman2003@gmail.com>2008-08-30 00:37:11 +0200
committerMaarten Maathuis <madman2003@gmail.com>2008-08-30 00:37:11 +0200
commit974db58f5b730c3770ee461665a02dd4334d1dea (patch)
treee4a6598a25e173474745dce4bccc73b7cd4822ef
parent454cb0802eec3c2c2cdbcc17971bced868462b83 (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-xmiext/damage/damage.c103
-rwxr-xr-xmiext/damage/damage.h11
-rwxr-xr-xmiext/damage/damagestr.h5
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 {