mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-04 06:12:04 +00:00
[client/host/idd] correct frame timing attribution
Use calibrated copy-queue timestamps to separate source and effect waits from the actual framebuffer copy. Exclude producer readiness waits from client import timing so the same interval is not counted in both Copy and Import.
This commit is contained in:
@@ -391,11 +391,13 @@ bool egl_desktopSetup(EGL_Desktop * desktop, const LG_RendererFormat format)
|
||||
}
|
||||
|
||||
bool egl_desktopUpdate(EGL_Desktop * desktop, const FrameBuffer * frame, int dmaFd,
|
||||
const FrameDamageRect * damageRects, int damageRectsCount)
|
||||
const FrameDamageRect * damageRects, int damageRectsCount,
|
||||
uint64_t * waitTimeNs)
|
||||
{
|
||||
if (likely(desktop->useDMA && dmaFd >= 0))
|
||||
{
|
||||
if (likely(egl_textureUpdateFromDMA(desktop->texture, frame, dmaFd)))
|
||||
if (likely(egl_textureUpdateFromDMA(
|
||||
desktop->texture, frame, dmaFd, waitTimeNs)))
|
||||
{
|
||||
atomic_store(&desktop->processFrame, true);
|
||||
return true;
|
||||
@@ -437,7 +439,7 @@ bool egl_desktopUpdate(EGL_Desktop * desktop, const FrameBuffer * frame, int dma
|
||||
* previous texture contents instead.
|
||||
*/
|
||||
if (likely(egl_textureUpdateFromFrame(desktop->texture, frame,
|
||||
damageRects, damageRectsCount)))
|
||||
damageRects, damageRectsCount, waitTimeNs)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
@@ -49,7 +49,8 @@ void egl_desktopGetHDRMapping(EGL_Desktop * desktop, bool * enabled,
|
||||
float * gain, float * contentPeak);
|
||||
bool egl_desktopSetup (EGL_Desktop * desktop, const LG_RendererFormat format);
|
||||
bool egl_desktopUpdate(EGL_Desktop * desktop, const FrameBuffer * frame, int dmaFd,
|
||||
const FrameDamageRect * damageRects, int damageRectsCount);
|
||||
const FrameDamageRect * damageRects, int damageRectsCount,
|
||||
uint64_t * waitTimeNs);
|
||||
void egl_desktopResize(EGL_Desktop * desktop, int width, int height);
|
||||
bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
unsigned int outputHeight, const float x, const float y,
|
||||
|
||||
@@ -748,14 +748,21 @@ static bool egl_onFrame(LG_Renderer * renderer, const FrameBuffer * frame, int d
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
egl_stateCheckShared();
|
||||
|
||||
const uint64_t start = nanotime();
|
||||
const uint64_t start = nanotime();
|
||||
uint64_t waitTimeNs = 0;
|
||||
if (unlikely(!egl_desktopUpdate(
|
||||
this->desktop, frame, dmaFd, damageRects, damageRectsCount)))
|
||||
this->desktop, frame, dmaFd, damageRects, damageRectsCount,
|
||||
&waitTimeNs)))
|
||||
{
|
||||
DEBUG_INFO("Failed to to update the desktop");
|
||||
return false;
|
||||
}
|
||||
app_setFrameImportTime(nanotime() - start);
|
||||
const uint64_t elapsed = nanotime() - start;
|
||||
|
||||
/* Producer Copy already covers the interval before FrameBuffer::wp becomes
|
||||
* ready. Exclude that overlapping wait from the client Import stage. */
|
||||
app_setFrameImportTime(
|
||||
elapsed > waitTimeNs ? elapsed - waitTimeNs : 0);
|
||||
|
||||
INTERLOCKED_SECTION(this->desktopDamageLock, {
|
||||
struct DesktopDamage * damage = this->desktopDamage + this->desktopDamageIdx;
|
||||
|
||||
@@ -161,27 +161,28 @@ bool egl_textureUpdateRect(EGL_Texture * this,
|
||||
|
||||
bool egl_textureUpdateFromFrame(EGL_Texture * this,
|
||||
const FrameBuffer * frame, const FrameDamageRect * damageRects,
|
||||
int damageRectsCount)
|
||||
int damageRectsCount, uint64_t * waitTimeNs)
|
||||
{
|
||||
const struct EGL_TexUpdate update =
|
||||
{
|
||||
.type = EGL_TEXTYPE_FRAMEBUFFER,
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = this->format.width,
|
||||
.height = this->format.height,
|
||||
.pitch = this->format.pitch,
|
||||
.stride = this->format.stride,
|
||||
.frame = frame,
|
||||
.rects = damageRects,
|
||||
.rectCount = damageRectsCount,
|
||||
.type = EGL_TEXTYPE_FRAMEBUFFER,
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = this->format.width,
|
||||
.height = this->format.height,
|
||||
.pitch = this->format.pitch,
|
||||
.stride = this->format.stride,
|
||||
.frame = frame,
|
||||
.rects = damageRects,
|
||||
.rectCount = damageRectsCount,
|
||||
.waitTimeNs = waitTimeNs,
|
||||
};
|
||||
|
||||
return this->ops.update(this, &update);
|
||||
}
|
||||
|
||||
bool egl_textureUpdateFromDMA(EGL_Texture * this,
|
||||
const FrameBuffer * frame, const int dmaFd)
|
||||
const FrameBuffer * frame, const int dmaFd, uint64_t * waitTimeNs)
|
||||
{
|
||||
const struct EGL_TexUpdate update =
|
||||
{
|
||||
@@ -196,7 +197,8 @@ bool egl_textureUpdateFromDMA(EGL_Texture * this,
|
||||
};
|
||||
|
||||
/* wait for completion */
|
||||
if (unlikely(!framebuffer_wait(frame, this->format.dataSize)))
|
||||
if (unlikely(!framebuffer_wait_timed(
|
||||
frame, this->format.dataSize, waitTimeNs)))
|
||||
return false;
|
||||
|
||||
return this->ops.update(this, &update);
|
||||
|
||||
@@ -41,6 +41,7 @@ typedef struct EGL_TexUpdate
|
||||
{
|
||||
/* the type of this update */
|
||||
EGL_TexType type;
|
||||
uint64_t * waitTimeNs;
|
||||
|
||||
int x, y, width, height;
|
||||
|
||||
@@ -125,10 +126,10 @@ bool egl_textureUpdateRect(EGL_Texture * texture,
|
||||
|
||||
bool egl_textureUpdateFromFrame(EGL_Texture * texture,
|
||||
const FrameBuffer * frame, const FrameDamageRect * damageRects,
|
||||
int damageRectsCount);
|
||||
int damageRectsCount, uint64_t * waitTimeNs);
|
||||
|
||||
bool egl_textureUpdateFromDMA(EGL_Texture * texture,
|
||||
const FrameBuffer * frame, const int dmaFd);
|
||||
const FrameBuffer * frame, const int dmaFd, uint64_t * waitTimeNs);
|
||||
|
||||
enum EGL_TexStatus egl_textureProcess(EGL_Texture * texture);
|
||||
|
||||
|
||||
@@ -94,14 +94,15 @@ static bool egl_texFBUpdate(EGL_Texture * texture, const EGL_TexUpdate * update)
|
||||
|
||||
if (damageAll)
|
||||
{
|
||||
complete = framebuffer_read(
|
||||
complete = framebuffer_read_timed(
|
||||
update->frame,
|
||||
parent->buf[parent->bufIndex].map,
|
||||
texture->format.pitch,
|
||||
texture->format.height,
|
||||
texture->format.width,
|
||||
texture->format.bpp,
|
||||
texture->format.pitch
|
||||
texture->format.pitch,
|
||||
update->waitTimeNs
|
||||
);
|
||||
}
|
||||
else
|
||||
@@ -123,7 +124,7 @@ static bool egl_texFBUpdate(EGL_Texture * texture, const EGL_TexUpdate * update)
|
||||
scaledDamageRects[i] = rect;
|
||||
}
|
||||
|
||||
complete = rectsFramebufferToBuffer(
|
||||
complete = rectsFramebufferToBufferTimed(
|
||||
scaledDamageRects,
|
||||
damage->count,
|
||||
texture->format.bpp,
|
||||
@@ -131,12 +132,13 @@ static bool egl_texFBUpdate(EGL_Texture * texture, const EGL_TexUpdate * update)
|
||||
texture->format.pitch,
|
||||
texture->format.height,
|
||||
update->frame,
|
||||
texture->format.pitch
|
||||
texture->format.pitch,
|
||||
update->waitTimeNs
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
complete = rectsFramebufferToBuffer(
|
||||
complete = rectsFramebufferToBufferTimed(
|
||||
damage->rects,
|
||||
damage->count,
|
||||
texture->format.bpp,
|
||||
@@ -144,7 +146,8 @@ static bool egl_texFBUpdate(EGL_Texture * texture, const EGL_TexUpdate * update)
|
||||
texture->format.pitch,
|
||||
texture->format.height,
|
||||
update->frame,
|
||||
texture->format.pitch
|
||||
texture->format.pitch,
|
||||
update->waitTimeNs
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user