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
compute_precision(const GrShaderCaps * caps,int width,int height,GrSamplerParams::FilterMode filter)15 static 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
reset(const SkMatrix & m,const GrTexture * texture,GrSamplerParams::FilterMode filter,bool normalize)53 void 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
reset(GrResourceProvider * resourceProvider,const SkMatrix & m,GrTextureProxy * proxy,GrSamplerParams::FilterMode filter,bool normalize)71 void 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