1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#ifndef GrAtlasedShaderHelpers_DEFINED 9cb93a386Sopenharmony_ci#define GrAtlasedShaderHelpers_DEFINED 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "src/gpu/GrDrawOpAtlas.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrShaderCaps.h" 13cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" 14cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVarying.h" 15cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h" 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_cistatic void append_index_uv_varyings(GrGeometryProcessor::ProgramImpl::EmitArgs& args, 18cb93a386Sopenharmony_ci int numTextureSamplers, 19cb93a386Sopenharmony_ci const char* inTexCoordsName, 20cb93a386Sopenharmony_ci const char* atlasDimensionsInvName, 21cb93a386Sopenharmony_ci GrGLSLVarying* uv, 22cb93a386Sopenharmony_ci GrGLSLVarying* texIdx, 23cb93a386Sopenharmony_ci GrGLSLVarying* st) { 24cb93a386Sopenharmony_ci using Interpolation = GrGLSLVaryingHandler::Interpolation; 25cb93a386Sopenharmony_ci // This extracts the texture index and texel coordinates from the same variable 26cb93a386Sopenharmony_ci // Packing structure: texel coordinates have the 2-bit texture page encoded in bits 13 & 14 of 27cb93a386Sopenharmony_ci // the x coordinate. It would be nice to use bits 14 and 15, but iphone6 has problem with those 28cb93a386Sopenharmony_ci // bits when in gles. Iphone6 works fine with bits 14 and 15 in metal. 29cb93a386Sopenharmony_ci if (args.fShaderCaps->integerSupport()) { 30cb93a386Sopenharmony_ci if (numTextureSamplers <= 1) { 31cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf(R"code( 32cb93a386Sopenharmony_ci int texIdx = 0; 33cb93a386Sopenharmony_ci float2 unormTexCoords = float2(%s.x, %s.y); 34cb93a386Sopenharmony_ci )code", inTexCoordsName, inTexCoordsName); 35cb93a386Sopenharmony_ci } else { 36cb93a386Sopenharmony_ci#ifdef SK_ENABLE_SMALL_PAGE 37cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf(R"code( 38cb93a386Sopenharmony_ci int2 coords = int2(%s.x, %s.y); 39cb93a386Sopenharmony_ci int texIdx = ((coords.x >> 12) & 0xc) + ((coords.y >> 14) & 0x3); 40cb93a386Sopenharmony_ci float2 unormTexCoords = float2(coords.x & 0x3FFF, coords.y & 0x3FFF); 41cb93a386Sopenharmony_ci )code", inTexCoordsName, inTexCoordsName); 42cb93a386Sopenharmony_ci#else 43cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf(R"code( 44cb93a386Sopenharmony_ci int2 coords = int2(%s.x, %s.y); 45cb93a386Sopenharmony_ci int texIdx = coords.x >> 13; 46cb93a386Sopenharmony_ci float2 unormTexCoords = float2(coords.x & 0x1FFF, coords.y); 47cb93a386Sopenharmony_ci )code", inTexCoordsName, inTexCoordsName); 48cb93a386Sopenharmony_ci#endif 49cb93a386Sopenharmony_ci } 50cb93a386Sopenharmony_ci } else { 51cb93a386Sopenharmony_ci if (numTextureSamplers <= 1) { 52cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf(R"code( 53cb93a386Sopenharmony_ci float texIdx = 0; 54cb93a386Sopenharmony_ci float2 unormTexCoords = float2(%s.x, %s.y); 55cb93a386Sopenharmony_ci )code", inTexCoordsName, inTexCoordsName); 56cb93a386Sopenharmony_ci } else { 57cb93a386Sopenharmony_ci#ifdef SK_ENABLE_SMALL_PAGE 58cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf(R"code( 59cb93a386Sopenharmony_ci float2 coord = float2(%s.x, %s.y); 60cb93a386Sopenharmony_ci float diff0 = floor(coord.x * exp2(-14)); 61cb93a386Sopenharmony_ci float diff1 = floor(coord.y * exp2(-14)); 62cb93a386Sopenharmony_ci float texIdx = 4 * diff0 + diff1; 63cb93a386Sopenharmony_ci float2 unormTexCoords = float2(coord.x - diff0, coord.y - diff1); 64cb93a386Sopenharmony_ci )code", inTexCoordsName, inTexCoordsName); 65cb93a386Sopenharmony_ci#else 66cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf(R"code( 67cb93a386Sopenharmony_ci float2 coord = float2(%s.x, %s.y); 68cb93a386Sopenharmony_ci float texIdx = floor(coord.x * exp2(-13)); 69cb93a386Sopenharmony_ci float2 unormTexCoords = float2(coord.x - texIdx * exp2(13), coord.y); 70cb93a386Sopenharmony_ci )code", inTexCoordsName, inTexCoordsName); 71cb93a386Sopenharmony_ci#endif 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci // Multiply by 1/atlasDimensions to get normalized texture coordinates 76cb93a386Sopenharmony_ci uv->reset(kFloat2_GrSLType); 77cb93a386Sopenharmony_ci args.fVaryingHandler->addVarying("TextureCoords", uv); 78cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf( 79cb93a386Sopenharmony_ci "%s = unormTexCoords * %s;", uv->vsOut(), atlasDimensionsInvName); 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci // On ANGLE there is a significant cost to using an int varying. We don't know of any case where 82cb93a386Sopenharmony_ci // it is worse to use a float so for now we always do. 83cb93a386Sopenharmony_ci texIdx->reset(kFloat_GrSLType); 84cb93a386Sopenharmony_ci // If we computed the local var "texIdx" as an int we will need to cast it to float 85cb93a386Sopenharmony_ci const char* cast = args.fShaderCaps->integerSupport() ? "float" : ""; 86cb93a386Sopenharmony_ci args.fVaryingHandler->addVarying("TexIndex", texIdx, Interpolation::kCanBeFlat); 87cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf("%s = %s(texIdx);", texIdx->vsOut(), cast); 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci if (st) { 90cb93a386Sopenharmony_ci st->reset(kFloat2_GrSLType); 91cb93a386Sopenharmony_ci args.fVaryingHandler->addVarying("IntTextureCoords", st); 92cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf("%s = unormTexCoords;", st->vsOut()); 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci} 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_cistatic void append_multitexture_lookup(GrGeometryProcessor::ProgramImpl::EmitArgs& args, 97cb93a386Sopenharmony_ci int numTextureSamplers, 98cb93a386Sopenharmony_ci const GrGLSLVarying& texIdx, 99cb93a386Sopenharmony_ci const char* coordName, 100cb93a386Sopenharmony_ci const char* colorName) { 101cb93a386Sopenharmony_ci SkASSERT(numTextureSamplers > 0); 102cb93a386Sopenharmony_ci // This shouldn't happen, but will avoid a crash if it does 103cb93a386Sopenharmony_ci if (numTextureSamplers <= 0) { 104cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf("%s = float4(1, 1, 1, 1);", colorName); 105cb93a386Sopenharmony_ci return; 106cb93a386Sopenharmony_ci } 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci // conditionally load from the indexed texture sampler 109cb93a386Sopenharmony_ci for (int i = 0; i < numTextureSamplers-1; ++i) { 110cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf("if (%s == %d) { %s = ", texIdx.fsIn(), i, colorName); 111cb93a386Sopenharmony_ci args.fFragBuilder->appendTextureLookup(args.fTexSamplers[i], coordName); 112cb93a386Sopenharmony_ci args.fFragBuilder->codeAppend("; } else "); 113cb93a386Sopenharmony_ci } 114cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf("{ %s = ", colorName); 115cb93a386Sopenharmony_ci args.fFragBuilder->appendTextureLookup(args.fTexSamplers[numTextureSamplers - 1], coordName); 116cb93a386Sopenharmony_ci args.fFragBuilder->codeAppend("; }"); 117cb93a386Sopenharmony_ci} 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_ci#endif 120