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