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