1 | /* |
2 | * Copyright 2017 Google Inc. |
3 | * |
4 | * Use of this source code is governed by a BSD-style license that can be |
5 | * found in the LICENSE file. |
6 | */ |
7 | |
8 | #ifndef GrAtlasedShaderHelpers_DEFINED |
9 | #define GrAtlasedShaderHelpers_DEFINED |
10 | |
11 | #include "src/gpu/GrShaderCaps.h" |
12 | #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" |
13 | #include "src/gpu/glsl/GrGLSLPrimitiveProcessor.h" |
14 | #include "src/gpu/glsl/GrGLSLVarying.h" |
15 | #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h" |
16 | |
17 | static void append_index_uv_varyings(GrGLSLPrimitiveProcessor::EmitArgs& args, |
18 | int numTextureSamplers, |
19 | const char* inTexCoordsName, |
20 | const char* atlasDimensionsInvName, |
21 | GrGLSLVarying* uv, |
22 | GrGLSLVarying* texIdx, |
23 | GrGLSLVarying* st) { |
24 | using Interpolation = GrGLSLVaryingHandler::Interpolation; |
25 | |
26 | // This extracts the texture index and texel coordinates from the same variable |
27 | // Packing structure: texel coordinates are multiplied by 2 (or shifted left 1) |
28 | // texture index is stored as lower bits of both x and y |
29 | if (args.fShaderCaps->integerSupport()) { |
30 | args.fVertBuilder->codeAppendf("int2 signedCoords = int2(%s.x, %s.y);" , |
31 | inTexCoordsName, inTexCoordsName); |
32 | args.fVertBuilder->codeAppend("float2 unormTexCoords = float2(signedCoords.x/2, signedCoords.y/2);" ); |
33 | if (numTextureSamplers <= 1) { |
34 | args.fVertBuilder->codeAppend("int texIdx = 0;" ); |
35 | } else { |
36 | args.fVertBuilder->codeAppend("int texIdx = 2*(signedCoords.x & 0x1) + (signedCoords.y & 0x1);" ); |
37 | } |
38 | } else { |
39 | args.fVertBuilder->codeAppendf("float2 indexTexCoords = float2(%s.x, %s.y);" , |
40 | inTexCoordsName, inTexCoordsName); |
41 | args.fVertBuilder->codeAppend("float2 unormTexCoords = floor(0.5*indexTexCoords);" ); |
42 | if (numTextureSamplers <= 1) { |
43 | args.fVertBuilder->codeAppend("float texIdx = 0;" ); |
44 | } else { |
45 | args.fVertBuilder->codeAppend("float2 diff = indexTexCoords - 2.0*unormTexCoords;" ); |
46 | args.fVertBuilder->codeAppend("float texIdx = 2.0*diff.x + diff.y;" ); |
47 | } |
48 | } |
49 | |
50 | // Multiply by 1/atlasDimensions to get normalized texture coordinates |
51 | args.fVaryingHandler->addVarying("TextureCoords" , uv); |
52 | args.fVertBuilder->codeAppendf("%s = unormTexCoords * %s;" , uv->vsOut(), |
53 | atlasDimensionsInvName); |
54 | |
55 | args.fVaryingHandler->addVarying("TexIndex" , texIdx, args.fShaderCaps->integerSupport() |
56 | ? Interpolation::kMustBeFlat |
57 | : Interpolation::kCanBeFlat); |
58 | args.fVertBuilder->codeAppendf("%s = texIdx;" , texIdx->vsOut()); |
59 | |
60 | if (st) { |
61 | args.fVaryingHandler->addVarying("IntTextureCoords" , st); |
62 | args.fVertBuilder->codeAppendf("%s = unormTexCoords;" , st->vsOut()); |
63 | } |
64 | } |
65 | |
66 | static void append_multitexture_lookup(GrGLSLPrimitiveProcessor::EmitArgs& args, |
67 | int numTextureSamplers, |
68 | const GrGLSLVarying &texIdx, |
69 | const char* coordName, |
70 | const char* colorName) { |
71 | SkASSERT(numTextureSamplers > 0); |
72 | // This shouldn't happen, but will avoid a crash if it does |
73 | if (numTextureSamplers <= 0) { |
74 | args.fFragBuilder->codeAppendf("%s = float4(1, 1, 1, 1);" , colorName); |
75 | return; |
76 | } |
77 | |
78 | // conditionally load from the indexed texture sampler |
79 | for (int i = 0; i < numTextureSamplers-1; ++i) { |
80 | args.fFragBuilder->codeAppendf("if (%s == %d) { %s = " , texIdx.fsIn(), i, colorName); |
81 | args.fFragBuilder->appendTextureLookup(args.fTexSamplers[i], coordName); |
82 | args.fFragBuilder->codeAppend("; } else " ); |
83 | } |
84 | args.fFragBuilder->codeAppendf("{ %s = " , colorName); |
85 | args.fFragBuilder->appendTextureLookup(args.fTexSamplers[numTextureSamplers - 1], coordName); |
86 | args.fFragBuilder->codeAppend("; }" ); |
87 | } |
88 | |
89 | #endif |
90 | |