/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This test only works with the GPU backend.

#include "gm.h"

#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrDrawContext.h"
#include "SkColorPriv.h"
#include "effects/GrPorterDuffXferProcessor.h"
#include "effects/GrSimpleTextureEffect.h"

static const int S = 200;

DEF_SIMPLE_GM_BG(texdata, canvas, 2 * S, 2 * S, SK_ColorBLACK) {
        GrRenderTarget* target = canvas->internal_private_accessTopLayerRenderTarget();
        GrContext* ctx = canvas->getGrContext();
        SkAutoTUnref<GrDrawContext> drawContext(ctx ? ctx->drawContext(target) : nullptr);
        if (drawContext && target) {
            SkAutoTArray<SkPMColor> gTextureData((2 * S) * (2 * S));
            static const int stride = 2 * S;
            static const SkPMColor gray  = SkPackARGB32(0x40, 0x40, 0x40, 0x40);
            static const SkPMColor white = SkPackARGB32(0xff, 0xff, 0xff, 0xff);
            static const SkPMColor red   = SkPackARGB32(0x80, 0x80, 0x00, 0x00);
            static const SkPMColor blue  = SkPackARGB32(0x80, 0x00, 0x00, 0x80);
            static const SkPMColor green = SkPackARGB32(0x80, 0x00, 0x80, 0x00);
            static const SkPMColor black = SkPackARGB32(0x00, 0x00, 0x00, 0x00);
            for (int i = 0; i < 2; ++i) {
                int offset = 0;
                // fill upper-left
                for (int y = 0; y < S; ++y) {
                    for (int x = 0; x < S; ++x) {
                        gTextureData[offset + y * stride + x] = gray;
                    }
                }
                // fill upper-right
                offset = S;
                for (int y = 0; y < S; ++y) {
                    for (int x = 0; x < S; ++x) {
                        gTextureData[offset + y * stride + x] = white;
                    }
                }
                // fill lower left
                offset = S * stride;
                for (int y = 0; y < S; ++y) {
                    for (int x = 0; x < S; ++x) {
                        gTextureData[offset + y * stride + x] = black;
                    }
                }
                // fill lower right
                offset = S * stride + S;
                for (int y = 0; y < S; ++y) {
                    for (int x = 0; x < S; ++x) {
                        gTextureData[offset + y * stride + x] = gray;
                    }
                }

                GrSurfaceDesc desc;
                // use RT flag bit because in GL it makes the texture be bottom-up
                desc.fFlags     = i ? kRenderTarget_GrSurfaceFlag :
                                      kNone_GrSurfaceFlags;
                desc.fConfig    = kSkia8888_GrPixelConfig;
                desc.fWidth     = 2 * S;
                desc.fHeight    = 2 * S;
                GrTexture* texture = ctx->textureProvider()->createTexture(
                    desc, SkBudgeted::kNo, gTextureData.get(), 0);

                if (!texture) {
                    return;
                }
                SkAutoTUnref<GrTexture> au(texture);

                // setup new clip
                GrClip clip(SkRect::MakeWH(2*S, 2*S));

                GrPaint paint;
                paint.setPorterDuffXPFactory(SkXfermode::kSrcOver_Mode);

                SkMatrix vm;
                if (i) {
                    vm.setRotate(90 * SK_Scalar1,
                                 S * SK_Scalar1,
                                 S * SK_Scalar1);
                } else {
                    vm.reset();
                }
                SkMatrix tm;
                tm = vm;
                tm.postIDiv(2*S, 2*S);
                paint.addColorTextureProcessor(texture, tm);

                drawContext->drawRect(clip, paint, vm, SkRect::MakeWH(2*S, 2*S));

                // now update the lower right of the texture in first pass
                // or upper right in second pass
                offset = 0;
                for (int y = 0; y < S; ++y) {
                    for (int x = 0; x < S; ++x) {
                        gTextureData[offset + y * stride + x] =
                            ((x + y) % 2) ? (i ? green : red) : blue;
                    }
                }
                texture->writePixels(S, (i ? 0 : S), S, S,
                                     texture->config(), gTextureData.get(),
                                     4 * stride);
                drawContext->drawRect(clip, paint, vm, SkRect::MakeWH(2*S, 2*S));
            }
        } else {
            skiagm::GM::DrawGpuOnlyMessage(canvas);
        }
}
#endif
