blob: f8282dc1073a80d8d93defec92e49e05ea48a459 [file] [log] [blame]
Chris Craikb565df12015-10-05 13:00:52 -07001/*
2 * Copyright (C) 2015 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
17#include "BakedOpRenderer.h"
18
19#include "Caches.h"
20#include "Glop.h"
21#include "GlopBuilder.h"
Chris Craik9fded232015-11-11 16:42:34 -080022#include "renderstate/OffscreenBufferPool.h"
Chris Craikb565df12015-10-05 13:00:52 -070023#include "renderstate/RenderState.h"
24#include "utils/GLUtils.h"
Chris Craik9fded232015-11-11 16:42:34 -080025#include "VertexBuffer.h"
Chris Craikb565df12015-10-05 13:00:52 -070026
Chris Craika1717272015-11-19 13:02:43 -080027#include <algorithm>
Chris Craika1717272015-11-19 13:02:43 -080028
Chris Craikb565df12015-10-05 13:00:52 -070029namespace android {
30namespace uirenderer {
31
Chris Craikd3daa312015-11-06 10:59:56 -080032OffscreenBuffer* BakedOpRenderer::startTemporaryLayer(uint32_t width, uint32_t height) {
Chris Craik9fded232015-11-11 16:42:34 -080033 LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");
34
35 OffscreenBuffer* buffer = mRenderState.layerPool().get(mRenderState, width, height);
Chris Craik98787e62015-11-13 10:55:30 -080036 startRepaintLayer(buffer, Rect(width, height));
Chris Craik0b7e8242015-10-28 16:50:44 -070037 return buffer;
38}
39
Chris Craik98787e62015-11-13 10:55:30 -080040void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) {
Chris Craikd3daa312015-11-06 10:59:56 -080041 LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");
42
Chris Craik0b7e8242015-10-28 16:50:44 -070043 mRenderTarget.offscreenBuffer = offscreenBuffer;
Chris Craik818c9fb2015-10-23 14:33:42 -070044
Chris Craik5854b342015-10-26 15:49:56 -070045 // create and bind framebuffer
46 mRenderTarget.frameBufferId = mRenderState.genFramebuffer();
47 mRenderState.bindFramebuffer(mRenderTarget.frameBufferId);
Chris Craik818c9fb2015-10-23 14:33:42 -070048
49 // attach the texture to the FBO
50 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
Chris Craik0b7e8242015-10-28 16:50:44 -070051 offscreenBuffer->texture.id, 0);
Chris Craik818c9fb2015-10-23 14:33:42 -070052 LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "startLayer FAILED");
53 LOG_ALWAYS_FATAL_IF(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
54 "framebuffer incomplete!");
55
Chris Craik818c9fb2015-10-23 14:33:42 -070056 // Change the viewport & ortho projection
Chris Craik0b7e8242015-10-28 16:50:44 -070057 setViewport(offscreenBuffer->viewportWidth, offscreenBuffer->viewportHeight);
Chris Craik98787e62015-11-13 10:55:30 -080058
59 clearColorBuffer(repaintRect);
Chris Craik818c9fb2015-10-23 14:33:42 -070060}
61
Chris Craik5854b342015-10-26 15:49:56 -070062void BakedOpRenderer::endLayer() {
Chris Craik8d2cf942015-11-02 14:52:21 -080063 mRenderTarget.offscreenBuffer->updateMeshFromRegion();
Chris Craik5854b342015-10-26 15:49:56 -070064 mRenderTarget.offscreenBuffer = nullptr;
Chris Craik818c9fb2015-10-23 14:33:42 -070065
66 // Detach the texture from the FBO
67 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
68 LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "endLayer FAILED");
Chris Craik5854b342015-10-26 15:49:56 -070069 mRenderState.deleteFramebuffer(mRenderTarget.frameBufferId);
70 mRenderTarget.frameBufferId = -1;
Chris Craik818c9fb2015-10-23 14:33:42 -070071}
72
Chris Craik98787e62015-11-13 10:55:30 -080073void BakedOpRenderer::startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) {
Chris Craik5854b342015-10-26 15:49:56 -070074 mRenderState.bindFramebuffer(0);
75 setViewport(width, height);
76 mCaches.clearGarbage();
Chris Craikb565df12015-10-05 13:00:52 -070077
Chris Craik5854b342015-10-26 15:49:56 -070078 if (!mOpaque) {
Chris Craik98787e62015-11-13 10:55:30 -080079 clearColorBuffer(repaintRect);
Chris Craikb565df12015-10-05 13:00:52 -070080 }
81}
Chris Craik5854b342015-10-26 15:49:56 -070082
83void BakedOpRenderer::endFrame() {
84 mCaches.pathCache.trim();
85 mCaches.tessellationCache.trim();
Chris Craikb565df12015-10-05 13:00:52 -070086
87#if DEBUG_OPENGL
88 GLUtils::dumpGLErrors();
89#endif
90
91#if DEBUG_MEMORY_USAGE
Chris Craik5854b342015-10-26 15:49:56 -070092 mCaches.dumpMemoryUsage();
Chris Craikb565df12015-10-05 13:00:52 -070093#else
94 if (Properties::debugLevel & kDebugMemory) {
Chris Craik5854b342015-10-26 15:49:56 -070095 mCaches.dumpMemoryUsage();
Chris Craikb565df12015-10-05 13:00:52 -070096 }
97#endif
98}
99
Chris Craik5854b342015-10-26 15:49:56 -0700100void BakedOpRenderer::setViewport(uint32_t width, uint32_t height) {
101 mRenderTarget.viewportWidth = width;
102 mRenderTarget.viewportHeight = height;
103 mRenderTarget.orthoMatrix.loadOrtho(width, height);
104
105 mRenderState.setViewport(width, height);
106 mRenderState.blend().syncEnabled();
107}
108
Chris Craik98787e62015-11-13 10:55:30 -0800109void BakedOpRenderer::clearColorBuffer(const Rect& rect) {
110 if (Rect(mRenderTarget.viewportWidth, mRenderTarget.viewportHeight).contains(rect)) {
111 // Full viewport is being cleared - disable scissor
112 mRenderState.scissor().setEnabled(false);
113 } else {
114 // Requested rect is subset of viewport - scissor to it to avoid over-clearing
115 mRenderState.scissor().setEnabled(true);
116 mRenderState.scissor().set(rect.left, mRenderTarget.viewportHeight - rect.bottom,
117 rect.getWidth(), rect.getHeight());
118 }
119 glClear(GL_COLOR_BUFFER_BIT);
120 if (!mRenderTarget.frameBufferId) mHasDrawn = true;
121}
122
Chris Craik5854b342015-10-26 15:49:56 -0700123Texture* BakedOpRenderer::getTexture(const SkBitmap* bitmap) {
Chris Craik15c3f192015-12-03 12:16:56 -0800124 Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap->pixelRef());
Chris Craik5854b342015-10-26 15:49:56 -0700125 if (!texture) {
126 return mCaches.textureCache.get(bitmap);
127 }
128 return texture;
129}
130
Chris Craike29ce6f2015-12-10 16:25:13 -0800131void BakedOpRenderer::prepareRender(const Rect* dirtyBounds, const Rect* clip) {
Chris Craik15c3f192015-12-03 12:16:56 -0800132 mRenderState.scissor().setEnabled(clip != nullptr);
133 if (clip) {
134 mRenderState.scissor().set(clip->left, mRenderTarget.viewportHeight - clip->bottom,
135 clip->getWidth(), clip->getHeight());
Chris Craik5854b342015-10-26 15:49:56 -0700136 }
Chris Craik15c3f192015-12-03 12:16:56 -0800137 if (dirtyBounds && mRenderTarget.offscreenBuffer) {
Chris Craik8d2cf942015-11-02 14:52:21 -0800138 // register layer damage to draw-back region
Chris Craik15c3f192015-12-03 12:16:56 -0800139 android::Rect dirty(dirtyBounds->left, dirtyBounds->top,
140 dirtyBounds->right, dirtyBounds->bottom);
Chris Craik8d2cf942015-11-02 14:52:21 -0800141 mRenderTarget.offscreenBuffer->region.orSelf(dirty);
142 }
Chris Craike29ce6f2015-12-10 16:25:13 -0800143}
144
145void BakedOpRenderer::renderGlop(const Rect* dirtyBounds, const Rect* clip, const Glop& glop) {
146 prepareRender(dirtyBounds, clip);
Chris Craik5854b342015-10-26 15:49:56 -0700147 mRenderState.render(glop, mRenderTarget.orthoMatrix);
Chris Craik98787e62015-11-13 10:55:30 -0800148 if (!mRenderTarget.frameBufferId) mHasDrawn = true;
Chris Craik5854b342015-10-26 15:49:56 -0700149}
150
Chris Craike29ce6f2015-12-10 16:25:13 -0800151void BakedOpRenderer::renderFunctor(const FunctorOp& op, const BakedOpState& state) {
152 prepareRender(&state.computedState.clippedBounds, &state.computedState.clipRect);
153
154 DrawGlInfo info;
155 auto&& clip = state.computedState.clipRect;
156 info.clipLeft = clip.left;
157 info.clipTop = clip.top;
158 info.clipRight = clip.right;
159 info.clipBottom = clip.bottom;
160 info.isLayer = offscreenRenderTarget();
161 info.width = mRenderTarget.viewportWidth;
162 info.height = mRenderTarget.viewportHeight;
163 state.computedState.transform.copyTo(&info.transform[0]);
164
165 mRenderState.invokeFunctor(op.functor, DrawGlInfo::kModeDraw, &info);
166}
167
Chris Craik15c3f192015-12-03 12:16:56 -0800168void BakedOpRenderer::dirtyRenderTarget(const Rect& uiDirty) {
169 if (mRenderTarget.offscreenBuffer) {
170 android::Rect dirty(uiDirty.left, uiDirty.top, uiDirty.right, uiDirty.bottom);
171 mRenderTarget.offscreenBuffer->region.orSelf(dirty);
172 }
173}
174
Chris Craikb565df12015-10-05 13:00:52 -0700175} // namespace uirenderer
176} // namespace android