• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
25 namespace android {
26 namespace uirenderer {
27 
DeferredLayerUpdater(RenderState & renderState,CreateLayerFn createLayerFn,Layer::Api layerApi)28 DeferredLayerUpdater::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 
~DeferredLayerUpdater()42 DeferredLayerUpdater::~DeferredLayerUpdater() {
43     SkSafeUnref(mColorFilter);
44     setTransform(nullptr);
45     mRenderState.unregisterDeferredLayerUpdater(this);
46     destroyLayer();
47 }
48 
destroyLayer()49 void 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 
setPaint(const SkPaint * paint)67 void 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 
apply()74 void 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 
doUpdateTexImage()111 void 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 
doUpdateVkTexImage()150 void 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 
updateLayer(bool forceFilter,const float * textureTransform)162 void 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 
detachSurfaceTexture()169 void DeferredLayerUpdater::detachSurfaceTexture() {
170     if (mSurfaceTexture.get()) {
171         destroyLayer();
172         mSurfaceTexture = nullptr;
173     }
174 }
175 
176 } /* namespace uirenderer */
177 } /* namespace android */
178