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

#if SK_SUPPORT_GPU

#include "GrContext.h"
#include "GrContextFactory.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkGpuDevice.h"
#include "SkPaint.h"
#include "SkPixelRef.h"
#include "SkRect.h"
#include "Test.h"

static const char* boolStr(bool value) {
    return value ? "true" : "false";
}

// these are in the same order as the SkBitmap::Config enum
static const char* gConfigName[] = {
    "None", "4444", "8888"
};

struct Pair {
    SkBitmap::Config    fConfig;
    const char*         fValid;
};

/**
 *  Check to ensure that copying a GPU-backed SkBitmap behaved as expected.
 *  @param reporter Used to report failures.
 *  @param desiredConfig Config being copied to. If the copy succeeded, dst must have this Config.
 *  @param success True if the copy succeeded.
 *  @param src A GPU-backed SkBitmap that had copyTo or deepCopyTo called on it.
 *  @param dst SkBitmap that was copied to.
 *  @param deepCopy True if deepCopyTo was used; false if copyTo was used.
 */
static void TestIndividualCopy(skiatest::Reporter* reporter, const SkBitmap::Config desiredConfig,
                               const bool success, const SkBitmap& src, const SkBitmap& dst,
                               const bool deepCopy = true) {
    if (success) {
        REPORTER_ASSERT(reporter, src.width() == dst.width());
        REPORTER_ASSERT(reporter, src.height() == dst.height());
        REPORTER_ASSERT(reporter, dst.config() == desiredConfig);
        if (src.config() == dst.config()) {
            // FIXME: When calling copyTo (so deepCopy is false here), sometimes we copy the pixels
            // exactly, in which case the IDs should be the same, but sometimes we do a bitmap draw,
            // in which case the IDs should not be the same. Is there any way to determine which is
            // the case at this point?
            if (deepCopy) {
                REPORTER_ASSERT(reporter, src.getGenerationID() == dst.getGenerationID());
            }
            REPORTER_ASSERT(reporter, src.pixelRef() != NULL && dst.pixelRef() != NULL);

            // Do read backs and make sure that the two are the same.
            SkBitmap srcReadBack, dstReadBack;
            {
                SkASSERT(src.getTexture() != NULL);
                bool readBack = src.pixelRef()->readPixels(&srcReadBack);
                REPORTER_ASSERT(reporter, readBack);
            }
            if (dst.getTexture() != NULL) {
                bool readBack = dst.pixelRef()->readPixels(&dstReadBack);
                REPORTER_ASSERT(reporter, readBack);
            } else {
                // If dst is not a texture, do a copy instead, to the same config as srcReadBack.
                bool copy = dst.copyTo(&dstReadBack, srcReadBack.config());
                REPORTER_ASSERT(reporter, copy);
            }

            SkAutoLockPixels srcLock(srcReadBack);
            SkAutoLockPixels dstLock(dstReadBack);
            REPORTER_ASSERT(reporter, srcReadBack.readyToDraw() && dstReadBack.readyToDraw());

            const char* srcP = static_cast<const char*>(srcReadBack.getAddr(0, 0));
            const char* dstP = static_cast<const char*>(dstReadBack.getAddr(0, 0));
            REPORTER_ASSERT(reporter, srcP != dstP);

            REPORTER_ASSERT(reporter, !memcmp(srcP, dstP, srcReadBack.getSize()));
        } else {
            REPORTER_ASSERT(reporter, src.getGenerationID() != dst.getGenerationID());
        }
    } else {
        // dst should be unchanged from its initial state
        REPORTER_ASSERT(reporter, dst.config() == SkBitmap::kNo_Config);
        REPORTER_ASSERT(reporter, dst.width() == 0);
        REPORTER_ASSERT(reporter, dst.height() == 0);
    }

}

// Stripped down version of TestBitmapCopy that checks basic fields (width, height, config, genID)
// to ensure that they were copied properly.
static void TestGpuBitmapCopy(skiatest::Reporter* reporter, GrContextFactory* factory) {
#ifdef SK_BUILD_FOR_ANDROID // https://code.google.com/p/skia/issues/detail?id=753
    return;
#endif
    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
        GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
        if (!GrContextFactory::IsRenderingGLContext(glType)) {
            continue;
        }

        GrContext* grContext = factory->get(glType);
        if (NULL == grContext) {
            continue;
        }


        if (NULL == grContext) {
            return;
        }
        static const Pair gPairs[] = {
            { SkBitmap::kNo_Config,         "000"  },
            { SkBitmap::kARGB_4444_Config,  "011"  },
            { SkBitmap::kARGB_8888_Config,  "011"  },
        };

        const int W = 20;
        const int H = 33;

        for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
            SkBitmap src, dst;

            SkGpuDevice* device = SkNEW_ARGS(SkGpuDevice, (grContext, gPairs[i].fConfig, W, H));
            SkAutoUnref aur(device);
            src = device->accessBitmap(false);
            device->clear(SK_ColorWHITE);

            // Draw something different to the same portion of the bitmap that we will extract as a
            // subset, so that comparing the pixels of the subset will be meaningful.
            SkIRect subsetRect = SkIRect::MakeLTRB(W/2, H/2, W, H);
            SkCanvas drawingCanvas(device);
            SkPaint paint;
            paint.setColor(SK_ColorRED);
            drawingCanvas.drawRect(SkRect::MakeFromIRect(subsetRect), paint);

            // Extract a subset. If this succeeds we will test copying the subset.
            SkBitmap subset;
            const bool extracted = src.extractSubset(&subset, subsetRect);

            for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
                dst.reset();
                bool success = src.deepCopyTo(&dst, gPairs[j].fConfig);
                bool expected = gPairs[i].fValid[j] != '0';
                if (success != expected) {
                    SkString str;
                    str.printf("SkBitmap::deepCopyTo from %s to %s. expected %s returned %s",
                               gConfigName[i], gConfigName[j], boolStr(expected),
                               boolStr(success));
                    reporter->reportFailed(str);
                }

                bool canSucceed = src.canCopyTo(gPairs[j].fConfig);
                if (success != canSucceed) {
                    SkString str;
                    str.printf("SkBitmap::deepCopyTo from %s to %s returned %s,"
                               "but canCopyTo returned %s",
                               gConfigName[i], gConfigName[j], boolStr(success),
                               boolStr(canSucceed));
                    reporter->reportFailed(str);
                }

                TestIndividualCopy(reporter, gPairs[j].fConfig, success, src, dst);

                // Test copying the subset bitmap, using both copyTo and deepCopyTo.
                if (extracted) {
                    SkBitmap subsetCopy;
                    success = subset.copyTo(&subsetCopy, gPairs[j].fConfig);
                    REPORTER_ASSERT(reporter, success == expected);
                    REPORTER_ASSERT(reporter, success == canSucceed);
                    TestIndividualCopy(reporter, gPairs[j].fConfig, success, subset, subsetCopy,
                                       false);

                    // Reset the bitmap so that a failed copyTo will leave it in the expected state.
                    subsetCopy.reset();
                    success = subset.deepCopyTo(&subsetCopy, gPairs[j].fConfig);
                    REPORTER_ASSERT(reporter, success == expected);
                    REPORTER_ASSERT(reporter, success == canSucceed);
                    TestIndividualCopy(reporter, gPairs[j].fConfig, success, subset, subsetCopy,
                                       true);
                }
            } // for (size_t j = ...
        } // for (size_t i = ...
    } // GrContextFactory::GLContextType
}

#include "TestClassDef.h"
DEFINE_GPUTESTCLASS("GpuBitmapCopy", TestGpuBitmapCopyClass, TestGpuBitmapCopy)

#endif
