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