Pass fence to HWC on first use of buffer
Also do a CPU-wait on the fence before using it for GL composition. Change-Id: I0f645a42a44803276cae11b904e5a26d65871562
This commit is contained in:
parent
b42b1ac158
commit
dc5b485f74
@ -172,6 +172,10 @@ public:
|
||||
// getCurrentScalingMode returns the scaling mode of the current buffer.
|
||||
uint32_t getCurrentScalingMode() const;
|
||||
|
||||
// getCurrentFence returns the fence indicating when the current buffer is
|
||||
// ready to be read from.
|
||||
sp<Fence> getCurrentFence() const;
|
||||
|
||||
// isSynchronousMode returns whether the SurfaceTexture is currently in
|
||||
// synchronous mode.
|
||||
bool isSynchronousMode() const;
|
||||
@ -303,6 +307,9 @@ private:
|
||||
// set to each time updateTexImage is called.
|
||||
uint32_t mCurrentScalingMode;
|
||||
|
||||
// mCurrentFence is the fence received from BufferQueue in updateTexImage.
|
||||
sp<Fence> mCurrentFence;
|
||||
|
||||
// mCurrentTransformMatrix is the transform matrix for the current texture.
|
||||
// It gets computed by computeTransformMatrix each time updateTexImage is
|
||||
// called.
|
||||
|
@ -260,14 +260,6 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
|
||||
}
|
||||
}
|
||||
|
||||
// Temporary; fence will be provided to clients soon
|
||||
if (item.mFence.get()) {
|
||||
err = item.mFence->wait(Fence::TIMEOUT_NEVER);
|
||||
if (err != OK) {
|
||||
ST_LOGE("updateTexImage: failure waiting for fence: %d", err);
|
||||
}
|
||||
}
|
||||
|
||||
if (err == NO_ERROR) {
|
||||
GLint error;
|
||||
while ((error = glGetError()) != GL_NO_ERROR) {
|
||||
@ -322,6 +314,7 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
|
||||
mCurrentTransform = item.mTransform;
|
||||
mCurrentScalingMode = item.mScalingMode;
|
||||
mCurrentTimestamp = item.mTimestamp;
|
||||
mCurrentFence = item.mFence;
|
||||
computeCurrentTransformMatrix();
|
||||
} else {
|
||||
if (err < 0) {
|
||||
@ -733,6 +726,11 @@ uint32_t SurfaceTexture::getCurrentScalingMode() const {
|
||||
return mCurrentScalingMode;
|
||||
}
|
||||
|
||||
sp<Fence> SurfaceTexture::getCurrentFence() const {
|
||||
Mutex::Autolock lock(mMutex);
|
||||
return mCurrentFence;
|
||||
}
|
||||
|
||||
bool SurfaceTexture::isSynchronousMode() const {
|
||||
Mutex::Autolock lock(mMutex);
|
||||
return mBufferQueue->isSynchronousMode();
|
||||
|
@ -350,6 +350,12 @@ public:
|
||||
// not supported on VERSION_03
|
||||
return -1;
|
||||
}
|
||||
virtual void setAcquireFenceFd(int fenceFd) {
|
||||
if (fenceFd != -1) {
|
||||
ALOGE("HWC 0.x can't handle acquire fences");
|
||||
close(fenceFd);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void setDefaultState() {
|
||||
getLayer()->compositionType = HWC_FRAMEBUFFER;
|
||||
@ -416,6 +422,9 @@ public:
|
||||
getLayer()->releaseFenceFd = -1;
|
||||
return fd;
|
||||
}
|
||||
virtual void setAcquireFenceFd(int fenceFd) {
|
||||
getLayer()->acquireFenceFd = fenceFd;
|
||||
}
|
||||
|
||||
virtual void setDefaultState() {
|
||||
getLayer()->compositionType = HWC_FRAMEBUFFER;
|
||||
|
@ -109,6 +109,7 @@ public:
|
||||
virtual void setCrop(const Rect& crop) = 0;
|
||||
virtual void setVisibleRegionScreen(const Region& reg) = 0;
|
||||
virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
|
||||
virtual void setAcquireFenceFd(int fenceFd) = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -60,6 +60,7 @@ Layer::Layer(SurfaceFlinger* flinger,
|
||||
mCurrentOpacity(true),
|
||||
mRefreshPending(false),
|
||||
mFrameLatencyNeeded(false),
|
||||
mNeedHwcFence(false),
|
||||
mFrameLatencyOffset(0),
|
||||
mFormat(PIXEL_FORMAT_NONE),
|
||||
mGLExtensions(GLExtensions::getInstance()),
|
||||
@ -299,6 +300,20 @@ void Layer::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
|
||||
// NOTE: buffer can be NULL if the client never drew into this
|
||||
// layer yet, or if we ran out of memory
|
||||
layer.setBuffer(buffer);
|
||||
|
||||
if (mNeedHwcFence) {
|
||||
sp<Fence> fence = mSurfaceTexture->getCurrentFence();
|
||||
if (fence.get()) {
|
||||
int fenceFd = fence->dup();
|
||||
if (fenceFd == -1) {
|
||||
ALOGW("failed to dup layer fence, skipping sync: %d", errno);
|
||||
}
|
||||
layer.setAcquireFenceFd(fenceFd);
|
||||
}
|
||||
mNeedHwcFence = false;
|
||||
} else {
|
||||
layer.setAcquireFenceFd(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
|
||||
@ -333,6 +348,15 @@ void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: replace this with a server-side wait
|
||||
sp<Fence> fence = mSurfaceTexture->getCurrentFence();
|
||||
if (fence.get()) {
|
||||
status_t err = fence->wait(Fence::TIMEOUT_NEVER);
|
||||
ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err);
|
||||
// Go ahead and draw the buffer anyway; no matter what we do the screen
|
||||
// is probably going to have something visibly wrong.
|
||||
}
|
||||
|
||||
if (!isProtected()) {
|
||||
// TODO: we could be more subtle with isFixedSize()
|
||||
const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
|
||||
@ -627,6 +651,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
||||
|
||||
mRefreshPending = true;
|
||||
mFrameLatencyNeeded = true;
|
||||
mNeedHwcFence = true;
|
||||
if (oldActiveBuffer == NULL) {
|
||||
// the first time we receive a buffer, we need to trigger a
|
||||
// geometry invalidation.
|
||||
|
@ -120,6 +120,7 @@ private:
|
||||
bool mCurrentOpacity;
|
||||
bool mRefreshPending;
|
||||
bool mFrameLatencyNeeded;
|
||||
bool mNeedHwcFence;
|
||||
int mFrameLatencyOffset;
|
||||
|
||||
struct Statistics {
|
||||
|
Loading…
Reference in New Issue
Block a user