19e7fcfda28fde747ba4e026772007cea77374e16Chris Craik/* 29e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * Copyright (C) 2015 The Android Open Source Project 39e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * 49e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 59e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * you may not use this file except in compliance with the License. 69e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * You may obtain a copy of the License at 79e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * 89e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * http://www.apache.org/licenses/LICENSE-2.0 99e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * 109e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * Unless required by applicable law or agreed to in writing, software 119e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * distributed under the License is distributed on an "AS IS" BASIS, 129e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * See the License for the specific language governing permissions and 149e7fcfda28fde747ba4e026772007cea77374e16Chris Craik * limitations under the License. 159e7fcfda28fde747ba4e026772007cea77374e16Chris Craik */ 169e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 179e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "BakedOpDispatcher.h" 189e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 199e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "BakedOpRenderer.h" 209e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "Caches.h" 213e9999bd866fac71c72e6b484a9836c87c328a08sergeyv#include "DeferredLayerUpdater.h" 229e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "Glop.h" 239e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "GlopBuilder.h" 24f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik#include "Patch.h" 25386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik#include "PathTessellator.h" 261bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include "VertexBuffer.h" 279e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "renderstate/OffscreenBufferPool.h" 289e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "renderstate/RenderState.h" 299e7fcfda28fde747ba4e026772007cea77374e16Chris Craik#include "utils/GLUtils.h" 309e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 31386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik#include <SkPaintDefaults.h> 32678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik#include <SkPathOps.h> 331bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include <math.h> 341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include <algorithm> 359e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 369e7fcfda28fde747ba4e026772007cea77374e16Chris Craiknamespace android { 379e7fcfda28fde747ba4e026772007cea77374e16Chris Craiknamespace uirenderer { 389e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 39253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guystatic void storeTexturedRect(TextureVertex* vertices, const Rect& bounds) { 401bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck vertices[0] = {bounds.left, bounds.top, 0, 0}; 411bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck vertices[1] = {bounds.right, bounds.top, 1, 0}; 421bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck vertices[2] = {bounds.left, bounds.bottom, 0, 1}; 431bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck vertices[3] = {bounds.right, bounds.bottom, 1, 1}; 4415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik} 4515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 4615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craikvoid BakedOpDispatcher::onMergedBitmapOps(BakedOpRenderer& renderer, 471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const MergedBakedOpList& opList) { 4815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const BakedOpState& firstState = *(opList.states[0]); 49ec4a4b13eae2241d1613890c1c1c096bed891845sergeyv Bitmap* bitmap = (static_cast<const BitmapOp*>(opList.states[0]->op))->bitmap; 5015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 51253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy Texture* texture = renderer.caches().textureCache.get(bitmap); 5215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (!texture) return; 5315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const AutoTexture autoCleanup(texture); 5415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 5515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik TextureVertex vertices[opList.count * 4]; 5615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik for (size_t i = 0; i < opList.count; i++) { 5715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const BakedOpState& state = *(opList.states[i]); 5815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik TextureVertex* rectVerts = &vertices[i * 4]; 59f6c20e4b4232e30901676bcdf1aed64801d50c7eChris Craik 60f6c20e4b4232e30901676bcdf1aed64801d50c7eChris Craik // calculate unclipped bounds, since they'll determine texture coordinates 61f6c20e4b4232e30901676bcdf1aed64801d50c7eChris Craik Rect opBounds = state.op->unmappedBounds; 62f6c20e4b4232e30901676bcdf1aed64801d50c7eChris Craik state.computedState.transform.mapRect(opBounds); 6315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (CC_LIKELY(state.computedState.transform.isPureTranslate())) { 6415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // pure translate, so snap (same behavior as onBitmapOp) 6515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik opBounds.snapToPixelBoundaries(); 6615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 67253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy storeTexturedRect(rectVerts, opBounds); 6815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.dirtyRenderTarget(opBounds); 6915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 7015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 7115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType) 721bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck ? TextureFillFlags::IsAlphaMaskTexture 731bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck : TextureFillFlags::None; 7415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Glop glop; 7515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 7615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setRoundRectClipState(firstState.roundRectClipState) 7715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setMeshTexturedIndexedQuads(vertices, opList.count * 6) 7815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setFillTexturePaint(*texture, textureFillFlags, firstState.op->paint, firstState.alpha) 7915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setTransform(Matrix4::identity(), TransformFlags::None) 80f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setModelViewIdentityEmptyBounds() 81f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .build(); 82e4db79de127cfe961195f52907af8451026eaa20Chris Craik ClipRect renderTargetClip(opList.clip); 83e4db79de127cfe961195f52907af8451026eaa20Chris Craik const ClipBase* clip = opList.clipSideFlags ? &renderTargetClip : nullptr; 84e4db79de127cfe961195f52907af8451026eaa20Chris Craik renderer.renderGlop(nullptr, clip, glop); 85f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik} 86f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 87f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craikvoid BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer, 881bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const MergedBakedOpList& opList) { 89f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const PatchOp& firstOp = *(static_cast<const PatchOp*>(opList.states[0]->op)); 90f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const BakedOpState& firstState = *(opList.states[0]); 91f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 92f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // Batches will usually contain a small number of items so it's 93f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // worth performing a first iteration to count the exact number 94f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // of vertices we need in the new mesh 95f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik uint32_t totalVertices = 0; 96f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 97f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik for (size_t i = 0; i < opList.count; i++) { 98f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const PatchOp& op = *(static_cast<const PatchOp*>(opList.states[i]->op)); 99f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 100f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // TODO: cache mesh lookups 101f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const Patch* opMesh = renderer.caches().patchCache.get( 1021bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.bitmap->width(), op.bitmap->height(), op.unmappedBounds.getWidth(), 1031bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.unmappedBounds.getHeight(), op.patch); 104f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik totalVertices += opMesh->verticesCount; 105f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } 106f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 107f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const bool dirtyRenderTarget = renderer.offscreenRenderTarget(); 108f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 109f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik uint32_t indexCount = 0; 110f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 111f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik TextureVertex vertices[totalVertices]; 112f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik TextureVertex* vertex = &vertices[0]; 113f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // Create a mesh that contains the transformed vertices for all the 114f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // 9-patch objects that are part of the batch. Note that onDefer() 115f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // enforces ops drawn by this function to have a pure translate or 116f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // identity matrix 117f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik for (size_t i = 0; i < opList.count; i++) { 118f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const PatchOp& op = *(static_cast<const PatchOp*>(opList.states[i]->op)); 119f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const BakedOpState& state = *opList.states[i]; 120f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 121f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // TODO: cache mesh lookups 122f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const Patch* opMesh = renderer.caches().patchCache.get( 1231bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.bitmap->width(), op.bitmap->height(), op.unmappedBounds.getWidth(), 1241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.unmappedBounds.getHeight(), op.patch); 125f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 126f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik uint32_t vertexCount = opMesh->verticesCount; 127f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik if (vertexCount == 0) continue; 128f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 129f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // We use the bounds to know where to translate our vertices 130f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // Using patchOp->state.mBounds wouldn't work because these 131f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // bounds are clipped 1321bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const float tx = floorf(state.computedState.transform.getTranslateX() + 1331bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.unmappedBounds.left + 0.5f); 1341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const float ty = floorf(state.computedState.transform.getTranslateY() + 1351bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.unmappedBounds.top + 0.5f); 136f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 137f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // Copy & transform all the vertices for the current operation 138f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik TextureVertex* opVertices = opMesh->vertices.get(); 139f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik for (uint32_t j = 0; j < vertexCount; j++, opVertices++) { 1401bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck TextureVertex::set(vertex++, opVertices->x + tx, opVertices->y + ty, opVertices->u, 1411bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck opVertices->v); 142f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } 143f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 144f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // Dirty the current layer if possible. When the 9-patch does not 145f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // contain empty quads we can take a shortcut and simply set the 146f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // dirty rect to the object's bounds. 147f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik if (dirtyRenderTarget) { 148f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik if (!opMesh->hasEmptyQuads) { 1491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck renderer.dirtyRenderTarget(Rect(tx, ty, tx + op.unmappedBounds.getWidth(), 1501bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck ty + op.unmappedBounds.getHeight())); 151f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } else { 152f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const size_t count = opMesh->quads.size(); 153f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik for (size_t i = 0; i < count; i++) { 154f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const Rect& quadBounds = opMesh->quads[i]; 155f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const float x = tx + quadBounds.left; 156f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const float y = ty + quadBounds.top; 1571bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck renderer.dirtyRenderTarget( 1581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck Rect(x, y, x + quadBounds.getWidth(), y + quadBounds.getHeight())); 159f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } 160f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } 161f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } 162f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 163f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik indexCount += opMesh->indexCount; 164f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } 165f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 166253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy Texture* texture = renderer.caches().textureCache.get(firstOp.bitmap); 167f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik if (!texture) return; 168f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const AutoTexture autoCleanup(texture); 169f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 170f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // 9 patches are built for stretching - always filter 171f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik int textureFillFlags = TextureFillFlags::ForceFilter; 172f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik if (firstOp.bitmap->colorType() == kAlpha_8_SkColorType) { 173f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture; 174f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } 175f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik Glop glop; 176f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 177f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setRoundRectClipState(firstState.roundRectClipState) 178f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setMeshTexturedIndexedQuads(vertices, indexCount) 179f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setFillTexturePaint(*texture, textureFillFlags, firstOp.paint, firstState.alpha) 180f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setTransform(Matrix4::identity(), TransformFlags::None) 181f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setModelViewIdentityEmptyBounds() 18215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .build(); 183e4db79de127cfe961195f52907af8451026eaa20Chris Craik ClipRect renderTargetClip(opList.clip); 184e4db79de127cfe961195f52907af8451026eaa20Chris Craik const ClipBase* clip = opList.clipSideFlags ? &renderTargetClip : nullptr; 185e4db79de127cfe961195f52907af8451026eaa20Chris Craik renderer.renderGlop(nullptr, clip, glop); 18615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik} 18715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 1881bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckstatic void renderTextShadow(BakedOpRenderer& renderer, const TextOp& op, 1891bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& textOpState) { 190284b765e3c1647859d4dac772744e8859c033216sergeyv if (CC_LIKELY(!PaintUtils::hasTextShadow(op.paint))) return; 191284b765e3c1647859d4dac772744e8859c033216sergeyv 192284b765e3c1647859d4dac772744e8859c033216sergeyv FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer(); 193284b765e3c1647859d4dac772744e8859c033216sergeyv fontRenderer.setFont(op.paint, SkMatrix::I()); 19415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.caches().textureState().activateTexture(0); 19515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 19615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik PaintUtils::TextShadow textShadow; 19715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (!PaintUtils::getTextShadow(op.paint, &textShadow)) { 19815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik LOG_ALWAYS_FATAL("failed to query shadow attributes"); 19915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 20015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 20115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.caches().dropShadowCache.setFontRenderer(fontRenderer); 20215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ShadowTexture* texture = renderer.caches().dropShadowCache.get( 203e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik op.paint, op.glyphs, op.glyphCount, textShadow.radius, op.positions); 20415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // If the drop shadow exceeds the max texture size or couldn't be 20515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // allocated, skip drawing 20615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (!texture) return; 20715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const AutoTexture autoCleanup(texture); 20815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 20915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const float sx = op.x - texture->left + textShadow.dx; 21015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const float sy = op.y - texture->top + textShadow.dy; 21115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 21215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Glop glop; 21315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 21470969ccde405ea410fc7ccfe869999a03f056686Chris Craik .setRoundRectClipState(textOpState.roundRectClipState) 21515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .setMeshTexturedUnitQuad(nullptr) 21670969ccde405ea410fc7ccfe869999a03f056686Chris Craik .setFillShadowTexturePaint(*texture, textShadow.color, *op.paint, textOpState.alpha) 21770969ccde405ea410fc7ccfe869999a03f056686Chris Craik .setTransform(textOpState.computedState.transform, TransformFlags::None) 21838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width(), sy + texture->height())) 21915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik .build(); 22070969ccde405ea410fc7ccfe869999a03f056686Chris Craik 22170969ccde405ea410fc7ccfe869999a03f056686Chris Craik // Compute damage bounds and clip (since may differ from those in textOpState). 22270969ccde405ea410fc7ccfe869999a03f056686Chris Craik // Bounds should be same as text op, but with dx/dy offset and radius outset 22370969ccde405ea410fc7ccfe869999a03f056686Chris Craik // applied in local space. 22470969ccde405ea410fc7ccfe869999a03f056686Chris Craik auto& transform = textOpState.computedState.transform; 2251bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck Rect shadowBounds = op.unmappedBounds; // STROKE 22670969ccde405ea410fc7ccfe869999a03f056686Chris Craik const bool expandForStroke = op.paint->getStyle() != SkPaint::kFill_Style; 22770969ccde405ea410fc7ccfe869999a03f056686Chris Craik if (expandForStroke) { 22870969ccde405ea410fc7ccfe869999a03f056686Chris Craik shadowBounds.outset(op.paint->getStrokeWidth() * 0.5f); 22970969ccde405ea410fc7ccfe869999a03f056686Chris Craik } 23070969ccde405ea410fc7ccfe869999a03f056686Chris Craik shadowBounds.translate(textShadow.dx, textShadow.dy); 23170969ccde405ea410fc7ccfe869999a03f056686Chris Craik shadowBounds.outset(textShadow.radius, textShadow.radius); 23270969ccde405ea410fc7ccfe869999a03f056686Chris Craik transform.mapRect(shadowBounds); 23370969ccde405ea410fc7ccfe869999a03f056686Chris Craik if (CC_UNLIKELY(expandForStroke && 2341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck (!transform.isPureTranslate() || op.paint->getStrokeWidth() < 1.0f))) { 23570969ccde405ea410fc7ccfe869999a03f056686Chris Craik shadowBounds.outset(0.5f); 23670969ccde405ea410fc7ccfe869999a03f056686Chris Craik } 23770969ccde405ea410fc7ccfe869999a03f056686Chris Craik 23870969ccde405ea410fc7ccfe869999a03f056686Chris Craik auto clipState = textOpState.computedState.clipState; 2391bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck if (clipState->mode != ClipMode::Rectangle || !clipState->rect.contains(shadowBounds)) { 24070969ccde405ea410fc7ccfe869999a03f056686Chris Craik // need clip, so pass it and clip bounds 24170969ccde405ea410fc7ccfe869999a03f056686Chris Craik shadowBounds.doIntersect(clipState->rect); 24270969ccde405ea410fc7ccfe869999a03f056686Chris Craik } else { 24370969ccde405ea410fc7ccfe869999a03f056686Chris Craik // don't need clip, ignore 24470969ccde405ea410fc7ccfe869999a03f056686Chris Craik clipState = nullptr; 24570969ccde405ea410fc7ccfe869999a03f056686Chris Craik } 24670969ccde405ea410fc7ccfe869999a03f056686Chris Craik 24770969ccde405ea410fc7ccfe869999a03f056686Chris Craik renderer.renderGlop(&shadowBounds, clipState, glop); 24815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik} 24915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 2501bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckenum class TextRenderType { Defer, Flush }; 25115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 252284b765e3c1647859d4dac772744e8859c033216sergeyvstatic void renderText(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& state, 2531bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const ClipBase* renderClip, TextRenderType renderType) { 25415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer(); 25515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik float x = op.x; 25615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik float y = op.y; 25715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const Matrix4& transform = state.computedState.transform; 25815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const bool pureTranslate = transform.isPureTranslate(); 25915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (CC_LIKELY(pureTranslate)) { 26015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik x = floorf(x + transform.getTranslateX() + 0.5f); 26115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik y = floorf(y + transform.getTranslateY() + 0.5f); 26215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.setFont(op.paint, SkMatrix::I()); 26315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.setTextureFiltering(false); 26415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } else if (CC_UNLIKELY(transform.isPerspective())) { 26515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.setFont(op.paint, SkMatrix::I()); 26615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.setTextureFiltering(true); 26715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } else { 26815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // We only pass a partial transform to the font renderer. That partial 26915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // matrix defines how glyphs are rasterized. Typically we want glyphs 27015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // to be rasterized at their final size on screen, which means the partial 27115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // matrix needs to take the scale factor into account. 27215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // When a partial matrix is used to transform glyphs during rasterization, 27315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // the mesh is generated with the inverse transform (in the case of scale, 27415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // the mesh is generated at 1.0 / scale for instance.) This allows us to 27515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // apply the full transform matrix at draw time in the vertex shader. 27615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // Applying the full matrix in the shader is the easiest way to handle 27715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // rotation and perspective and allows us to always generated quads in the 27815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // font renderer which greatly simplifies the code, clipping in particular. 27915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik float sx, sy; 28015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik transform.decomposeScale(sx, sy); 2811bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck fontRenderer.setFont(op.paint, SkMatrix::MakeScale(roundf(std::max(1.0f, sx)), 2821bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck roundf(std::max(1.0f, sy)))); 28315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik fontRenderer.setTextureFiltering(true); 28415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 28515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); 28615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 28715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha; 288260ab726486317496bc12a57d599ea96dcde3284Mike Reed SkBlendMode mode = PaintUtils::getBlendModeDirect(op.paint); 2891bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck TextDrawFunctor functor(&renderer, &state, renderClip, x, y, pureTranslate, alpha, mode, 2901bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.paint); 29115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 29215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik bool forceFinish = (renderType == TextRenderType::Flush); 29315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik bool mustDirtyRenderTarget = renderer.offscreenRenderTarget(); 294e4db79de127cfe961195f52907af8451026eaa20Chris Craik const Rect* localOpClip = pureTranslate ? &state.computedState.clipRect() : nullptr; 2951bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck fontRenderer.renderPosText(op.paint, localOpClip, op.glyphs, op.glyphCount, x, y, op.positions, 2961bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck mustDirtyRenderTarget ? &layerBounds : nullptr, &functor, 2971bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck forceFinish); 29815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 29915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (mustDirtyRenderTarget) { 30015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik if (!pureTranslate) { 30115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik transform.mapRect(layerBounds); 30215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 30315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.dirtyRenderTarget(layerBounds); 30415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 30515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik} 30615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 30715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craikvoid BakedOpDispatcher::onMergedTextOps(BakedOpRenderer& renderer, 3081bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const MergedBakedOpList& opList) { 309284b765e3c1647859d4dac772744e8859c033216sergeyv for (size_t i = 0; i < opList.count; i++) { 310284b765e3c1647859d4dac772744e8859c033216sergeyv const BakedOpState& state = *(opList.states[i]); 311284b765e3c1647859d4dac772744e8859c033216sergeyv const TextOp& op = *(static_cast<const TextOp*>(state.op)); 312284b765e3c1647859d4dac772744e8859c033216sergeyv renderTextShadow(renderer, op, state); 313284b765e3c1647859d4dac772744e8859c033216sergeyv } 314284b765e3c1647859d4dac772744e8859c033216sergeyv 315e4db79de127cfe961195f52907af8451026eaa20Chris Craik ClipRect renderTargetClip(opList.clip); 316e4db79de127cfe961195f52907af8451026eaa20Chris Craik const ClipBase* clip = opList.clipSideFlags ? &renderTargetClip : nullptr; 31715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik for (size_t i = 0; i < opList.count; i++) { 31815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const BakedOpState& state = *(opList.states[i]); 31915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const TextOp& op = *(static_cast<const TextOp*>(state.op)); 3201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck TextRenderType renderType = 3211bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck (i + 1 == opList.count) ? TextRenderType::Flush : TextRenderType::Defer; 322284b765e3c1647859d4dac772744e8859c033216sergeyv renderText(renderer, op, state, clip, renderType); 32315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 32415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik} 32515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 326386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craiknamespace VertexBufferRenderFlags { 3271bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckenum { 3281bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck Offset = 0x1, 3291bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck ShadowInterp = 0x2, 3301bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck}; 331386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 332386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 333386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craikstatic void renderVertexBuffer(BakedOpRenderer& renderer, const BakedOpState& state, 3341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const VertexBuffer& vertexBuffer, float translateX, float translateY, 3351bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const SkPaint& paint, int vertexBufferRenderFlags) { 336386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (CC_LIKELY(vertexBuffer.getVertexCount())) { 337386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik bool shadowInterp = vertexBufferRenderFlags & VertexBufferRenderFlags::ShadowInterp; 33892a5d4b99a5554adca0e94627d44d2bd7f4f0bc0sergeyv const int transformFlags = vertexBufferRenderFlags & VertexBufferRenderFlags::Offset 3391bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck ? TransformFlags::OffsetByFudgeFactor 3401bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck : 0; 341138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik 342386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik Glop glop; 343386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 344386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .setRoundRectClipState(state.roundRectClipState) 345138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik .setMeshVertexBuffer(vertexBuffer) 346138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik .setFillPaint(paint, state.alpha, shadowInterp) 347386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .setTransform(state.computedState.transform, transformFlags) 348386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds()) 349386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .build(); 350386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik renderer.renderGlop(state, glop); 351386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 352386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 353386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 354386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craikstatic void renderConvexPath(BakedOpRenderer& renderer, const BakedOpState& state, 3551bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const SkPath& path, const SkPaint& paint) { 356386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik VertexBuffer vertexBuffer; 357386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik // TODO: try clipping large paths to viewport 358386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik PathTessellator::tessellatePath(path, &paint, state.computedState.transform, vertexBuffer); 359386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik renderVertexBuffer(renderer, state, vertexBuffer, 0.0f, 0.0f, paint, 0); 360386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 361386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 3621bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckstatic void renderPathTexture(BakedOpRenderer& renderer, const BakedOpState& state, float xOffset, 3631bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck float yOffset, PathTexture& texture, const SkPaint& paint) { 36438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck Rect dest(texture.width(), texture.height()); 3651bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck dest.translate(xOffset + texture.left - texture.offset, yOffset + texture.top - texture.offset); 366386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik Glop glop; 367386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 368386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .setRoundRectClipState(state.roundRectClipState) 369386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .setMeshTexturedUnitQuad(nullptr) 370e2822e4c799815e6e5633af0f75fe5f221897d87Chris Craik .setFillPathTexturePaint(texture, paint, state.alpha) 3711bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck .setTransform(state.computedState.transform, TransformFlags::None) 372386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .setModelViewMapUnitToRect(dest) 373386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .build(); 374386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik renderer.renderGlop(state, glop); 375386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 376386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 377386aa031793bb037ec43b6cdbd8908c343cc86cbChris CraikSkRect getBoundsOfFill(const RecordedOp& op) { 378386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkRect bounds = op.unmappedBounds.toSkRect(); 379386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (op.paint->getStyle() == SkPaint::kStrokeAndFill_Style) { 380386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik float outsetDistance = op.paint->getStrokeWidth() / 2; 381386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik bounds.outset(outsetDistance, outsetDistance); 382386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 383386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik return bounds; 384386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 385386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 3861bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onArcOp(BakedOpRenderer& renderer, const ArcOp& op, 3871bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 388386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180) 3891bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck if (op.paint->getStyle() != SkPaint::kStroke_Style || op.paint->getPathEffect() != nullptr || 3901bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.useCenter) { 391386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik PathTexture* texture = renderer.caches().pathCache.getArc( 3921bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.startAngle, 3931bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.sweepAngle, op.useCenter, op.paint); 394386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik const AutoTexture holder(texture); 395386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (CC_LIKELY(holder.texture)) { 3960066a01d7ceb9db89fe5edb97e06f62db1c52a74Chris Craik renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top, 3971bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck *texture, *(op.paint)); 398386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 399386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } else { 400386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkRect rect = getBoundsOfFill(op); 401386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkPath path; 402386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (op.useCenter) { 403386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik path.moveTo(rect.centerX(), rect.centerY()); 404386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 405386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik path.arcTo(rect, op.startAngle, op.sweepAngle, !op.useCenter); 406386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (op.useCenter) { 407386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik path.close(); 408386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 409386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik renderConvexPath(renderer, state, path, *(op.paint)); 410386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 411386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 412386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 4131bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onBitmapOp(BakedOpRenderer& renderer, const BitmapOp& op, 4141bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 4159e7fcfda28fde747ba4e026772007cea77374e16Chris Craik Texture* texture = renderer.getTexture(op.bitmap); 4169e7fcfda28fde747ba4e026772007cea77374e16Chris Craik if (!texture) return; 4179e7fcfda28fde747ba4e026772007cea77374e16Chris Craik const AutoTexture autoCleanup(texture); 4189e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 4199e7fcfda28fde747ba4e026772007cea77374e16Chris Craik const int textureFillFlags = (op.bitmap->colorType() == kAlpha_8_SkColorType) 4201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck ? TextureFillFlags::IsAlphaMaskTexture 4211bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck : TextureFillFlags::None; 4229e7fcfda28fde747ba4e026772007cea77374e16Chris Craik Glop glop; 4239e7fcfda28fde747ba4e026772007cea77374e16Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 4249e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setRoundRectClipState(state.roundRectClipState) 4259e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setMeshTexturedUnitQuad(texture->uvMapper) 4269e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha) 4279e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setTransform(state.computedState.transform, TransformFlags::None) 42838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck .setModelViewMapUnitToRectSnap(Rect(texture->width(), texture->height())) 4299e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .build(); 4309e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderer.renderGlop(state, glop); 4319e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 4329e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 4331bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onBitmapMeshOp(BakedOpRenderer& renderer, const BitmapMeshOp& op, 4341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 435253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy Texture* texture = renderer.caches().textureCache.get(op.bitmap); 436253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy if (!texture) { 437253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy return; 438253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy } 439253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy const AutoTexture autoCleanup(texture); 440253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy 441f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const uint32_t elementCount = op.meshWidth * op.meshHeight * 6; 442f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 443f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik std::unique_ptr<ColorTextureVertex[]> mesh(new ColorTextureVertex[elementCount]); 444f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik ColorTextureVertex* vertex = &mesh[0]; 445f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 446f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const int* colors = op.colors; 447f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik std::unique_ptr<int[]> tempColors; 448f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik if (!colors) { 449f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik uint32_t colorsCount = (op.meshWidth + 1) * (op.meshHeight + 1); 450f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik tempColors.reset(new int[colorsCount]); 451f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik memset(tempColors.get(), 0xff, colorsCount * sizeof(int)); 452f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik colors = tempColors.get(); 453f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } 454f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 455f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik for (int32_t y = 0; y < op.meshHeight; y++) { 456f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik for (int32_t x = 0; x < op.meshWidth; x++) { 457f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik uint32_t i = (y * (op.meshWidth + 1) + x) * 2; 458f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 459f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik float u1 = float(x) / op.meshWidth; 460f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik float u2 = float(x + 1) / op.meshWidth; 461f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik float v1 = float(y) / op.meshHeight; 462f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik float v2 = float(y + 1) / op.meshHeight; 463f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 464f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik int ax = i + (op.meshWidth + 1) * 2; 465f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik int ay = ax + 1; 466f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik int bx = i; 467f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik int by = bx + 1; 468f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik int cx = i + 2; 469f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik int cy = cx + 1; 470f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik int dx = i + (op.meshWidth + 1) * 2 + 2; 471f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik int dy = dx + 1; 472f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 473f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const float* vertices = op.vertices; 474f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]); 475f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik ColorTextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2, colors[ax / 2]); 476f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]); 477f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 478f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]); 479f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]); 480f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik ColorTextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1, colors[cx / 2]); 481f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } 482f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } 483f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 484f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik /* 485f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik * TODO: handle alpha_8 textures correctly by applying paint color, but *not* 486f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik * shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh. 487f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik */ 488f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const int textureFillFlags = TextureFillFlags::None; 489f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik Glop glop; 490f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 491f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setRoundRectClipState(state.roundRectClipState) 492f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setMeshColoredTexturedMesh(mesh.get(), elementCount) 493f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha) 4941bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck .setTransform(state.computedState.transform, TransformFlags::None) 495f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setModelViewOffsetRect(0, 0, op.unmappedBounds) 496f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .build(); 497f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik renderer.renderGlop(state, glop); 498f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik} 499f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 5001bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onBitmapRectOp(BakedOpRenderer& renderer, const BitmapRectOp& op, 5011bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 502f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik Texture* texture = renderer.getTexture(op.bitmap); 503f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik if (!texture) return; 504f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const AutoTexture autoCleanup(texture); 505f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 50638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck Rect uv(std::max(0.0f, op.src.left / texture->width()), 50738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck std::max(0.0f, op.src.top / texture->height()), 50838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck std::min(1.0f, op.src.right / texture->width()), 50938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck std::min(1.0f, op.src.bottom / texture->height())); 510f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 511f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik const int textureFillFlags = (op.bitmap->colorType() == kAlpha_8_SkColorType) 5121bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck ? TextureFillFlags::IsAlphaMaskTexture 5131bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck : TextureFillFlags::None; 5141bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const bool tryToSnap = MathUtils::areEqual(op.src.getWidth(), op.unmappedBounds.getWidth()) && 5151bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck MathUtils::areEqual(op.src.getHeight(), op.unmappedBounds.getHeight()); 516f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik Glop glop; 517f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 518f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setRoundRectClipState(state.roundRectClipState) 519f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setMeshTexturedUvQuad(texture->uvMapper, uv) 520f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha) 521f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setTransform(state.computedState.transform, TransformFlags::None) 522f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .setModelViewMapUnitToRectOptionalSnap(tryToSnap, op.unmappedBounds) 523f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik .build(); 524f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik renderer.renderGlop(state, glop); 525f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik} 526f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 5271bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onColorOp(BakedOpRenderer& renderer, const ColorOp& op, 5281bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 529a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik SkPaint paint; 530a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik paint.setColor(op.color); 531260ab726486317496bc12a57d599ea96dcde3284Mike Reed paint.setBlendMode(op.mode); 532a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 533a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik Glop glop; 534a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 535a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik .setRoundRectClipState(state.roundRectClipState) 536a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik .setMeshUnitQuad() 537a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik .setFillPaint(paint, state.alpha) 538a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik .setTransform(Matrix4::identity(), TransformFlags::None) 539a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik .setModelViewMapUnitToRect(state.computedState.clipState->rect) 540a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik .build(); 541a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik renderer.renderGlop(state, glop); 542a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik} 543a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 5441bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onFunctorOp(BakedOpRenderer& renderer, const FunctorOp& op, 5451bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 546e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik renderer.renderFunctor(op, state); 547e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik} 548e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik 5491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onLinesOp(BakedOpRenderer& renderer, const LinesOp& op, 5501bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 551386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik VertexBuffer buffer; 552386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik PathTessellator::tessellateLines(op.points, op.floatCount, op.paint, 5531bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck state.computedState.transform, buffer); 554386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik int displayFlags = op.paint->isAntiAlias() ? 0 : VertexBufferRenderFlags::Offset; 555386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik renderVertexBuffer(renderer, state, buffer, 0, 0, *(op.paint), displayFlags); 5569e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 5579e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 5581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onOvalOp(BakedOpRenderer& renderer, const OvalOp& op, 5591bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 560386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (op.paint->getPathEffect() != nullptr) { 561386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik PathTexture* texture = renderer.caches().pathCache.getOval( 562386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.paint); 563386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik const AutoTexture holder(texture); 564386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (CC_LIKELY(holder.texture)) { 565e98a046d3110eb2ff11a17f4ff27764b803a1379Chris Craik renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top, 5661bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck *texture, *(op.paint)); 567386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 568386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } else { 569386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkPath path; 570386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkRect rect = getBoundsOfFill(op); 571386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik path.addOval(rect); 572678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 573678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik if (state.computedState.localProjectionPathMask != nullptr) { 574678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Mask the ripple path by the local space projection mask in local space. 575678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Note that this can create CCW paths. 576678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Op(path, *state.computedState.localProjectionPathMask, kIntersect_SkPathOp, &path); 577678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 578386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik renderConvexPath(renderer, state, path, *(op.paint)); 579386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 5809e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 5819e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 5821bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onPatchOp(BakedOpRenderer& renderer, const PatchOp& op, 5831bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 584f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // 9 patches are built for stretching - always filter 585f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik int textureFillFlags = TextureFillFlags::ForceFilter; 586f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik if (op.bitmap->colorType() == kAlpha_8_SkColorType) { 587f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture; 588f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik } 589f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 590f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik // TODO: avoid redoing the below work each frame: 5911bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const Patch* mesh = renderer.caches().patchCache.get(op.bitmap->width(), op.bitmap->height(), 5921bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.unmappedBounds.getWidth(), 5931bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.unmappedBounds.getHeight(), op.patch); 594f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 595253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy Texture* texture = renderer.caches().textureCache.get(op.bitmap); 59689ceb5c97745c6901620c20eb0828a5c2f768f4fChris Craik if (CC_LIKELY(texture)) { 59789ceb5c97745c6901620c20eb0828a5c2f768f4fChris Craik const AutoTexture autoCleanup(texture); 59889ceb5c97745c6901620c20eb0828a5c2f768f4fChris Craik Glop glop; 59989ceb5c97745c6901620c20eb0828a5c2f768f4fChris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 60089ceb5c97745c6901620c20eb0828a5c2f768f4fChris Craik .setRoundRectClipState(state.roundRectClipState) 60189ceb5c97745c6901620c20eb0828a5c2f768f4fChris Craik .setMeshPatchQuads(*mesh) 60289ceb5c97745c6901620c20eb0828a5c2f768f4fChris Craik .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha) 60389ceb5c97745c6901620c20eb0828a5c2f768f4fChris Craik .setTransform(state.computedState.transform, TransformFlags::None) 6041bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck .setModelViewOffsetRectSnap( 6051bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.unmappedBounds.left, op.unmappedBounds.top, 60689ceb5c97745c6901620c20eb0828a5c2f768f4fChris Craik Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight())) 60789ceb5c97745c6901620c20eb0828a5c2f768f4fChris Craik .build(); 60889ceb5c97745c6901620c20eb0828a5c2f768f4fChris Craik renderer.renderGlop(state, glop); 60989ceb5c97745c6901620c20eb0828a5c2f768f4fChris Craik } 610f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik} 611f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik 6121bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onPathOp(BakedOpRenderer& renderer, const PathOp& op, 6131bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 614386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik PathTexture* texture = renderer.caches().pathCache.get(op.path, op.paint); 615386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik const AutoTexture holder(texture); 616386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (CC_LIKELY(holder.texture)) { 617e2822e4c799815e6e5633af0f75fe5f221897d87Chris Craik // Unlike other callers to renderPathTexture, no offsets are used because PathOp doesn't 618e2822e4c799815e6e5633af0f75fe5f221897d87Chris Craik // have any translate built in, other than what's in the SkPath itself 619e2822e4c799815e6e5633af0f75fe5f221897d87Chris Craik renderPathTexture(renderer, state, 0, 0, *texture, *(op.paint)); 620386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 6219e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 6229e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 6231bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onPointsOp(BakedOpRenderer& renderer, const PointsOp& op, 6241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 625386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik VertexBuffer buffer; 626386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik PathTessellator::tessellatePoints(op.points, op.floatCount, op.paint, 6271bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck state.computedState.transform, buffer); 628386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik int displayFlags = op.paint->isAntiAlias() ? 0 : VertexBufferRenderFlags::Offset; 629386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik renderVertexBuffer(renderer, state, buffer, 0, 0, *(op.paint), displayFlags); 630386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 631386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 632386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik// See SkPaintDefaults.h 633386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik#define SkPaintDefaults_MiterLimit SkIntToScalar(4) 634386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 6351bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onRectOp(BakedOpRenderer& renderer, const RectOp& op, 6361bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 637386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (op.paint->getStyle() != SkPaint::kFill_Style) { 638386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik // only fill + default miter is supported by drawConvexPath, since others must handle joins 639386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik static_assert(SkPaintDefaults_MiterLimit == 4.0f, "Miter limit has changed"); 6401bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck if (CC_UNLIKELY(op.paint->getPathEffect() != nullptr || 6411bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.paint->getStrokeJoin() != SkPaint::kMiter_Join || 6421bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.paint->getStrokeMiter() != SkPaintDefaults_MiterLimit)) { 6431bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck PathTexture* texture = renderer.caches().pathCache.getRect( 6441bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.paint); 6451bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const AutoTexture holder(texture); 6461bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck if (CC_LIKELY(holder.texture)) { 6471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top, 6481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck *texture, *(op.paint)); 6491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck } 650386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } else { 651386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkPath path; 652386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik path.addRect(getBoundsOfFill(op)); 653386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik renderConvexPath(renderer, state, path, *(op.paint)); 654386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 655386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } else { 656386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (op.paint->isAntiAlias() && !state.computedState.transform.isSimple()) { 657386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkPath path; 658386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik path.addRect(op.unmappedBounds.toSkRect()); 659386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik renderConvexPath(renderer, state, path, *(op.paint)); 660386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } else { 661386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik // render simple unit quad, no tessellation required 662386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik Glop glop; 663386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 664386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .setRoundRectClipState(state.roundRectClipState) 665386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .setMeshUnitQuad() 666386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .setFillPaint(*op.paint, state.alpha) 667386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .setTransform(state.computedState.transform, TransformFlags::None) 668386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .setModelViewMapUnitToRect(op.unmappedBounds) 669386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik .build(); 670386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik renderer.renderGlop(state, glop); 671386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 672386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 673386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 674386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 6751bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onRoundRectOp(BakedOpRenderer& renderer, const RoundRectOp& op, 6761bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 677386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (op.paint->getPathEffect() != nullptr) { 678386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik PathTexture* texture = renderer.caches().pathCache.getRoundRect( 6791bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.rx, op.ry, 6801bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.paint); 681386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik const AutoTexture holder(texture); 682386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (CC_LIKELY(holder.texture)) { 683e2822e4c799815e6e5633af0f75fe5f221897d87Chris Craik renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top, 6841bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck *texture, *(op.paint)); 685386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 686386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } else { 687386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik const VertexBuffer* buffer = renderer.caches().tessellationCache.getRoundRect( 6881bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck state.computedState.transform, *(op.paint), op.unmappedBounds.getWidth(), 6891bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.unmappedBounds.getHeight(), op.rx, op.ry); 6901bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck renderVertexBuffer(renderer, state, *buffer, op.unmappedBounds.left, op.unmappedBounds.top, 6911bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck *(op.paint), 0); 6929e7fcfda28fde747ba4e026772007cea77374e16Chris Craik } 6939e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 6949e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 6959e7fcfda28fde747ba4e026772007cea77374e16Chris Craikstatic void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, float casterAlpha, 6961bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const VertexBuffer* ambientShadowVertexBuffer, 6971bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const VertexBuffer* spotShadowVertexBuffer) { 6989e7fcfda28fde747ba4e026772007cea77374e16Chris Craik SkPaint paint; 6991bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck paint.setAntiAlias(true); // want to use AlphaVertex 7009e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 7019e7fcfda28fde747ba4e026772007cea77374e16Chris Craik // The caller has made sure casterAlpha > 0. 7029e7fcfda28fde747ba4e026772007cea77374e16Chris Craik uint8_t ambientShadowAlpha = renderer.getLightInfo().ambientShadowAlpha; 7039e7fcfda28fde747ba4e026772007cea77374e16Chris Craik if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) { 7049e7fcfda28fde747ba4e026772007cea77374e16Chris Craik ambientShadowAlpha = Properties::overrideAmbientShadowStrength; 7059e7fcfda28fde747ba4e026772007cea77374e16Chris Craik } 7069e7fcfda28fde747ba4e026772007cea77374e16Chris Craik if (ambientShadowVertexBuffer && ambientShadowAlpha > 0) { 7079e7fcfda28fde747ba4e026772007cea77374e16Chris Craik paint.setAlpha((uint8_t)(casterAlpha * ambientShadowAlpha)); 7081bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck renderVertexBuffer(renderer, state, *ambientShadowVertexBuffer, 0, 0, paint, 7091bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck VertexBufferRenderFlags::ShadowInterp); 7109e7fcfda28fde747ba4e026772007cea77374e16Chris Craik } 7119e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 7129e7fcfda28fde747ba4e026772007cea77374e16Chris Craik uint8_t spotShadowAlpha = renderer.getLightInfo().spotShadowAlpha; 7139e7fcfda28fde747ba4e026772007cea77374e16Chris Craik if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) { 7149e7fcfda28fde747ba4e026772007cea77374e16Chris Craik spotShadowAlpha = Properties::overrideSpotShadowStrength; 7159e7fcfda28fde747ba4e026772007cea77374e16Chris Craik } 7169e7fcfda28fde747ba4e026772007cea77374e16Chris Craik if (spotShadowVertexBuffer && spotShadowAlpha > 0) { 7179e7fcfda28fde747ba4e026772007cea77374e16Chris Craik paint.setAlpha((uint8_t)(casterAlpha * spotShadowAlpha)); 7181bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck renderVertexBuffer(renderer, state, *spotShadowVertexBuffer, 0, 0, paint, 7191bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck VertexBufferRenderFlags::ShadowInterp); 7209e7fcfda28fde747ba4e026772007cea77374e16Chris Craik } 7219e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 7229e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 7231bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op, 7241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 725d8165e863b37d82c937ad960dc970f2d2cf72c2aChris Craik TessellationCache::vertexBuffer_pair_t buffers = op.shadowTask->getResult(); 7269e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second); 7279e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 7289e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 7291bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleRectsOp& op, 7301bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 7319e7fcfda28fde747ba4e026772007cea77374e16Chris Craik Glop glop; 7329e7fcfda28fde747ba4e026772007cea77374e16Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 7339e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setRoundRectClipState(state.roundRectClipState) 7349e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setMeshIndexedQuads(&op.vertices[0], op.vertexCount / 4) 7359e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setFillPaint(*op.paint, state.alpha) 7369e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setTransform(state.computedState.transform, TransformFlags::None) 7379e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .setModelViewOffsetRect(0, 0, op.unmappedBounds) 7389e7fcfda28fde747ba4e026772007cea77374e16Chris Craik .build(); 7399e7fcfda28fde747ba4e026772007cea77374e16Chris Craik renderer.renderGlop(state, glop); 7409e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 7419e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 7421bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onTextOp(BakedOpRenderer& renderer, const TextOp& op, 7431bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 744284b765e3c1647859d4dac772744e8859c033216sergeyv renderTextShadow(renderer, op, state); 745284b765e3c1647859d4dac772744e8859c033216sergeyv renderText(renderer, op, state, state.computedState.getClipIfNeeded(), TextRenderType::Flush); 7469e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 7479e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 7481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPathOp& op, 7491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 750d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik // Note: can't trust clipSideFlags since we record with unmappedBounds == clip. 751d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik // TODO: respect clipSideFlags, once we record with bounds 752e4db79de127cfe961195f52907af8451026eaa20Chris Craik auto renderTargetClip = state.computedState.clipState; 753d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 754d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer(); 755d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik fontRenderer.setFont(op.paint, SkMatrix::I()); 756d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik fontRenderer.setTextureFiltering(true); 757d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 758d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); 759d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 760d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha; 761260ab726486317496bc12a57d599ea96dcde3284Mike Reed SkBlendMode mode = PaintUtils::getBlendModeDirect(op.paint); 7621bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck TextDrawFunctor functor(&renderer, &state, renderTargetClip, 0.0f, 0.0f, false, alpha, mode, 7631bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.paint); 764d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 765d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik bool mustDirtyRenderTarget = renderer.offscreenRenderTarget(); 766d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik const Rect localSpaceClip = state.computedState.computeLocalSpaceClip(); 7671bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck if (fontRenderer.renderTextOnPath(op.paint, &localSpaceClip, op.glyphs, op.glyphCount, op.path, 7681bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.hOffset, op.vOffset, 7691bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck mustDirtyRenderTarget ? &layerBounds : nullptr, &functor)) { 770d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik if (mustDirtyRenderTarget) { 771d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik // manually dirty render target, since TextDrawFunctor won't 772d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik state.computedState.transform.mapRect(layerBounds); 773d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik renderer.dirtyRenderTarget(layerBounds); 774d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik } 775d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik } 776d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik} 777d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 7781bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onTextureLayerOp(BakedOpRenderer& renderer, const TextureLayerOp& op, 7791bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 7803e9999bd866fac71c72e6b484a9836c87c328a08sergeyv GlLayer* layer = static_cast<GlLayer*>(op.layerHandle->backingLayer()); 7813e9999bd866fac71c72e6b484a9836c87c328a08sergeyv if (!layer) { 7823e9999bd866fac71c72e6b484a9836c87c328a08sergeyv return; 7833e9999bd866fac71c72e6b484a9836c87c328a08sergeyv } 7843e9999bd866fac71c72e6b484a9836c87c328a08sergeyv const bool tryToSnap = layer->getForceFilter(); 7853e9999bd866fac71c72e6b484a9836c87c328a08sergeyv float alpha = (layer->getAlpha() / 255.0f) * state.alpha; 786d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik Glop glop; 787d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 788d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik .setRoundRectClipState(state.roundRectClipState) 7891bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO 7903e9999bd866fac71c72e6b484a9836c87c328a08sergeyv .setFillTextureLayer(*(layer), alpha) 791d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik .setTransform(state.computedState.transform, TransformFlags::None) 7921bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck .setModelViewMapUnitToRectOptionalSnap(tryToSnap, 7931bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck Rect(layer->getWidth(), layer->getHeight())) 794d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik .build(); 795d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik renderer.renderGlop(state, glop); 796d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik} 797d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 79837413289478a965336239c731ebfea37ac4dde28Chris Craikvoid renderRectForLayer(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state, 7991bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck int color, SkBlendMode mode, SkColorFilter* colorFilter) { 80037413289478a965336239c731ebfea37ac4dde28Chris Craik SkPaint paint; 80137413289478a965336239c731ebfea37ac4dde28Chris Craik paint.setColor(color); 802260ab726486317496bc12a57d599ea96dcde3284Mike Reed paint.setBlendMode(mode); 803260ab726486317496bc12a57d599ea96dcde3284Mike Reed paint.setColorFilter(sk_ref_sp(colorFilter)); 80437413289478a965336239c731ebfea37ac4dde28Chris Craik RectOp rectOp(op.unmappedBounds, op.localMatrix, op.localClip, &paint); 80537413289478a965336239c731ebfea37ac4dde28Chris Craik BakedOpDispatcher::onRectOp(renderer, rectOp, state); 80637413289478a965336239c731ebfea37ac4dde28Chris Craik} 80737413289478a965336239c731ebfea37ac4dde28Chris Craik 8081bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, 8091bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 810c0f3f2f8c0c2fa97099e5f3c5e3860653ce0f261Chris Craik // Note that we don't use op->paint in this function - it's never set on a LayerOp 8119e7fcfda28fde747ba4e026772007cea77374e16Chris Craik OffscreenBuffer* buffer = *op.layerHandle; 8129e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 813aebbbef5658fea13b06586d39adca351135d9edbsergeyv if (CC_UNLIKELY(!buffer)) return; 814aebbbef5658fea13b06586d39adca351135d9edbsergeyv 815aebbbef5658fea13b06586d39adca351135d9edbsergeyv float layerAlpha = op.alpha * state.alpha; 816aebbbef5658fea13b06586d39adca351135d9edbsergeyv Glop glop; 817aebbbef5658fea13b06586d39adca351135d9edbsergeyv GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 818aebbbef5658fea13b06586d39adca351135d9edbsergeyv .setRoundRectClipState(state.roundRectClipState) 819aebbbef5658fea13b06586d39adca351135d9edbsergeyv .setMeshTexturedIndexedVbo(buffer->vbo, buffer->elementCount) 8201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode, 8211bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck Blend::ModeOrderSwap::NoSwap) 822aebbbef5658fea13b06586d39adca351135d9edbsergeyv .setTransform(state.computedState.transform, TransformFlags::None) 8231bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck .setModelViewOffsetRectSnap( 8241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck op.unmappedBounds.left, op.unmappedBounds.top, 825aebbbef5658fea13b06586d39adca351135d9edbsergeyv Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight())) 826aebbbef5658fea13b06586d39adca351135d9edbsergeyv .build(); 827aebbbef5658fea13b06586d39adca351135d9edbsergeyv renderer.renderGlop(state, glop); 82837413289478a965336239c731ebfea37ac4dde28Chris Craik 829aebbbef5658fea13b06586d39adca351135d9edbsergeyv if (!buffer->hasRenderedSinceRepaint) { 83037413289478a965336239c731ebfea37ac4dde28Chris Craik buffer->hasRenderedSinceRepaint = true; 83137413289478a965336239c731ebfea37ac4dde28Chris Craik if (CC_UNLIKELY(Properties::debugLayersUpdates)) { 83237413289478a965336239c731ebfea37ac4dde28Chris Craik // render debug layer highlight 8331bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck renderRectForLayer(renderer, op, state, 0x7f00ff00, SkBlendMode::kSrcOver, nullptr); 83437413289478a965336239c731ebfea37ac4dde28Chris Craik } else if (CC_UNLIKELY(Properties::debugOverdraw)) { 83537413289478a965336239c731ebfea37ac4dde28Chris Craik // render transparent to increment overdraw for repaint area 8361bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck renderRectForLayer(renderer, op, state, SK_ColorTRANSPARENT, SkBlendMode::kSrcOver, 8371bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck nullptr); 83837413289478a965336239c731ebfea37ac4dde28Chris Craik } 83937413289478a965336239c731ebfea37ac4dde28Chris Craik } 8409e7fcfda28fde747ba4e026772007cea77374e16Chris Craik} 8419e7fcfda28fde747ba4e026772007cea77374e16Chris Craik 8421bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onCopyToLayerOp(BakedOpRenderer& renderer, const CopyToLayerOp& op, 8431bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 8447435eb148e72382126e9073183e881357bb38a8bChris Craik LOG_ALWAYS_FATAL_IF(*(op.layerHandle) != nullptr, "layer already exists!"); 8457435eb148e72382126e9073183e881357bb38a8bChris Craik *(op.layerHandle) = renderer.copyToLayer(state.computedState.clippedBounds); 8467435eb148e72382126e9073183e881357bb38a8bChris Craik LOG_ALWAYS_FATAL_IF(*op.layerHandle == nullptr, "layer copy failed"); 847b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 848b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 8491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckvoid BakedOpDispatcher::onCopyFromLayerOp(BakedOpRenderer& renderer, const CopyFromLayerOp& op, 8501bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const BakedOpState& state) { 8517435eb148e72382126e9073183e881357bb38a8bChris Craik LOG_ALWAYS_FATAL_IF(*op.layerHandle == nullptr, "no layer to draw underneath!"); 8527435eb148e72382126e9073183e881357bb38a8bChris Craik if (!state.computedState.clippedBounds.isEmpty()) { 8537435eb148e72382126e9073183e881357bb38a8bChris Craik if (op.paint && op.paint->getAlpha() < 255) { 8547435eb148e72382126e9073183e881357bb38a8bChris Craik SkPaint layerPaint; 8557435eb148e72382126e9073183e881357bb38a8bChris Craik layerPaint.setAlpha(op.paint->getAlpha()); 856260ab726486317496bc12a57d599ea96dcde3284Mike Reed layerPaint.setBlendMode(SkBlendMode::kDstIn); 857260ab726486317496bc12a57d599ea96dcde3284Mike Reed layerPaint.setColorFilter(sk_ref_sp(op.paint->getColorFilter())); 8581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck RectOp rectOp(state.computedState.clippedBounds, Matrix4::identity(), nullptr, 8591bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck &layerPaint); 8607435eb148e72382126e9073183e881357bb38a8bChris Craik BakedOpDispatcher::onRectOp(renderer, rectOp, state); 8617435eb148e72382126e9073183e881357bb38a8bChris Craik } 8627435eb148e72382126e9073183e881357bb38a8bChris Craik 8637435eb148e72382126e9073183e881357bb38a8bChris Craik OffscreenBuffer& layer = **(op.layerHandle); 864260ab726486317496bc12a57d599ea96dcde3284Mike Reed auto mode = PaintUtils::getBlendModeDirect(op.paint); 8657435eb148e72382126e9073183e881357bb38a8bChris Craik Glop glop; 8667435eb148e72382126e9073183e881357bb38a8bChris Craik GlopBuilder(renderer.renderState(), renderer.caches(), &glop) 8677435eb148e72382126e9073183e881357bb38a8bChris Craik .setRoundRectClipState(state.roundRectClipState) 8687435eb148e72382126e9073183e881357bb38a8bChris Craik .setMeshTexturedUvQuad(nullptr, layer.getTextureCoordinates()) 8697435eb148e72382126e9073183e881357bb38a8bChris Craik .setFillLayer(layer.texture, nullptr, 1.0f, mode, Blend::ModeOrderSwap::Swap) 8707435eb148e72382126e9073183e881357bb38a8bChris Craik .setTransform(state.computedState.transform, TransformFlags::None) 8717435eb148e72382126e9073183e881357bb38a8bChris Craik .setModelViewMapUnitToRect(state.computedState.clippedBounds) 8727435eb148e72382126e9073183e881357bb38a8bChris Craik .build(); 8737435eb148e72382126e9073183e881357bb38a8bChris Craik renderer.renderGlop(state, glop); 8747435eb148e72382126e9073183e881357bb38a8bChris Craik } 8757db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck renderer.renderState().layerPool().putOrDelete(*op.layerHandle); 876b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 877b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 8781bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck} // namespace uirenderer 8791bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck} // namespace android 880