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

/*
 * This is a straightforward test of floating point textures, which are
 * supported on some platforms.  As of right now, this test only supports
 * 32 bit floating point textures, and indeed floating point test values
 * have been selected to require 32 bits of precision and full IEEE conformance
 */
#if SK_SUPPORT_GPU
#include <float.h>
#include "Test.h"
#include "GrContext.h"
#include "GrTexture.h"
#include "GrContextFactory.h"

#include "SkGpuDevice.h"
#include "SkHalf.h"

static const int DEV_W = 100, DEV_H = 100;
static const int FP_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * 4;
static const float kMaxIntegerRepresentableInSPFloatingPoint = 16777216;  // 2 ^ 24

static const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H);

DEF_GPUTEST(FloatingPointTextureTest, reporter, factory) {
    SkTDArray<float> controlPixelData, readBuffer;
    controlPixelData.setCount(FP_CONTROL_ARRAY_SIZE);
    readBuffer.setCount(FP_CONTROL_ARRAY_SIZE);

    for (int i = 0; i < FP_CONTROL_ARRAY_SIZE; i += 4) {
        controlPixelData[i] = FLT_MIN;
        controlPixelData[i + 1] = FLT_MAX;
        controlPixelData[i + 2] = FLT_EPSILON;
        controlPixelData[i + 3] = kMaxIntegerRepresentableInSPFloatingPoint;
    }

    for (int origin = 0; origin < 2; ++origin) {
        int glCtxTypeCnt = 1;
        glCtxTypeCnt = GrContextFactory::kGLContextTypeCnt;
        for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) {
            GrSurfaceDesc desc;
            desc.fFlags = kRenderTarget_GrSurfaceFlag;
            desc.fWidth = DEV_W;
            desc.fHeight = DEV_H;
            desc.fConfig = kRGBA_float_GrPixelConfig;
            desc.fOrigin = 0 == origin ?
                kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;

            GrContext* context = NULL;
            GrContextFactory::GLContextType type =
                    static_cast<GrContextFactory::GLContextType>(glCtxType);
            if (!GrContextFactory::IsRenderingGLContext(type)) {
                continue;
            }
            context = factory->get(type);
            if (NULL == context){
                continue;
            }

            SkAutoTUnref<GrTexture> fpTexture(context->createUncachedTexture(desc,
                                                                             NULL,
                                                                             0));

            // Floating point textures are NOT supported everywhere
            if (NULL == fpTexture) {
                continue;
            }

            // write square
            fpTexture->writePixels(0, 0, DEV_W, DEV_H, desc.fConfig, controlPixelData.begin(), 0);
            fpTexture->readPixels(0, 0, DEV_W, DEV_H, desc.fConfig, readBuffer.begin(), 0);
            for (int j = 0; j < FP_CONTROL_ARRAY_SIZE; ++j) {
                REPORTER_ASSERT(reporter, readBuffer[j] == controlPixelData[j]);
            }
        }
    }
}

static const int HALF_CONTROL_ARRAY_SIZE = DEV_W * DEV_H;

DEF_GPUTEST(HalfFloatTextureTest, reporter, factory) {
    SkTDArray<SkHalf> controlPixelData, readBuffer;
    controlPixelData.setCount(HALF_CONTROL_ARRAY_SIZE);
    readBuffer.setCount(HALF_CONTROL_ARRAY_SIZE);

    for (int i = 0; i < HALF_CONTROL_ARRAY_SIZE; i += 4) {
        controlPixelData[i] = SK_HalfMin;
        controlPixelData[i + 1] = SK_HalfMax;
        controlPixelData[i + 2] = SK_HalfEpsilon;
        controlPixelData[i + 3] = 0x6800;   // 2^11
    }

    for (int origin = 0; origin < 2; ++origin) {
        int glCtxTypeCnt = 1;
        glCtxTypeCnt = GrContextFactory::kGLContextTypeCnt;
        for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++glCtxType) {
            GrSurfaceDesc desc;
            desc.fFlags = kRenderTarget_GrSurfaceFlag;
            desc.fWidth = DEV_W;
            desc.fHeight = DEV_H;
            desc.fConfig = kAlpha_half_GrPixelConfig;
            desc.fOrigin = 0 == origin ?
            kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;

            GrContext* context = NULL;
            GrContextFactory::GLContextType type =
            static_cast<GrContextFactory::GLContextType>(glCtxType);
            if (!GrContextFactory::IsRenderingGLContext(type)) {
                continue;
            }
            context = factory->get(type);
            if (NULL == context){
                continue;
            }

            SkAutoTUnref<GrTexture> fpTexture(context->createUncachedTexture(desc,
                                                                             NULL,
                                                                             0));

            // 16-bit floating point textures are NOT supported everywhere
            if (NULL == fpTexture) {
                continue;
            }

            // write square
            fpTexture->writePixels(0, 0, DEV_W, DEV_H, desc.fConfig, controlPixelData.begin(), 0);
            fpTexture->readPixels(0, 0, DEV_W, DEV_H, desc.fConfig, readBuffer.begin(), 0);
            for (int j = 0; j < HALF_CONTROL_ARRAY_SIZE; ++j) {
                REPORTER_ASSERT(reporter, readBuffer[j] == controlPixelData[j]);
            }
        }
    }
}

#endif
