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, ¤tCrop);
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