blob: a1c8dca35bfb4e2f492bebe2167e5f80db7ed95c [file] [log] [blame]
John Reck3b202512014-06-23 13:13:08 -07001/*
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 */
John Reck1bcacfd2017-11-03 10:12:19 -070016#include "renderstate/RenderState.h"
17#include <GpuMemoryTracker.h>
sergeyv3e9999b2017-01-19 15:37:02 -080018#include "DeferredLayerUpdater.h"
Greg Daniel8cd3edf2017-01-09 14:15:41 -050019#include "GlLayer.h"
Greg Daniel45ec62b2017-01-04 14:27:00 -050020#include "VkLayer.h"
John Reckd9d7f122018-05-03 14:40:56 -070021#include "Snapshot.h"
John Reck3b202512014-06-23 13:13:08 -070022
John Reck443a7142014-09-04 17:40:05 -070023#include "renderthread/CanvasContext.h"
John Reck0e89e2b2014-10-31 14:49:06 -070024#include "renderthread/EglManager.h"
Chris Craik117bdbc2015-02-05 10:12:38 -080025#include "utils/GLUtils.h"
Romain Guycaaaa662017-03-27 00:40:21 -070026
Chris Craik9db58c02015-08-19 15:19:18 -070027#include <algorithm>
28
Romain Guycaaaa662017-03-27 00:40:21 -070029#include <ui/ColorSpace.h>
30
John Reck3b202512014-06-23 13:13:08 -070031namespace android {
32namespace uirenderer {
33
John Reck0e89e2b2014-10-31 14:49:06 -070034RenderState::RenderState(renderthread::RenderThread& thread)
John Reck1bcacfd2017-11-03 10:12:19 -070035 : mRenderThread(thread), mViewportWidth(0), mViewportHeight(0), mFramebuffer(0) {
John Reck0e89e2b2014-10-31 14:49:06 -070036 mThreadId = pthread_self();
John Reck3b202512014-06-23 13:13:08 -070037}
38
39RenderState::~RenderState() {
40}
41
42void RenderState::onGLContextCreated() {
Greg Daniel45ec62b2017-01-04 14:27:00 -050043 GpuMemoryTracker::onGpuContextCreated();
John Reck38e0c322015-11-10 12:19:17 -080044
John Reck642ebea2017-07-17 09:55:02 -070045 // Deferred because creation needs GL context for texture limits
46 if (!mLayerPool) {
47 mLayerPool = new OffscreenBufferPool();
48 }
49
Chris Craik96a5c4c2015-01-27 15:46:35 -080050 // This is delayed because the first access of Caches makes GL calls
Chris Craikff5c8e82015-01-30 09:46:18 -080051 if (!mCaches) {
52 mCaches = &Caches::createInstance(*this);
53 }
Chris Craik96a5c4c2015-01-27 15:46:35 -080054 mCaches->init();
John Reck3b202512014-06-23 13:13:08 -070055}
56
John Reck49bc4ac2015-01-29 12:53:38 -080057static void layerLostGlContext(Layer* layer) {
Greg Daniel8cd3edf2017-01-09 14:15:41 -050058 LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::OpenGL,
John Reck1bcacfd2017-11-03 10:12:19 -070059 "layerLostGlContext on non GL layer");
Greg Daniel8cd3edf2017-01-09 14:15:41 -050060 static_cast<GlLayer*>(layer)->onGlContextLost();
John Reck49bc4ac2015-01-29 12:53:38 -080061}
62
Chris Craik1d477422014-08-26 17:30:15 -070063void RenderState::onGLContextDestroyed() {
John Reck642ebea2017-07-17 09:55:02 -070064 mLayerPool->clear();
Chris Craik9fded232015-11-11 16:42:34 -080065
Chris Craik96a5c4c2015-01-27 15:46:35 -080066 // TODO: reset all cached state in state objects
John Reck49bc4ac2015-01-29 12:53:38 -080067 std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerLostGlContext);
Chris Craik96a5c4c2015-01-27 15:46:35 -080068
Chris Craik44eb2c02015-01-29 09:45:09 -080069 mCaches->terminate();
70
sergeyvc3f13162017-02-06 11:45:14 -080071 destroyLayersInUpdater();
Greg Daniel45ec62b2017-01-04 14:27:00 -050072 GpuMemoryTracker::onGpuContextDestroyed();
73}
74
75void RenderState::onVkContextCreated() {
Greg Daniel45ec62b2017-01-04 14:27:00 -050076 GpuMemoryTracker::onGpuContextCreated();
77}
78
79static void layerDestroyedVkContext(Layer* layer) {
80 LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::Vulkan,
81 "layerLostVkContext on non Vulkan layer");
82 static_cast<VkLayer*>(layer)->onVkContextDestroyed();
83}
84
85void RenderState::onVkContextDestroyed() {
Greg Daniel45ec62b2017-01-04 14:27:00 -050086 std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerDestroyedVkContext);
Derek Sollenberger7a4216b2017-10-25 09:52:23 -040087 destroyLayersInUpdater();
Greg Daniel45ec62b2017-01-04 14:27:00 -050088 GpuMemoryTracker::onGpuContextDestroyed();
89}
90
91GrContext* RenderState::getGrContext() const {
92 return mRenderThread.getGrContext();
Chris Craik1d477422014-08-26 17:30:15 -070093}
94
Chris Craik9fded232015-11-11 16:42:34 -080095void RenderState::flush(Caches::FlushMode mode) {
96 switch (mode) {
97 case Caches::FlushMode::Full:
John Reck1bcacfd2017-11-03 10:12:19 -070098 // fall through
Chris Craik9fded232015-11-11 16:42:34 -080099 case Caches::FlushMode::Moderate:
John Reck1bcacfd2017-11-03 10:12:19 -0700100 // fall through
Chris Craik9fded232015-11-11 16:42:34 -0800101 case Caches::FlushMode::Layers:
John Reck642ebea2017-07-17 09:55:02 -0700102 if (mLayerPool) mLayerPool->clear();
Chris Craik9fded232015-11-11 16:42:34 -0800103 break;
104 }
John Reck642ebea2017-07-17 09:55:02 -0700105 if (mCaches) mCaches->flush(mode);
Chris Craik9fded232015-11-11 16:42:34 -0800106}
107
John Reck9a814872017-05-22 15:04:21 -0700108void RenderState::onBitmapDestroyed(uint32_t pixelRefId) {
Mike Reed8cafcc62018-05-03 11:32:46 -0400109 // DEAD CODE
John Reck9a814872017-05-22 15:04:21 -0700110}
111
John Reck3b202512014-06-23 13:13:08 -0700112void RenderState::setViewport(GLsizei width, GLsizei height) {
113 mViewportWidth = width;
114 mViewportHeight = height;
115 glViewport(0, 0, mViewportWidth, mViewportHeight);
116}
117
John Reck3b202512014-06-23 13:13:08 -0700118void RenderState::getViewport(GLsizei* outWidth, GLsizei* outHeight) {
119 *outWidth = mViewportWidth;
120 *outHeight = mViewportHeight;
121}
122
123void RenderState::bindFramebuffer(GLuint fbo) {
124 if (mFramebuffer != fbo) {
125 mFramebuffer = fbo;
126 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
127 }
128}
129
John Reck0b8d0672016-01-29 14:18:22 -0800130GLuint RenderState::createFramebuffer() {
Chris Craik818c9fb2015-10-23 14:33:42 -0700131 GLuint ret;
132 glGenFramebuffers(1, &ret);
133 return ret;
134}
135
136void RenderState::deleteFramebuffer(GLuint fbo) {
137 if (mFramebuffer == fbo) {
138 // GL defines that deleting the currently bound FBO rebinds FBO 0.
139 // Reflect this in our cached value.
140 mFramebuffer = 0;
141 }
142 glDeleteFramebuffers(1, &fbo);
143}
144
John Reck3b202512014-06-23 13:13:08 -0700145void RenderState::invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info) {
John Reck95cd24b2015-08-04 11:17:39 -0700146 if (mode == DrawGlInfo::kModeProcessNoContext) {
147 // If there's no context we don't need to interrupt as there's
148 // no gl state to save/restore
149 (*functor)(mode, info);
150 } else {
151 interruptForFunctorInvoke();
152 (*functor)(mode, info);
153 resumeFromFunctorInvoke();
154 }
John Reck3b202512014-06-23 13:13:08 -0700155}
156
157void RenderState::interruptForFunctorInvoke() {
Chris Craik6c15ffa2015-02-02 13:50:55 -0800158 mCaches->setProgram(nullptr);
Chris Craik44eb2c02015-01-29 09:45:09 -0800159 mCaches->textureState().resetActiveTexture();
John Reck3b202512014-06-23 13:13:08 -0700160 debugOverdraw(false, false);
Romain Guy253f2c22016-09-28 17:34:42 -0700161 // TODO: We need a way to know whether the functor is sRGB aware (b/32072673)
John Reck1bcacfd2017-11-03 10:12:19 -0700162 if (mCaches->extensions().hasLinearBlending() && mCaches->extensions().hasSRGBWriteControl()) {
Romain Guy253f2c22016-09-28 17:34:42 -0700163 glDisable(GL_FRAMEBUFFER_SRGB_EXT);
164 }
John Reck3b202512014-06-23 13:13:08 -0700165}
166
167void RenderState::resumeFromFunctorInvoke() {
John Reck1bcacfd2017-11-03 10:12:19 -0700168 if (mCaches->extensions().hasLinearBlending() && mCaches->extensions().hasSRGBWriteControl()) {
Romain Guy253f2c22016-09-28 17:34:42 -0700169 glEnable(GL_FRAMEBUFFER_SRGB_EXT);
170 }
171
John Reck3b202512014-06-23 13:13:08 -0700172 glViewport(0, 0, mViewportWidth, mViewportHeight);
173 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
174 debugOverdraw(false, false);
175
176 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
177
Chris Craik44eb2c02015-01-29 09:45:09 -0800178 mCaches->textureState().activateTexture(0);
179 mCaches->textureState().resetBoundTextures();
John Reck3b202512014-06-23 13:13:08 -0700180}
181
182void RenderState::debugOverdraw(bool enable, bool clear) {
Mike Reede7f688b2018-05-04 15:21:43 -0400183 // DEAD CODE
John Reck3b202512014-06-23 13:13:08 -0700184}
185
sergeyv3e9999b2017-01-19 15:37:02 -0800186static void destroyLayerInUpdater(DeferredLayerUpdater* layerUpdater) {
187 layerUpdater->destroyLayer();
188}
189
190void RenderState::destroyLayersInUpdater() {
191 std::for_each(mActiveLayerUpdaters.begin(), mActiveLayerUpdaters.end(), destroyLayerInUpdater);
192}
193
John Reck0e89e2b2014-10-31 14:49:06 -0700194void RenderState::postDecStrong(VirtualLightRefBase* object) {
John Recka55b5d62016-01-14 15:09:10 -0800195 if (pthread_equal(mThreadId, pthread_self())) {
196 object->decStrong(nullptr);
197 } else {
John Reckf8441e62017-10-23 13:10:41 -0700198 mRenderThread.queue().post([object]() { object->decStrong(nullptr); });
John Recka55b5d62016-01-14 15:09:10 -0800199 }
John Reck0e89e2b2014-10-31 14:49:06 -0700200}
201
Chris Craik6c15ffa2015-02-02 13:50:55 -0800202///////////////////////////////////////////////////////////////////////////////
203// Render
204///////////////////////////////////////////////////////////////////////////////
205
Arun530a2b42017-01-23 12:47:57 +0000206void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix,
John Reck1bcacfd2017-11-03 10:12:19 -0700207 bool overrideDisableBlending) {
Chris Craik0519c8102015-02-11 13:17:06 -0800208 const Glop::Fill& fill = glop.fill;
Chris Craik6c15ffa2015-02-02 13:50:55 -0800209
John Reck975591a2016-01-22 16:28:07 -0800210 GL_CHECKPOINT(MODERATE);
John Reck9372ac32016-01-19 11:46:52 -0800211
Chris Craik0519c8102015-02-11 13:17:06 -0800212 // ---------------------------------------------
213 // ---------- Program + uniform setup ----------
214 // ---------------------------------------------
215 mCaches->setProgram(fill.program);
Chris Craik6c15ffa2015-02-02 13:50:55 -0800216
Chris Craik0519c8102015-02-11 13:17:06 -0800217 if (fill.colorEnabled) {
218 fill.program->setColor(fill.color);
219 }
Chris Craik6c15ffa2015-02-02 13:50:55 -0800220
John Reck1bcacfd2017-11-03 10:12:19 -0700221 fill.program->set(orthoMatrix, glop.transform.modelView, glop.transform.meshTransform(),
222 glop.transform.transformFlags & TransformFlags::OffsetByFudgeFactor);
Chris Craik6c15ffa2015-02-02 13:50:55 -0800223
Chris Craik0519c8102015-02-11 13:17:06 -0800224 // Color filter uniforms
Chris Craikb9ce116d2015-08-20 15:14:06 -0700225 if (fill.filterMode == ProgramDescription::ColorFilterMode::Blend) {
Chris Craikef250742015-02-25 17:16:16 -0800226 const FloatColor& color = fill.filter.color;
John Reck1bcacfd2017-11-03 10:12:19 -0700227 glUniform4f(mCaches->program().getUniform("colorBlend"), color.r, color.g, color.b,
228 color.a);
Chris Craikb9ce116d2015-08-20 15:14:06 -0700229 } else if (fill.filterMode == ProgramDescription::ColorFilterMode::Matrix) {
Chris Craik117bdbc2015-02-05 10:12:38 -0800230 glUniformMatrix4fv(mCaches->program().getUniform("colorMatrix"), 1, GL_FALSE,
John Reck1bcacfd2017-11-03 10:12:19 -0700231 fill.filter.matrix.matrix);
Chris Craik117bdbc2015-02-05 10:12:38 -0800232 glUniform4fv(mCaches->program().getUniform("colorMatrixVector"), 1,
John Reck1bcacfd2017-11-03 10:12:19 -0700233 fill.filter.matrix.vector);
Chris Craik117bdbc2015-02-05 10:12:38 -0800234 }
235
Chris Craik0519c8102015-02-11 13:17:06 -0800236 // Round rect clipping uniforms
237 if (glop.roundRectClipState) {
238 // TODO: avoid query, and cache values (or RRCS ptr) in program
239 const RoundRectClipState* state = glop.roundRectClipState;
240 const Rect& innerRect = state->innerRect;
Chris Craik0519c8102015-02-11 13:17:06 -0800241
242 // add half pixel to round out integer rect space to cover pixel centers
243 float roundedOutRadius = state->radius + 0.5f;
Arun06e9f322017-01-23 11:59:21 +0000244
245 // Divide by the radius to simplify the calculations in the fragment shader
246 // roundRectPos is also passed from vertex shader relative to top/left & radius
247 glUniform4f(fill.program->getUniform("roundRectInnerRectLTWH"),
John Reck1bcacfd2017-11-03 10:12:19 -0700248 innerRect.left / roundedOutRadius, innerRect.top / roundedOutRadius,
249 (innerRect.right - innerRect.left) / roundedOutRadius,
250 (innerRect.bottom - innerRect.top) / roundedOutRadius);
Arun06e9f322017-01-23 11:59:21 +0000251
John Reck1bcacfd2017-11-03 10:12:19 -0700252 glUniformMatrix4fv(fill.program->getUniform("roundRectInvTransform"), 1, GL_FALSE,
253 &state->matrix.data[0]);
Arun06e9f322017-01-23 11:59:21 +0000254
John Reck1bcacfd2017-11-03 10:12:19 -0700255 glUniform1f(fill.program->getUniform("roundRectRadius"), roundedOutRadius);
Chris Craik0519c8102015-02-11 13:17:06 -0800256 }
Chris Craikef250742015-02-25 17:16:16 -0800257
John Reck975591a2016-01-22 16:28:07 -0800258 GL_CHECKPOINT(MODERATE);
John Reck9372ac32016-01-19 11:46:52 -0800259
Chris Craik138c21f2016-04-28 16:59:42 -0700260 // texture
261 if (fill.texture.texture != nullptr) {
Chris Craik26bf3422015-02-26 16:28:17 -0800262 const Glop::Fill::TextureData& texture = fill.texture;
263 // texture always takes slot 0, shader samplers increment from there
Chris Craik0519c8102015-02-11 13:17:06 -0800264 mCaches->textureState().activateTexture(0);
265
sergeyv2a38c422016-10-25 15:21:50 -0700266 mCaches->textureState().bindTexture(texture.texture->target(), texture.texture->id());
Chris Craik26bf3422015-02-26 16:28:17 -0800267 if (texture.clamp != GL_INVALID_ENUM) {
sergeyv2a38c422016-10-25 15:21:50 -0700268 texture.texture->setWrap(texture.clamp, false, false);
Chris Craik30036092015-02-12 10:41:39 -0800269 }
Chris Craik26bf3422015-02-26 16:28:17 -0800270 if (texture.filter != GL_INVALID_ENUM) {
sergeyv2a38c422016-10-25 15:21:50 -0700271 texture.texture->setFilter(texture.filter, false, false);
Chris Craik30036092015-02-12 10:41:39 -0800272 }
Chris Craik0519c8102015-02-11 13:17:06 -0800273
Chris Craik26bf3422015-02-26 16:28:17 -0800274 if (texture.textureTransform) {
John Reck1bcacfd2017-11-03 10:12:19 -0700275 glUniformMatrix4fv(fill.program->getUniform("mainTextureTransform"), 1, GL_FALSE,
276 &texture.textureTransform->data[0]);
Chris Craik26bf3422015-02-26 16:28:17 -0800277 }
Chris Craik138c21f2016-04-28 16:59:42 -0700278 }
279
Chris Craik922d3a72015-02-13 17:47:21 -0800280 // Shader uniforms
Romain Guy253f2c22016-09-28 17:34:42 -0700281 SkiaShader::apply(*mCaches, fill.skiaShaderData, mViewportWidth, mViewportHeight);
Chris Craik922d3a72015-02-13 17:47:21 -0800282
John Reck975591a2016-01-22 16:28:07 -0800283 GL_CHECKPOINT(MODERATE);
John Reck1bcacfd2017-11-03 10:12:19 -0700284 Texture* texture = (fill.skiaShaderData.skiaShaderType & kBitmap_SkiaShaderType)
285 ? fill.skiaShaderData.bitmapData.bitmapTexture
286 : nullptr;
Dohyun Leec5a3efd2016-01-21 13:46:21 +0900287 const AutoTexture autoCleanup(texture);
John Reck9372ac32016-01-19 11:46:52 -0800288
Romain Guycaaaa662017-03-27 00:40:21 -0700289 // If we have a shader and a base texture, the base texture is assumed to be an alpha mask
290 // which means the color space conversion applies to the shader's bitmap
291 Texture* colorSpaceTexture = texture != nullptr ? texture : fill.texture.texture;
292 if (colorSpaceTexture != nullptr) {
293 if (colorSpaceTexture->hasColorSpaceConversion()) {
294 const ColorSpaceConnector* connector = colorSpaceTexture->getColorSpaceConnector();
John Reck1bcacfd2017-11-03 10:12:19 -0700295 glUniformMatrix3fv(fill.program->getUniform("colorSpaceMatrix"), 1, GL_FALSE,
296 connector->getTransform().asArray());
Romain Guycaaaa662017-03-27 00:40:21 -0700297 }
298
299 TransferFunctionType transferFunction = colorSpaceTexture->getTransferFunctionType();
300 if (transferFunction != TransferFunctionType::None) {
301 const ColorSpaceConnector* connector = colorSpaceTexture->getColorSpaceConnector();
302 const ColorSpace& source = connector->getSource();
303
304 switch (transferFunction) {
305 case TransferFunctionType::None:
306 break;
307 case TransferFunctionType::Full:
308 glUniform1fv(fill.program->getUniform("transferFunction"), 7,
John Reck1bcacfd2017-11-03 10:12:19 -0700309 reinterpret_cast<const float*>(&source.getTransferParameters().g));
Romain Guycaaaa662017-03-27 00:40:21 -0700310 break;
311 case TransferFunctionType::Limited:
312 glUniform1fv(fill.program->getUniform("transferFunction"), 5,
John Reck1bcacfd2017-11-03 10:12:19 -0700313 reinterpret_cast<const float*>(&source.getTransferParameters().g));
Romain Guycaaaa662017-03-27 00:40:21 -0700314 break;
315 case TransferFunctionType::Gamma:
316 glUniform1f(fill.program->getUniform("transferFunctionGamma"),
John Reck1bcacfd2017-11-03 10:12:19 -0700317 source.getTransferParameters().g);
Romain Guycaaaa662017-03-27 00:40:21 -0700318 break;
319 }
320 }
321 }
322
John Reck975591a2016-01-22 16:28:07 -0800323 GL_CHECKPOINT(MODERATE);
Chris Craik117bdbc2015-02-05 10:12:38 -0800324}
325
326void RenderState::dump() {
Mike Reede7f688b2018-05-04 15:21:43 -0400327 // DEAD CODE
Chris Craik6c15ffa2015-02-02 13:50:55 -0800328}
329
John Reck3b202512014-06-23 13:13:08 -0700330} /* namespace uirenderer */
331} /* namespace android */