1031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik/*
2031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik * Copyright (C) 2015 The Android Open Source Project
3031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik *
4031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik * Licensed under the Apache License, Version 2.0 (the "License");
5031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik * you may not use this file except in compliance with the License.
6031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik * You may obtain a copy of the License at
7031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik *
8031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik *      http://www.apache.org/licenses/LICENSE-2.0
9031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik *
10031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik * Unless required by applicable law or agreed to in writing, software
11031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik * distributed under the License is distributed on an "AS IS" BASIS,
12031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik * See the License for the specific language governing permissions and
14031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik * limitations under the License.
15031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik */
16031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik#include "GlopBuilder.h"
17031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik
18031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik#include "Caches.h"
198cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel#include "GlLayer.h"
20031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik#include "Glop.h"
215e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik#include "Layer.h"
22031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik#include "Matrix.h"
230556d90253902ae797e4fcea79602a30ff16f82cChris Craik#include "Patch.h"
245e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik#include "PathCache.h"
25031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik#include "renderstate/MeshState.h"
26031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik#include "renderstate/RenderState.h"
27117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik#include "SkiaShader.h"
28117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik#include "Texture.h"
29031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik#include "utils/PaintUtils.h"
30117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik#include "VertexBuffer.h"
31031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik
32031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik#include <GLES2/gl2.h>
33031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik#include <SkPaint.h>
34031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik
35b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik#define DEBUG_GLOP_BUILDER 0
36b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik
37b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik#if DEBUG_GLOP_BUILDER
38031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik
39117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik#define TRIGGER_STAGE(stageFlag) \
4014100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik    LOG_ALWAYS_FATAL_IF((stageFlag) & mStageFlags, "Stage %d cannot be run twice", (stageFlag)); \
410519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mStageFlags = static_cast<StageFlags>(mStageFlags | (stageFlag))
42117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik
4308fa43fdeb646f56edcd8b33d06ee7d79b203426Chris Craik#define REQUIRE_STAGES(requiredFlags) \
440519c810a56bded1284fcb2ae40f438878c6585fChris Craik    LOG_ALWAYS_FATAL_IF((mStageFlags & (requiredFlags)) != (requiredFlags), \
4508fa43fdeb646f56edcd8b33d06ee7d79b203426Chris Craik            "not prepared for current stage")
4608fa43fdeb646f56edcd8b33d06ee7d79b203426Chris Craik
47b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik#else
48b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik
49b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik#define TRIGGER_STAGE(stageFlag) ((void)0)
50b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik#define REQUIRE_STAGES(requiredFlags) ((void)0)
51b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik
52b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik#endif
53b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik
54b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craiknamespace android {
55b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craiknamespace uirenderer {
56b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik
57922d3a7f6f8c1c05a996ee3e91e8cbadfff560c9Chris Craikstatic void setUnitQuadTextureCoords(Rect uvs, TextureVertex* quadVertex) {
5814100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik    quadVertex[0] = {0, 0, uvs.left, uvs.top};
5914100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik    quadVertex[1] = {1, 0, uvs.right, uvs.top};
6014100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik    quadVertex[2] = {0, 1, uvs.left, uvs.bottom};
6114100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik    quadVertex[3] = {1, 1, uvs.right, uvs.bottom};
620519c810a56bded1284fcb2ae40f438878c6585fChris Craik}
630519c810a56bded1284fcb2ae40f438878c6585fChris Craik
64031888744e24b5c7243ac99ec98b78aff5db1c78Chris CraikGlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop)
65031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik        : mRenderState(renderState)
66031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik        , mCaches(caches)
67922d3a7f6f8c1c05a996ee3e91e8cbadfff560c9Chris Craik        , mShader(nullptr)
680519c810a56bded1284fcb2ae40f438878c6585fChris Craik        , mOutGlop(outGlop) {
69117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    mStageFlags = kInitialStage;
70117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik}
71117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik
720519c810a56bded1284fcb2ae40f438878c6585fChris Craik////////////////////////////////////////////////////////////////////////////////
730519c810a56bded1284fcb2ae40f438878c6585fChris Craik// Mesh
740519c810a56bded1284fcb2ae40f438878c6585fChris Craik////////////////////////////////////////////////////////////////////////////////
75117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik
768d2cf943d9c7292e54726399faefdec4a01c084bChris CraikGlopBuilder& GlopBuilder::setMeshTexturedIndexedVbo(GLuint vbo, GLsizei elementCount) {
778d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    TRIGGER_STAGE(kMeshStage);
788d2cf943d9c7292e54726399faefdec4a01c084bChris Craik
798d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
808d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
818d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    mOutGlop->mesh.vertices = {
828d2cf943d9c7292e54726399faefdec4a01c084bChris Craik            vbo,
838d2cf943d9c7292e54726399faefdec4a01c084bChris Craik            VertexAttribFlags::TextureCoord,
84e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik            nullptr, (const void*) kMeshTextureOffset, nullptr,
858d2cf943d9c7292e54726399faefdec4a01c084bChris Craik            kTextureVertexStride };
868d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    mOutGlop->mesh.elementCount = elementCount;
878d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    return *this;
888d2cf943d9c7292e54726399faefdec4a01c084bChris Craik}
898d2cf943d9c7292e54726399faefdec4a01c084bChris Craik
900519c810a56bded1284fcb2ae40f438878c6585fChris CraikGlopBuilder& GlopBuilder::setMeshUnitQuad() {
910519c810a56bded1284fcb2ae40f438878c6585fChris Craik    TRIGGER_STAGE(kMeshStage);
92117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik
93117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
94ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.indices = { 0, nullptr };
95ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.vertices = {
96ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            mRenderState.meshState().getUnitQuadVBO(),
9753e51e4aa933f9603587e1780f446c18816bf9beChris Craik            VertexAttribFlags::None,
98ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            nullptr, nullptr, nullptr,
99ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            kTextureVertexStride };
1000519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mOutGlop->mesh.elementCount = 4;
101117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    return *this;
102031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik}
103031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik
104f27133df2d179c99d6bc1ae644af09e9153a0071Chris CraikGlopBuilder& GlopBuilder::setMeshTexturedUnitQuad(const UvMapper* uvMapper) {
10514100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik    if (uvMapper) {
10614100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik        // can't use unit quad VBO, so build UV vertices manually
1075430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik        return setMeshTexturedUvQuad(uvMapper, Rect(1, 1));
10814100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik    }
10914100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik
11014100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik    TRIGGER_STAGE(kMeshStage);
11114100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik
11214100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik    mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
113ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.indices = { 0, nullptr };
114ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.vertices = {
115ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            mRenderState.meshState().getUnitQuadVBO(),
11653e51e4aa933f9603587e1780f446c18816bf9beChris Craik            VertexAttribFlags::TextureCoord,
117ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            nullptr, (const void*) kMeshTextureOffset, nullptr,
118ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            kTextureVertexStride };
11914100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik    mOutGlop->mesh.elementCount = 4;
12014100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik    return *this;
12114100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik}
12214100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik
12314100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris CraikGlopBuilder& GlopBuilder::setMeshTexturedUvQuad(const UvMapper* uvMapper, Rect uvs) {
124117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    TRIGGER_STAGE(kMeshStage);
125117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik
1260519c810a56bded1284fcb2ae40f438878c6585fChris Craik    if (CC_UNLIKELY(uvMapper)) {
1270519c810a56bded1284fcb2ae40f438878c6585fChris Craik        uvMapper->map(uvs);
1280519c810a56bded1284fcb2ae40f438878c6585fChris Craik    }
12914100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik    setUnitQuadTextureCoords(uvs, &mOutGlop->mesh.mappedVertices[0]);
13014100ac9f8efc1a2407e3f5a5c8b2532a49585dbChris Craik
131ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    const TextureVertex* textureVertex = mOutGlop->mesh.mappedVertices;
132ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
133ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.indices = { 0, nullptr };
134ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.vertices = {
135ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            0,
13653e51e4aa933f9603587e1780f446c18816bf9beChris Craik            VertexAttribFlags::TextureCoord,
137ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            &textureVertex[0].x, &textureVertex[0].u, nullptr,
138ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            kTextureVertexStride };
1390519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mOutGlop->mesh.elementCount = 4;
140031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik    return *this;
141031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik}
142031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik
143ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris CraikGlopBuilder& GlopBuilder::setMeshIndexedQuads(Vertex* vertexData, int quadCount) {
1442ab95d780b023152556d9f8659de734ec7b55047Chris Craik    TRIGGER_STAGE(kMeshStage);
1452ab95d780b023152556d9f8659de734ec7b55047Chris Craik
1462ab95d780b023152556d9f8659de734ec7b55047Chris Craik    mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
147ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
148ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.vertices = {
149ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            0,
15053e51e4aa933f9603587e1780f446c18816bf9beChris Craik            VertexAttribFlags::None,
151ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            vertexData, nullptr, nullptr,
152ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            kVertexStride };
1530519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mOutGlop->mesh.elementCount = 6 * quadCount;
1542ab95d780b023152556d9f8659de734ec7b55047Chris Craik    return *this;
1552ab95d780b023152556d9f8659de734ec7b55047Chris Craik}
1562ab95d780b023152556d9f8659de734ec7b55047Chris Craik
157f27133df2d179c99d6bc1ae644af09e9153a0071Chris CraikGlopBuilder& GlopBuilder::setMeshTexturedIndexedQuads(TextureVertex* vertexData, int elementCount) {
158f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    TRIGGER_STAGE(kMeshStage);
159f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
160f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
161ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
162ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.vertices = {
163ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            0,
16453e51e4aa933f9603587e1780f446c18816bf9beChris Craik            VertexAttribFlags::TextureCoord,
165ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            &vertexData[0].x, &vertexData[0].u, nullptr,
166ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            kTextureVertexStride };
167ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.elementCount = elementCount;
168ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    return *this;
169ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik}
170ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik
171ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris CraikGlopBuilder& GlopBuilder::setMeshColoredTexturedMesh(ColorTextureVertex* vertexData, int elementCount) {
172ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    TRIGGER_STAGE(kMeshStage);
173ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik
174ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
175ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.indices = { 0, nullptr };
176ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.vertices = {
177ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            0,
17853e51e4aa933f9603587e1780f446c18816bf9beChris Craik            VertexAttribFlags::TextureCoord | VertexAttribFlags::Color,
179ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            &vertexData[0].x, &vertexData[0].u, &vertexData[0].r,
180ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            kColorTextureVertexStride };
181f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    mOutGlop->mesh.elementCount = elementCount;
182f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    return *this;
183f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik}
184f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
185138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris CraikGlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer) {
1860519c810a56bded1284fcb2ae40f438878c6585fChris Craik    TRIGGER_STAGE(kMeshStage);
187117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik
1880519c810a56bded1284fcb2ae40f438878c6585fChris Craik    const VertexBuffer::MeshFeatureFlags flags = vertexBuffer.getMeshFeatureFlags();
1892ab95d780b023152556d9f8659de734ec7b55047Chris Craik
1900519c810a56bded1284fcb2ae40f438878c6585fChris Craik    bool alphaVertex = flags & VertexBuffer::kAlpha;
1910519c810a56bded1284fcb2ae40f438878c6585fChris Craik    bool indices = flags & VertexBuffer::kIndices;
192ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik
1930519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
194ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.indices = { 0, vertexBuffer.getIndices() };
195ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->mesh.vertices = {
196ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            0,
19753e51e4aa933f9603587e1780f446c18816bf9beChris Craik            alphaVertex ? VertexAttribFlags::Alpha : VertexAttribFlags::None,
198ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            vertexBuffer.getBuffer(), nullptr, nullptr,
199ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik            alphaVertex ? kAlphaVertexStride : kVertexStride };
2000519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mOutGlop->mesh.elementCount = indices
201ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik                ? vertexBuffer.getIndexCount() : vertexBuffer.getVertexCount();
202b0a9477c8e07d4530f07c78a5d20b4cde0fe8d60Arun    mOutGlop->mesh.vertexCount = vertexBuffer.getVertexCount(); // used for glDrawRangeElements()
2032ab95d780b023152556d9f8659de734ec7b55047Chris Craik    return *this;
2042ab95d780b023152556d9f8659de734ec7b55047Chris Craik}
2052ab95d780b023152556d9f8659de734ec7b55047Chris Craik
2060556d90253902ae797e4fcea79602a30ff16f82cChris CraikGlopBuilder& GlopBuilder::setMeshPatchQuads(const Patch& patch) {
2070556d90253902ae797e4fcea79602a30ff16f82cChris Craik    TRIGGER_STAGE(kMeshStage);
2080556d90253902ae797e4fcea79602a30ff16f82cChris Craik
2090556d90253902ae797e4fcea79602a30ff16f82cChris Craik    mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
2100556d90253902ae797e4fcea79602a30ff16f82cChris Craik    mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
2110556d90253902ae797e4fcea79602a30ff16f82cChris Craik    mOutGlop->mesh.vertices = {
2120556d90253902ae797e4fcea79602a30ff16f82cChris Craik            mCaches.patchCache.getMeshBuffer(),
21353e51e4aa933f9603587e1780f446c18816bf9beChris Craik            VertexAttribFlags::TextureCoord,
2148820fd1d82acaefda98ae73ccf61413d5044f9f3Chris Craik            (void*)patch.positionOffset, (void*)patch.textureOffset, nullptr,
2150556d90253902ae797e4fcea79602a30ff16f82cChris Craik            kTextureVertexStride };
2160556d90253902ae797e4fcea79602a30ff16f82cChris Craik    mOutGlop->mesh.elementCount = patch.indexCount;
2170556d90253902ae797e4fcea79602a30ff16f82cChris Craik    return *this;
2180556d90253902ae797e4fcea79602a30ff16f82cChris Craik}
2190556d90253902ae797e4fcea79602a30ff16f82cChris Craik
2200519c810a56bded1284fcb2ae40f438878c6585fChris Craik////////////////////////////////////////////////////////////////////////////////
2210519c810a56bded1284fcb2ae40f438878c6585fChris Craik// Fill
2220519c810a56bded1284fcb2ae40f438878c6585fChris Craik////////////////////////////////////////////////////////////////////////////////
2232ab95d780b023152556d9f8659de734ec7b55047Chris Craik
224182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craikvoid GlopBuilder::setFill(int color, float alphaScale,
225260ab726486317496bc12a57d599ea96dcde3284Mike Reed        SkBlendMode mode, Blend::ModeOrderSwap modeUsage,
2260519c810a56bded1284fcb2ae40f438878c6585fChris Craik        const SkShader* shader, const SkColorFilter* colorFilter) {
227260ab726486317496bc12a57d599ea96dcde3284Mike Reed    if (mode != SkBlendMode::kClear) {
228117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        if (!shader) {
229253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy            FloatColor c;
230253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy            c.set(color);
231253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy            c.r *= alphaScale;
232253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy            c.g *= alphaScale;
233253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy            c.b *= alphaScale;
234253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy            c.a *= alphaScale;
235253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy            mOutGlop->fill.color = c;
236117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        } else {
237253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy            float alpha = (SkColorGetA(color) / 255.0f) * alphaScale;
2380519c810a56bded1284fcb2ae40f438878c6585fChris Craik            mOutGlop->fill.color = { 1, 1, 1, alpha };
239031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik        }
240031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik    } else {
2410519c810a56bded1284fcb2ae40f438878c6585fChris Craik        mOutGlop->fill.color = { 0, 0, 0, 1 };
242031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik    }
243031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik
244117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    mOutGlop->blend = { GL_ZERO, GL_ZERO };
245031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik    if (mOutGlop->fill.color.a < 1.0f
24653e51e4aa933f9603587e1780f446c18816bf9beChris Craik            || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
247f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik            || (mOutGlop->fill.texture.texture && mOutGlop->fill.texture.texture->blend)
2480519c810a56bded1284fcb2ae40f438878c6585fChris Craik            || mOutGlop->roundRectClipState
249117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik            || PaintUtils::isBlendedShader(shader)
250031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik            || PaintUtils::isBlendedColorFilter(colorFilter)
251260ab726486317496bc12a57d599ea96dcde3284Mike Reed            || mode != SkBlendMode::kSrcOver) {
252260ab726486317496bc12a57d599ea96dcde3284Mike Reed        if (CC_LIKELY(mode <= SkBlendMode::kScreen)) {
253182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik            Blend::getFactors(mode, modeUsage,
254031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik                    &mOutGlop->blend.src, &mOutGlop->blend.dst);
255031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik        } else {
256031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik            // These blend modes are not supported by OpenGL directly and have
257031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik            // to be implemented using shaders. Since the shader will perform
258031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik            // the blending, don't enable GL blending off here
259031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik            // If the blend mode cannot be implemented using shaders, fall
260031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik            // back to the default SrcOver blend mode instead
261117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik            if (CC_UNLIKELY(mCaches.extensions().hasFramebufferFetch())) {
262c2f31df8b3b9a237e9abffc59c61804ad8495073Mike Reed                mDescription.framebufferMode = mode;
263182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik                mDescription.swapSrcDst = (modeUsage == Blend::ModeOrderSwap::Swap);
264031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik                // blending in shader, don't enable
265031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik            } else {
266031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik                // unsupported
267260ab726486317496bc12a57d599ea96dcde3284Mike Reed                Blend::getFactors(SkBlendMode::kSrcOver, modeUsage,
268031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik                        &mOutGlop->blend.src, &mOutGlop->blend.dst);
269031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik            }
270031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik        }
271031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik    }
272922d3a7f6f8c1c05a996ee3e91e8cbadfff560c9Chris Craik    mShader = shader; // shader resolved in ::build()
273117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik
274117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    if (colorFilter) {
275117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        SkColor color;
276c2f31df8b3b9a237e9abffc59c61804ad8495073Mike Reed        SkBlendMode bmode;
277117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        SkScalar srcColorMatrix[20];
278c2f31df8b3b9a237e9abffc59c61804ad8495073Mike Reed        if (colorFilter->asColorMode(&color, &bmode)) {
279b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik            mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Blend;
280c2f31df8b3b9a237e9abffc59c61804ad8495073Mike Reed            mDescription.colorMode = bmode;
281253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy            mOutGlop->fill.filter.color.set(color);
282117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        } else if (colorFilter->asColorMatrix(srcColorMatrix)) {
283b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik            mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::ColorFilterMode::Matrix;
284117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik
285117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik            float* colorMatrix = mOutGlop->fill.filter.matrix.matrix;
286117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik            memcpy(colorMatrix, srcColorMatrix, 4 * sizeof(float));
287117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik            memcpy(&colorMatrix[4], &srcColorMatrix[5], 4 * sizeof(float));
288117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik            memcpy(&colorMatrix[8], &srcColorMatrix[10], 4 * sizeof(float));
289117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik            memcpy(&colorMatrix[12], &srcColorMatrix[15], 4 * sizeof(float));
290117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik
291117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik            // Skia uses the range [0..255] for the addition vector, but we need
292117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik            // the [0..1] range to apply the vector in GLSL
293117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik            float* colorVector = mOutGlop->fill.filter.matrix.vector;
2948762e332e3797fb41929a1c6069207f4906ca329Romain Guy            colorVector[0] = EOCF(srcColorMatrix[4]  / 255.0f);
2958762e332e3797fb41929a1c6069207f4906ca329Romain Guy            colorVector[1] = EOCF(srcColorMatrix[9]  / 255.0f);
2968762e332e3797fb41929a1c6069207f4906ca329Romain Guy            colorVector[2] = EOCF(srcColorMatrix[14] / 255.0f);
2978762e332e3797fb41929a1c6069207f4906ca329Romain Guy            colorVector[3] =      srcColorMatrix[19] / 255.0f;  // alpha is linear
2982ab95d780b023152556d9f8659de734ec7b55047Chris Craik        } else {
2992ab95d780b023152556d9f8659de734ec7b55047Chris Craik            LOG_ALWAYS_FATAL("unsupported ColorFilter");
300117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        }
301117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    } else {
302b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        mOutGlop->fill.filterMode = ProgramDescription::ColorFilterMode::None;
303117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    }
3040519c810a56bded1284fcb2ae40f438878c6585fChris Craik}
3050519c810a56bded1284fcb2ae40f438878c6585fChris Craik
30653e51e4aa933f9603587e1780f446c18816bf9beChris CraikGlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture,
30753e51e4aa933f9603587e1780f446c18816bf9beChris Craik        const int textureFillFlags, const SkPaint* paint, float alphaScale) {
3080519c810a56bded1284fcb2ae40f438878c6585fChris Craik    TRIGGER_STAGE(kFillStage);
309b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
3100519c810a56bded1284fcb2ae40f438878c6585fChris Craik
31153e51e4aa933f9603587e1780f446c18816bf9beChris Craik    GLenum filter = (textureFillFlags & TextureFillFlags::ForceFilter)
312a6b52198b9e73a4b7f80103116feeace74433246Chris Craik            ? GL_LINEAR : PaintUtils::getFilter(paint);
3132a38c42e921451abebb4ee5f5ecd738f1b6b04edsergeyv    mOutGlop->fill.texture = { &texture, filter, GL_CLAMP_TO_EDGE, nullptr };
3140519c810a56bded1284fcb2ae40f438878c6585fChris Craik
3150519c810a56bded1284fcb2ae40f438878c6585fChris Craik    if (paint) {
3160519c810a56bded1284fcb2ae40f438878c6585fChris Craik        int color = paint->getColor();
3170519c810a56bded1284fcb2ae40f438878c6585fChris Craik        SkShader* shader = paint->getShader();
3180519c810a56bded1284fcb2ae40f438878c6585fChris Craik
31953e51e4aa933f9603587e1780f446c18816bf9beChris Craik        if (!(textureFillFlags & TextureFillFlags::IsAlphaMaskTexture)) {
3200519c810a56bded1284fcb2ae40f438878c6585fChris Craik            // Texture defines color, so disable shaders, and reset all non-alpha color channels
3210519c810a56bded1284fcb2ae40f438878c6585fChris Craik            color |= 0x00FFFFFF;
3220519c810a56bded1284fcb2ae40f438878c6585fChris Craik            shader = nullptr;
3230519c810a56bded1284fcb2ae40f438878c6585fChris Craik        }
324182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik        setFill(color, alphaScale,
325260ab726486317496bc12a57d599ea96dcde3284Mike Reed                paint->getBlendMode(), Blend::ModeOrderSwap::NoSwap,
3260519c810a56bded1284fcb2ae40f438878c6585fChris Craik                shader, paint->getColorFilter());
3270519c810a56bded1284fcb2ae40f438878c6585fChris Craik    } else {
3280519c810a56bded1284fcb2ae40f438878c6585fChris Craik        mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale };
3290519c810a56bded1284fcb2ae40f438878c6585fChris Craik
3300519c810a56bded1284fcb2ae40f438878c6585fChris Craik        if (alphaScale < 1.0f
33153e51e4aa933f9603587e1780f446c18816bf9beChris Craik                || (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
3320519c810a56bded1284fcb2ae40f438878c6585fChris Craik                || texture.blend
3330519c810a56bded1284fcb2ae40f438878c6585fChris Craik                || mOutGlop->roundRectClipState) {
334260ab726486317496bc12a57d599ea96dcde3284Mike Reed            Blend::getFactors(SkBlendMode::kSrcOver, Blend::ModeOrderSwap::NoSwap,
3350519c810a56bded1284fcb2ae40f438878c6585fChris Craik                    &mOutGlop->blend.src, &mOutGlop->blend.dst);
3360519c810a56bded1284fcb2ae40f438878c6585fChris Craik        } else {
3370519c810a56bded1284fcb2ae40f438878c6585fChris Craik            mOutGlop->blend = { GL_ZERO, GL_ZERO };
3380519c810a56bded1284fcb2ae40f438878c6585fChris Craik        }
3390519c810a56bded1284fcb2ae40f438878c6585fChris Craik    }
3400519c810a56bded1284fcb2ae40f438878c6585fChris Craik
34153e51e4aa933f9603587e1780f446c18816bf9beChris Craik    if (textureFillFlags & TextureFillFlags::IsAlphaMaskTexture) {
3422bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik        mDescription.modulate = mOutGlop->fill.color.isNotBlack();
343a6b52198b9e73a4b7f80103116feeace74433246Chris Craik        mDescription.hasAlpha8Texture = true;
3440519c810a56bded1284fcb2ae40f438878c6585fChris Craik    } else {
3450519c810a56bded1284fcb2ae40f438878c6585fChris Craik        mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
3460519c810a56bded1284fcb2ae40f438878c6585fChris Craik    }
3470519c810a56bded1284fcb2ae40f438878c6585fChris Craik    return *this;
3480519c810a56bded1284fcb2ae40f438878c6585fChris Craik}
3490519c810a56bded1284fcb2ae40f438878c6585fChris Craik
350138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris CraikGlopBuilder& GlopBuilder::setFillPaint(const SkPaint& paint, float alphaScale, bool shadowInterp) {
3510519c810a56bded1284fcb2ae40f438878c6585fChris Craik    TRIGGER_STAGE(kFillStage);
352b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
3530519c810a56bded1284fcb2ae40f438878c6585fChris Craik
354138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik    if (CC_LIKELY(!shadowInterp)) {
355138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik        mOutGlop->fill.texture = {
3562a38c42e921451abebb4ee5f5ecd738f1b6b04edsergeyv                nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
357138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik    } else {
358138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik        mOutGlop->fill.texture = {
3592a38c42e921451abebb4ee5f5ecd738f1b6b04edsergeyv                mCaches.textureState().getShadowLutTexture(),
360138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik                GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
361138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik    }
3620519c810a56bded1284fcb2ae40f438878c6585fChris Craik
363182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    setFill(paint.getColor(), alphaScale,
364260ab726486317496bc12a57d599ea96dcde3284Mike Reed            paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
3650519c810a56bded1284fcb2ae40f438878c6585fChris Craik            paint.getShader(), paint.getColorFilter());
366138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik    mDescription.useShadowAlphaInterp = shadowInterp;
3670519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
3680519c810a56bded1284fcb2ae40f438878c6585fChris Craik    return *this;
3690519c810a56bded1284fcb2ae40f438878c6585fChris Craik}
3700519c810a56bded1284fcb2ae40f438878c6585fChris Craik
3712bb8f5606d4a28549d95005304305b3aff1ce090Chris CraikGlopBuilder& GlopBuilder::setFillPathTexturePaint(PathTexture& texture,
37230036092b40badecbe64d9c2bff4850132147f78Chris Craik        const SkPaint& paint, float alphaScale) {
37330036092b40badecbe64d9c2bff4850132147f78Chris Craik    TRIGGER_STAGE(kFillStage);
374b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
37530036092b40badecbe64d9c2bff4850132147f78Chris Craik
376f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    //specify invalid filter/clamp, since these are always static for PathTextures
3772a38c42e921451abebb4ee5f5ecd738f1b6b04edsergeyv    mOutGlop->fill.texture = { &texture, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
37830036092b40badecbe64d9c2bff4850132147f78Chris Craik
379182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    setFill(paint.getColor(), alphaScale,
380260ab726486317496bc12a57d599ea96dcde3284Mike Reed            paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
38130036092b40badecbe64d9c2bff4850132147f78Chris Craik            paint.getShader(), paint.getColorFilter());
38230036092b40badecbe64d9c2bff4850132147f78Chris Craik
383f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    mDescription.hasAlpha8Texture = true;
3842bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik    mDescription.modulate = mOutGlop->fill.color.isNotBlack();
38530036092b40badecbe64d9c2bff4850132147f78Chris Craik    return *this;
38630036092b40badecbe64d9c2bff4850132147f78Chris Craik}
38730036092b40badecbe64d9c2bff4850132147f78Chris Craik
3882bb8f5606d4a28549d95005304305b3aff1ce090Chris CraikGlopBuilder& GlopBuilder::setFillShadowTexturePaint(ShadowTexture& texture, int shadowColor,
3892bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik        const SkPaint& paint, float alphaScale) {
3902bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik    TRIGGER_STAGE(kFillStage);
391b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
3922bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik
393f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    //specify invalid filter/clamp, since these are always static for ShadowTextures
3942a38c42e921451abebb4ee5f5ecd738f1b6b04edsergeyv    mOutGlop->fill.texture = { &texture, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
3952bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik
3962bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik    const int ALPHA_BITMASK = SK_ColorBLACK;
3972bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik    const int COLOR_BITMASK = ~ALPHA_BITMASK;
3982bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik    if ((shadowColor & ALPHA_BITMASK) == ALPHA_BITMASK) {
3992bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik        // shadow color is fully opaque: override its alpha with that of paint
4002bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik        shadowColor &= paint.getColor() | COLOR_BITMASK;
4012bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik    }
4022bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik
403182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    setFill(shadowColor, alphaScale,
404260ab726486317496bc12a57d599ea96dcde3284Mike Reed            paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
4052bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik            paint.getShader(), paint.getColorFilter());
4062bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik
407f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    mDescription.hasAlpha8Texture = true;
4082bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik    mDescription.modulate = mOutGlop->fill.color.isNotBlack();
4092bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik    return *this;
4102bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik}
4112bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik
4122bb8f5606d4a28549d95005304305b3aff1ce090Chris CraikGlopBuilder& GlopBuilder::setFillBlack() {
4132bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik    TRIGGER_STAGE(kFillStage);
414b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
4152bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik
4162a38c42e921451abebb4ee5f5ecd738f1b6b04edsergeyv    mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
417260ab726486317496bc12a57d599ea96dcde3284Mike Reed    setFill(SK_ColorBLACK, 1.0f, SkBlendMode::kSrcOver, Blend::ModeOrderSwap::NoSwap,
418182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik            nullptr, nullptr);
4192bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik    return *this;
4202bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik}
4212bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik
4222bb8f5606d4a28549d95005304305b3aff1ce090Chris CraikGlopBuilder& GlopBuilder::setFillClear() {
4232bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik    TRIGGER_STAGE(kFillStage);
424b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
4252bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik
4262a38c42e921451abebb4ee5f5ecd738f1b6b04edsergeyv    mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
427260ab726486317496bc12a57d599ea96dcde3284Mike Reed    setFill(SK_ColorBLACK, 1.0f, SkBlendMode::kClear, Blend::ModeOrderSwap::NoSwap,
428182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik            nullptr, nullptr);
429f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    return *this;
430f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik}
4312bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik
432f27133df2d179c99d6bc1ae644af09e9153a0071Chris CraikGlopBuilder& GlopBuilder::setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
433260ab726486317496bc12a57d599ea96dcde3284Mike Reed        float alpha, SkBlendMode mode, Blend::ModeOrderSwap modeUsage) {
434f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    TRIGGER_STAGE(kFillStage);
435b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
436f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
4372a38c42e921451abebb4ee5f5ecd738f1b6b04edsergeyv    mOutGlop->fill.texture = { &texture, GL_LINEAR, GL_CLAMP_TO_EDGE, nullptr };
438f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
439182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    setFill(SK_ColorWHITE, alpha, mode, modeUsage, nullptr, colorFilter);
440f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
441f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
4422bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik    return *this;
4432bb8f5606d4a28549d95005304305b3aff1ce090Chris Craik}
444f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
4458cd3edfa15cc9cdbffa935d19ab894426b08d174Greg DanielGlopBuilder& GlopBuilder::setFillTextureLayer(GlLayer& layer, float alpha) {
44626bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik    TRIGGER_STAGE(kFillStage);
447b1f990de4075866ad8f40849c01d58b2dac8b1e5Chris Craik    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
44826bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik
44926bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik    mOutGlop->fill.texture = { &(layer.getTexture()),
4502a38c42e921451abebb4ee5f5ecd738f1b6b04edsergeyv            GL_LINEAR, GL_CLAMP_TO_EDGE, &layer.getTexTransform() };
45126bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik
452182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    setFill(SK_ColorWHITE, alpha, layer.getMode(), Blend::ModeOrderSwap::NoSwap,
453182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik            nullptr, layer.getColorFilter());
45426bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik
45526bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik    mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
45626bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik    mDescription.hasTextureTransform = true;
45726bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik    return *this;
45826bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik}
45926bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik
4607bf96a0a6f4824f2d15ec95249b8ff038fe02239John ReckGlopBuilder& GlopBuilder::setFillExternalTexture(Texture& texture, Matrix4& textureTransform,
4617bf96a0a6f4824f2d15ec95249b8ff038fe02239John Reck        bool requiresFilter) {
4622f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    TRIGGER_STAGE(kFillStage);
4632f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
4642f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
4657bf96a0a6f4824f2d15ec95249b8ff038fe02239John Reck    GLenum filter = requiresFilter ? GL_LINEAR : GL_NEAREST;
4667bf96a0a6f4824f2d15ec95249b8ff038fe02239John Reck    mOutGlop->fill.texture = { &texture, filter, GL_CLAMP_TO_EDGE, &textureTransform };
4672f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
468260ab726486317496bc12a57d599ea96dcde3284Mike Reed    setFill(SK_ColorWHITE, 1.0f, SkBlendMode::kSrc, Blend::ModeOrderSwap::NoSwap,
4692f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck            nullptr, nullptr);
4702f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
4712f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
4722f69d6d4fdd4994912e5515016421625d1e1c4ecJohn Reck    mDescription.hasTextureTransform = true;
4732f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    return *this;
4742f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck}
4752f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
476253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain GuyGlopBuilder& GlopBuilder::setGammaCorrection(bool enabled) {
477253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    REQUIRE_STAGES(kFillStage);
478253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy
479253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    mDescription.hasGammaCorrection = enabled;
480253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    return *this;
481253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy}
482253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy
4830519c810a56bded1284fcb2ae40f438878c6585fChris Craik////////////////////////////////////////////////////////////////////////////////
4840519c810a56bded1284fcb2ae40f438878c6585fChris Craik// Transform
4850519c810a56bded1284fcb2ae40f438878c6585fChris Craik////////////////////////////////////////////////////////////////////////////////
4860519c810a56bded1284fcb2ae40f438878c6585fChris Craik
487b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikGlopBuilder& GlopBuilder::setTransform(const Matrix4& canvas, const int transformFlags) {
4880519c810a56bded1284fcb2ae40f438878c6585fChris Craik    TRIGGER_STAGE(kTransformStage);
4890519c810a56bded1284fcb2ae40f438878c6585fChris Craik
4907c85c54499994c687a833644f7f213e747fadb98Chris Craik    mOutGlop->transform.canvas = canvas;
49153e51e4aa933f9603587e1780f446c18816bf9beChris Craik    mOutGlop->transform.transformFlags = transformFlags;
492b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return *this;
4930519c810a56bded1284fcb2ae40f438878c6585fChris Craik}
4940519c810a56bded1284fcb2ae40f438878c6585fChris Craik
4950519c810a56bded1284fcb2ae40f438878c6585fChris Craik////////////////////////////////////////////////////////////////////////////////
4960519c810a56bded1284fcb2ae40f438878c6585fChris Craik// ModelView
4970519c810a56bded1284fcb2ae40f438878c6585fChris Craik////////////////////////////////////////////////////////////////////////////////
4980519c810a56bded1284fcb2ae40f438878c6585fChris Craik
4990519c810a56bded1284fcb2ae40f438878c6585fChris CraikGlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) {
5000519c810a56bded1284fcb2ae40f438878c6585fChris Craik    TRIGGER_STAGE(kModelViewStage);
5010519c810a56bded1284fcb2ae40f438878c6585fChris Craik
5020519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f);
5030519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f);
5040519c810a56bded1284fcb2ae40f438878c6585fChris Craik    return *this;
5050519c810a56bded1284fcb2ae40f438878c6585fChris Craik}
5060519c810a56bded1284fcb2ae40f438878c6585fChris Craik
5070519c810a56bded1284fcb2ae40f438878c6585fChris CraikGlopBuilder& GlopBuilder::setModelViewMapUnitToRectSnap(const Rect destination) {
5080519c810a56bded1284fcb2ae40f438878c6585fChris Craik    TRIGGER_STAGE(kModelViewStage);
5090519c810a56bded1284fcb2ae40f438878c6585fChris Craik    REQUIRE_STAGES(kTransformStage | kFillStage);
5100519c810a56bded1284fcb2ae40f438878c6585fChris Craik
5110519c810a56bded1284fcb2ae40f438878c6585fChris Craik    float left = destination.left;
5120519c810a56bded1284fcb2ae40f438878c6585fChris Craik    float top = destination.top;
5130519c810a56bded1284fcb2ae40f438878c6585fChris Craik
51453e51e4aa933f9603587e1780f446c18816bf9beChris Craik    const Matrix4& meshTransform = mOutGlop->transform.meshTransform();
51553e51e4aa933f9603587e1780f446c18816bf9beChris Craik    if (CC_LIKELY(meshTransform.isPureTranslate())) {
516f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik        // snap by adjusting the model view matrix
51753e51e4aa933f9603587e1780f446c18816bf9beChris Craik        const float translateX = meshTransform.getTranslateX();
51853e51e4aa933f9603587e1780f446c18816bf9beChris Craik        const float translateY = meshTransform.getTranslateY();
5190519c810a56bded1284fcb2ae40f438878c6585fChris Craik
5200519c810a56bded1284fcb2ae40f438878c6585fChris Craik        left = (int) floorf(left + translateX + 0.5f) - translateX;
5210519c810a56bded1284fcb2ae40f438878c6585fChris Craik        top = (int) floorf(top + translateY + 0.5f) - translateY;
522f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik        mOutGlop->fill.texture.filter = GL_NEAREST;
5230519c810a56bded1284fcb2ae40f438878c6585fChris Craik    }
5240519c810a56bded1284fcb2ae40f438878c6585fChris Craik
5250519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mOutGlop->transform.modelView.loadTranslate(left, top, 0.0f);
5260519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f);
5270519c810a56bded1284fcb2ae40f438878c6585fChris Craik    return *this;
5280519c810a56bded1284fcb2ae40f438878c6585fChris Craik}
5290519c810a56bded1284fcb2ae40f438878c6585fChris Craik
5300519c810a56bded1284fcb2ae40f438878c6585fChris CraikGlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, const Rect source) {
5310519c810a56bded1284fcb2ae40f438878c6585fChris Craik    TRIGGER_STAGE(kModelViewStage);
5320519c810a56bded1284fcb2ae40f438878c6585fChris Craik
5330519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
5340519c810a56bded1284fcb2ae40f438878c6585fChris Craik    return *this;
5350519c810a56bded1284fcb2ae40f438878c6585fChris Craik}
536031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik
537f27133df2d179c99d6bc1ae644af09e9153a0071Chris CraikGlopBuilder& GlopBuilder::setModelViewOffsetRectSnap(float offsetX, float offsetY, const Rect source) {
538f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    TRIGGER_STAGE(kModelViewStage);
539f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    REQUIRE_STAGES(kTransformStage | kFillStage);
540f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
54153e51e4aa933f9603587e1780f446c18816bf9beChris Craik    const Matrix4& meshTransform = mOutGlop->transform.meshTransform();
54253e51e4aa933f9603587e1780f446c18816bf9beChris Craik    if (CC_LIKELY(meshTransform.isPureTranslate())) {
543f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik        // snap by adjusting the model view matrix
54453e51e4aa933f9603587e1780f446c18816bf9beChris Craik        const float translateX = meshTransform.getTranslateX();
54553e51e4aa933f9603587e1780f446c18816bf9beChris Craik        const float translateY = meshTransform.getTranslateY();
546f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
547f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik        offsetX = (int) floorf(offsetX + translateX + source.left + 0.5f) - translateX - source.left;
548f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik        offsetY = (int) floorf(offsetY + translateY + source.top + 0.5f) - translateY - source.top;
549f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik        mOutGlop->fill.texture.filter = GL_NEAREST;
550f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    }
551f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
552f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
553f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    return *this;
554f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik}
555f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
556f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik////////////////////////////////////////////////////////////////////////////////
557f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik// RoundRectClip
558f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik////////////////////////////////////////////////////////////////////////////////
559f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
5600519c810a56bded1284fcb2ae40f438878c6585fChris CraikGlopBuilder& GlopBuilder::setRoundRectClipState(const RoundRectClipState* roundRectClipState) {
5610519c810a56bded1284fcb2ae40f438878c6585fChris Craik    TRIGGER_STAGE(kRoundRectClipStage);
5620519c810a56bded1284fcb2ae40f438878c6585fChris Craik
5630519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mOutGlop->roundRectClipState = roundRectClipState;
5640519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mDescription.hasRoundRectClip = roundRectClipState != nullptr;
565031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik    return *this;
566031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik}
567031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik
5680519c810a56bded1284fcb2ae40f438878c6585fChris Craik////////////////////////////////////////////////////////////////////////////////
5690519c810a56bded1284fcb2ae40f438878c6585fChris Craik// Build
5700519c810a56bded1284fcb2ae40f438878c6585fChris Craik////////////////////////////////////////////////////////////////////////////////
5710519c810a56bded1284fcb2ae40f438878c6585fChris Craik
572f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craikvoid verify(const ProgramDescription& description, const Glop& glop) {
573eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik    if (glop.fill.texture.texture != nullptr) {
574eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik        LOG_ALWAYS_FATAL_IF(((description.hasTexture && description.hasExternalTexture)
575138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik                        || (!description.hasTexture
576138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik                                && !description.hasExternalTexture
577138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik                                && !description.useShadowAlphaInterp)
578138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik                        || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) == 0
579138c21fbec12bead3c7ca1f181c3fd35542ccb00Chris Craik                                && !description.useShadowAlphaInterp)),
580eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik                "Texture %p, hT%d, hET %d, attribFlags %x",
581eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik                glop.fill.texture.texture,
582eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik                description.hasTexture, description.hasExternalTexture,
583eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik                glop.mesh.vertices.attribFlags);
584eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik    } else {
585eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik        LOG_ALWAYS_FATAL_IF((description.hasTexture
586eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik                        || description.hasExternalTexture
58753e51e4aa933f9603587e1780f446c18816bf9beChris Craik                        || ((glop.mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) != 0)),
588eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik                "No texture, hT%d, hET %d, attribFlags %x",
589eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik                description.hasTexture, description.hasExternalTexture,
590eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik                glop.mesh.vertices.attribFlags);
591eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik    }
592ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik
59353e51e4aa933f9603587e1780f446c18816bf9beChris Craik    if ((glop.mesh.vertices.attribFlags & VertexAttribFlags::Alpha)
594eb911c2b0e8edeb7595a98af4b9f1bd47de1381eChris Craik            && glop.mesh.vertices.bufferObject) {
595ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik        LOG_ALWAYS_FATAL("VBO and alpha attributes are not currently compatible");
596ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    }
59726bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik
59826bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik    if (description.hasTextureTransform != (glop.fill.texture.textureTransform != nullptr)) {
59926bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik        LOG_ALWAYS_FATAL("Texture transform incorrectly specified");
60026bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik    }
601f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik}
602f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
603031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craikvoid GlopBuilder::build() {
60408fa43fdeb646f56edcd8b33d06ee7d79b203426Chris Craik    REQUIRE_STAGES(kAllStages);
60553e51e4aa933f9603587e1780f446c18816bf9beChris Craik    if (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) {
60655455181233cadcd6d2e28d28d0dfc9a653f7787Romain Guy        Texture* texture = mOutGlop->fill.texture.texture;
60755455181233cadcd6d2e28d28d0dfc9a653f7787Romain Guy        if (texture->target() == GL_TEXTURE_2D) {
60848f650cb24e5b028deaff01baddc1d154f78d91aChris Craik            mDescription.hasTexture = true;
60948f650cb24e5b028deaff01baddc1d154f78d91aChris Craik        } else {
61048f650cb24e5b028deaff01baddc1d154f78d91aChris Craik            mDescription.hasExternalTexture = true;
61148f650cb24e5b028deaff01baddc1d154f78d91aChris Craik        }
612caaaa66e57293e4a6f312649bf472eab84d5c7feRomain Guy        mDescription.hasLinearTexture = texture->isLinear();
613caaaa66e57293e4a6f312649bf472eab84d5c7feRomain Guy        mDescription.hasColorSpaceConversion = texture->hasColorSpaceConversion();
614caaaa66e57293e4a6f312649bf472eab84d5c7feRomain Guy        mDescription.transferFunction = texture->getTransferFunctionType();
615caaaa66e57293e4a6f312649bf472eab84d5c7feRomain Guy        mDescription.hasTranslucentConversion = texture->blend;
61626bf34200e40a0fa8c66366559aa016380cd8c6fChris Craik    }
61753e51e4aa933f9603587e1780f446c18816bf9beChris Craik
61853e51e4aa933f9603587e1780f446c18816bf9beChris Craik    mDescription.hasColors = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Color;
61953e51e4aa933f9603587e1780f446c18816bf9beChris Craik    mDescription.hasVertexAlpha = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::Alpha;
620ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik
621828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craik    // Enable debug highlight when what we're about to draw is tested against
622828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craik    // the stencil buffer and if stencil highlight debugging is on
6232507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik    mDescription.hasDebugHighlight = !Properties::debugOverdraw
6242507c34d91bb0d722b6012e85cb47387b2aa6873Chris Craik            && Properties::debugStencilClip == StencilClipDebug::ShowHighlight
625828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craik            && mRenderState.stencil().isTestEnabled();
626828407356dd5c34a3e441604aaf895cbec7c7e66Chris Craik
627922d3a7f6f8c1c05a996ee3e91e8cbadfff560c9Chris Craik    // serialize shader info into ShaderData
628f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    GLuint textureUnit = mOutGlop->fill.texture.texture ? 1 : 0;
62953e51e4aa933f9603587e1780f446c18816bf9beChris Craik
63053e51e4aa933f9603587e1780f446c18816bf9beChris Craik    if (CC_LIKELY(!mShader)) {
63153e51e4aa933f9603587e1780f446c18816bf9beChris Craik        mOutGlop->fill.skiaShaderData.skiaShaderType = kNone_SkiaShaderType;
63253e51e4aa933f9603587e1780f446c18816bf9beChris Craik    } else {
63353e51e4aa933f9603587e1780f446c18816bf9beChris Craik        Matrix4 shaderMatrix;
63453e51e4aa933f9603587e1780f446c18816bf9beChris Craik        if (mOutGlop->transform.transformFlags & TransformFlags::MeshIgnoresCanvasTransform) {
63553e51e4aa933f9603587e1780f446c18816bf9beChris Craik            // canvas level transform was built into the modelView and geometry,
63653e51e4aa933f9603587e1780f446c18816bf9beChris Craik            // so the shader matrix must reverse this
63753e51e4aa933f9603587e1780f446c18816bf9beChris Craik            shaderMatrix.loadInverse(mOutGlop->transform.canvas);
63853e51e4aa933f9603587e1780f446c18816bf9beChris Craik            shaderMatrix.multiply(mOutGlop->transform.modelView);
63953e51e4aa933f9603587e1780f446c18816bf9beChris Craik        } else {
6407c85c54499994c687a833644f7f213e747fadb98Chris Craik            shaderMatrix = mOutGlop->transform.modelView;
64153e51e4aa933f9603587e1780f446c18816bf9beChris Craik        }
64253e51e4aa933f9603587e1780f446c18816bf9beChris Craik        SkiaShader::store(mCaches, *mShader, shaderMatrix,
64353e51e4aa933f9603587e1780f446c18816bf9beChris Craik                &textureUnit, &mDescription, &(mOutGlop->fill.skiaShaderData));
64453e51e4aa933f9603587e1780f446c18816bf9beChris Craik    }
645922d3a7f6f8c1c05a996ee3e91e8cbadfff560c9Chris Craik
6460519c810a56bded1284fcb2ae40f438878c6585fChris Craik    // duplicates ProgramCache's definition of color uniform presence
6470519c810a56bded1284fcb2ae40f438878c6585fChris Craik    const bool singleColor = !mDescription.hasTexture
6480519c810a56bded1284fcb2ae40f438878c6585fChris Craik            && !mDescription.hasExternalTexture
6490519c810a56bded1284fcb2ae40f438878c6585fChris Craik            && !mDescription.hasGradient
6500519c810a56bded1284fcb2ae40f438878c6585fChris Craik            && !mDescription.hasBitmap;
6510519c810a56bded1284fcb2ae40f438878c6585fChris Craik    mOutGlop->fill.colorEnabled = mDescription.modulate || singleColor;
652f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik
653f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    verify(mDescription, *mOutGlop);
654ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik
655ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    // Final step: populate program and map bounds into render target space
656ef2507439c08f4e9c4c9bba1c6243ca9df2ee827Chris Craik    mOutGlop->fill.program = mCaches.programCache.get(mDescription);
657031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik}
658031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik
659b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid GlopBuilder::dump(const Glop& glop) {
660b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ALOGD("Glop Mesh");
661b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    const Glop::Mesh& mesh = glop.mesh;
662b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ALOGD("    primitive mode: %d", mesh.primitiveMode);
663b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ALOGD("    indices: buffer obj %x, indices %p", mesh.indices.bufferObject, mesh.indices.indices);
664b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
665b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    const Glop::Mesh::Vertices& vertices = glop.mesh.vertices;
666b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ALOGD("    vertices: buffer obj %x, flags %x, pos %p, tex %p, clr %p, stride %d",
667b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            vertices.bufferObject, vertices.attribFlags,
668b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            vertices.position, vertices.texCoord, vertices.color, vertices.stride);
669b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ALOGD("    element count: %d", mesh.elementCount);
670b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
671b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ALOGD("Glop Fill");
672b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    const Glop::Fill& fill = glop.fill;
673b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ALOGD("    program %p", fill.program);
674b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (fill.texture.texture) {
675b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        ALOGD("    texture %p, target %d, filter %d, clamp %d",
6762a38c42e921451abebb4ee5f5ecd738f1b6b04edsergeyv                fill.texture.texture, fill.texture.texture->target(),
6772a38c42e921451abebb4ee5f5ecd738f1b6b04edsergeyv                fill.texture.filter, fill.texture.clamp);
678b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        if (fill.texture.textureTransform) {
679b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            fill.texture.textureTransform->dump("texture transform");
680b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
681b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
682b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ALOGD_IF(fill.colorEnabled, "    color (argb) %.2f %.2f %.2f %.2f",
683b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            fill.color.a, fill.color.r, fill.color.g, fill.color.b);
684b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ALOGD_IF(fill.filterMode != ProgramDescription::ColorFilterMode::None,
685b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            "    filterMode %d", (int)fill.filterMode);
686b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ALOGD_IF(fill.skiaShaderData.skiaShaderType, "    shader type %d",
687b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            fill.skiaShaderData.skiaShaderType);
688b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
689b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ALOGD("Glop transform");
690701b3cc0db71d01dd5df21edcb09813334e7205bChris Craik    glop.transform.modelView.dump("  model view");
691701b3cc0db71d01dd5df21edcb09813334e7205bChris Craik    glop.transform.canvas.dump("  canvas");
692701b3cc0db71d01dd5df21edcb09813334e7205bChris Craik    ALOGD_IF(glop.transform.transformFlags, "  transformFlags 0x%x", glop.transform.transformFlags);
693701b3cc0db71d01dd5df21edcb09813334e7205bChris Craik
694701b3cc0db71d01dd5df21edcb09813334e7205bChris Craik    ALOGD_IF(glop.roundRectClipState, "Glop RRCS %p", glop.roundRectClipState);
695b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
696b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    ALOGD("Glop blend %d %d", glop.blend.src, glop.blend.dst);
697b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
698b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
699031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik} /* namespace uirenderer */
700031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik} /* namespace android */
701