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 
15 #include "GrClip.h"
16 #include "GrContext.h"
17 #include "GrContextPriv.h"
18 #include "GrProxyProvider.h"
19 #include "GrRenderTargetContext.h"
20 #include "GrFragmentProcessor.h"
21 #include "GrCoordTransform.h"
22 class GrConfigConversionEffect : public GrFragmentProcessor {
23 public:
TestForPreservingPMConversions(GrContext * context)24     static bool TestForPreservingPMConversions(GrContext* context) {
25         static constexpr int kSize = 256;
26         static constexpr GrPixelConfig kConfig = kRGBA_8888_GrPixelConfig;
27         static constexpr SkColorType kColorType = kRGBA_8888_SkColorType;
28         const GrBackendFormat format =
29                 context->contextPriv().caps()->getBackendFormatFromColorType(kColorType);
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] = SkTMin(x, y);
43                 color[1] = SkTMin(x, y);
44                 color[0] = SkTMin(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         sk_sp<GrRenderTargetContext> readRTC(context->contextPriv().makeDeferredRenderTargetContext(
54                 format, SkBackingFit::kExact, kSize, kSize, kConfig, nullptr));
55         sk_sp<GrRenderTargetContext> tempRTC(context->contextPriv().makeDeferredRenderTargetContext(
56                 format, SkBackingFit::kExact, kSize, kSize, kConfig, nullptr));
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         GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
65 
66         SkPixmap pixmap(ii, srcData, 4 * kSize);
67 
68         // This function is only ever called if we are in a GrContext that has a GrGpu since we are
69         // calling read pixels here. Thus the pixel data will be uploaded immediately and we don't
70         // need to keep the pixel data alive in the proxy. Therefore the ReleaseProc is nullptr.
71         sk_sp<SkImage> image = SkImage::MakeFromRaster(pixmap, nullptr, nullptr);
72 
73         sk_sp<GrTextureProxy> dataProxy = proxyProvider->createTextureProxy(
74                 std::move(image), kNone_GrSurfaceFlags, 1, SkBudgeted::kYes, SkBackingFit::kExact);
75         if (!dataProxy) {
76             return false;
77         }
78 
79         static const SkRect kRect = SkRect::MakeIWH(kSize, kSize);
80 
81         // We do a PM->UPM draw from dataTex to readTex and read the data. Then we do a UPM->PM draw
82         // from readTex to tempTex followed by a PM->UPM draw to readTex and finally read the data.
83         // We then verify that two reads produced the same values.
84 
85         GrPaint paint1;
86         GrPaint paint2;
87         GrPaint paint3;
88         std::unique_ptr<GrFragmentProcessor> pmToUPM(
89                 new GrConfigConversionEffect(PMConversion::kToUnpremul));
90         std::unique_ptr<GrFragmentProcessor> upmToPM(
91                 new GrConfigConversionEffect(PMConversion::kToPremul));
92 
93         paint1.addColorTextureProcessor(dataProxy, SkMatrix::I());
94         paint1.addColorFragmentProcessor(pmToUPM->clone());
95         paint1.setPorterDuffXPFactory(SkBlendMode::kSrc);
96 
97         readRTC->fillRectToRect(GrNoClip(), std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect,
98                                 kRect);
99         if (!readRTC->readPixels(ii, firstRead, 0, 0, 0)) {
100             return false;
101         }
102 
103         // Adding discard to appease vulkan validation warning about loading uninitialized data on
104         // draw
105         tempRTC->discard();
106 
107         paint2.addColorTextureProcessor(readRTC->asTextureProxyRef(), SkMatrix::I());
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.addColorTextureProcessor(tempRTC->asTextureProxyRef(), SkMatrix::I());
115         paint3.addColorFragmentProcessor(std::move(pmToUPM));
116         paint3.setPorterDuffXPFactory(SkBlendMode::kSrc);
117 
118         readRTC->fillRectToRect(GrNoClip(), std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect,
119                                 kRect);
120 
121         if (!readRTC->readPixels(ii, secondRead, 0, 0, 0)) {
122             return false;
123         }
124 
125         for (int y = 0; y < kSize; ++y) {
126             for (int x = 0; x <= y; ++x) {
127                 if (firstRead[kSize * y + x] != secondRead[kSize * y + x]) {
128                     return false;
129                 }
130             }
131         }
132 
133         return true;
134     }
pmConversion()135     const PMConversion& pmConversion() const { return fPmConversion; }
136 
Make(std::unique_ptr<GrFragmentProcessor> fp,PMConversion pmConversion)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;
name()148     const char* name() const override { return "ConfigConversionEffect"; }
149 
150 private:
GrConfigConversionEffect(PMConversion pmConversion)151     GrConfigConversionEffect(PMConversion pmConversion)
152             : INHERITED(kGrConfigConversionEffect_ClassID, kNone_OptimizationFlags)
153             , fPmConversion(pmConversion) {}
154     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
155     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
156     bool onIsEqual(const GrFragmentProcessor&) const override;
157     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
158     PMConversion fPmConversion;
159     typedef GrFragmentProcessor INHERITED;
160 };
161 #endif
162