DeferredLayerUpdater.cpp revision 8cd3edfa15cc9cdbffa935d19ab894426b08d174
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 "GlLayer.h" 19#include "renderthread/EglManager.h" 20#include "renderthread/RenderTask.h" 21#include "utils/PaintUtils.h" 22 23namespace android { 24namespace uirenderer { 25 26DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer) 27 : mSurfaceTexture(nullptr) 28 , mTransform(nullptr) 29 , mNeedsGLContextAttach(false) 30 , mUpdateTexImage(false) 31 , mLayer(layer) { 32 mWidth = mLayer->getWidth(); 33 mHeight = mLayer->getHeight(); 34 mBlend = mLayer->isBlend(); 35 mColorFilter = SkSafeRef(mLayer->getColorFilter()); 36 mAlpha = mLayer->getAlpha(); 37 mMode = mLayer->getMode(); 38} 39 40DeferredLayerUpdater::~DeferredLayerUpdater() { 41 SkSafeUnref(mColorFilter); 42 setTransform(nullptr); 43 mLayer->postDecStrong(); 44 mLayer = nullptr; 45} 46 47void DeferredLayerUpdater::setPaint(const SkPaint* paint) { 48 mAlpha = PaintUtils::getAlphaDirect(paint); 49 mMode = PaintUtils::getBlendModeDirect(paint); 50 SkColorFilter* colorFilter = (paint) ? paint->getColorFilter() : nullptr; 51 SkRefCnt_SafeAssign(mColorFilter, colorFilter); 52} 53 54void DeferredLayerUpdater::apply() { 55 mLayer->setColorFilter(mColorFilter); 56 mLayer->setAlpha(mAlpha, mMode); 57 58 if (mSurfaceTexture.get()) { 59 LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL, 60 "apply surfaceTexture with non GL backend %x, GL %x, VK %x", 61 mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan); 62 if (mNeedsGLContextAttach) { 63 mNeedsGLContextAttach = false; 64 mSurfaceTexture->attachToContext(static_cast<GlLayer*>(mLayer)->getTextureId()); 65 } 66 if (mUpdateTexImage) { 67 mUpdateTexImage = false; 68 doUpdateTexImage(); 69 } 70 if (mTransform) { 71 mLayer->getTransform().load(*mTransform); 72 setTransform(nullptr); 73 } 74 } 75} 76 77void DeferredLayerUpdater::doUpdateTexImage() { 78 LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL, 79 "doUpdateTexImage non GL backend %x, GL %x, VK %x", 80 mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan); 81 if (mSurfaceTexture->updateTexImage() == NO_ERROR) { 82 float transform[16]; 83 84 int64_t frameNumber = mSurfaceTexture->getFrameNumber(); 85 // If the GLConsumer queue is in synchronous mode, need to discard all 86 // but latest frame, using the frame number to tell when we no longer 87 // have newer frames to target. Since we can't tell which mode it is in, 88 // do this unconditionally. 89 int dropCounter = 0; 90 while (mSurfaceTexture->updateTexImage() == NO_ERROR) { 91 int64_t newFrameNumber = mSurfaceTexture->getFrameNumber(); 92 if (newFrameNumber == frameNumber) break; 93 frameNumber = newFrameNumber; 94 dropCounter++; 95 } 96 97 bool forceFilter = false; 98 sp<GraphicBuffer> buffer = mSurfaceTexture->getCurrentBuffer(); 99 if (buffer != nullptr) { 100 // force filtration if buffer size != layer size 101 forceFilter = mWidth != static_cast<int>(buffer->getWidth()) 102 || mHeight != static_cast<int>(buffer->getHeight()); 103 } 104 105 #if DEBUG_RENDERER 106 if (dropCounter > 0) { 107 RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter); 108 } 109 #endif 110 mSurfaceTexture->getTransformMatrix(transform); 111 GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget(); 112 113 LOG_ALWAYS_FATAL_IF(renderTarget != GL_TEXTURE_2D && renderTarget != GL_TEXTURE_EXTERNAL_OES, 114 "doUpdateTexImage target %x, 2d %x, EXT %x", 115 renderTarget, GL_TEXTURE_2D, GL_TEXTURE_EXTERNAL_OES); 116 updateLayer(forceFilter, renderTarget, transform); 117 } 118} 119 120void DeferredLayerUpdater::updateLayer(bool forceFilter, GLenum renderTarget, 121 const float* textureTransform) { 122 LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL, 123 "updateLayer non GL backend %x, GL %x, VK %x", 124 mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan); 125 126 mLayer->setBlend(mBlend); 127 mLayer->setForceFilter(forceFilter); 128 mLayer->setSize(mWidth, mHeight); 129 mLayer->getTexTransform().load(textureTransform); 130 131 GlLayer* glLayer = static_cast<GlLayer*>(mLayer); 132 if (renderTarget != glLayer->getRenderTarget()) { 133 glLayer->setRenderTarget(renderTarget); 134 glLayer->bindTexture(); 135 glLayer->setFilter(GL_NEAREST, false, true); 136 glLayer->setWrap(GL_CLAMP_TO_EDGE, false, true); 137 } 138} 139 140void DeferredLayerUpdater::detachSurfaceTexture() { 141 if (mSurfaceTexture.get()) { 142 LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL, 143 "detachSurfaceTexture with non GL backend %x, GL %x, VK %x", 144 mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan); 145 status_t err = mSurfaceTexture->detachFromContext(); 146 if (err != 0) { 147 // TODO: Elevate to fatal exception 148 ALOGE("Failed to detach SurfaceTexture from context %d", err); 149 } 150 mSurfaceTexture = nullptr; 151 static_cast<GlLayer*>(mLayer)->clearTexture(); 152 } 153} 154 155} /* namespace uirenderer */ 156} /* namespace android */ 157