BakedOpRenderer.cpp revision a1717271caac5e8ea3808c331d4141ac01a42134
1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/* 2b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Copyright (C) 2015 The Android Open Source Project 3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * you may not use this file except in compliance with the License. 6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * You may obtain a copy of the License at 7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * http://www.apache.org/licenses/LICENSE-2.0 9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Unless required by applicable law or agreed to in writing, software 11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * See the License for the specific language governing permissions and 14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * limitations under the License. 15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "BakedOpRenderer.h" 18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 19b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "Caches.h" 20b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "Glop.h" 21b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "GlopBuilder.h" 229fded232a9548a304e0145011df8849fba0dcda7Chris Craik#include "renderstate/OffscreenBufferPool.h" 23b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "renderstate/RenderState.h" 24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "utils/GLUtils.h" 259fded232a9548a304e0145011df8849fba0dcda7Chris Craik#include "VertexBuffer.h" 26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 27a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik#include <algorithm> 28a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik#include <math.h> 29a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android { 31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer { 32b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 335854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik//////////////////////////////////////////////////////////////////////////////// 345854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik// BakedOpRenderer 355854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik//////////////////////////////////////////////////////////////////////////////// 36818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 37d3daa3198e2212c985c634821682d5819346b653Chris CraikOffscreenBuffer* BakedOpRenderer::startTemporaryLayer(uint32_t width, uint32_t height) { 389fded232a9548a304e0145011df8849fba0dcda7Chris Craik LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer..."); 399fded232a9548a304e0145011df8849fba0dcda7Chris Craik 409fded232a9548a304e0145011df8849fba0dcda7Chris Craik OffscreenBuffer* buffer = mRenderState.layerPool().get(mRenderState, width, height); 4198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik startRepaintLayer(buffer, Rect(width, height)); 420b7e8245db728d127ada698be63d78b33fc6e4daChris Craik return buffer; 430b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 440b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 4598787e6c9b2c10b1ab7820bdac168686025b924aChris Craikvoid BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) { 46d3daa3198e2212c985c634821682d5819346b653Chris Craik LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer..."); 47d3daa3198e2212c985c634821682d5819346b653Chris Craik 480b7e8245db728d127ada698be63d78b33fc6e4daChris Craik mRenderTarget.offscreenBuffer = offscreenBuffer; 49818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 505854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // create and bind framebuffer 515854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderTarget.frameBufferId = mRenderState.genFramebuffer(); 525854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderState.bindFramebuffer(mRenderTarget.frameBufferId); 53818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 54818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // attach the texture to the FBO 55818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 560b7e8245db728d127ada698be63d78b33fc6e4daChris Craik offscreenBuffer->texture.id, 0); 57818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "startLayer FAILED"); 58818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik LOG_ALWAYS_FATAL_IF(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, 59818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik "framebuffer incomplete!"); 60818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 61818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // Change the viewport & ortho projection 620b7e8245db728d127ada698be63d78b33fc6e4daChris Craik setViewport(offscreenBuffer->viewportWidth, offscreenBuffer->viewportHeight); 6398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 6498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik clearColorBuffer(repaintRect); 65818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik} 66818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 675854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikvoid BakedOpRenderer::endLayer() { 688d2cf943d9c7292e54726399faefdec4a01c084bChris Craik mRenderTarget.offscreenBuffer->updateMeshFromRegion(); 695854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderTarget.offscreenBuffer = nullptr; 70818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 71818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // Detach the texture from the FBO 72818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); 73818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "endLayer FAILED"); 745854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderState.deleteFramebuffer(mRenderTarget.frameBufferId); 755854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderTarget.frameBufferId = -1; 76818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik} 77818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 7898787e6c9b2c10b1ab7820bdac168686025b924aChris Craikvoid BakedOpRenderer::startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) { 795854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderState.bindFramebuffer(0); 805854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik setViewport(width, height); 815854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mCaches.clearGarbage(); 82b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 835854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik if (!mOpaque) { 8498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik clearColorBuffer(repaintRect); 85b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 86b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 875854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 885854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikvoid BakedOpRenderer::endFrame() { 895854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mCaches.pathCache.trim(); 905854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mCaches.tessellationCache.trim(); 91b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 92b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#if DEBUG_OPENGL 93b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik GLUtils::dumpGLErrors(); 94b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#endif 95b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 96b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#if DEBUG_MEMORY_USAGE 975854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mCaches.dumpMemoryUsage(); 98b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#else 99b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (Properties::debugLevel & kDebugMemory) { 1005854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mCaches.dumpMemoryUsage(); 101b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 102b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#endif 103b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 104b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1055854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikvoid BakedOpRenderer::setViewport(uint32_t width, uint32_t height) { 1065854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderTarget.viewportWidth = width; 1075854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderTarget.viewportHeight = height; 1085854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderTarget.orthoMatrix.loadOrtho(width, height); 1095854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 1105854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderState.setViewport(width, height); 1115854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderState.blend().syncEnabled(); 1125854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik} 1135854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 11498787e6c9b2c10b1ab7820bdac168686025b924aChris Craikvoid BakedOpRenderer::clearColorBuffer(const Rect& rect) { 11598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik if (Rect(mRenderTarget.viewportWidth, mRenderTarget.viewportHeight).contains(rect)) { 11698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // Full viewport is being cleared - disable scissor 11798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik mRenderState.scissor().setEnabled(false); 11898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } else { 11998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // Requested rect is subset of viewport - scissor to it to avoid over-clearing 12098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik mRenderState.scissor().setEnabled(true); 12198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik mRenderState.scissor().set(rect.left, mRenderTarget.viewportHeight - rect.bottom, 12298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik rect.getWidth(), rect.getHeight()); 12398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 12498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik glClear(GL_COLOR_BUFFER_BIT); 12598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik if (!mRenderTarget.frameBufferId) mHasDrawn = true; 12698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 12798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1285854b34881b1a747ac80b5077869ef270a92b1f4Chris CraikTexture* BakedOpRenderer::getTexture(const SkBitmap* bitmap) { 1295854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap); 1305854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik if (!texture) { 1315854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik return mCaches.textureCache.get(bitmap); 1325854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik } 1335854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik return texture; 1345854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik} 1355854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 1365854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikvoid BakedOpRenderer::renderGlop(const BakedOpState& state, const Glop& glop) { 1375854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik bool useScissor = state.computedState.clipSideFlags != OpClipSideFlags::None; 1385854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderState.scissor().setEnabled(useScissor); 1395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik if (useScissor) { 1405854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik const Rect& clip = state.computedState.clipRect; 1415854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderState.scissor().set(clip.left, mRenderTarget.viewportHeight - clip.bottom, 1425854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik clip.getWidth(), clip.getHeight()); 1435854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik } 1448d2cf943d9c7292e54726399faefdec4a01c084bChris Craik if (mRenderTarget.offscreenBuffer) { // TODO: not with multi-draw 1458d2cf943d9c7292e54726399faefdec4a01c084bChris Craik // register layer damage to draw-back region 1468d2cf943d9c7292e54726399faefdec4a01c084bChris Craik const Rect& uiDirty = state.computedState.clippedBounds; 1478d2cf943d9c7292e54726399faefdec4a01c084bChris Craik android::Rect dirty(uiDirty.left, uiDirty.top, uiDirty.right, uiDirty.bottom); 1488d2cf943d9c7292e54726399faefdec4a01c084bChris Craik mRenderTarget.offscreenBuffer->region.orSelf(dirty); 1498d2cf943d9c7292e54726399faefdec4a01c084bChris Craik } 1505854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mRenderState.render(glop, mRenderTarget.orthoMatrix); 15198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik if (!mRenderTarget.frameBufferId) mHasDrawn = true; 1525854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik} 1535854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 1545854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik//////////////////////////////////////////////////////////////////////////////// 1555854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik// static BakedOpDispatcher methods 1565854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik//////////////////////////////////////////////////////////////////////////////// 1575854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 1585854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikvoid BakedOpDispatcher::onRenderNodeOp(BakedOpRenderer&, const RenderNodeOp&, const BakedOpState&) { 159b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik LOG_ALWAYS_FATAL("unsupported operation"); 160b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 161b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1628d2cf943d9c7292e54726399faefdec4a01c084bChris Craikvoid BakedOpDispatcher::onBeginLayerOp(BakedOpRenderer& renderer, const BeginLayerOp& op, const BakedOpState& state) { 1638d2cf943d9c7292e54726399faefdec4a01c084bChris Craik LOG_ALWAYS_FATAL("unsupported operation"); 1648d2cf943d9c7292e54726399faefdec4a01c084bChris Craik} 1658d2cf943d9c7292e54726399faefdec4a01c084bChris Craik 1668d2cf943d9c7292e54726399faefdec4a01c084bChris Craikvoid BakedOpDispatcher::onEndLayerOp(BakedOpRenderer& renderer, const EndLayerOp& op, const BakedOpState& state) { 1678d2cf943d9c7292e54726399faefdec4a01c084bChris Craik LOG_ALWAYS_FATAL("unsupported operation"); 1688d2cf943d9c7292e54726399faefdec4a01c084bChris Craik} 1698d2cf943d9c7292e54726399faefdec4a01c084bChris Craik 1705854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikvoid BakedOpDispatcher::onBitmapOp(BakedOpRenderer& renderer, const BitmapOp& op, const BakedOpState& state) { 1715854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik renderer.caches().textureState().activateTexture(0); // TODO: should this be automatic, and/or elsewhere? 1725854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik Texture* texture = renderer.getTexture(op.bitmap); 173b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!texture) return; 174b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const AutoTexture autoCleanup(texture); 175b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 176b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const int textureFillFlags = (op.bitmap->colorType() == kAlpha_8_SkColorType) 177b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None; 178b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Glop glop; 1795854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 180b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setRoundRectClipState(state.roundRectClipState) 181b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setMeshTexturedUnitQuad(texture->uvMapper) 182b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha) 183b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setTransform(state.computedState.transform, TransformFlags::None) 184b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height)) 185b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .build(); 1865854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik renderer.renderGlop(state, glop); 187b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 188b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 189a1717271caac5e8ea3808c331d4141ac01a42134Chris Craikvoid BakedOpDispatcher::onLinesOp(BakedOpRenderer& renderer, const LinesOp& op, const BakedOpState& state) { 190a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik LOG_ALWAYS_FATAL("todo"); 191a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik} 192a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 1935854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikvoid BakedOpDispatcher::onRectOp(BakedOpRenderer& renderer, const RectOp& op, const BakedOpState& state) { 194b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Glop glop; 1955854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 196b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setRoundRectClipState(state.roundRectClipState) 197b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setMeshUnitQuad() 198b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setFillPaint(*op.paint, state.alpha) 199b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setTransform(state.computedState.transform, TransformFlags::None) 200b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setModelViewMapUnitToRect(op.unmappedBounds) 201b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .build(); 2025854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik renderer.renderGlop(state, glop); 203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 204b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 205d3daa3198e2212c985c634821682d5819346b653Chris Craiknamespace VertexBufferRenderFlags { 206d3daa3198e2212c985c634821682d5819346b653Chris Craik enum { 207d3daa3198e2212c985c634821682d5819346b653Chris Craik Offset = 0x1, 208d3daa3198e2212c985c634821682d5819346b653Chris Craik ShadowInterp = 0x2, 209d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 210d3daa3198e2212c985c634821682d5819346b653Chris Craik} 211d3daa3198e2212c985c634821682d5819346b653Chris Craik 212d3daa3198e2212c985c634821682d5819346b653Chris Craikstatic void renderVertexBuffer(BakedOpRenderer& renderer, const BakedOpState& state, 213d3daa3198e2212c985c634821682d5819346b653Chris Craik const VertexBuffer& vertexBuffer, float translateX, float translateY, 214d3daa3198e2212c985c634821682d5819346b653Chris Craik SkPaint& paint, int vertexBufferRenderFlags) { 215d3daa3198e2212c985c634821682d5819346b653Chris Craik if (CC_LIKELY(vertexBuffer.getVertexCount())) { 216d3daa3198e2212c985c634821682d5819346b653Chris Craik bool shadowInterp = vertexBufferRenderFlags & VertexBufferRenderFlags::ShadowInterp; 217d3daa3198e2212c985c634821682d5819346b653Chris Craik const int transformFlags = TransformFlags::OffsetByFudgeFactor; 218d3daa3198e2212c985c634821682d5819346b653Chris Craik Glop glop; 219d3daa3198e2212c985c634821682d5819346b653Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 220d3daa3198e2212c985c634821682d5819346b653Chris Craik .setRoundRectClipState(state.roundRectClipState) 221d3daa3198e2212c985c634821682d5819346b653Chris Craik .setMeshVertexBuffer(vertexBuffer, shadowInterp) 222d3daa3198e2212c985c634821682d5819346b653Chris Craik .setFillPaint(paint, state.alpha) 223d3daa3198e2212c985c634821682d5819346b653Chris Craik .setTransform(state.computedState.transform, transformFlags) 224d3daa3198e2212c985c634821682d5819346b653Chris Craik .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds()) 225d3daa3198e2212c985c634821682d5819346b653Chris Craik .build(); 226d3daa3198e2212c985c634821682d5819346b653Chris Craik renderer.renderGlop(state, glop); 227d3daa3198e2212c985c634821682d5819346b653Chris Craik } 228d3daa3198e2212c985c634821682d5819346b653Chris Craik} 229d3daa3198e2212c985c634821682d5819346b653Chris Craik 230d3daa3198e2212c985c634821682d5819346b653Chris Craikstatic void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, float casterAlpha, 231d3daa3198e2212c985c634821682d5819346b653Chris Craik const VertexBuffer* ambientShadowVertexBuffer, const VertexBuffer* spotShadowVertexBuffer) { 232d3daa3198e2212c985c634821682d5819346b653Chris Craik SkPaint paint; 233d3daa3198e2212c985c634821682d5819346b653Chris Craik paint.setAntiAlias(true); // want to use AlphaVertex 234d3daa3198e2212c985c634821682d5819346b653Chris Craik 235d3daa3198e2212c985c634821682d5819346b653Chris Craik // The caller has made sure casterAlpha > 0. 23698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik uint8_t ambientShadowAlpha = renderer.getLightInfo().ambientShadowAlpha; 237d3daa3198e2212c985c634821682d5819346b653Chris Craik if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) { 238d3daa3198e2212c985c634821682d5819346b653Chris Craik ambientShadowAlpha = Properties::overrideAmbientShadowStrength; 239d3daa3198e2212c985c634821682d5819346b653Chris Craik } 240d3daa3198e2212c985c634821682d5819346b653Chris Craik if (ambientShadowVertexBuffer && ambientShadowAlpha > 0) { 241d3daa3198e2212c985c634821682d5819346b653Chris Craik paint.setAlpha((uint8_t)(casterAlpha * ambientShadowAlpha)); 242d3daa3198e2212c985c634821682d5819346b653Chris Craik renderVertexBuffer(renderer, state, *ambientShadowVertexBuffer, 0, 0, 243d3daa3198e2212c985c634821682d5819346b653Chris Craik paint, VertexBufferRenderFlags::ShadowInterp); 244d3daa3198e2212c985c634821682d5819346b653Chris Craik } 245d3daa3198e2212c985c634821682d5819346b653Chris Craik 24698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik uint8_t spotShadowAlpha = renderer.getLightInfo().spotShadowAlpha; 247d3daa3198e2212c985c634821682d5819346b653Chris Craik if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) { 248d3daa3198e2212c985c634821682d5819346b653Chris Craik spotShadowAlpha = Properties::overrideSpotShadowStrength; 249d3daa3198e2212c985c634821682d5819346b653Chris Craik } 250d3daa3198e2212c985c634821682d5819346b653Chris Craik if (spotShadowVertexBuffer && spotShadowAlpha > 0) { 251d3daa3198e2212c985c634821682d5819346b653Chris Craik paint.setAlpha((uint8_t)(casterAlpha * spotShadowAlpha)); 252d3daa3198e2212c985c634821682d5819346b653Chris Craik renderVertexBuffer(renderer, state, *spotShadowVertexBuffer, 0, 0, 253d3daa3198e2212c985c634821682d5819346b653Chris Craik paint, VertexBufferRenderFlags::ShadowInterp); 254d3daa3198e2212c985c634821682d5819346b653Chris Craik } 255d3daa3198e2212c985c634821682d5819346b653Chris Craik} 256d3daa3198e2212c985c634821682d5819346b653Chris Craik 257d3daa3198e2212c985c634821682d5819346b653Chris Craikvoid BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op, const BakedOpState& state) { 258d3daa3198e2212c985c634821682d5819346b653Chris Craik TessellationCache::vertexBuffer_pair_t buffers; 259d3daa3198e2212c985c634821682d5819346b653Chris Craik renderer.caches().tessellationCache.getShadowBuffers(&state.computedState.transform, 260d3daa3198e2212c985c634821682d5819346b653Chris Craik op.localClipRect, op.casterAlpha >= 1.0f, op.casterPath, 26198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik &op.shadowMatrixXY, &op.shadowMatrixZ, 26298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik op.lightCenter, renderer.getLightInfo().lightRadius, 263d3daa3198e2212c985c634821682d5819346b653Chris Craik buffers); 264d3daa3198e2212c985c634821682d5819346b653Chris Craik 265d3daa3198e2212c985c634821682d5819346b653Chris Craik renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second); 266d3daa3198e2212c985c634821682d5819346b653Chris Craik} 267d3daa3198e2212c985c634821682d5819346b653Chris Craik 2685854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikvoid BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleRectsOp& op, const BakedOpState& state) { 269b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Glop glop; 2705854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 271b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setRoundRectClipState(state.roundRectClipState) 272b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setMeshIndexedQuads(&op.vertices[0], op.vertexCount / 4) 273b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setFillPaint(*op.paint, state.alpha) 274b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setTransform(state.computedState.transform, TransformFlags::None) 275b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .setModelViewOffsetRect(0, 0, op.unmappedBounds) 276b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik .build(); 2775854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik renderer.renderGlop(state, glop); 278b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 279b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 280a1717271caac5e8ea3808c331d4141ac01a42134Chris Craikstatic void renderTextShadow(BakedOpRenderer& renderer, FontRenderer& fontRenderer, 281a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const TextOp& op, const BakedOpState& state) { 282a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik renderer.caches().textureState().activateTexture(0); 283a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 284a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik PaintUtils::TextShadow textShadow; 285a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik if (!PaintUtils::getTextShadow(op.paint, &textShadow)) { 286a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik LOG_ALWAYS_FATAL("failed to query shadow attributes"); 287a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 288a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 289a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik renderer.caches().dropShadowCache.setFontRenderer(fontRenderer); 290a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik ShadowTexture* texture = renderer.caches().dropShadowCache.get( 291a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik op.paint, (const char*) op.glyphs, 292a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik op.glyphCount, textShadow.radius, op.positions); 293a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // If the drop shadow exceeds the max texture size or couldn't be 294a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // allocated, skip drawing 295a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik if (!texture) return; 296a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const AutoTexture autoCleanup(texture); 297a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 298a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const float sx = op.x - texture->left + textShadow.dx; 299a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const float sy = op.y - texture->top + textShadow.dy; 300a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 301a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik Glop glop; 302a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 303a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik .setRoundRectClipState(state.roundRectClipState) 304a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik .setMeshTexturedUnitQuad(nullptr) 305a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik .setFillShadowTexturePaint(*texture, textShadow.color, *op.paint, state.alpha) 306a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik .setTransform(state.computedState.transform, TransformFlags::None) 307a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height)) 308a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik .build(); 309a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik renderer.renderGlop(state, glop); 310a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik} 311a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 312a1717271caac5e8ea3808c331d4141ac01a42134Chris Craikvoid BakedOpDispatcher::onTextOp(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& state) { 313a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer(); 314a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 315a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik if (CC_UNLIKELY(PaintUtils::hasTextShadow(op.paint))) { 316a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik fontRenderer.setFont(op.paint, SkMatrix::I()); 317a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik renderTextShadow(renderer, fontRenderer, op, state); 318a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 319a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 320a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik float x = op.x; 321a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik float y = op.y; 322a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const Matrix4& transform = state.computedState.transform; 323a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const bool pureTranslate = transform.isPureTranslate(); 324a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik if (CC_LIKELY(pureTranslate)) { 325a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik x = floorf(x + transform.getTranslateX() + 0.5f); 326a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik y = floorf(y + transform.getTranslateY() + 0.5f); 327a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik fontRenderer.setFont(op.paint, SkMatrix::I()); 328a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik fontRenderer.setTextureFiltering(false); 329a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } else if (CC_UNLIKELY(transform.isPerspective())) { 330a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik fontRenderer.setFont(op.paint, SkMatrix::I()); 331a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik fontRenderer.setTextureFiltering(true); 332a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } else { 333a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // We only pass a partial transform to the font renderer. That partial 334a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // matrix defines how glyphs are rasterized. Typically we want glyphs 335a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // to be rasterized at their final size on screen, which means the partial 336a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // matrix needs to take the scale factor into account. 337a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // When a partial matrix is used to transform glyphs during rasterization, 338a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // the mesh is generated with the inverse transform (in the case of scale, 339a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // the mesh is generated at 1.0 / scale for instance.) This allows us to 340a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // apply the full transform matrix at draw time in the vertex shader. 341a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // Applying the full matrix in the shader is the easiest way to handle 342a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // rotation and perspective and allows us to always generated quads in the 343a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // font renderer which greatly simplifies the code, clipping in particular. 344a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik float sx, sy; 345a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik transform.decomposeScale(sx, sy); 346a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik fontRenderer.setFont(op.paint, SkMatrix::MakeScale( 347a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik roundf(std::max(1.0f, sx)), 348a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik roundf(std::max(1.0f, sy)))); 349a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik fontRenderer.setTextureFiltering(true); 350a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 351a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 352a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik // TODO: Implement better clipping for scaled/rotated text 353a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const Rect* clip = !pureTranslate ? nullptr : &state.computedState.clipRect; 354a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); 355a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 356a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha; 357a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(op.paint); 358a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik TextDrawFunctor functor(&renderer, &state, x, y, pureTranslate, alpha, mode, op.paint); 359a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 360a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik bool hasActiveLayer = false; // TODO 361a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik fontRenderer.renderPosText(op.paint, clip, (const char*) op.glyphs, op.glyphCount, x, y, 362a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik op.positions, hasActiveLayer ? &layerBounds : nullptr, &functor, true); // TODO: merging 363a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik} 364a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 3655854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikvoid BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) { 3665854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik OffscreenBuffer* buffer = *op.layerHandle; 367818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 3685854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // TODO: extend this to handle HW layers & paint properties which 3695854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // reside in node.properties().layerProperties() 3700b7e8245db728d127ada698be63d78b33fc6e4daChris Craik float layerAlpha = op.alpha * state.alpha; 371818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik Glop glop; 3725854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 373818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik .setRoundRectClipState(state.roundRectClipState) 3748d2cf943d9c7292e54726399faefdec4a01c084bChris Craik .setMeshTexturedIndexedVbo(buffer->vbo, buffer->elementCount) 3750b7e8245db728d127ada698be63d78b33fc6e4daChris Craik .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode, Blend::ModeOrderSwap::NoSwap) 376818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik .setTransform(state.computedState.transform, TransformFlags::None) 3778d2cf943d9c7292e54726399faefdec4a01c084bChris Craik .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top, 3788d2cf943d9c7292e54726399faefdec4a01c084bChris Craik Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight())) 379818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik .build(); 3805854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik renderer.renderGlop(state, glop); 3815854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 3820b7e8245db728d127ada698be63d78b33fc6e4daChris Craik if (op.destroy) { 3839fded232a9548a304e0145011df8849fba0dcda7Chris Craik renderer.renderState().layerPool().putOrDelete(buffer); 3840b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } 3856fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 386b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 387b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} // namespace uirenderer 388b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} // namespace android 389