blob: 415e850d0fe81ce67e96fb011dcd9403223e882b [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
Greg Daniel8cd3edf2017-01-09 14:15:41 -050018#include "GlLayer.h"
Greg Daniel45ec62b2017-01-04 14:27:00 -050019#include "VkLayer.h"
sergeyv3e9999b2017-01-19 15:37:02 -080020#include "renderstate/RenderState.h"
John Reck749906b2014-10-03 15:02:19 -070021#include "renderthread/EglManager.h"
22#include "renderthread/RenderTask.h"
Chris Craik5e00c7c2016-07-06 16:10:09 -070023#include "utils/PaintUtils.h"
John Reck04fc5832014-02-05 16:38:25 -080024
25namespace android {
26namespace uirenderer {
27
sergeyv3e9999b2017-01-19 15:37:02 -080028DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState, CreateLayerFn createLayerFn,
29 Layer::Api layerApi)
30 : mRenderState(renderState)
31 , mBlend(false)
32 , mSurfaceTexture(nullptr)
Chris Craikd41c4d82015-01-05 15:51:13 -080033 , mTransform(nullptr)
John Reck04fc5832014-02-05 16:38:25 -080034 , mNeedsGLContextAttach(false)
35 , mUpdateTexImage(false)
sergeyv3e9999b2017-01-19 15:37:02 -080036 , mLayer(nullptr)
37 , mLayerApi(layerApi)
38 , mCreateLayerFn(createLayerFn) {
39 renderState.registerDeferredLayerUpdater(this);
John Reck04fc5832014-02-05 16:38:25 -080040}
41
42DeferredLayerUpdater::~DeferredLayerUpdater() {
Derek Sollenberger674554f2014-02-19 16:47:32 +000043 SkSafeUnref(mColorFilter);
Chris Craikd41c4d82015-01-05 15:51:13 -080044 setTransform(nullptr);
sergeyv3e9999b2017-01-19 15:37:02 -080045 mRenderState.unregisterDeferredLayerUpdater(this);
46 destroyLayer();
47}
48
49void DeferredLayerUpdater::destroyLayer() {
50 if (mLayer) {
51 mLayer->postDecStrong();
52 mLayer = nullptr;
53 }
John Reck04fc5832014-02-05 16:38:25 -080054}
55
Derek Sollenberger674554f2014-02-19 16:47:32 +000056void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
Chris Craikbf6f0f22015-10-01 12:36:07 -070057 mAlpha = PaintUtils::getAlphaDirect(paint);
Mike Reed260ab722016-10-07 15:59:20 -040058 mMode = PaintUtils::getBlendModeDirect(paint);
Chris Craikd41c4d82015-01-05 15:51:13 -080059 SkColorFilter* colorFilter = (paint) ? paint->getColorFilter() : nullptr;
John Reck04fc5832014-02-05 16:38:25 -080060 SkRefCnt_SafeAssign(mColorFilter, colorFilter);
61}
62
Chris Craikd2dfd8f2015-12-16 14:27:20 -080063void DeferredLayerUpdater::apply() {
sergeyv3e9999b2017-01-19 15:37:02 -080064 if (!mLayer) {
65 mLayer = mCreateLayerFn(mRenderState, mWidth, mHeight, mColorFilter, mAlpha, mMode, mBlend);
66 }
67
John Reck04fc5832014-02-05 16:38:25 -080068 mLayer->setColorFilter(mColorFilter);
69 mLayer->setAlpha(mAlpha, mMode);
70
John Reck25fbb3f2014-06-12 13:46:45 -070071 if (mSurfaceTexture.get()) {
Greg Daniel45ec62b2017-01-04 14:27:00 -050072 if (mLayer->getApi() == Layer::Api::Vulkan) {
73 if (mUpdateTexImage) {
74 mUpdateTexImage = false;
75 doUpdateVkTexImage();
76 }
77 } else {
78 LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
79 "apply surfaceTexture with non GL backend %x, GL %x, VK %x",
80 mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
81 if (mNeedsGLContextAttach) {
82 mNeedsGLContextAttach = false;
83 mSurfaceTexture->attachToContext(static_cast<GlLayer*>(mLayer)->getTextureId());
84 }
85 if (mUpdateTexImage) {
86 mUpdateTexImage = false;
87 doUpdateTexImage();
88 }
John Reck04fc5832014-02-05 16:38:25 -080089 }
90 if (mTransform) {
91 mLayer->getTransform().load(*mTransform);
Chris Craikd41c4d82015-01-05 15:51:13 -080092 setTransform(nullptr);
John Reck04fc5832014-02-05 16:38:25 -080093 }
94 }
John Reck04fc5832014-02-05 16:38:25 -080095}
96
97void DeferredLayerUpdater::doUpdateTexImage() {
Greg Daniel8cd3edf2017-01-09 14:15:41 -050098 LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
99 "doUpdateTexImage non GL backend %x, GL %x, VK %x",
100 mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
John Reck04fc5832014-02-05 16:38:25 -0800101 if (mSurfaceTexture->updateTexImage() == NO_ERROR) {
102 float transform[16];
103
104 int64_t frameNumber = mSurfaceTexture->getFrameNumber();
105 // If the GLConsumer queue is in synchronous mode, need to discard all
106 // but latest frame, using the frame number to tell when we no longer
107 // have newer frames to target. Since we can't tell which mode it is in,
108 // do this unconditionally.
109 int dropCounter = 0;
110 while (mSurfaceTexture->updateTexImage() == NO_ERROR) {
111 int64_t newFrameNumber = mSurfaceTexture->getFrameNumber();
112 if (newFrameNumber == frameNumber) break;
113 frameNumber = newFrameNumber;
114 dropCounter++;
115 }
Chris Craik9757ac02014-02-25 18:50:17 -0800116
117 bool forceFilter = false;
118 sp<GraphicBuffer> buffer = mSurfaceTexture->getCurrentBuffer();
Chris Craikd41c4d82015-01-05 15:51:13 -0800119 if (buffer != nullptr) {
Chris Craik9757ac02014-02-25 18:50:17 -0800120 // force filtration if buffer size != layer size
Dan Stoza32d2e762014-11-18 14:47:11 -0800121 forceFilter = mWidth != static_cast<int>(buffer->getWidth())
122 || mHeight != static_cast<int>(buffer->getHeight());
Chris Craik9757ac02014-02-25 18:50:17 -0800123 }
124
John Reck04fc5832014-02-05 16:38:25 -0800125 #if DEBUG_RENDERER
126 if (dropCounter > 0) {
127 RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter);
128 }
129 #endif
130 mSurfaceTexture->getTransformMatrix(transform);
131 GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget();
132
Chris Craik48f650c2015-03-10 11:03:39 -0700133 LOG_ALWAYS_FATAL_IF(renderTarget != GL_TEXTURE_2D && renderTarget != GL_TEXTURE_EXTERNAL_OES,
134 "doUpdateTexImage target %x, 2d %x, EXT %x",
135 renderTarget, GL_TEXTURE_2D, GL_TEXTURE_EXTERNAL_OES);
Derek Sollenberger56ad6ec2016-07-22 12:13:32 -0400136 updateLayer(forceFilter, renderTarget, transform);
137 }
138}
139
Greg Daniel45ec62b2017-01-04 14:27:00 -0500140void DeferredLayerUpdater::doUpdateVkTexImage() {
141 LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::Vulkan,
142 "updateLayer non Vulkan backend %x, GL %x, VK %x",
143 mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
144
145 static const mat4 identityMatrix;
Greg Daniel98c78dad2017-01-04 14:45:56 -0500146 updateLayer(false, GL_NONE, identityMatrix.data);
Greg Daniel45ec62b2017-01-04 14:27:00 -0500147
148 VkLayer* vkLayer = static_cast<VkLayer*>(mLayer);
149 vkLayer->updateTexture();
150}
151
Derek Sollenberger56ad6ec2016-07-22 12:13:32 -0400152void DeferredLayerUpdater::updateLayer(bool forceFilter, GLenum renderTarget,
153 const float* textureTransform) {
Greg Daniel45ec62b2017-01-04 14:27:00 -0500154 mLayer->setBlend(mBlend);
155 mLayer->setForceFilter(forceFilter);
156 mLayer->setSize(mWidth, mHeight);
157 mLayer->getTexTransform().load(textureTransform);
Greg Daniel98c78dad2017-01-04 14:45:56 -0500158
159 if (mLayer->getApi() == Layer::Api::OpenGL) {
160 GlLayer* glLayer = static_cast<GlLayer*>(mLayer);
161 if (renderTarget != glLayer->getRenderTarget()) {
162 glLayer->setRenderTarget(renderTarget);
163 glLayer->bindTexture();
164 glLayer->setFilter(GL_NEAREST, false, true);
165 glLayer->setWrap(GL_CLAMP_TO_EDGE, false, true);
166 }
167 }
Greg Daniel45ec62b2017-01-04 14:27:00 -0500168}
169
John Reck918ad522014-06-27 14:45:25 -0700170void DeferredLayerUpdater::detachSurfaceTexture() {
171 if (mSurfaceTexture.get()) {
sergeyvdb92bb72017-02-02 12:57:30 -0800172 if (mLayerApi == Layer::Api::OpenGL) {
Greg Daniel45ec62b2017-01-04 14:27:00 -0500173 status_t err = mSurfaceTexture->detachFromContext();
174 if (err != 0) {
175 // TODO: Elevate to fatal exception
176 ALOGE("Failed to detach SurfaceTexture from context %d", err);
177 }
sergeyvdb92bb72017-02-02 12:57:30 -0800178 if (mLayer) {
179 static_cast<GlLayer*>(mLayer)->clearTexture();
180 }
John Reck749906b2014-10-03 15:02:19 -0700181 }
Chris Craikd41c4d82015-01-05 15:51:13 -0800182 mSurfaceTexture = nullptr;
John Reck918ad522014-06-27 14:45:25 -0700183 }
184}
185
John Reck04fc5832014-02-05 16:38:25 -0800186} /* namespace uirenderer */
187} /* namespace android */