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