1/* 2 * Copyright 2014 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#include "GrCoordTransform.h" 9#include "GrCaps.h" 10#include "GrContext.h" 11#include "GrGpu.h" 12#include "GrResourceProvider.h" 13#include "GrTextureProxy.h" 14 15static GrSLPrecision compute_precision(const GrShaderCaps* caps, 16 int width, int height, 17 GrSamplerParams::FilterMode filter) { 18 // Always start at kDefault. Then if precisions differ we see if the precision needs to be 19 // increased. Our rule is that we want at least 4 subpixel values in the representation for 20 // coords between 0 to 1 when bi- or tri-lerping and 1 value when nearest filtering. Note that 21 // this still might not be enough when drawing with repeat or mirror-repeat modes but that case 22 // can be arbitrarily bad. 23 int subPixelThresh = filter > GrSamplerParams::kNone_FilterMode ? 4 : 1; 24 GrSLPrecision precision = kDefault_GrSLPrecision; 25 if (caps) { 26 if (caps->floatPrecisionVaries()) { 27 int maxD = SkTMax(width, height); 28 const GrShaderCaps::PrecisionInfo* info; 29 info = &caps->getFloatShaderPrecisionInfo(kFragment_GrShaderType, precision); 30 do { 31 SkASSERT(info->supported()); 32 // Make sure there is at least 2 bits of subpixel precision in the range of 33 // texture coords from 0.5 to 1.0. 34 if ((2 << info->fBits) / maxD > subPixelThresh) { 35 break; 36 } 37 if (kHigh_GrSLPrecision == precision) { 38 break; 39 } 40 GrSLPrecision nextP = static_cast<GrSLPrecision>(precision + 1); 41 info = &caps->getFloatShaderPrecisionInfo(kFragment_GrShaderType, nextP); 42 if (!info->supported()) { 43 break; 44 } 45 precision = nextP; 46 } while (true); 47 } 48 } 49 50 return precision; 51} 52 53void GrCoordTransform::reset(const SkMatrix& m, const GrTexture* texture, 54 GrSamplerParams::FilterMode filter, bool normalize) { 55 SkASSERT(texture); 56 SkASSERT(!fInProcessor); 57 58 fMatrix = m; 59 fTexture = texture; 60 fNormalize = normalize; 61 fReverseY = kBottomLeft_GrSurfaceOrigin == texture->origin(); 62 63 if (texture->getContext()) { 64 fPrecision = compute_precision(texture->getContext()->caps()->shaderCaps(), 65 texture->width(), texture->height(), filter); 66 } else { 67 fPrecision = kDefault_GrSLPrecision; 68 } 69} 70 71void GrCoordTransform::reset(GrResourceProvider* resourceProvider, const SkMatrix& m, 72 GrTextureProxy* proxy, 73 GrSamplerParams::FilterMode filter, bool normalize) { 74 SkASSERT(proxy); 75 SkASSERT(!fInProcessor); 76 77 fMatrix = m; 78 // MDB TODO: just GrCaps is needed for this method 79 // MDB TODO: once all the coord transforms take a proxy just store it here and 80 // instantiate later 81 fTexture = proxy->instantiate(resourceProvider); 82 fNormalize = normalize; 83 fReverseY = kBottomLeft_GrSurfaceOrigin == proxy->origin(); 84 85 const GrCaps* caps = resourceProvider->caps(); 86 fPrecision = compute_precision(caps->shaderCaps(), 87 proxy->worstCaseWidth(*caps), 88 proxy->worstCaseHeight(*caps), filter); 89} 90 91