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