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