Home | History | Annotate | Download | only in gm
      1 /*
      2  * Copyright 2014 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 // This test only works with the GPU backend.
      9 
     10 #include "gm.h"
     11 
     12 #include "GrContext.h"
     13 #include "GrContextPriv.h"
     14 #include "GrProxyProvider.h"
     15 #include "GrRenderTargetContextPriv.h"
     16 #include "GrTextureProxy.h"
     17 #include "SkBitmap.h"
     18 #include "SkGr.h"
     19 #include "SkGradientShader.h"
     20 #include "effects/GrYUVtoRGBEffect.h"
     21 #include "ops/GrDrawOp.h"
     22 #include "ops/GrFillRectOp.h"
     23 
     24 #define YSIZE 8
     25 #define USIZE 4
     26 #define VSIZE 4
     27 
     28 namespace skiagm {
     29 /**
     30  * This GM directly exercises GrYUVtoRGBEffect.
     31  */
     32 class YUVtoRGBEffect : public GpuGM {
     33 public:
     34     YUVtoRGBEffect() {
     35         this->setBGColor(0xFFFFFFFF);
     36     }
     37 
     38 protected:
     39     SkString onShortName() override {
     40         return SkString("yuv_to_rgb_effect");
     41     }
     42 
     43     SkISize onISize() override {
     44         int numRows = kLastEnum_SkYUVColorSpace + 1;
     45         return SkISize::Make(238, kDrawPad + numRows * kColorSpaceOffset);
     46     }
     47 
     48     void onOnceBeforeDraw() override {
     49         SkBitmap bmp[3];
     50         SkImageInfo yinfo = SkImageInfo::MakeA8(YSIZE, YSIZE);
     51         bmp[0].allocPixels(yinfo);
     52         SkImageInfo uinfo = SkImageInfo::MakeA8(USIZE, USIZE);
     53         bmp[1].allocPixels(uinfo);
     54         SkImageInfo vinfo = SkImageInfo::MakeA8(VSIZE, VSIZE);
     55         bmp[2].allocPixels(vinfo);
     56         unsigned char* pixels[3];
     57         for (int i = 0; i < 3; ++i) {
     58             pixels[i] = (unsigned char*)bmp[i].getPixels();
     59         }
     60         int color[] = {0, 85, 170};
     61         const int limit[] = {255, 0, 255};
     62         const int invl[]  = {0, 255, 0};
     63         const int inc[]   = {1, -1, 1};
     64         for (int i = 0; i < 3; ++i) {
     65             const size_t nbBytes = bmp[i].rowBytes() * bmp[i].height();
     66             for (size_t j = 0; j < nbBytes; ++j) {
     67                 pixels[i][j] = (unsigned char)color[i];
     68                 color[i] = (color[i] == limit[i]) ? invl[i] : color[i] + inc[i];
     69             }
     70         }
     71         for (int i = 0; i < 3; ++i) {
     72             fImage[i] = SkImage::MakeFromBitmap(bmp[i]);
     73         }
     74     }
     75 
     76     DrawResult onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
     77                       SkCanvas* canvas, SkString* errorMsg) override {
     78         GrProxyProvider* proxyProvider = context->priv().proxyProvider();
     79         sk_sp<GrTextureProxy> proxies[3];
     80 
     81         for (int i = 0; i < 3; ++i) {
     82             proxies[i] = proxyProvider->createTextureProxy(fImage[i], kNone_GrSurfaceFlags, 1,
     83                                                            SkBudgeted::kYes, SkBackingFit::kExact);
     84             if (!proxies[i]) {
     85                 *errorMsg = "Failed to create proxy";
     86                 return DrawResult::kFail;
     87             }
     88         }
     89 
     90         for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace; ++space) {
     91             SkRect renderRect = SkRect::MakeWH(SkIntToScalar(fImage[0]->width()),
     92                                                SkIntToScalar(fImage[0]->height()));
     93             renderRect.outset(kDrawPad, kDrawPad);
     94 
     95             SkScalar y = kDrawPad + kTestPad + space * kColorSpaceOffset;
     96             SkScalar x = kDrawPad + kTestPad;
     97 
     98             const int indices[6][3] = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2},
     99                                        {1, 2, 0}, {2, 0, 1}, {2, 1, 0}};
    100 
    101             for (int i = 0; i < 6; ++i) {
    102                 SkYUVAIndex yuvaIndices[4] = {
    103                     { indices[i][0], SkColorChannel::kR },
    104                     { indices[i][1], SkColorChannel::kR },
    105                     { indices[i][2], SkColorChannel::kR },
    106                     { -1, SkColorChannel::kA }
    107                 };
    108 
    109                 std::unique_ptr<GrFragmentProcessor> fp(
    110                         GrYUVtoRGBEffect::Make(proxies, yuvaIndices,
    111                                                static_cast<SkYUVColorSpace>(space),
    112                                                GrSamplerState::Filter::kNearest));
    113                 if (fp) {
    114                     GrPaint grPaint;
    115                     grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
    116                     grPaint.addColorFragmentProcessor(std::move(fp));
    117                     SkMatrix viewMatrix;
    118                     viewMatrix.setTranslate(x, y);
    119                     renderTargetContext->priv().testingOnly_addDrawOp(
    120                             GrFillRectOp::Make(context, std::move(grPaint), GrAAType::kNone,
    121                                                viewMatrix, renderRect));
    122                 }
    123                 x += renderRect.width() + kTestPad;
    124             }
    125         }
    126         return DrawResult::kOk;
    127      }
    128 
    129 private:
    130     sk_sp<SkImage> fImage[3];
    131 
    132     static constexpr SkScalar kDrawPad = 10.f;
    133     static constexpr SkScalar kTestPad = 10.f;
    134     static constexpr SkScalar kColorSpaceOffset = 36.f;
    135 
    136     typedef GM INHERITED;
    137 };
    138 
    139 DEF_GM(return new YUVtoRGBEffect;)
    140 
    141 //////////////////////////////////////////////////////////////////////////////
    142 
    143 class YUVNV12toRGBEffect : public GpuGM {
    144 public:
    145     YUVNV12toRGBEffect() {
    146         this->setBGColor(0xFFFFFFFF);
    147     }
    148 
    149 protected:
    150     SkString onShortName() override {
    151         return SkString("yuv_nv12_to_rgb_effect");
    152     }
    153 
    154     SkISize onISize() override {
    155         int numRows = kLastEnum_SkYUVColorSpace + 1;
    156         return SkISize::Make(48, kDrawPad + numRows * kColorSpaceOffset);
    157     }
    158 
    159     void onOnceBeforeDraw() override {
    160         SkBitmap bmp[2];
    161         SkImageInfo yinfo = SkImageInfo::MakeA8(YSIZE, YSIZE);
    162         bmp[0].allocPixels(yinfo);
    163         SkImageInfo uvinfo = SkImageInfo::MakeN32Premul(USIZE, USIZE);
    164         bmp[1].allocPixels(uvinfo);
    165         int color[] = {0, 85, 170};
    166         const int limit[] = {255, 0, 255};
    167         const int invl[] = {0, 255, 0};
    168         const int inc[] = {1, -1, 1};
    169 
    170         {
    171             unsigned char* pixels = (unsigned char*)bmp[0].getPixels();
    172             const size_t nbBytes = bmp[0].rowBytes() * bmp[0].height();
    173             for (size_t j = 0; j < nbBytes; ++j) {
    174                 pixels[j] = (unsigned char)color[0];
    175                 color[0] = (color[0] == limit[0]) ? invl[0] : color[0] + inc[0];
    176             }
    177         }
    178 
    179         {
    180             for (int y = 0; y < bmp[1].height(); ++y) {
    181                 uint32_t* pixels = bmp[1].getAddr32(0, y);
    182                 for (int j = 0; j < bmp[1].width(); ++j) {
    183                     pixels[j] = SkColorSetARGB(0, color[1], color[2], 0);
    184                     color[1] = (color[1] == limit[1]) ? invl[1] : color[1] + inc[1];
    185                     color[2] = (color[2] == limit[2]) ? invl[2] : color[2] + inc[2];
    186                 }
    187             }
    188         }
    189 
    190         for (int i = 0; i < 2; ++i) {
    191             fImage[i] = SkImage::MakeFromBitmap(bmp[i]);
    192         }
    193     }
    194 
    195     DrawResult onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
    196                       SkCanvas* canvas, SkString* errorMsg) override {
    197         GrProxyProvider* proxyProvider = context->priv().proxyProvider();
    198         sk_sp<GrTextureProxy> proxies[2];
    199 
    200         for (int i = 0; i < 2; ++i) {
    201             proxies[i] = proxyProvider->createTextureProxy(fImage[i], kNone_GrSurfaceFlags, 1,
    202                                                            SkBudgeted::kYes, SkBackingFit::kExact);
    203             if (!proxies[i]) {
    204                 *errorMsg = "Failed to create proxy";
    205                 return DrawResult::kFail;
    206             }
    207         }
    208 
    209         SkYUVAIndex yuvaIndices[4] = {
    210             {  0, SkColorChannel::kR },
    211             {  1, SkColorChannel::kR },
    212             {  1, SkColorChannel::kG },
    213             { -1, SkColorChannel::kA }
    214         };
    215 
    216         for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace; ++space) {
    217             SkRect renderRect = SkRect::MakeWH(SkIntToScalar(fImage[0]->width()),
    218                                                SkIntToScalar(fImage[0]->height()));
    219             renderRect.outset(kDrawPad, kDrawPad);
    220 
    221             SkScalar y = kDrawPad + kTestPad + space * kColorSpaceOffset;
    222             SkScalar x = kDrawPad + kTestPad;
    223 
    224             GrPaint grPaint;
    225             grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
    226             auto fp = GrYUVtoRGBEffect::Make(proxies, yuvaIndices,
    227                                              static_cast<SkYUVColorSpace>(space),
    228                                              GrSamplerState::Filter::kNearest);
    229             if (fp) {
    230                 SkMatrix viewMatrix;
    231                 viewMatrix.setTranslate(x, y);
    232                 grPaint.addColorFragmentProcessor(std::move(fp));
    233                 std::unique_ptr<GrDrawOp> op(GrFillRectOp::Make(context, std::move(grPaint),
    234                         GrAAType::kNone, viewMatrix, renderRect));
    235                 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
    236             }
    237         }
    238         return DrawResult::kOk;
    239     }
    240 
    241 private:
    242     sk_sp<SkImage> fImage[2];
    243 
    244     static constexpr SkScalar kDrawPad = 10.f;
    245     static constexpr SkScalar kTestPad = 10.f;
    246     static constexpr SkScalar kColorSpaceOffset = 36.f;
    247 
    248     typedef GM INHERITED;
    249 };
    250 
    251 DEF_GM(return new YUVNV12toRGBEffect;)
    252 }
    253