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"
23class GrConfigConversionEffect : public GrFragmentProcessor {
24public:
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
145private:
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