diff options
author | 2013-10-23 05:42:03 +0000 | |
---|---|---|
committer | 2013-10-23 05:42:03 +0000 | |
commit | a34995e18b1f0a7d8c9f23451718bb30ff0105b0 (patch) | |
tree | 88164026f4b0e31a1acc164ed39191ea34fdee57 /tests | |
parent | afba64434d23f135392f0e9e4f00a9c6a077a0ec (diff) |
Implement SkColorFilter as a GrGLEffect
Adds GrEffect::willUseInputColor() which indicates whether or not the
input color affects the output of the effect. This is needed for
certain Xfermodes, such as kSrc_Mode. For these modes the color filter
will not use the input color.
An effect with GrEffect::willUseInputColor() true will cause all color
or coverage effects before it to be discarded, as their computations
cannot affect the output. In these cases program is marked as having
white input color.
This fixes an assert when Skia is compiled in a mode that prefers
using uniforms instead of attributes for constants. (Flags
GR_GL_USE_NV_PATH_RENDERING or GR_GL_NO_CONSTANT_ATTRIBUTES). Using
attributes hides the problem where the fragment shader does not need
input color for color filters that ignore DST part of the filter. The
assert would be hit when uniform manager tries to bind an uniform which
has been optimized away by the shader compiler.
Adds specific GrGLSLExpr4 and GrGLSLExpr1 classes. This way the GLSL
expressions like "(v - src.a)" can remain somewhat readable in form of
"(v - src.a())". The GrGLSLExpr<typename> template implements the
generic functionality, GrGLSLExprX is the specialization that exposes
the type-safe interface to this functionality.
Also adds operators so that GLSL binary operators of the form
"(float * vecX)" can be expressed in C++. Before only the equivalent
"(vecX * float)" was possible. This reverts the common blending
calculations to more conventional order, such as "(1-a) * c" instead of
"c * (1-a)".
Changes GrGLSLExpr1::OnesStr from 1 to 1.0 in order to preserve the
color filter blending formula string the same (with the exception of
variable name change).
Shaders change in case of input color being needed:
- vec4 filteredColor;
- filteredColor = (((1.0 - uFilterColor.a) * output_Stage0) + uFilterColor);
- fsColorOut = filteredColor;
+ vec4 output_Stage1;
+ { // Stage 1: ModeColorFilterEffect
+ output_Stage1 = (((1.0 - uFilterColor_Stage1.a) * output_Stage0) + uFilterColor_Stage1);
+ }
+ fsColorOut = output_Stage1;
Shaders change in case of input color being not needed:
-uniform vec4 uFilterColor;
-in vec4 vColor;
+uniform vec4 uFilterColor_Stage0;
out vec4 fsColorOut;
void main() {
- vec4 filteredColor;
- filteredColor = uFilterColor;
- fsColorOut = filteredColor;
+ vec4 output_Stage0;
+ { // Stage 0: ModeColorFilterEffect
+ output_Stage0 = uFilterColor_Stage0;
+ }
+ fsColorOut = output_Stage0;
}
R=bsalomon@google.com, robertphillips@google.com, jvanverth@google.com
Author: kkinnunen@nvidia.com
Review URL: https://codereview.chromium.org/25023003
git-svn-id: http://skia.googlecode.com/svn/trunk@11912 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'tests')
-rw-r--r-- | tests/GLProgramsTest.cpp | 3 | ||||
-rw-r--r-- | tests/GpuColorFilterTest.cpp | 131 |
2 files changed, 131 insertions, 3 deletions
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index 12107f4356..a3cb3bc65d 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -61,9 +61,6 @@ void GrGLProgramDesc::setRandom(SkRandom* random, currAttribIndex++ : -1; - header->fColorFilterXfermode = static_cast<SkXfermode::Mode>( - random->nextULessThan(SkXfermode::kLastCoeffMode + 1)); - #if GR_GL_EXPERIMENTAL_GS header->fExperimentalGS = gpu->caps()->geometryShaderSupport() && random->nextBool(); #endif diff --git a/tests/GpuColorFilterTest.cpp b/tests/GpuColorFilterTest.cpp new file mode 100644 index 0000000000..9fb1c770e1 --- /dev/null +++ b/tests/GpuColorFilterTest.cpp @@ -0,0 +1,131 @@ + +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#if SK_SUPPORT_GPU + +#include "GrContext.h" +#include "GrContextFactory.h" +#include "GrEffect.h" +#include "SkColorFilter.h" +#include "Test.h" +#include "SkGr.h" + +namespace { + +static GrColor filterColor(const GrColor& color, uint32_t flags) { + uint32_t mask = 0; + if (flags & kR_GrColorComponentFlag) { + mask = 0xFF << GrColor_SHIFT_R; + } + if (flags & kG_GrColorComponentFlag) { + mask |= 0xFF << GrColor_SHIFT_G; + } + if (flags & kB_GrColorComponentFlag) { + mask |= 0xFF << GrColor_SHIFT_B; + } + if (flags & kA_GrColorComponentFlag) { + mask |= 0xFF << GrColor_SHIFT_A; + } + return color & mask; +} + +static void test_getConstantColorComponents(skiatest::Reporter* reporter, GrContext* grContext) { + struct GetConstantComponentTestCase { + // "Shape drawn with" + uint32_t inputComponents; // "rgb of", "red of", "alpha of", ... + GrColor inputColor; // "[color]" + + SkColor filterColor; // "with filter color [color]" + SkXfermode::Mode filterMode; // "in mode [mode]" + + // "produces" + uint32_t outputComponents; // "rgb of", "red of", "alpha of", ... + GrColor outputColor; // "[color]" + }; + + // Shorthands. + enum { + kR = kR_GrColorComponentFlag, + kG = kG_GrColorComponentFlag, + kB = kB_GrColorComponentFlag, + kA = kA_GrColorComponentFlag, + kRGB = kRGB_GrColorComponentFlags, + kRGBA = kRGBA_GrColorComponentFlags + }; + + // Note: below, SkColors are non-premultiplied, where as GrColors are premultiplied. + + const SkColor c1 = SkColorSetARGB(200, 200, 200, 200); + const SkColor c2 = SkColorSetARGB(60, 60, 60, 60); + const GrColor gr_c1 = SkColor2GrColor(c1); + const GrColor gr_c2 = SkColor2GrColor(c2); + + const GrColor gr_black = GrColorPackRGBA(0, 0, 0, 0); + const GrColor gr_white = GrColorPackRGBA(255, 255, 255, 255); + const GrColor gr_whiteTrans = GrColorPackRGBA(128, 128, 128, 128); + + GetConstantComponentTestCase filterTests[] = { + // A color filtered with Clear produces black. + { kRGBA, gr_white, SK_ColorBLACK, SkXfermode::kClear_Mode, kRGBA, gr_black }, + { kRGBA, gr_c1, SK_ColorWHITE, SkXfermode::kClear_Mode, kRGBA, gr_black }, + { kR, gr_white, c1, SkXfermode::kClear_Mode, kRGBA, gr_black }, + + // A color filtered with a color in mode Src, produces the filter color. + { kRGBA, gr_c2, c1, SkXfermode::kSrc_Mode, kRGBA, gr_c1 }, + { kA, gr_c1, c1, SkXfermode::kSrc_Mode, kRGBA, gr_c1 }, + + // A color filtered with SrcOver produces a color. + { kRGBA, gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kRGBA, GrColorPackRGBA(164, 164, 164, 192)}, + // An unknown color with known alpha filtered with SrcOver produces an unknown color with known alpha. + { kA , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kA , GrColorPackRGBA(0, 0, 0, 192)}, + // A color with unknown alpha filtered with SrcOver produces a color with unknown alpha. + { kRGB , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kRGB, GrColorPackRGBA(164, 164, 164, 0)}, + + // A color filtered with DstOver produces a color. + { kRGBA, gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, kRGBA, GrColorPackRGBA(178, 178, 178, 192)}, + // An unknown color with known alpha filtered with DstOver produces an unknown color with known alpha. + { kA , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, kA , GrColorPackRGBA(0, 0, 0, 192)}, + // A color with unknown alpha filtered with DstOver produces an unknown color. + { kRGB , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, 0 , gr_black}, + + // An unknown color with known alpha and red component filtered with Multiply produces an unknown color with known red and alpha. + { kR|kA , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kModulate_Mode, kR|kA, GrColorPackRGBA(50, 0, 0, 64) } + }; + + for (size_t i = 0; i < SK_ARRAY_COUNT(filterTests); ++i) { + const GetConstantComponentTestCase& test = filterTests[i]; + SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(test.filterColor, test.filterMode)); + SkAutoTUnref<GrEffectRef> grEffect(cf->asNewEffect(grContext)); + GrColor color = test.inputColor; + uint32_t components = test.inputComponents; + grEffect->get()->getConstantColorComponents(&color, &components); + + REPORTER_ASSERT(reporter, filterColor(color, components) == test.outputColor); + REPORTER_ASSERT(reporter, test.outputComponents == components); + } +} + +static void TestGpuColorFilter(skiatest::Reporter* reporter, GrContextFactory* factory) { + for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { + GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type); + + GrContext* grContext = factory->get(glType); + if (NULL == grContext) { + continue; + } + + test_getConstantColorComponents(reporter, grContext); + } +} + +} + +#include "TestClassDef.h" +DEFINE_GPUTESTCLASS("GpuColorFilter", TestGpuColorFilterClass, TestGpuColorFilter) + +#endif |