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