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