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:
Jesse Hall 2012-06-29 15:21:18 -07:00
parent b42b1ac158
commit dc5b485f74
6 changed files with 49 additions and 8 deletions

View File

@ -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.

View File

@ -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();

View File

@ -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;

View File

@ -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;
};
/*

View File

@ -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.

View File

@ -120,6 +120,7 @@ private:
bool mCurrentOpacity;
bool mRefreshPending;
bool mFrameLatencyNeeded;
bool mNeedHwcFence;
int mFrameLatencyOffset;
struct Statistics {