• 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 
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                 // unref to match the ref added by ASurfaceTexture_dequeueBuffer. eglCreateImageKHR
173                 // (invoked by createIfNeeded) will add a ref to the AHardwareBuffer.
174                 AHardwareBuffer_release(hardwareBuffer);
175                 if (layerImage.get()) {
176                     // force filtration if buffer size != layer size
177                     bool forceFilter =
178                             mWidth != layerImage->width() || mHeight != layerImage->height();
179                     SkRect currentCropRect =
180                             SkRect::MakeLTRB(currentCrop.left, currentCrop.top, currentCrop.right,
181                                              currentCrop.bottom);
182 
183                     float maxLuminanceNits = -1.f;
184                     if (hdrMetadataType & HDR10_SMPTE2086) {
185                         maxLuminanceNits = std::max(smpte2086.maxLuminance, maxLuminanceNits);
186                     }
187 
188                     if (hdrMetadataType & HDR10_CTA861_3) {
189                         maxLuminanceNits =
190                                 std::max(cta861_3.maxContentLightLevel, maxLuminanceNits);
191                     }
192                     updateLayer(forceFilter, layerImage, outTransform, currentCropRect,
193                                 maxLuminanceNits);
194                 }
195             }
196         }
197 
198         if (mTransform) {
199             mLayer->getTransform() = *mTransform;
200             setTransform(nullptr);
201         }
202     }
203 }
204 
updateLayer(bool forceFilter,const sk_sp<SkImage> & layerImage,const uint32_t transform,SkRect currentCrop,float maxLuminanceNits)205 void DeferredLayerUpdater::updateLayer(bool forceFilter, const sk_sp<SkImage>& layerImage,
206                                        const uint32_t transform, SkRect currentCrop,
207                                        float maxLuminanceNits) {
208     mLayer->setBlend(mBlend);
209     mLayer->setForceFilter(forceFilter);
210     mLayer->setSize(mWidth, mHeight);
211     mLayer->setCurrentCropRect(currentCrop);
212     mLayer->setWindowTransform(transform);
213     mLayer->setImage(layerImage);
214     mLayer->setMaxLuminanceNits(maxLuminanceNits);
215 }
216 
detachSurfaceTexture()217 void DeferredLayerUpdater::detachSurfaceTexture() {
218     if (mSurfaceTexture.get()) {
219         destroyLayer();
220         mSurfaceTexture = nullptr;
221     }
222 }
223 
createIfNeeded(AHardwareBuffer * buffer,android_dataspace dataspace,bool forceCreate,GrDirectContext * context)224 sk_sp<SkImage> DeferredLayerUpdater::ImageSlot::createIfNeeded(AHardwareBuffer* buffer,
225                                                                android_dataspace dataspace,
226                                                                bool forceCreate,
227                                                                GrDirectContext* context) {
228     if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace ||
229         forceCreate || mBuffer != buffer) {
230         if (buffer != mBuffer) {
231             clear(context);
232         }
233 
234         if (!buffer) {
235             return nullptr;
236         }
237 
238         if (!mTextureRelease) {
239             mTextureRelease = new AutoBackendTextureRelease(context, buffer);
240         } else {
241             mTextureRelease->newBufferContent(context);
242         }
243 
244         mDataspace = dataspace;
245         mBuffer = buffer;
246         mTextureRelease->makeImage(buffer, dataspace, context);
247     }
248     return mTextureRelease ? mTextureRelease->getImage() : nullptr;
249 }
250 
clear(GrDirectContext * context)251 void DeferredLayerUpdater::ImageSlot::clear(GrDirectContext* context) {
252     if (mTextureRelease) {
253         if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
254             this->releaseQueueOwnership(context);
255         }
256         // The following unref counteracts the initial mUsageCount of 1, set by default initializer.
257         mTextureRelease->unref(true);
258         mTextureRelease = nullptr;
259     }
260 
261     mBuffer = nullptr;
262 }
263 
releaseQueueOwnership(GrDirectContext * context)264 void DeferredLayerUpdater::ImageSlot::releaseQueueOwnership(GrDirectContext* context) {
265     LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan);
266     if (mTextureRelease) {
267         mTextureRelease->releaseQueueOwnership(context);
268     }
269 }
270 
271 } /* namespace uirenderer */
272 } /* namespace android */
273