1 | /* |
2 | * Copyright 2018 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 | /************************************************************************************************** |
9 | *** This file was autogenerated from GrConfigConversionEffect.fp; do not modify. |
10 | **************************************************************************************************/ |
11 | #ifndef GrConfigConversionEffect_DEFINED |
12 | #define GrConfigConversionEffect_DEFINED |
13 | #include "include/core/SkTypes.h" |
14 | #include "include/core/SkM44.h" |
15 | |
16 | #include "include/gpu/GrContext.h" |
17 | #include "src/gpu/GrBitmapTextureMaker.h" |
18 | #include "src/gpu/GrClip.h" |
19 | #include "src/gpu/GrContextPriv.h" |
20 | #include "src/gpu/GrImageInfo.h" |
21 | #include "src/gpu/GrRenderTargetContext.h" |
22 | |
23 | #include "src/gpu/GrCoordTransform.h" |
24 | #include "src/gpu/GrFragmentProcessor.h" |
25 | class GrConfigConversionEffect : public GrFragmentProcessor { |
26 | public: |
27 | static bool TestForPreservingPMConversions(GrContext* context) { |
28 | static constexpr int kSize = 256; |
29 | static constexpr GrColorType kColorType = GrColorType::kRGBA_8888; |
30 | SkAutoTMalloc<uint32_t> data(kSize * kSize * 3); |
31 | uint32_t* srcData = data.get(); |
32 | uint32_t* firstRead = data.get() + kSize * kSize; |
33 | uint32_t* secondRead = data.get() + 2 * kSize * kSize; |
34 | |
35 | // Fill with every possible premultiplied A, color channel value. There will be 256-y |
36 | // duplicate values in row y. We set r, g, and b to the same value since they are handled |
37 | // identically. |
38 | for (int y = 0; y < kSize; ++y) { |
39 | for (int x = 0; x < kSize; ++x) { |
40 | uint8_t* color = reinterpret_cast<uint8_t*>(&srcData[kSize * y + x]); |
41 | color[3] = y; |
42 | color[2] = std::min(x, y); |
43 | color[1] = std::min(x, y); |
44 | color[0] = std::min(x, y); |
45 | } |
46 | } |
47 | memset(firstRead, 0, kSize * kSize * sizeof(uint32_t)); |
48 | memset(secondRead, 0, kSize * kSize * sizeof(uint32_t)); |
49 | |
50 | const SkImageInfo ii = |
51 | SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType); |
52 | |
53 | auto readRTC = GrRenderTargetContext::Make(context, kColorType, nullptr, |
54 | SkBackingFit::kExact, {kSize, kSize}); |
55 | auto tempRTC = GrRenderTargetContext::Make(context, kColorType, nullptr, |
56 | SkBackingFit::kExact, {kSize, kSize}); |
57 | if (!readRTC || !readRTC->asTextureProxy() || !tempRTC) { |
58 | return false; |
59 | } |
60 | // Adding discard to appease vulkan validation warning about loading uninitialized data on |
61 | // draw |
62 | readRTC->discard(); |
63 | |
64 | // This function is only ever called if we are in a GrContext that has a GrGpu since we are |
65 | // calling read pixels here. Thus the pixel data will be uploaded immediately and we don't |
66 | // need to keep the pixel data alive in the proxy. Therefore the ReleaseProc is nullptr. |
67 | SkBitmap bitmap; |
68 | bitmap.installPixels(ii, srcData, 4 * kSize); |
69 | bitmap.setImmutable(); |
70 | |
71 | GrBitmapTextureMaker maker(context, bitmap, GrImageTexGenPolicy::kNew_Uncached_Budgeted); |
72 | auto dataView = maker.view(GrMipMapped::kNo); |
73 | if (!dataView) { |
74 | return false; |
75 | } |
76 | |
77 | static const SkRect kRect = SkRect::MakeIWH(kSize, kSize); |
78 | |
79 | // We do a PM->UPM draw from dataTex to readTex and read the data. Then we do a UPM->PM draw |
80 | // from readTex to tempTex followed by a PM->UPM draw to readTex and finally read the data. |
81 | // We then verify that two reads produced the same values. |
82 | |
83 | GrPaint paint1; |
84 | GrPaint paint2; |
85 | GrPaint paint3; |
86 | std::unique_ptr<GrFragmentProcessor> pmToUPM( |
87 | new GrConfigConversionEffect(PMConversion::kToUnpremul)); |
88 | std::unique_ptr<GrFragmentProcessor> upmToPM( |
89 | new GrConfigConversionEffect(PMConversion::kToPremul)); |
90 | |
91 | paint1.addColorFragmentProcessor( |
92 | GrTextureEffect::Make(std::move(dataView), kPremul_SkAlphaType)); |
93 | paint1.addColorFragmentProcessor(pmToUPM->clone()); |
94 | paint1.setPorterDuffXPFactory(SkBlendMode::kSrc); |
95 | |
96 | readRTC->fillRectToRect(GrNoClip(), std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect, |
97 | kRect); |
98 | if (!readRTC->readPixels(ii, firstRead, 0, {0, 0})) { |
99 | return false; |
100 | } |
101 | |
102 | // Adding discard to appease vulkan validation warning about loading uninitialized data on |
103 | // draw |
104 | tempRTC->discard(); |
105 | |
106 | paint2.addColorFragmentProcessor( |
107 | GrTextureEffect::Make(readRTC->readSurfaceView(), kUnpremul_SkAlphaType)); |
108 | paint2.addColorFragmentProcessor(std::move(upmToPM)); |
109 | paint2.setPorterDuffXPFactory(SkBlendMode::kSrc); |
110 | |
111 | tempRTC->fillRectToRect(GrNoClip(), std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect, |
112 | kRect); |
113 | |
114 | paint3.addColorFragmentProcessor( |
115 | GrTextureEffect::Make(tempRTC->readSurfaceView(), kPremul_SkAlphaType)); |
116 | paint3.addColorFragmentProcessor(std::move(pmToUPM)); |
117 | paint3.setPorterDuffXPFactory(SkBlendMode::kSrc); |
118 | |
119 | readRTC->fillRectToRect(GrNoClip(), std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect, |
120 | kRect); |
121 | |
122 | if (!readRTC->readPixels(ii, secondRead, 0, {0, 0})) { |
123 | return false; |
124 | } |
125 | |
126 | for (int y = 0; y < kSize; ++y) { |
127 | for (int x = 0; x <= y; ++x) { |
128 | if (firstRead[kSize * y + x] != secondRead[kSize * y + x]) { |
129 | return false; |
130 | } |
131 | } |
132 | } |
133 | |
134 | return true; |
135 | } |
136 | |
137 | static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp, |
138 | PMConversion pmConversion) { |
139 | if (!fp) { |
140 | return nullptr; |
141 | } |
142 | std::unique_ptr<GrFragmentProcessor> ccFP(new GrConfigConversionEffect(pmConversion)); |
143 | std::unique_ptr<GrFragmentProcessor> fpPipeline[] = {std::move(fp), std::move(ccFP)}; |
144 | return GrFragmentProcessor::RunInSeries(fpPipeline, 2); |
145 | } |
146 | GrConfigConversionEffect(const GrConfigConversionEffect& src); |
147 | std::unique_ptr<GrFragmentProcessor> clone() const override; |
148 | const char* name() const override { return "ConfigConversionEffect" ; } |
149 | PMConversion pmConversion; |
150 | |
151 | private: |
152 | GrConfigConversionEffect(PMConversion pmConversion) |
153 | : INHERITED(kGrConfigConversionEffect_ClassID, kNone_OptimizationFlags) |
154 | , pmConversion(pmConversion) {} |
155 | GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; |
156 | void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; |
157 | bool onIsEqual(const GrFragmentProcessor&) const override; |
158 | GR_DECLARE_FRAGMENT_PROCESSOR_TEST |
159 | typedef GrFragmentProcessor INHERITED; |
160 | }; |
161 | #endif |
162 | |