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     mImageSlots.clear();
80 }
81 
setPaint(const SkPaint * paint)82 void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
83     mAlpha = PaintUtils::getAlphaDirect(paint);
84     mMode = PaintUtils::getBlendModeDirect(paint);
85     if (paint) {
86         mColorFilter = paint->refColorFilter();
87     } else {
88         mColorFilter.reset();
89     }
90 }
91 
createReleaseFence(bool useFenceSync,EGLSyncKHR * eglFence,EGLDisplay * display,int * releaseFence,void * handle)92 static status_t createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence, EGLDisplay* display,
93                                    int* releaseFence, void* handle) {
94     *display = EGL_NO_DISPLAY;
95     RenderState* renderState = (RenderState*)handle;
96     status_t err;
97     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
98         EglManager& eglManager = renderState->getRenderThread().eglManager();
99         *display = eglManager.eglDisplay();
100         err = eglManager.createReleaseFence(useFenceSync, eglFence, releaseFence);
101     } else {
102         err = renderState->getRenderThread().vulkanManager().createReleaseFence(
103                 releaseFence, renderState->getRenderThread().getGrContext());
104     }
105     return err;
106 }
107 
fenceWait(int fence,void * handle)108 static status_t fenceWait(int fence, void* handle) {
109     // Wait on the producer fence for the buffer to be ready.
110     status_t err;
111     RenderState* renderState = (RenderState*)handle;
112     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
113         err = renderState->getRenderThread().eglManager().fenceWait(fence);
114     } else {
115         err = renderState->getRenderThread().vulkanManager().fenceWait(
116                 fence, renderState->getRenderThread().getGrContext());
117     }
118     return err;
119 }
120 
apply()121 void DeferredLayerUpdater::apply() {
122     if (!mLayer) {
123         mLayer = new Layer(mRenderState, mColorFilter, mAlpha, mMode);
124     }
125 
126     mLayer->setColorFilter(mColorFilter);
127     mLayer->setAlpha(mAlpha, mMode);
128 
129     if (mSurfaceTexture.get()) {
130         if (!mGLContextAttached) {
131             mGLContextAttached = true;
132             mUpdateTexImage = true;
133             ASurfaceTexture_takeConsumerOwnership(mSurfaceTexture.get());
134         }
135         if (mUpdateTexImage) {
136             mUpdateTexImage = false;
137             float transformMatrix[16];
138             android_dataspace dataspace;
139             int slot;
140             bool newContent = false;
141             // Note: ASurfaceTexture_dequeueBuffer discards all but the last frame. This
142             // is necessary if the SurfaceTexture queue is in synchronous mode, and we
143             // cannot tell which mode it is in.
144             AHardwareBuffer* hardwareBuffer = ASurfaceTexture_dequeueBuffer(
145                     mSurfaceTexture.get(), &slot, &dataspace, transformMatrix, &newContent,
146                     createReleaseFence, fenceWait, &mRenderState);
147 
148             if (hardwareBuffer) {
149                 sk_sp<SkImage> layerImage = mImageSlots[slot].createIfNeeded(
150                         hardwareBuffer, dataspace, newContent,
151                         mRenderState.getRenderThread().getGrContext());
152                 // unref to match the ref added by ASurfaceTexture_dequeueBuffer. eglCreateImageKHR
153                 // (invoked by createIfNeeded) will add a ref to the AHardwareBuffer.
154                 AHardwareBuffer_release(hardwareBuffer);
155                 if (layerImage.get()) {
156                     SkMatrix textureTransform;
157                     mat4(transformMatrix).copyTo(textureTransform);
158                     // force filtration if buffer size != layer size
159                     bool forceFilter =
160                             mWidth != layerImage->width() || mHeight != layerImage->height();
161                     updateLayer(forceFilter, textureTransform, layerImage);
162                 }
163             }
164         }
165 
166         if (mTransform) {
167             mLayer->getTransform() = *mTransform;
168             setTransform(nullptr);
169         }
170     }
171 }
172 
updateLayer(bool forceFilter,const SkMatrix & textureTransform,const sk_sp<SkImage> & layerImage)173 void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
174                                        const sk_sp<SkImage>& layerImage) {
175     mLayer->setBlend(mBlend);
176     mLayer->setForceFilter(forceFilter);
177     mLayer->setSize(mWidth, mHeight);
178     mLayer->getTexTransform() = textureTransform;
179     mLayer->setImage(layerImage);
180 }
181 
detachSurfaceTexture()182 void DeferredLayerUpdater::detachSurfaceTexture() {
183     if (mSurfaceTexture.get()) {
184         destroyLayer();
185         mSurfaceTexture = nullptr;
186     }
187 }
188 
createIfNeeded(AHardwareBuffer * buffer,android_dataspace dataspace,bool forceCreate,GrContext * context)189 sk_sp<SkImage> DeferredLayerUpdater::ImageSlot::createIfNeeded(AHardwareBuffer* buffer,
190                                                                android_dataspace dataspace,
191                                                                bool forceCreate,
192                                                                GrContext* context) {
193     if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace ||
194         forceCreate || mBuffer != buffer) {
195         if (buffer != mBuffer) {
196             clear();
197         }
198 
199         if (!buffer) {
200             return nullptr;
201         }
202 
203         if (!mTextureRelease) {
204             mTextureRelease = new AutoBackendTextureRelease(context, buffer);
205         } else {
206             mTextureRelease->newBufferContent(context);
207         }
208 
209         mDataspace = dataspace;
210         mBuffer = buffer;
211         mTextureRelease->makeImage(buffer, dataspace, context);
212     }
213     return mTextureRelease ? mTextureRelease->getImage() : nullptr;
214 }
215 
clear()216 void DeferredLayerUpdater::ImageSlot::clear() {
217     if (mTextureRelease) {
218         // The following unref counteracts the initial mUsageCount of 1, set by default initializer.
219         mTextureRelease->unref(true);
220         mTextureRelease = nullptr;
221     }
222 
223     mBuffer = nullptr;
224 }
225 
226 } /* namespace uirenderer */
227 } /* namespace android */
228