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/*
9 * This is a straightforward test of floating point textures, which are
10 * supported on some platforms.  As of right now, this test only supports
11 * 32 bit floating point textures, and indeed floating point test values
12 * have been selected to require 32 bits of precision and full IEEE conformance
13 */
14
15#include "tests/Test.h"
16
17#include "include/gpu/GrDirectContext.h"
18#include "include/private/SkHalf.h"
19#include "src/gpu/GrDirectContextPriv.h"
20#include "src/gpu/GrImageInfo.h"
21#include "src/gpu/GrProxyProvider.h"
22#include "src/gpu/GrTextureProxy.h"
23#include "src/gpu/SurfaceContext.h"
24#include "tools/gpu/ProxyUtils.h"
25
26#include <float.h>
27
28static const int DEV_W = 100, DEV_H = 100;
29
30template <typename T>
31void runFPTest(skiatest::Reporter* reporter, GrDirectContext* dContext,
32               T min, T max, T epsilon, T maxInt,
33               int arraySize, GrColorType colorType) {
34    if (0 != arraySize % 4) {
35        REPORT_FAILURE(reporter, "(0 != arraySize % 4)",
36                       SkString("arraySize must be divisible by 4."));
37        return;
38    }
39
40    SkTDArray<T> controlPixelData, readBuffer;
41    controlPixelData.setCount(arraySize);
42    readBuffer.setCount(arraySize);
43
44    for (int i = 0; i < arraySize; i += 4) {
45        controlPixelData[i + 0] = min;
46        controlPixelData[i + 1] = max;
47        controlPixelData[i + 2] = epsilon;
48        controlPixelData[i + 3] = maxInt;
49    }
50
51    for (auto origin : {kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin}) {
52        GrImageInfo info(colorType, kPremul_SkAlphaType, nullptr, {DEV_W, DEV_H});
53        GrCPixmap controlPixmap(info, controlPixelData.begin(), info.minRowBytes());
54        auto fpView = sk_gpu_test::MakeTextureProxyViewFromData(dContext,
55                                                                GrRenderable::kYes,
56                                                                origin,
57                                                                controlPixmap);
58        // Floating point textures are NOT supported everywhere
59        if (!fpView) {
60            continue;
61        }
62
63        auto sc = dContext->priv().makeSC(std::move(fpView), info.colorInfo());
64        REPORTER_ASSERT(reporter, sc);
65
66        GrPixmap readPixmap(info, readBuffer.begin(), info.minRowBytes());
67        bool result = sc->readPixels(dContext, readPixmap, {0, 0});
68        REPORTER_ASSERT(reporter, result);
69        REPORTER_ASSERT(reporter,
70                        !memcmp(readBuffer.begin(), controlPixelData.begin(), readBuffer.bytes()));
71    }
72}
73
74static const int HALF_ALPHA_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * 1 /*alpha-only*/;
75static const SkHalf kMaxIntegerRepresentableInHalfFloatingPoint = 0x6800;  // 2 ^ 11
76
77DEF_GPUTEST_FOR_RENDERING_CONTEXTS(HalfFloatAlphaTextureTest, reporter, ctxInfo) {
78    auto direct = ctxInfo.directContext();
79
80    runFPTest<SkHalf>(reporter, direct, SK_HalfMin, SK_HalfMax, SK_HalfEpsilon,
81                      kMaxIntegerRepresentableInHalfFloatingPoint, HALF_ALPHA_CONTROL_ARRAY_SIZE,
82                      GrColorType::kAlpha_F16);
83}
84
85static const int HALF_RGBA_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * 4 /*RGBA*/;
86
87DEF_GPUTEST_FOR_RENDERING_CONTEXTS(HalfFloatRGBATextureTest, reporter, ctxInfo) {
88    auto direct = ctxInfo.directContext();
89
90    runFPTest<SkHalf>(reporter, direct, SK_HalfMin, SK_HalfMax, SK_HalfEpsilon,
91                      kMaxIntegerRepresentableInHalfFloatingPoint, HALF_RGBA_CONTROL_ARRAY_SIZE,
92                      GrColorType::kRGBA_F16);
93}
94