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 mImageSlots.clear();
80 }
81
setPaint(const SkPaint * paint)82 void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
83 mAlpha = PaintUtils::getAlphaDirect(paint);
84 mMode = PaintUtils::getBlendModeDirect(paint);
85 if (paint) {
86 mColorFilter = paint->refColorFilter();
87 } else {
88 mColorFilter.reset();
89 }
90 }
91
createReleaseFence(bool useFenceSync,EGLSyncKHR * eglFence,EGLDisplay * display,int * releaseFence,void * handle)92 static status_t createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence, EGLDisplay* display,
93 int* releaseFence, void* handle) {
94 *display = EGL_NO_DISPLAY;
95 RenderState* renderState = (RenderState*)handle;
96 status_t err;
97 if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
98 EglManager& eglManager = renderState->getRenderThread().eglManager();
99 *display = eglManager.eglDisplay();
100 err = eglManager.createReleaseFence(useFenceSync, eglFence, releaseFence);
101 } else {
102 err = renderState->getRenderThread().vulkanManager().createReleaseFence(
103 releaseFence, renderState->getRenderThread().getGrContext());
104 }
105 return err;
106 }
107
fenceWait(int fence,void * handle)108 static status_t fenceWait(int fence, void* handle) {
109 // Wait on the producer fence for the buffer to be ready.
110 status_t err;
111 RenderState* renderState = (RenderState*)handle;
112 if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
113 err = renderState->getRenderThread().eglManager().fenceWait(fence);
114 } else {
115 err = renderState->getRenderThread().vulkanManager().fenceWait(
116 fence, renderState->getRenderThread().getGrContext());
117 }
118 return err;
119 }
120
apply()121 void DeferredLayerUpdater::apply() {
122 if (!mLayer) {
123 mLayer = new Layer(mRenderState, mColorFilter, mAlpha, mMode);
124 }
125
126 mLayer->setColorFilter(mColorFilter);
127 mLayer->setAlpha(mAlpha, mMode);
128
129 if (mSurfaceTexture.get()) {
130 if (!mGLContextAttached) {
131 mGLContextAttached = true;
132 mUpdateTexImage = true;
133 ASurfaceTexture_takeConsumerOwnership(mSurfaceTexture.get());
134 }
135 if (mUpdateTexImage) {
136 mUpdateTexImage = false;
137 float transformMatrix[16];
138 android_dataspace dataspace;
139 int slot;
140 bool newContent = false;
141 // Note: ASurfaceTexture_dequeueBuffer discards all but the last frame. This
142 // is necessary if the SurfaceTexture queue is in synchronous mode, and we
143 // cannot tell which mode it is in.
144 AHardwareBuffer* hardwareBuffer = ASurfaceTexture_dequeueBuffer(
145 mSurfaceTexture.get(), &slot, &dataspace, transformMatrix, &newContent,
146 createReleaseFence, fenceWait, &mRenderState);
147
148 if (hardwareBuffer) {
149 sk_sp<SkImage> layerImage = mImageSlots[slot].createIfNeeded(
150 hardwareBuffer, dataspace, newContent,
151 mRenderState.getRenderThread().getGrContext());
152 // unref to match the ref added by ASurfaceTexture_dequeueBuffer. eglCreateImageKHR
153 // (invoked by createIfNeeded) will add a ref to the AHardwareBuffer.
154 AHardwareBuffer_release(hardwareBuffer);
155 if (layerImage.get()) {
156 SkMatrix textureTransform;
157 mat4(transformMatrix).copyTo(textureTransform);
158 // force filtration if buffer size != layer size
159 bool forceFilter =
160 mWidth != layerImage->width() || mHeight != layerImage->height();
161 updateLayer(forceFilter, textureTransform, layerImage);
162 }
163 }
164 }
165
166 if (mTransform) {
167 mLayer->getTransform() = *mTransform;
168 setTransform(nullptr);
169 }
170 }
171 }
172
updateLayer(bool forceFilter,const SkMatrix & textureTransform,const sk_sp<SkImage> & layerImage)173 void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
174 const sk_sp<SkImage>& layerImage) {
175 mLayer->setBlend(mBlend);
176 mLayer->setForceFilter(forceFilter);
177 mLayer->setSize(mWidth, mHeight);
178 mLayer->getTexTransform() = textureTransform;
179 mLayer->setImage(layerImage);
180 }
181
detachSurfaceTexture()182 void DeferredLayerUpdater::detachSurfaceTexture() {
183 if (mSurfaceTexture.get()) {
184 destroyLayer();
185 mSurfaceTexture = nullptr;
186 }
187 }
188
createIfNeeded(AHardwareBuffer * buffer,android_dataspace dataspace,bool forceCreate,GrContext * context)189 sk_sp<SkImage> DeferredLayerUpdater::ImageSlot::createIfNeeded(AHardwareBuffer* buffer,
190 android_dataspace dataspace,
191 bool forceCreate,
192 GrContext* context) {
193 if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace ||
194 forceCreate || mBuffer != buffer) {
195 if (buffer != mBuffer) {
196 clear();
197 }
198
199 if (!buffer) {
200 return nullptr;
201 }
202
203 if (!mTextureRelease) {
204 mTextureRelease = new AutoBackendTextureRelease(context, buffer);
205 } else {
206 mTextureRelease->newBufferContent(context);
207 }
208
209 mDataspace = dataspace;
210 mBuffer = buffer;
211 mTextureRelease->makeImage(buffer, dataspace, context);
212 }
213 return mTextureRelease ? mTextureRelease->getImage() : nullptr;
214 }
215
clear()216 void DeferredLayerUpdater::ImageSlot::clear() {
217 if (mTextureRelease) {
218 // The following unref counteracts the initial mUsageCount of 1, set by default initializer.
219 mTextureRelease->unref(true);
220 mTextureRelease = nullptr;
221 }
222
223 mBuffer = nullptr;
224 }
225
226 } /* namespace uirenderer */
227 } /* namespace android */
228