blob: 95f30c02ee8cac6bbfe32f29ec9adb2ad6a056e2 [file] [log] [blame]
bsalomon17168df2014-12-09 09:00:49 -08001/*
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"
bsalomoneb1cb5c2015-05-22 08:01:09 -07009#include "GrCaps.h"
bsalomon17168df2014-12-09 09:00:49 -080010#include "GrContext.h"
bsalomon17168df2014-12-09 09:00:49 -080011#include "GrGpu.h"
Robert Phillipsbc7a4fb2017-01-23 15:30:35 -050012#include "GrTextureProxy.h"
13
14static GrSLPrecision compute_precision(const GrShaderCaps* caps,
15 int width, int height,
16 GrSamplerParams::FilterMode filter) {
17 // Always start at kDefault. Then if precisions differ we see if the precision needs to be
18 // increased. Our rule is that we want at least 4 subpixel values in the representation for
19 // coords between 0 to 1 when bi- or tri-lerping and 1 value when nearest filtering. Note that
20 // this still might not be enough when drawing with repeat or mirror-repeat modes but that case
21 // can be arbitrarily bad.
22 int subPixelThresh = filter > GrSamplerParams::kNone_FilterMode ? 4 : 1;
23 GrSLPrecision precision = kDefault_GrSLPrecision;
24 if (caps) {
25 if (caps->floatPrecisionVaries()) {
26 int maxD = SkTMax(width, height);
27 const GrShaderCaps::PrecisionInfo* info;
28 info = &caps->getFloatShaderPrecisionInfo(kFragment_GrShaderType, precision);
29 do {
30 SkASSERT(info->supported());
31 // Make sure there is at least 2 bits of subpixel precision in the range of
32 // texture coords from 0.5 to 1.0.
33 if ((2 << info->fBits) / maxD > subPixelThresh) {
34 break;
35 }
36 if (kHigh_GrSLPrecision == precision) {
37 break;
38 }
39 GrSLPrecision nextP = static_cast<GrSLPrecision>(precision + 1);
40 info = &caps->getFloatShaderPrecisionInfo(kFragment_GrShaderType, nextP);
41 if (!info->supported()) {
42 break;
43 }
44 precision = nextP;
45 } while (true);
46 }
47 }
48
49 return precision;
50}
bsalomon17168df2014-12-09 09:00:49 -080051
Brian Salomon2ebd0c82016-10-03 17:15:28 -040052void GrCoordTransform::reset(const SkMatrix& m, const GrTexture* texture,
Robert Phillips67c18d62017-01-20 12:44:06 -050053 GrSamplerParams::FilterMode filter, bool normalize) {
bsalomon17168df2014-12-09 09:00:49 -080054 SkASSERT(texture);
55 SkASSERT(!fInProcessor);
56
bsalomon17168df2014-12-09 09:00:49 -080057 fMatrix = m;
Robert Phillips67c18d62017-01-20 12:44:06 -050058 fTexture = texture;
59 fNormalize = normalize;
bsalomon17168df2014-12-09 09:00:49 -080060 fReverseY = kBottomLeft_GrSurfaceOrigin == texture->origin();
61
bsalomon17168df2014-12-09 09:00:49 -080062 if (texture->getContext()) {
Robert Phillipsbc7a4fb2017-01-23 15:30:35 -050063 fPrecision = compute_precision(texture->getContext()->caps()->shaderCaps(),
64 texture->width(), texture->height(), filter);
65 } else {
66 fPrecision = kDefault_GrSLPrecision;
bsalomon17168df2014-12-09 09:00:49 -080067 }
68}
69
Robert Phillipsbc7a4fb2017-01-23 15:30:35 -050070void GrCoordTransform::reset(GrContext* context, const SkMatrix& m,
71 GrTextureProxy* proxy,
72 GrSamplerParams::FilterMode filter, bool normalize) {
73 SkASSERT(proxy);
74 SkASSERT(!fInProcessor);
75
76 fMatrix = m;
77 // MDB TODO: just GrCaps is needed for this method
78 // MDB TODO: once all the coord transforms take a proxy just store it here and
79 // instantiate later
Brian Osman32342f02017-03-04 08:12:46 -050080 fTexture = proxy->instantiate(context->resourceProvider());
Robert Phillipsbc7a4fb2017-01-23 15:30:35 -050081 fNormalize = normalize;
82 fReverseY = kBottomLeft_GrSurfaceOrigin == proxy->origin();
83
84 const GrCaps* caps = context->caps();
85 fPrecision = compute_precision(caps->shaderCaps(),
86 proxy->worstCaseWidth(*caps),
87 proxy->worstCaseHeight(*caps), filter);
88}
89