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 #if SK_SUPPORT_GPU
     13 
     14 #include "GrContext.h"
     15 #include "GrContextPriv.h"
     16 #include "GrProxyProvider.h"
     17 #include "GrRenderTargetContextPriv.h"
     18 #include "GrTextureProxy.h"
     19 #include "SkBitmap.h"
     20 #include "SkGr.h"
     21 #include "SkGradientShader.h"
     22 #include "effects/GrYUVtoRGBEffect.h"
     23 #include "ops/GrDrawOp.h"
     24 #include "ops/GrRectOpFactory.h"
     25 
     26 #define YSIZE 8
     27 #define USIZE 4
     28 #define VSIZE 4
     29 
     30 namespace skiagm {
     31 /**
     32  * This GM directly exercises GrYUVtoRGBEffect.
     33  */
     34 class YUVtoRGBEffect : public GM {
     35 public:
     36     YUVtoRGBEffect() {
     37         this->setBGColor(0xFFFFFFFF);
     38     }
     39 
     40 protected:
     41     SkString onShortName() override {
     42         return SkString("yuv_to_rgb_effect");
     43     }
     44 
     45     SkISize onISize() override {
     46         return SkISize::Make(238, 120);
     47     }
     48 
     49     void onOnceBeforeDraw() override {
     50         SkImageInfo yinfo = SkImageInfo::MakeA8(YSIZE, YSIZE);
     51         fBmp[0].allocPixels(yinfo);
     52         SkImageInfo uinfo = SkImageInfo::MakeA8(USIZE, USIZE);
     53         fBmp[1].allocPixels(uinfo);
     54         SkImageInfo vinfo = SkImageInfo::MakeA8(VSIZE, VSIZE);
     55         fBmp[2].allocPixels(vinfo);
     56         unsigned char* pixels[3];
     57         for (int i = 0; i < 3; ++i) {
     58             pixels[i] = (unsigned char*)fBmp[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 = fBmp[i].rowBytes() * fBmp[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     }
     72 
     73     void onDraw(SkCanvas* canvas) override {
     74         GrRenderTargetContext* renderTargetContext =
     75             canvas->internal_private_accessTopLayerRenderTargetContext();
     76         if (!renderTargetContext) {
     77             skiagm::GM::DrawGpuOnlyMessage(canvas);
     78             return;
     79         }
     80 
     81         GrContext* context = canvas->getGrContext();
     82         if (!context) {
     83             return;
     84         }
     85 
     86         GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
     87         sk_sp<GrTextureProxy> proxy[3];
     88 
     89         {
     90             GrSurfaceDesc desc;
     91             desc.fOrigin = kTopLeft_GrSurfaceOrigin;
     92 
     93             for (int i = 0; i < 3; ++i) {
     94                 desc.fWidth = fBmp[i].width();
     95                 desc.fHeight = fBmp[i].height();
     96                 desc.fConfig = SkImageInfo2GrPixelConfig(fBmp[i].info(), *context->caps());
     97 
     98                 proxy[i] = proxyProvider->createTextureProxy(desc, SkBudgeted::kYes,
     99                                                              fBmp[i].getPixels(),
    100                                                              fBmp[i].rowBytes());
    101                 if (!proxy[i]) {
    102                     return;
    103                 }
    104             }
    105         }
    106 
    107         constexpr SkScalar kDrawPad = 10.f;
    108         constexpr SkScalar kTestPad = 10.f;
    109         constexpr SkScalar kColorSpaceOffset = 36.f;
    110         SkISize sizes[3] = {{YSIZE, YSIZE}, {USIZE, USIZE}, {VSIZE, VSIZE}};
    111 
    112         for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace; ++space) {
    113             SkRect renderRect = SkRect::MakeWH(SkIntToScalar(fBmp[0].width()),
    114                                                SkIntToScalar(fBmp[0].height()));
    115             renderRect.outset(kDrawPad, kDrawPad);
    116 
    117             SkScalar y = kDrawPad + kTestPad + space * kColorSpaceOffset;
    118             SkScalar x = kDrawPad + kTestPad;
    119 
    120             const int indices[6][3] = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2},
    121                                        {1, 2, 0}, {2, 0, 1}, {2, 1, 0}};
    122 
    123             for (int i = 0; i < 6; ++i) {
    124                 std::unique_ptr<GrFragmentProcessor> fp(
    125                         GrYUVtoRGBEffect::Make(proxy[indices[i][0]],
    126                                                proxy[indices[i][1]],
    127                                                proxy[indices[i][2]],
    128                                                sizes,
    129                                                static_cast<SkYUVColorSpace>(space),
    130                                                false));
    131                 if (fp) {
    132                     GrPaint grPaint;
    133                     grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
    134                     grPaint.addColorFragmentProcessor(std::move(fp));
    135                     SkMatrix viewMatrix;
    136                     viewMatrix.setTranslate(x, y);
    137                     renderTargetContext->priv().testingOnly_addDrawOp(
    138                             GrRectOpFactory::MakeNonAAFill(std::move(grPaint), viewMatrix,
    139                                                            renderRect, GrAAType::kNone));
    140                 }
    141                 x += renderRect.width() + kTestPad;
    142             }
    143         }
    144      }
    145 
    146 private:
    147     SkBitmap fBmp[3];
    148 
    149     typedef GM INHERITED;
    150 };
    151 
    152 DEF_GM(return new YUVtoRGBEffect;)
    153 
    154 //////////////////////////////////////////////////////////////////////////////
    155 
    156 class YUVNV12toRGBEffect : public GM {
    157 public:
    158     YUVNV12toRGBEffect() {
    159         this->setBGColor(0xFFFFFFFF);
    160     }
    161 
    162 protected:
    163     SkString onShortName() override {
    164         return SkString("yuv_nv12_to_rgb_effect");
    165     }
    166 
    167     SkISize onISize() override {
    168         return SkISize::Make(48, 120);
    169     }
    170 
    171     void onOnceBeforeDraw() override {
    172         SkImageInfo yinfo = SkImageInfo::MakeA8(YSIZE, YSIZE);
    173         fBmp[0].allocPixels(yinfo);
    174         SkImageInfo uvinfo = SkImageInfo::MakeN32Premul(USIZE, USIZE);
    175         fBmp[1].allocPixels(uvinfo);
    176         int color[] = {0, 85, 170};
    177         const int limit[] = {255, 0, 255};
    178         const int invl[] = {0, 255, 0};
    179         const int inc[] = {1, -1, 1};
    180 
    181         {
    182             unsigned char* pixels = (unsigned char*)fBmp[0].getPixels();
    183             const size_t nbBytes = fBmp[0].rowBytes() * fBmp[0].height();
    184             for (size_t j = 0; j < nbBytes; ++j) {
    185                 pixels[j] = (unsigned char)color[0];
    186                 color[0] = (color[0] == limit[0]) ? invl[0] : color[0] + inc[0];
    187             }
    188         }
    189 
    190         {
    191             for (int y = 0; y < fBmp[1].height(); ++y) {
    192                 uint32_t* pixels = fBmp[1].getAddr32(0, y);
    193                 for (int j = 0; j < fBmp[1].width(); ++j) {
    194                     pixels[j] = SkColorSetARGB(0, color[1], color[2], 0);
    195                     color[1] = (color[1] == limit[1]) ? invl[1] : color[1] + inc[1];
    196                     color[2] = (color[2] == limit[2]) ? invl[2] : color[2] + inc[2];
    197                 }
    198             }
    199         }
    200     }
    201 
    202     void onDraw(SkCanvas* canvas) override {
    203         GrRenderTargetContext* renderTargetContext =
    204             canvas->internal_private_accessTopLayerRenderTargetContext();
    205         if (!renderTargetContext) {
    206             skiagm::GM::DrawGpuOnlyMessage(canvas);
    207             return;
    208         }
    209 
    210         GrContext* context = canvas->getGrContext();
    211         if (!context) {
    212             return;
    213         }
    214 
    215         GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
    216         sk_sp<GrTextureProxy> proxy[3];
    217 
    218         {
    219             GrSurfaceDesc desc;
    220             desc.fOrigin = kTopLeft_GrSurfaceOrigin;
    221 
    222             for (int i = 0; i < 3; ++i) {
    223                 int index = (0 == i) ? 0 : 1;
    224 
    225                 desc.fWidth = fBmp[index].width();
    226                 desc.fHeight = fBmp[index].height();
    227                 desc.fConfig = SkImageInfo2GrPixelConfig(fBmp[index].info(), *context->caps());
    228 
    229                 proxy[i] = proxyProvider->createTextureProxy(desc, SkBudgeted::kYes,
    230                                                              fBmp[index].getPixels(),
    231                                                              fBmp[index].rowBytes());
    232                 if (!proxy[i]) {
    233                     return;
    234                 }
    235             }
    236         }
    237 
    238         constexpr SkScalar kDrawPad = 10.f;
    239         constexpr SkScalar kTestPad = 10.f;
    240         constexpr SkScalar kColorSpaceOffset = 36.f;
    241         SkISize sizes[3] = {{YSIZE, YSIZE}, {USIZE, USIZE}, {VSIZE, VSIZE}};
    242 
    243         for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace; ++space) {
    244             SkRect renderRect =
    245                 SkRect::MakeWH(SkIntToScalar(fBmp[0].width()), SkIntToScalar(fBmp[0].height()));
    246             renderRect.outset(kDrawPad, kDrawPad);
    247 
    248             SkScalar y = kDrawPad + kTestPad + space * kColorSpaceOffset;
    249             SkScalar x = kDrawPad + kTestPad;
    250 
    251             GrPaint grPaint;
    252             grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
    253             auto fp = GrYUVtoRGBEffect::Make(proxy[0], proxy[1], proxy[2], sizes,
    254                                              static_cast<SkYUVColorSpace>(space), true);
    255             if (fp) {
    256                 SkMatrix viewMatrix;
    257                 viewMatrix.setTranslate(x, y);
    258                 grPaint.addColorFragmentProcessor(std::move(fp));
    259                 std::unique_ptr<GrDrawOp> op(GrRectOpFactory::MakeNonAAFill(
    260                                 std::move(grPaint), viewMatrix, renderRect, GrAAType::kNone));
    261                 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
    262             }
    263         }
    264     }
    265 
    266 private:
    267     SkBitmap fBmp[2];
    268 
    269     typedef GM INHERITED;
    270 };
    271 
    272 DEF_GM(return new YUVNV12toRGBEffect;)
    273 }
    274 
    275 #endif
    276