blob: 0546439a5f7df3490ec619e1e76852e857e073ea [file] [log] [blame]
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/renderer/rasterizer/blitter/linear_gradient_cache.h"
#include <vector>
#include "cobalt/math/point_f.h"
#include "cobalt/render_tree/brush.h"
#include "cobalt/render_tree/color_rgba.h"
#include "starboard/blitter.h"
#include "testing/gtest/include/gtest/gtest.h"
#if SB_HAS(BLITTER)
using cobalt::math::PointF;
using cobalt::render_tree::ColorRGBA;
using cobalt::render_tree::ColorStop;
using cobalt::render_tree::ColorStopList;
using cobalt::render_tree::LinearGradientBrush;
namespace {
const int kDefaultSurfaceSizeInPixels = 64;
struct TestData {
TestData(LinearGradientBrush brush_arg, SbBlitterSurface surface_arg)
: brush(brush_arg), surface(surface_arg) {}
LinearGradientBrush brush;
SbBlitterSurface surface;
};
float GenerateRandomFloatBetween0and1() {
return (std::rand() / static_cast<float>(RAND_MAX));
}
SbBlitterSurface GenerateRandomSurface(SbBlitterDevice device, int width,
int height,
SbBlitterPixelDataFormat pixel_format) {
SbBlitterPixelData pixel_data =
SbBlitterCreatePixelData(device, width, height, pixel_format);
if (!SbBlitterIsPixelDataValid(pixel_data)) return kSbBlitterInvalidSurface;
SbBlitterSurface surface =
SbBlitterCreateSurfaceFromPixelData(device, pixel_data);
return surface;
}
TestData GenerateRandomTestData(const SbBlitterDevice &device, int width,
int height,
SbBlitterPixelDataFormat pixel_format) {
bool horizontal_brush = (height == 1);
if (horizontal_brush) {
DCHECK_EQ(height, 1);
} else {
DCHECK_EQ(width, 1);
}
PointF source(20.0f, 20.0f);
PointF dest(0.0f, 0.0f);
// Gradient size is randomly chosen between -5.0 and 5.0
float gradient_size = 2.0 * (GenerateRandomFloatBetween0and1() - 0.5) * 5.0f;
if (fabs(gradient_size) < 0.1f) {
// Try not to generate 0s.
gradient_size = 0.1f;
}
if (horizontal_brush) {
dest.set_x(source.x() + gradient_size);
dest.set_y(source.y());
} else {
dest.set_x(source.x());
dest.set_y(source.y() + gradient_size);
}
ColorStopList stops;
ColorRGBA color1(GenerateRandomFloatBetween0and1(),
GenerateRandomFloatBetween0and1(),
GenerateRandomFloatBetween0and1());
ColorRGBA color2(GenerateRandomFloatBetween0and1(),
GenerateRandomFloatBetween0and1(),
GenerateRandomFloatBetween0and1());
stops.push_back(ColorStop(0.0, color1));
stops.push_back(ColorStop(1.0, color2));
LinearGradientBrush brush(source, dest, stops);
SbBlitterSurface random_surface(
GenerateRandomSurface(device, width, height, pixel_format));
return TestData(brush, random_surface);
}
} // namespace
namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace blitter {
class LinearGradientCacheFixture : public ::testing::Test {
public:
LinearGradientCacheFixture()
: default_device(kSbBlitterInvalidDevice), pixel_format() {}
virtual void SetUp() {
pixel_format = kSbBlitterInvalidPixelDataFormat;
switch (SB_PREFERRED_RGBA_BYTE_ORDER) {
case SB_PREFERRED_RGBA_BYTE_ORDER_RGBA:
pixel_format = kSbBlitterPixelDataFormatRGBA8;
break;
case SB_PREFERRED_RGBA_BYTE_ORDER_BGRA:
pixel_format = kSbBlitterPixelDataFormatBGRA8;
break;
case SB_PREFERRED_RGBA_BYTE_ORDER_ARGB:
pixel_format = kSbBlitterPixelDataFormatARGB8;
break;
default:
NOTREACHED() << "Invalid SB_PREFERRED_RGBA_BYTE_ORDER_RGBA"
<< SB_PREFERRED_RGBA_BYTE_ORDER_RGBA;
}
default_device = SbBlitterCreateDefaultDevice();
ASSERT_TRUE(SbBlitterIsDeviceValid(default_device));
ASSERT_TRUE(SbBlitterIsPixelFormatSupportedByPixelData(default_device,
pixel_format));
}
virtual void TearDown() {
if (SbBlitterIsDeviceValid(default_device)) {
SbBlitterDestroyDevice(default_device);
}
}
TestData GenerateRandomTestData(bool horizontal_brush) {
int width = 1;
int height = 1;
if (horizontal_brush) {
width = kDefaultSurfaceSizeInPixels;
} else {
height = kDefaultSurfaceSizeInPixels;
}
return ::GenerateRandomTestData(default_device, width, height,
pixel_format);
}
LinearGradientCache cache;
SbBlitterDevice default_device;
SbBlitterPixelDataFormat pixel_format;
};
TEST_F(LinearGradientCacheFixture, CheckConstructDestruct) {}
TEST_F(LinearGradientCacheFixture, DoNotCacheInvalidSurface) {
math::PointF source(0.0f, 0.0f);
math::PointF dest(15.0f, 20.0f);
ColorStopList stops;
ColorRGBA color1(0.8, 1.0, 0.5);
ColorRGBA color2(0.6, 1.0, 0.5);
stops.push_back(ColorStop(0.0, color1));
stops.push_back(ColorStop(1.0, color2));
LinearGradientBrush brush(source, dest, stops);
SbBlitterSurface surface = kSbBlitterInvalidSurface;
bool inserted_in_cache = cache.Put(brush, surface);
EXPECT_FALSE(inserted_in_cache);
}
TEST_F(LinearGradientCacheFixture, PutSuccessful) {
TestData test_data(GenerateRandomTestData(true));
bool inserted_in_cache = cache.Put(test_data.brush, test_data.surface);
EXPECT_TRUE(inserted_in_cache);
}
TEST_F(LinearGradientCacheFixture, ValidGet) {
TestData test_data(GenerateRandomTestData(true));
cache.Put(test_data.brush, test_data.surface);
SbBlitterSurface surface = cache.Get(test_data.brush);
EXPECT_TRUE(SbBlitterIsSurfaceValid(surface));
}
TEST_F(LinearGradientCacheFixture, InvalidGet) {
TestData test_data_1(GenerateRandomTestData(true));
TestData test_data_2(GenerateRandomTestData(false));
cache.Put(test_data_1.brush, test_data_1.surface);
SbBlitterSurface surface = cache.Get(test_data_2.brush);
SbBlitterDestroySurface(test_data_2.surface);
EXPECT_FALSE(SbBlitterIsSurfaceValid(surface));
}
TEST_F(LinearGradientCacheFixture, FetchTwoItems) {
TestData test_data_1(GenerateRandomTestData(true));
cache.Put(test_data_1.brush, test_data_1.surface);
TestData test_data_2(GenerateRandomTestData(false));
cache.Put(test_data_2.brush, test_data_2.surface);
SbBlitterSurface surface1 = cache.Get(test_data_1.brush);
EXPECT_TRUE(SbBlitterIsSurfaceValid(surface1));
SbBlitterSurface surface2 = cache.Get(test_data_2.brush);
EXPECT_TRUE(SbBlitterIsSurfaceValid(surface2));
}
TEST_F(LinearGradientCacheFixture, GetSameSizeGradientInSameDirection) {
TestData test_data_1(GenerateRandomTestData(true));
cache.Put(test_data_1.brush, test_data_1.surface);
PointF source(test_data_1.brush.source());
source.set_x(source.x() + 20);
source.set_y(source.y() + 10);
PointF dest(test_data_1.brush.dest());
dest.set_x(dest.x() + 20);
dest.set_y(dest.y() + 10);
LinearGradientBrush similar_brush(source, dest,
test_data_1.brush.color_stops());
SbBlitterSurface surface1 = cache.Get(similar_brush);
EXPECT_TRUE(SbBlitterIsSurfaceValid(surface1));
EXPECT_TRUE(surface1 == test_data_1.surface);
}
} // namespace blitter
} // namespace rasterizer
} // namespace renderer
} // namespace cobalt
#endif // SB_HAS(BLITTER)