DeferredLayerUpdater.cpp revision 749906b468912dab7bf69a86e852deac3e80b0cc
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16#include "DeferredLayerUpdater.h" 17 18#include "OpenGLRenderer.h" 19 20#include "LayerRenderer.h" 21#include "renderthread/EglManager.h" 22#include "renderthread/RenderTask.h" 23 24namespace android { 25namespace uirenderer { 26 27class DeleteLayerTask : public renderthread::RenderTask { 28public: 29 DeleteLayerTask(renderthread::EglManager& eglManager, Layer* layer) 30 : mEglManager(eglManager) 31 , mLayer(layer) 32 {} 33 34 virtual void run() { 35 mEglManager.requireGlContext(); 36 LayerRenderer::destroyLayer(mLayer); 37 mLayer = 0; 38 delete this; 39 } 40 41private: 42 renderthread::EglManager& mEglManager; 43 Layer* mLayer; 44}; 45 46DeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, Layer* layer) 47 : mSurfaceTexture(0) 48 , mTransform(0) 49 , mNeedsGLContextAttach(false) 50 , mUpdateTexImage(false) 51 , mLayer(layer) 52 , mCaches(Caches::getInstance()) 53 , mRenderThread(thread) { 54 mWidth = mLayer->layer.getWidth(); 55 mHeight = mLayer->layer.getHeight(); 56 mBlend = mLayer->isBlend(); 57 mColorFilter = SkSafeRef(mLayer->getColorFilter()); 58 mAlpha = mLayer->getAlpha(); 59 mMode = mLayer->getMode(); 60} 61 62DeferredLayerUpdater::~DeferredLayerUpdater() { 63 SkSafeUnref(mColorFilter); 64 setTransform(0); 65 mRenderThread.queue(new DeleteLayerTask(mRenderThread.eglManager(), mLayer)); 66 mLayer = 0; 67} 68 69void DeferredLayerUpdater::setPaint(const SkPaint* paint) { 70 OpenGLRenderer::getAlphaAndModeDirect(paint, &mAlpha, &mMode); 71 SkColorFilter* colorFilter = (paint) ? paint->getColorFilter() : NULL; 72 SkRefCnt_SafeAssign(mColorFilter, colorFilter); 73} 74 75bool DeferredLayerUpdater::apply() { 76 bool success = true; 77 // These properties are applied the same to both layer types 78 mLayer->setColorFilter(mColorFilter); 79 mLayer->setAlpha(mAlpha, mMode); 80 81 if (mSurfaceTexture.get()) { 82 if (mNeedsGLContextAttach) { 83 mNeedsGLContextAttach = false; 84 mSurfaceTexture->attachToContext(mLayer->getTexture()); 85 } 86 if (mUpdateTexImage) { 87 mUpdateTexImage = false; 88 doUpdateTexImage(); 89 } 90 if (mTransform) { 91 mLayer->getTransform().load(*mTransform); 92 setTransform(0); 93 } 94 } 95 return success; 96} 97 98void DeferredLayerUpdater::doUpdateTexImage() { 99 if (mSurfaceTexture->updateTexImage() == NO_ERROR) { 100 float transform[16]; 101 102 int64_t frameNumber = mSurfaceTexture->getFrameNumber(); 103 // If the GLConsumer queue is in synchronous mode, need to discard all 104 // but latest frame, using the frame number to tell when we no longer 105 // have newer frames to target. Since we can't tell which mode it is in, 106 // do this unconditionally. 107 int dropCounter = 0; 108 while (mSurfaceTexture->updateTexImage() == NO_ERROR) { 109 int64_t newFrameNumber = mSurfaceTexture->getFrameNumber(); 110 if (newFrameNumber == frameNumber) break; 111 frameNumber = newFrameNumber; 112 dropCounter++; 113 } 114 115 bool forceFilter = false; 116 sp<GraphicBuffer> buffer = mSurfaceTexture->getCurrentBuffer(); 117 if (buffer != NULL) { 118 // force filtration if buffer size != layer size 119 forceFilter = mWidth != buffer->getWidth() 120 || mHeight != buffer->getHeight(); 121 } 122 123 #if DEBUG_RENDERER 124 if (dropCounter > 0) { 125 RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter); 126 } 127 #endif 128 mSurfaceTexture->getTransformMatrix(transform); 129 GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget(); 130 131 LayerRenderer::updateTextureLayer(mLayer, mWidth, mHeight, 132 !mBlend, forceFilter, renderTarget, transform); 133 } 134} 135 136void DeferredLayerUpdater::detachSurfaceTexture() { 137 if (mSurfaceTexture.get()) { 138 mRenderThread.eglManager().requireGlContext(); 139 status_t err = mSurfaceTexture->detachFromContext(); 140 if (err != 0) { 141 // TODO: Elevate to fatal exception 142 ALOGE("Failed to detach SurfaceTexture from context %d", err); 143 } 144 mSurfaceTexture = 0; 145 mLayer->clearTexture(); 146 } 147} 148 149} /* namespace uirenderer */ 150} /* namespace android */ 151