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.
This commit is contained in:
parent
454cb0802e
commit
974db58f5b
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue