• 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 <GLES2/gl2.h>
19 #include <GLES2/gl2ext.h>
20 
21 // TODO: Use public SurfaceTexture APIs once available and include public NDK header file instead.
22 #include <surfacetexture/surface_texture_platform.h>
23 #include "AutoBackendTextureRelease.h"
24 #include "Matrix.h"
25 #include "Properties.h"
26 #include "renderstate/RenderState.h"
27 #include "renderthread/EglManager.h"
28 #include "renderthread/RenderThread.h"
29 #include "renderthread/VulkanManager.h"
30 
31 using namespace android::uirenderer::renderthread;
32 
33 namespace android {
34 namespace uirenderer {
35 
DeferredLayerUpdater(RenderState & renderState)36 DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState)
37         : mRenderState(renderState)
38         , mBlend(false)
39         , mSurfaceTexture(nullptr, [](ASurfaceTexture*) {})
40         , mTransform(nullptr)
41         , mGLContextAttached(false)
42         , mUpdateTexImage(false)
43         , mLayer(nullptr) {
44     renderState.registerContextCallback(this);
45 }
46 
~DeferredLayerUpdater()47 DeferredLayerUpdater::~DeferredLayerUpdater() {
48     setTransform(nullptr);
49     mRenderState.removeContextCallback(this);
50     destroyLayer();
51 }
52 
setSurfaceTexture(AutoTextureRelease && consumer)53 void DeferredLayerUpdater::setSurfaceTexture(AutoTextureRelease&& consumer) {
54     mSurfaceTexture = std::move(consumer);
55 
56     GLenum target = ASurfaceTexture_getCurrentTextureTarget(mSurfaceTexture.get());
57     LOG_ALWAYS_FATAL_IF(target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES,
58                         "set unsupported SurfaceTexture with target %x", target);
59 }
60 
onContextDestroyed()61 void DeferredLayerUpdater::onContextDestroyed() {
62     destroyLayer();
63 }
64 
destroyLayer()65 void DeferredLayerUpdater::destroyLayer() {
66     if (!mLayer) {
67         return;
68     }
69 
70     if (mSurfaceTexture.get() && mGLContextAttached) {
71         ASurfaceTexture_releaseConsumerOwnership(mSurfaceTexture.get());
72         mGLContextAttached = false;
73     }
74 
75     mLayer->postDecStrong();
76 
77     mLayer = nullptr;
78 
79     for (auto& [index, slot] : mImageSlots) {
80         slot.clear(mRenderState.getRenderThread().getGrContext());
81     }
82     mImageSlots.clear();
83 }
84 
setPaint(const SkPaint * paint)85 void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
86     mAlpha = PaintUtils::getAlphaDirect(paint);
87     mMode = PaintUtils::getBlendModeDirect(paint);
88     if (paint) {
89         mColorFilter = paint->refColorFilter();
90     } else {
91         mColorFilter.reset();
92     }
93 }
94 
createReleaseFence(bool useFenceSync,EGLSyncKHR * eglFence,EGLDisplay * display,int * releaseFence,void * handle)95 status_t DeferredLayerUpdater::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence,
96                                                   EGLDisplay* display, int* releaseFence,
97                                                   void* handle) {
98     *display = EGL_NO_DISPLAY;
99     DeferredLayerUpdater* dlu = (DeferredLayerUpdater*)handle;
100     RenderState& renderState = dlu->mRenderState;
101     status_t err;
102     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
103         EglManager& eglManager = renderState.getRenderThread().eglManager();
104         *display = eglManager.eglDisplay();
105         err = eglManager.createReleaseFence(useFenceSync, eglFence, releaseFence);
106     } else {
107         int previousSlot = dlu->mCurrentSlot;
108         if (previousSlot != -1) {
109             dlu->mImageSlots[previousSlot].releaseQueueOwnership(
110                     renderState.getRenderThread().getGrContext());
111         }
112         err = renderState.getRenderThread().vulkanManager().createReleaseFence(
113                 releaseFence, renderState.getRenderThread().getGrContext());
114     }
115     return err;
116 }
117 
fenceWait(int fence,void * handle)118 status_t DeferredLayerUpdater::fenceWait(int fence, void* handle) {
119     // Wait on the producer fence for the buffer to be ready.
120     status_t err;
121     DeferredLayerUpdater* dlu = (DeferredLayerUpdater*)handle;
122     RenderState& renderState = dlu->mRenderState;
123     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
124         err = renderState.getRenderThread().eglManager().fenceWait(fence);
125     } else {
126         err = renderState.getRenderThread().vulkanManager().fenceWait(
127                 fence, renderState.getRenderThread().getGrContext());
128     }
129     return err;
130 }
131 
apply()132 void DeferredLayerUpdater::apply() {
133     if (!mLayer) {
134         mLayer = new Layer(mRenderState, mColorFilter, mAlpha, mMode);
135     }
136 
137     mLayer->setColorFilter(mColorFilter);
138     mLayer->setAlpha(mAlpha, mMode);
139 
140     if (mSurfaceTexture.get()) {
141         if (!mGLContextAttached) {
142             mGLContextAttached = true;
143             mUpdateTexImage = true;
144             ASurfaceTexture_takeConsumerOwnership(mSurfaceTexture.get());
145         }
146         if (mUpdateTexImage) {
147             mUpdateTexImage = false;
148             float transformMatrix[16];
149             android_dataspace dataspace;
150             int slot;
151             bool newContent = false;
152             // Note: ASurfaceTexture_dequeueBuffer discards all but the last frame. This
153             // is necessary if the SurfaceTexture queue is in synchronous mode, and we
154             // cannot tell which mode it is in.
155             AHardwareBuffer* hardwareBuffer = ASurfaceTexture_dequeueBuffer(
156                     mSurfaceTexture.get(), &slot, &dataspace, transformMatrix, &newContent,
157                     createReleaseFence, fenceWait, this);
158 
159             if (hardwareBuffer) {
160                 mCurrentSlot = slot;
161                 sk_sp<SkImage> layerImage = mImageSlots[slot].createIfNeeded(
162                         hardwareBuffer, dataspace, newContent,
163                         mRenderState.getRenderThread().getGrContext());
164                 // unref to match the ref added by ASurfaceTexture_dequeueBuffer. eglCreateImageKHR
165                 // (invoked by createIfNeeded) will add a ref to the AHardwareBuffer.
166                 AHardwareBuffer_release(hardwareBuffer);
167                 if (layerImage.get()) {
168                     SkMatrix textureTransform;
169                     mat4(transformMatrix).copyTo(textureTransform);
170                     // force filtration if buffer size != layer size
171                     bool forceFilter =
172                             mWidth != layerImage->width() || mHeight != layerImage->height();
173                     updateLayer(forceFilter, textureTransform, layerImage);
174                 }
175             }
176         }
177 
178         if (mTransform) {
179             mLayer->getTransform() = *mTransform;
180             setTransform(nullptr);
181         }
182     }
183 }
184 
updateLayer(bool forceFilter,const SkMatrix & textureTransform,const sk_sp<SkImage> & layerImage)185 void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
186                                        const sk_sp<SkImage>& layerImage) {
187     mLayer->setBlend(mBlend);
188     mLayer->setForceFilter(forceFilter);
189     mLayer->setSize(mWidth, mHeight);
190     mLayer->getTexTransform() = textureTransform;
191     mLayer->setImage(layerImage);
192 }
193 
detachSurfaceTexture()194 void DeferredLayerUpdater::detachSurfaceTexture() {
195     if (mSurfaceTexture.get()) {
196         destroyLayer();
197         mSurfaceTexture = nullptr;
198     }
199 }
200 
createIfNeeded(AHardwareBuffer * buffer,android_dataspace dataspace,bool forceCreate,GrDirectContext * context)201 sk_sp<SkImage> DeferredLayerUpdater::ImageSlot::createIfNeeded(AHardwareBuffer* buffer,
202                                                                android_dataspace dataspace,
203                                                                bool forceCreate,
204                                                                GrDirectContext* context) {
205     if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace ||
206         forceCreate || mBuffer != buffer) {
207         if (buffer != mBuffer) {
208             clear(context);
209         }
210 
211         if (!buffer) {
212             return nullptr;
213         }
214 
215         if (!mTextureRelease) {
216             mTextureRelease = new AutoBackendTextureRelease(context, buffer);
217         } else {
218             mTextureRelease->newBufferContent(context);
219         }
220 
221         mDataspace = dataspace;
222         mBuffer = buffer;
223         mTextureRelease->makeImage(buffer, dataspace, context);
224     }
225     return mTextureRelease ? mTextureRelease->getImage() : nullptr;
226 }
227 
clear(GrDirectContext * context)228 void DeferredLayerUpdater::ImageSlot::clear(GrDirectContext* context) {
229     if (mTextureRelease) {
230         if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
231             this->releaseQueueOwnership(context);
232         }
233         // The following unref counteracts the initial mUsageCount of 1, set by default initializer.
234         mTextureRelease->unref(true);
235         mTextureRelease = nullptr;
236     }
237 
238     mBuffer = nullptr;
239 }
240 
releaseQueueOwnership(GrDirectContext * context)241 void DeferredLayerUpdater::ImageSlot::releaseQueueOwnership(GrDirectContext* context) {
242     LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan);
243     if (mTextureRelease) {
244         mTextureRelease->releaseQueueOwnership(context);
245     }
246 }
247 
248 } /* namespace uirenderer */
249 } /* namespace android */
250