blob: 8d112d1c64bf6eba1901d85d642eaf6d04ea8be0 [file] [log] [blame]
John Reck04fc5832014-02-05 16:38:25 -08001/*
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
Fedor Kudasovd501e102019-06-21 10:22:53 +010018#include <GLES2/gl2.h>
19#include <GLES2/gl2ext.h>
20
Stan Iliev5af5d302020-01-13 11:29:18 -050021// TODO: Use public SurfaceTexture APIs once available and include public NDK header file instead.
22#include <surfacetexture/surface_texture_platform.h>
Stan Ilievaaa9e832019-09-17 14:07:23 -040023#include "AutoBackendTextureRelease.h"
bsears9df09ccf2021-08-06 15:18:26 +000024#include "Matrix.h"
Stan Ilievaaa9e832019-09-17 14:07:23 -040025#include "Properties.h"
sergeyv3e9999b2017-01-19 15:37:02 -080026#include "renderstate/RenderState.h"
Stan Ilievaaa9e832019-09-17 14:07:23 -040027#include "renderthread/EglManager.h"
28#include "renderthread/RenderThread.h"
29#include "renderthread/VulkanManager.h"
30
31using namespace android::uirenderer::renderthread;
John Reck04fc5832014-02-05 16:38:25 -080032
33namespace android {
34namespace uirenderer {
35
Stan Iliev564ca3e2018-09-04 22:00:00 +000036DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState)
sergeyv3e9999b2017-01-19 15:37:02 -080037 : mRenderState(renderState)
38 , mBlend(false)
Stan Iliev5af5d302020-01-13 11:29:18 -050039 , mSurfaceTexture(nullptr, [](ASurfaceTexture*) {})
Chris Craikd41c4d82015-01-05 15:51:13 -080040 , mTransform(nullptr)
sergeyv00eb43d2017-02-13 14:34:15 -080041 , mGLContextAttached(false)
John Reck04fc5832014-02-05 16:38:25 -080042 , mUpdateTexImage(false)
Stan Iliev564ca3e2018-09-04 22:00:00 +000043 , mLayer(nullptr) {
Derek Sollenberger28a4d992018-09-20 13:37:24 -040044 renderState.registerContextCallback(this);
John Reck04fc5832014-02-05 16:38:25 -080045}
46
47DeferredLayerUpdater::~DeferredLayerUpdater() {
Chris Craikd41c4d82015-01-05 15:51:13 -080048 setTransform(nullptr);
Derek Sollenberger28a4d992018-09-20 13:37:24 -040049 mRenderState.removeContextCallback(this);
50 destroyLayer();
51}
52
Stan Ilievaaa9e832019-09-17 14:07:23 -040053void DeferredLayerUpdater::setSurfaceTexture(AutoTextureRelease&& consumer) {
54 mSurfaceTexture = std::move(consumer);
Fedor Kudasovd501e102019-06-21 10:22:53 +010055
Stan Ilievaaa9e832019-09-17 14:07:23 -040056 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);
Fedor Kudasovd501e102019-06-21 10:22:53 +010059}
60
Derek Sollenberger28a4d992018-09-20 13:37:24 -040061void DeferredLayerUpdater::onContextDestroyed() {
sergeyv3e9999b2017-01-19 15:37:02 -080062 destroyLayer();
63}
64
65void DeferredLayerUpdater::destroyLayer() {
sergeyv00eb43d2017-02-13 14:34:15 -080066 if (!mLayer) {
67 return;
sergeyv3e9999b2017-01-19 15:37:02 -080068 }
sergeyv00eb43d2017-02-13 14:34:15 -080069
Stan Iliev564ca3e2018-09-04 22:00:00 +000070 if (mSurfaceTexture.get() && mGLContextAttached) {
Stan Ilievaaa9e832019-09-17 14:07:23 -040071 ASurfaceTexture_releaseConsumerOwnership(mSurfaceTexture.get());
sergeyv00eb43d2017-02-13 14:34:15 -080072 mGLContextAttached = false;
sergeyv00eb43d2017-02-13 14:34:15 -080073 }
74
75 mLayer->postDecStrong();
Stan Iliev1a025a72018-09-05 16:35:11 -040076
sergeyv00eb43d2017-02-13 14:34:15 -080077 mLayer = nullptr;
Stan Ilievaaa9e832019-09-17 14:07:23 -040078
Greg Daniel27e1fa22021-05-26 09:24:15 -040079 for (auto& [index, slot] : mImageSlots) {
80 slot.clear(mRenderState.getRenderThread().getGrContext());
81 }
Stan Ilievaaa9e832019-09-17 14:07:23 -040082 mImageSlots.clear();
John Reck04fc5832014-02-05 16:38:25 -080083}
84
Derek Sollenberger674554f2014-02-19 16:47:32 +000085void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
Chris Craikbf6f0f22015-10-01 12:36:07 -070086 mAlpha = PaintUtils::getAlphaDirect(paint);
Mike Reed260ab722016-10-07 15:59:20 -040087 mMode = PaintUtils::getBlendModeDirect(paint);
Derek Sollenbergerbe3876c2018-04-20 16:13:31 -040088 if (paint) {
89 mColorFilter = paint->refColorFilter();
90 } else {
91 mColorFilter.reset();
92 }
John Reck04fc5832014-02-05 16:38:25 -080093}
94
Greg Daniel27e1fa22021-05-26 09:24:15 -040095status_t DeferredLayerUpdater::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence,
96 EGLDisplay* display, int* releaseFence,
97 void* handle) {
Stan Ilievaaa9e832019-09-17 14:07:23 -040098 *display = EGL_NO_DISPLAY;
Greg Daniel27e1fa22021-05-26 09:24:15 -040099 DeferredLayerUpdater* dlu = (DeferredLayerUpdater*)handle;
100 RenderState& renderState = dlu->mRenderState;
Stan Ilievaaa9e832019-09-17 14:07:23 -0400101 status_t err;
102 if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
Greg Daniel27e1fa22021-05-26 09:24:15 -0400103 EglManager& eglManager = renderState.getRenderThread().eglManager();
Stan Ilievaaa9e832019-09-17 14:07:23 -0400104 *display = eglManager.eglDisplay();
105 err = eglManager.createReleaseFence(useFenceSync, eglFence, releaseFence);
106 } else {
Greg Daniel27e1fa22021-05-26 09:24:15 -0400107 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());
Stan Ilievaaa9e832019-09-17 14:07:23 -0400114 }
115 return err;
116}
117
Greg Daniel27e1fa22021-05-26 09:24:15 -0400118status_t DeferredLayerUpdater::fenceWait(int fence, void* handle) {
Stan Ilievaaa9e832019-09-17 14:07:23 -0400119 // Wait on the producer fence for the buffer to be ready.
120 status_t err;
Greg Daniel27e1fa22021-05-26 09:24:15 -0400121 DeferredLayerUpdater* dlu = (DeferredLayerUpdater*)handle;
122 RenderState& renderState = dlu->mRenderState;
Stan Ilievaaa9e832019-09-17 14:07:23 -0400123 if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
Greg Daniel27e1fa22021-05-26 09:24:15 -0400124 err = renderState.getRenderThread().eglManager().fenceWait(fence);
Stan Ilievaaa9e832019-09-17 14:07:23 -0400125 } else {
Greg Daniel27e1fa22021-05-26 09:24:15 -0400126 err = renderState.getRenderThread().vulkanManager().fenceWait(
127 fence, renderState.getRenderThread().getGrContext());
Stan Ilievaaa9e832019-09-17 14:07:23 -0400128 }
129 return err;
130}
131
Chris Craikd2dfd8f2015-12-16 14:27:20 -0800132void DeferredLayerUpdater::apply() {
sergeyv3e9999b2017-01-19 15:37:02 -0800133 if (!mLayer) {
Stan Iliev564ca3e2018-09-04 22:00:00 +0000134 mLayer = new Layer(mRenderState, mColorFilter, mAlpha, mMode);
sergeyv3e9999b2017-01-19 15:37:02 -0800135 }
136
John Reck04fc5832014-02-05 16:38:25 -0800137 mLayer->setColorFilter(mColorFilter);
138 mLayer->setAlpha(mAlpha, mMode);
139
John Reck25fbb3f2014-06-12 13:46:45 -0700140 if (mSurfaceTexture.get()) {
Stan Iliev564ca3e2018-09-04 22:00:00 +0000141 if (!mGLContextAttached) {
142 mGLContextAttached = true;
143 mUpdateTexImage = true;
Stan Ilievaaa9e832019-09-17 14:07:23 -0400144 ASurfaceTexture_takeConsumerOwnership(mSurfaceTexture.get());
Stan Iliev85f90962018-08-31 18:35:06 +0000145 }
Stan Iliev564ca3e2018-09-04 22:00:00 +0000146 if (mUpdateTexImage) {
147 mUpdateTexImage = false;
bsears9df09ccf2021-08-06 15:18:26 +0000148 float transformMatrix[16];
Stan Ilievaaa9e832019-09-17 14:07:23 -0400149 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(
bsears9df09ccf2021-08-06 15:18:26 +0000156 mSurfaceTexture.get(), &slot, &dataspace, transformMatrix, &newContent,
157 createReleaseFence, fenceWait, this);
Stan Ilievaaa9e832019-09-17 14:07:23 -0400158
159 if (hardwareBuffer) {
Greg Daniel27e1fa22021-05-26 09:24:15 -0400160 mCurrentSlot = slot;
Stan Ilievaaa9e832019-09-17 14:07:23 -0400161 sk_sp<SkImage> layerImage = mImageSlots[slot].createIfNeeded(
162 hardwareBuffer, dataspace, newContent,
163 mRenderState.getRenderThread().getGrContext());
Stan Ilievd125b442020-07-16 17:03:27 -0400164 // 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);
Stan Ilievaaa9e832019-09-17 14:07:23 -0400167 if (layerImage.get()) {
bsears9df09ccf2021-08-06 15:18:26 +0000168 SkMatrix textureTransform;
169 mat4(transformMatrix).copyTo(textureTransform);
Stan Ilievaaa9e832019-09-17 14:07:23 -0400170 // force filtration if buffer size != layer size
171 bool forceFilter =
172 mWidth != layerImage->width() || mHeight != layerImage->height();
bsears9df09ccf2021-08-06 15:18:26 +0000173 updateLayer(forceFilter, textureTransform, layerImage);
Stan Ilievaaa9e832019-09-17 14:07:23 -0400174 }
Stan Iliev564ca3e2018-09-04 22:00:00 +0000175 }
176 }
177
John Reck04fc5832014-02-05 16:38:25 -0800178 if (mTransform) {
Stan Iliev564ca3e2018-09-04 22:00:00 +0000179 mLayer->getTransform() = *mTransform;
Chris Craikd41c4d82015-01-05 15:51:13 -0800180 setTransform(nullptr);
John Reck04fc5832014-02-05 16:38:25 -0800181 }
182 }
John Reck04fc5832014-02-05 16:38:25 -0800183}
184
bsears9df09ccf2021-08-06 15:18:26 +0000185void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
186 const sk_sp<SkImage>& layerImage) {
Greg Daniel45ec62b2017-01-04 14:27:00 -0500187 mLayer->setBlend(mBlend);
188 mLayer->setForceFilter(forceFilter);
189 mLayer->setSize(mWidth, mHeight);
bsears9df09ccf2021-08-06 15:18:26 +0000190 mLayer->getTexTransform() = textureTransform;
Stan Iliev564ca3e2018-09-04 22:00:00 +0000191 mLayer->setImage(layerImage);
Greg Daniel45ec62b2017-01-04 14:27:00 -0500192}
193
John Reck918ad522014-06-27 14:45:25 -0700194void DeferredLayerUpdater::detachSurfaceTexture() {
195 if (mSurfaceTexture.get()) {
sergeyv00eb43d2017-02-13 14:34:15 -0800196 destroyLayer();
Chris Craikd41c4d82015-01-05 15:51:13 -0800197 mSurfaceTexture = nullptr;
John Reck918ad522014-06-27 14:45:25 -0700198 }
199}
200
Stan Ilievaaa9e832019-09-17 14:07:23 -0400201sk_sp<SkImage> DeferredLayerUpdater::ImageSlot::createIfNeeded(AHardwareBuffer* buffer,
202 android_dataspace dataspace,
203 bool forceCreate,
Adlai Hollerf8c434e2020-07-27 11:42:45 -0400204 GrDirectContext* context) {
Stan Ilievaaa9e832019-09-17 14:07:23 -0400205 if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace ||
206 forceCreate || mBuffer != buffer) {
207 if (buffer != mBuffer) {
Greg Daniel27e1fa22021-05-26 09:24:15 -0400208 clear(context);
Stan Ilievaaa9e832019-09-17 14:07:23 -0400209 }
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
Greg Daniel27e1fa22021-05-26 09:24:15 -0400228void DeferredLayerUpdater::ImageSlot::clear(GrDirectContext* context) {
Stan Ilievaaa9e832019-09-17 14:07:23 -0400229 if (mTextureRelease) {
Greg Daniel27e1fa22021-05-26 09:24:15 -0400230 if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
231 this->releaseQueueOwnership(context);
232 }
Stan Ilievaaa9e832019-09-17 14:07:23 -0400233 // 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
Greg Daniel27e1fa22021-05-26 09:24:15 -0400241void DeferredLayerUpdater::ImageSlot::releaseQueueOwnership(GrDirectContext* context) {
242 LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan);
243 if (mTextureRelease) {
244 mTextureRelease->releaseQueueOwnership(context);
245 }
246}
247
John Reck04fc5832014-02-05 16:38:25 -0800248} /* namespace uirenderer */
249} /* namespace android */