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 "SkTypes.h"
14 #if SK_SUPPORT_GPU
15 
16 #include "GrClip.h"
17 #include "GrContext.h"
18 #include "GrContextPriv.h"
19 #include "GrProxyProvider.h"
20 #include "GrRenderTargetContext.h"
21 #include "GrFragmentProcessor.h"
22 #include "GrCoordTransform.h"
23 class GrConfigConversionEffect : public GrFragmentProcessor {
24 public:
25     static bool TestForPreservingPMConversions(GrContext* context) {
26         static constexpr int kSize = 256;
27         static constexpr GrPixelConfig kConfig = kRGBA_8888_GrPixelConfig;
28         SkAutoTMalloc<uint32_t> data(kSize * kSize * 3);
29         uint32_t* srcData = data.get();
30         uint32_t* firstRead = data.get() + kSize * kSize;
31         uint32_t* secondRead = data.get() + 2 * kSize * kSize;
32 
33         // Fill with every possible premultiplied A, color channel value. There will be 256-y
34         // duplicate values in row y. We set r, g, and b to the same value since they are handled
35         // identically.
36         for (int y = 0; y < kSize; ++y) {
37             for (int x = 0; x < kSize; ++x) {
38                 uint8_t* color = reinterpret_cast<uint8_t*>(&srcData[kSize * y + x]);
39                 color[3] = y;
40                 color[2] = SkTMin(x, y);
41                 color[1] = SkTMin(x, y);
42                 color[0] = SkTMin(x, y);
43             }
44         }
45 
46         const SkImageInfo ii =
47                 SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
48 
49         sk_sp<GrRenderTargetContext> readRTC(context->makeDeferredRenderTargetContext(
50                 SkBackingFit::kExact, kSize, kSize, kConfig, nullptr));
51         sk_sp<GrRenderTargetContext> tempRTC(context->makeDeferredRenderTargetContext(
52                 SkBackingFit::kExact, kSize, kSize, kConfig, nullptr));
53         if (!readRTC || !readRTC->asTextureProxy() || !tempRTC) {
54             return false;
55         }
56         // Adding discard to appease vulkan validation warning about loading uninitialized data on
57         // draw
58         readRTC->discard();
59 
60         GrSurfaceDesc desc;
61         desc.fOrigin = kTopLeft_GrSurfaceOrigin;
62         desc.fWidth = kSize;
63         desc.fHeight = kSize;
64         desc.fConfig = kConfig;
65 
66         GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
67 
68         sk_sp<GrTextureProxy> dataProxy =
69                 proxyProvider->createTextureProxy(desc, SkBudgeted::kYes, data, 0);
70         if (!dataProxy) {
71             return false;
72         }
73 
74         static const SkRect kRect = SkRect::MakeIWH(kSize, kSize);
75 
76         // We do a PM->UPM draw from dataTex to readTex and read the data. Then we do a UPM->PM draw
77         // from readTex to tempTex followed by a PM->UPM draw to readTex and finally read the data.
78         // We then verify that two reads produced the same values.
79 
80         GrPaint paint1;
81         GrPaint paint2;
82         GrPaint paint3;
83         std::unique_ptr<GrFragmentProcessor> pmToUPM(
84                 new GrConfigConversionEffect(PMConversion::kToUnpremul));
85         std::unique_ptr<GrFragmentProcessor> upmToPM(
86                 new GrConfigConversionEffect(PMConversion::kToPremul));
87 
88         paint1.addColorTextureProcessor(dataProxy, SkMatrix::I());
89         paint1.addColorFragmentProcessor(pmToUPM->clone());
90         paint1.setPorterDuffXPFactory(SkBlendMode::kSrc);
91 
92         readRTC->fillRectToRect(GrNoClip(), std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect,
93                                 kRect);
94         if (!readRTC->readPixels(ii, firstRead, 0, 0, 0)) {
95             return false;
96         }
97 
98         // Adding discard to appease vulkan validation warning about loading uninitialized data on
99         // draw
100         tempRTC->discard();
101 
102         paint2.addColorTextureProcessor(readRTC->asTextureProxyRef(), SkMatrix::I());
103         paint2.addColorFragmentProcessor(std::move(upmToPM));
104         paint2.setPorterDuffXPFactory(SkBlendMode::kSrc);
105 
106         tempRTC->fillRectToRect(GrNoClip(), std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect,
107                                 kRect);
108 
109         paint3.addColorTextureProcessor(tempRTC->asTextureProxyRef(), SkMatrix::I());
110         paint3.addColorFragmentProcessor(std::move(pmToUPM));
111         paint3.setPorterDuffXPFactory(SkBlendMode::kSrc);
112 
113         readRTC->fillRectToRect(GrNoClip(), std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect,
114                                 kRect);
115 
116         if (!readRTC->readPixels(ii, secondRead, 0, 0, 0)) {
117             return false;
118         }
119 
120         for (int y = 0; y < kSize; ++y) {
121             for (int x = 0; x <= y; ++x) {
122                 if (firstRead[kSize * y + x] != secondRead[kSize * y + x]) {
123                     return false;
124                 }
125             }
126         }
127 
128         return true;
129     }
130     PMConversion pmConversion() const { return fPmConversion; }
131 
132     static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
133                                                      PMConversion pmConversion) {
134         if (!fp) {
135             return nullptr;
136         }
137         std::unique_ptr<GrFragmentProcessor> ccFP(new GrConfigConversionEffect(pmConversion));
138         std::unique_ptr<GrFragmentProcessor> fpPipeline[] = {std::move(fp), std::move(ccFP)};
139         return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
140     }
141     GrConfigConversionEffect(const GrConfigConversionEffect& src);
142     std::unique_ptr<GrFragmentProcessor> clone() const override;
143     const char* name() const override { return "ConfigConversionEffect"; }
144 
145 private:
146     GrConfigConversionEffect(PMConversion pmConversion)
147             : INHERITED(kGrConfigConversionEffect_ClassID, kNone_OptimizationFlags)
148             , fPmConversion(pmConversion) {}
149     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
150     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
151     bool onIsEqual(const GrFragmentProcessor&) const override;
152     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
153     PMConversion fPmConversion;
154     typedef GrFragmentProcessor INHERITED;
155 };
156 #endif
157 #endif
158