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