diff options
author | John Reck <jreck@google.com> | 2014-02-05 16:38:25 -0800 |
---|---|---|
committer | John Reck <jreck@google.com> | 2014-02-10 20:55:39 -0800 |
commit | 04fc583c3dd3144bc6b718fcac4b3e1afdfdb067 (patch) | |
tree | 4682660942c57456293a88bd3e78a28569ae9c71 /libs/hwui/DeferredLayerUpdater.cpp | |
parent | 740dfefcfcba7a254e65bda3ac0d965ca161458b (diff) |
Refactor HardwareLayer
Defer all the things!
Groundwork to allow hardware layers to work in a renderthread world
Change-Id: Ib3aa47525f393083621254a743dbaa6352f933bd
Diffstat (limited to 'libs/hwui/DeferredLayerUpdater.cpp')
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.cpp | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp new file mode 100644 index 000000000000..ed05d0475437 --- /dev/null +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "DeferredLayerUpdater.h" + +#include "OpenGLRenderer.h" + +#include "LayerRenderer.h" + +namespace android { +namespace uirenderer { + +DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, OpenGLRenderer* renderer) + : mDisplayList(0) + , mSurfaceTexture(0) + , mTransform(0) + , mNeedsGLContextAttach(false) + , mUpdateTexImage(false) + , mLayer(layer) + , mRenderer(renderer) + , mCaches(Caches::getInstance()) { + mCaches.resourceCache.incrementRefcount(mLayer); + mWidth = mLayer->layer.getWidth(); + mHeight = mLayer->layer.getHeight(); + mBlend = mLayer->isBlend(); + mColorFilter = mLayer->getColorFilter(); + mAlpha = mLayer->getAlpha(); + mMode = mLayer->getMode(); + mDirtyRect.setEmpty(); +} + +DeferredLayerUpdater::~DeferredLayerUpdater() { + setColorFilter(NULL); + if (mLayer) { + mCaches.resourceCache.decrementRefcount(mLayer); + } + delete mRenderer; +} + +void DeferredLayerUpdater::setColorFilter(SkColorFilter* colorFilter) { + SkRefCnt_SafeAssign(mColorFilter, colorFilter); +} + +void DeferredLayerUpdater::setDisplayList(DisplayList* displayList, + int left, int top, int right, int bottom) { + mDisplayList = displayList; + if (mDirtyRect.isEmpty()) { + mDirtyRect.set(left, top, right, bottom); + } else { + mDirtyRect.unionWith(Rect(left, top, right, bottom)); + } +} + +bool DeferredLayerUpdater::apply() { + bool success = true; + // These properties are applied the same to both layer types + mLayer->setColorFilter(mColorFilter); + mLayer->setAlpha(mAlpha, mMode); + + if (mDisplayList) { + if (mWidth != mLayer->layer.getWidth() || mHeight != mLayer->layer.getHeight()) { + success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight); + } + mLayer->setBlend(mBlend); + mLayer->updateDeferred(mRenderer, mDisplayList, + mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom); + mDirtyRect.setEmpty(); + mDisplayList = 0; + } else if (mSurfaceTexture.get()) { + if (mNeedsGLContextAttach) { + mNeedsGLContextAttach = false; + mSurfaceTexture->attachToContext(mLayer->getTexture()); + } + if (mUpdateTexImage) { + mUpdateTexImage = false; + doUpdateTexImage(); + } + if (mTransform) { + mLayer->getTransform().load(*mTransform); + setTransform(0); + } + } + return success; +} + +void DeferredLayerUpdater::doUpdateTexImage() { + if (mSurfaceTexture->updateTexImage() == NO_ERROR) { + float transform[16]; + + int64_t frameNumber = mSurfaceTexture->getFrameNumber(); + // If the GLConsumer queue is in synchronous mode, need to discard all + // but latest frame, using the frame number to tell when we no longer + // have newer frames to target. Since we can't tell which mode it is in, + // do this unconditionally. + int dropCounter = 0; + while (mSurfaceTexture->updateTexImage() == NO_ERROR) { + int64_t newFrameNumber = mSurfaceTexture->getFrameNumber(); + if (newFrameNumber == frameNumber) break; + frameNumber = newFrameNumber; + dropCounter++; + } + #if DEBUG_RENDERER + if (dropCounter > 0) { + RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter); + } + #endif + mSurfaceTexture->getTransformMatrix(transform); + GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget(); + + LayerRenderer::updateTextureLayer(mLayer, mWidth, mHeight, !mBlend, + renderTarget, transform); + } +} + +void DeferredLayerUpdater::applyDeferred(DeferredLayerUpdater* deferredApply) { + // Default assignment operator doesn't quite work, and fails due to mCaches anyway + deferredApply->mWidth = mWidth; + deferredApply->mHeight = mHeight; + deferredApply->mBlend = mBlend; + deferredApply->mAlpha = mAlpha; + deferredApply->mMode = mMode; + deferredApply->mDirtyRect.set(mDirtyRect); + deferredApply->mDisplayList = mDisplayList; + deferredApply->mSurfaceTexture = mSurfaceTexture; + deferredApply->mNeedsGLContextAttach = mNeedsGLContextAttach; + deferredApply->mUpdateTexImage = mUpdateTexImage; + deferredApply->setColorFilter(mColorFilter); + deferredApply->setTransform(mTransform); + + mDisplayList = 0; + mDirtyRect.setEmpty(); + mTransform = 0; + mNeedsGLContextAttach = false; + mUpdateTexImage = false; +} + +} /* namespace uirenderer */ +} /* namespace android */ |