GrTextureDomain.cpp revision 1aa90cf11e136a722bce71dd77f4bb03cc2b56f8
12f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com/*
22f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com * Copyright 2012 Google Inc.
32f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com *
42f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com * Use of this source code is governed by a BSD-style license that can be
52f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com * found in the LICENSE file.
62f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com */
72f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
82f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com#include "GrTextureDomainEffect.h"
92eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com#include "GrTBackendEffectFactory.h"
10d698f77c13d97c61109b861eac4d25b14a5de935bsalomon@google.com#include "gl/GrGLEffect.h"
1192b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com#include "gl/GrGLEffectMatrix.h"
1292b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com#include "SkFloatingPoint.h"
132f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
1422a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.comclass GrGLTextureDomainEffect : public GrGLEffect {
152f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.compublic:
16396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com    GrGLTextureDomainEffect(const GrBackendEffectFactory&, const GrEffect&);
172f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
1822a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com    virtual void emitCode(GrGLShaderBuilder*,
192eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com                          const GrEffectStage&,
2022a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com                          EffectKey,
2122a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com                          const char* vertexCoords,
2222a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com                          const char* outputColor,
2322a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com                          const char* inputColor,
2422a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com                          const TextureSamplerArray&) SK_OVERRIDE;
252f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
2628a15fb8d603847949a61657ef5cb73ed9915021bsalomon@google.com    virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
272f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
2892b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com    static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
292f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
302f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.comprivate:
31dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    GrGLUniformManager::UniformHandle fNameUni;
3292b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com    GrGLEffectMatrix                  fEffectMatrix;
3392b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com    GrGLfloat                         fPrevDomain[4];
342f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
3522a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com    typedef GrGLEffect INHERITED;
362f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com};
372f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
38396e61fe440590744345e0c56970b26ab464591dbsalomon@google.comGrGLTextureDomainEffect::GrGLTextureDomainEffect(const GrBackendEffectFactory& factory,
39021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com                                                 const GrEffect&)
40374e75956e7a56bbbd2da5509f9c4117512515d2bsalomon@google.com    : INHERITED(factory)
41dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    , fNameUni(GrGLUniformManager::kInvalidUniformHandle) {
4292b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com    fPrevDomain[0] = SK_FloatNaN;
432f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com}
442f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
4522a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.comvoid GrGLTextureDomainEffect::emitCode(GrGLShaderBuilder* builder,
462eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com                                       const GrEffectStage&,
4792b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com                                       EffectKey key,
4822a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com                                       const char* vertexCoords,
4922a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com                                       const char* outputColor,
5022a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com                                       const char* inputColor,
5122a800a2578564a8b66bd4d9903ef4186c37f35cbsalomon@google.com                                       const TextureSamplerArray& samplers) {
5292b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com    const char* coords;
5392b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com    fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, vertexCoords, &coords);
5457143a2d87ef5fb7276ffc11abaa2e77d31f0ad8tomhudson@google.com    fNameUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
55777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                   kVec4f_GrSLType, "TexDom");
562f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
5734bcb9f80336fe0dc56ad5f67aeb0859bf84d92ebsalomon@google.com    builder->fFSCode.appendf("\tvec2 clampCoord = clamp(%s, %s.xy, %s.zw);\n",
5892b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com                           coords,
5957143a2d87ef5fb7276ffc11abaa2e77d31f0ad8tomhudson@google.com                           builder->getUniformCStr(fNameUni),
6057143a2d87ef5fb7276ffc11abaa2e77d31f0ad8tomhudson@google.com                           builder->getUniformCStr(fNameUni));
612f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
62868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com    builder->fFSCode.appendf("\t%s = ", outputColor);
63f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com    builder->appendTextureLookupAndModulate(&builder->fFSCode,
64f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com                                            inputColor,
65f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com                                            samplers[0],
66f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com                                            "clampCoord");
67868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com    builder->fFSCode.append(";\n");
682f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com}
692f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
7028a15fb8d603847949a61657ef5cb73ed9915021bsalomon@google.comvoid GrGLTextureDomainEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
7128a15fb8d603847949a61657ef5cb73ed9915021bsalomon@google.com    const GrTextureDomainEffect& effect =
7228a15fb8d603847949a61657ef5cb73ed9915021bsalomon@google.com        static_cast<const GrTextureDomainEffect&>(*stage.getEffect());
732f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com    const GrRect& domain = effect.domain();
742f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
752f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com    float values[4] = {
7681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com        SkScalarToFloat(domain.left()),
7781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com        SkScalarToFloat(domain.top()),
7881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com        SkScalarToFloat(domain.right()),
7981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com        SkScalarToFloat(domain.bottom())
802f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com    };
812f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com    // vertical flip if necessary
822d0baded0f45dfde9dc8c25313ff14ea18c0c915bsalomon@google.com    if (GrSurface::kBottomLeft_Origin == effect.texture(0)->origin()) {
832f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com        values[1] = 1.0f - values[1];
842f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com        values[3] = 1.0f - values[3];
852f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com        // The top and bottom were just flipped, so correct the ordering
862f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com        // of elements so that values = (l, t, r, b).
872f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com        SkTSwap(values[1], values[3]);
882f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com    }
8992b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com    if (0 != memcmp(values, fPrevDomain, 4 * sizeof(GrGLfloat))) {
9092b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com        uman.set4fv(fNameUni, 0, 1, values);
9192b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com    }
9292b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com    fEffectMatrix.setData(uman,
9392b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com                          effect.getMatrix(),
9492b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com                          stage.getCoordChangeMatrix(),
9592b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com                          effect.texture(0));
961aa90cf11e136a722bce71dd77f4bb03cc2b56f8skia.committer@gmail.com}
9792b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com
9892b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.comGrGLEffect::EffectKey GrGLTextureDomainEffect::GenKey(const GrEffectStage& stage, const GrGLCaps&) {
9992b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com    const GrTextureDomainEffect& effect =
10092b6a94ac103ea3f37a8f9f02072ef884cc17a7cbsalomon@google.com        static_cast<const GrTextureDomainEffect&>(*stage.getEffect());
10131ca955c0611712528c0897928bf3b1100be2fcdbsalomon@google.com    return GrGLEffectMatrix::GenKey(effect.getMatrix(), stage.getCoordChangeMatrix(), effect.texture(0));
1022f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com}
1032f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
1042f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
1052f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com///////////////////////////////////////////////////////////////////////////////
1062f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
1071ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.comGrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture, const GrRect& domain)
1082f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com    : GrSingleTextureEffect(texture)
1092f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com    , fTextureDomain(domain) {
1102f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com}
1112f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
1121ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.comGrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture,
1131ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com                                             const GrRect& domain,
1141ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com                                             const GrTextureParams& params)
1151ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com    : GrSingleTextureEffect(texture, params)
1161ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com    , fTextureDomain(domain) {
1171ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com}
1181ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com
1192f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.comGrTextureDomainEffect::~GrTextureDomainEffect() {
1202f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
1212f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com}
1222f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
123396e61fe440590744345e0c56970b26ab464591dbsalomon@google.comconst GrBackendEffectFactory& GrTextureDomainEffect::getFactory() const {
124396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com    return GrTBackendEffectFactory<GrTextureDomainEffect>::getInstance();
1252f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com}
1262f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com
127a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.combool GrTextureDomainEffect::isEqual(const GrEffect& sBase) const {
1282f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com    const GrTextureDomainEffect& s = static_cast<const GrTextureDomainEffect&>(sBase);
1292f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com    return (INHERITED::isEqual(sBase) && this->fTextureDomain == s.fTextureDomain);
1302f68e7684bb2ecdf0c03a513c31d0626d2caf752tomhudson@google.com}
1310a7672f85ef7655b343679609d02018f83fcfc23bsalomon@google.com
1320a7672f85ef7655b343679609d02018f83fcfc23bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
1330a7672f85ef7655b343679609d02018f83fcfc23bsalomon@google.com
134f271cc7183fe48ac64d2d9a454eb013c91b42d53bsalomon@google.comGR_DEFINE_EFFECT_TEST(GrTextureDomainEffect);
1350a7672f85ef7655b343679609d02018f83fcfc23bsalomon@google.com
136a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.comGrEffect* GrTextureDomainEffect::TestCreate(SkRandom* random,
137a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.com                                            GrContext* context,
138a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.com                                            GrTexture* textures[]) {
1396f261bed0252e3f3caa595798364e0bf12a2573absalomon@google.com    int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
1406f261bed0252e3f3caa595798364e0bf12a2573absalomon@google.com                                      GrEffectUnitTest::kAlphaTextureIdx;
1410a7672f85ef7655b343679609d02018f83fcfc23bsalomon@google.com    GrRect domain;
1420a7672f85ef7655b343679609d02018f83fcfc23bsalomon@google.com    domain.fLeft = random->nextUScalar1();
1430a7672f85ef7655b343679609d02018f83fcfc23bsalomon@google.com    domain.fRight = random->nextRangeScalar(domain.fLeft, SK_Scalar1);
1440a7672f85ef7655b343679609d02018f83fcfc23bsalomon@google.com    domain.fTop = random->nextUScalar1();
1450a7672f85ef7655b343679609d02018f83fcfc23bsalomon@google.com    domain.fBottom = random->nextRangeScalar(domain.fTop, SK_Scalar1);
1460a7672f85ef7655b343679609d02018f83fcfc23bsalomon@google.com    return SkNEW_ARGS(GrTextureDomainEffect, (textures[texIdx], domain));
1470a7672f85ef7655b343679609d02018f83fcfc23bsalomon@google.com}
148