// // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #include "gmock/gmock.h" #include "gtest/gtest.h" #include "libANGLE/AttributeMap.h" #include "libANGLE/Config.h" // Create a generic, valid EGL config that can be modified to test sorting and // filtering routines static egl::Config GenerateGenericConfig() { egl::Config config; config.bufferSize = 24; config.redSize = 8; config.greenSize = 8; config.blueSize = 8; config.luminanceSize = 0; config.alphaSize = 8; config.alphaMaskSize = 0; config.bindToTextureRGB = EGL_TRUE; config.bindToTextureRGBA = EGL_TRUE; config.colorBufferType = EGL_RGB_BUFFER; config.configCaveat = EGL_NONE; config.configID = 0; config.conformant = EGL_OPENGL_ES2_BIT; config.depthSize = 24; config.level = 0; config.matchNativePixmap = EGL_NONE; config.maxPBufferWidth = 1024; config.maxPBufferHeight = 1024; config.maxPBufferPixels = config.maxPBufferWidth * config.maxPBufferWidth; config.maxSwapInterval = 0; config.minSwapInterval = 4; config.nativeRenderable = EGL_OPENGL_ES2_BIT; config.nativeVisualID = 0; config.nativeVisualType = 0; config.renderableType = EGL_FALSE; config.sampleBuffers = 0; config.samples = 0; config.stencilSize = 8; config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; config.transparentType = EGL_NONE; config.transparentRedValue = 0; config.transparentGreenValue = 0; config.transparentBlueValue = 0; return config; } static std::vector GenerateUniqueConfigs(size_t count) { std::vector configs; for (size_t i = 0; i < count; i++) { egl::Config config = GenerateGenericConfig(); config.samples = static_cast(i); configs.push_back(config); } return configs; } // Add unique configs to a ConfigSet and expect that the size of the // set is equal to the number of configs added. TEST(ConfigSetTest, Size) { egl::ConfigSet set; std::vector uniqueConfigs = GenerateUniqueConfigs(16); for (size_t i = 0; i < uniqueConfigs.size(); i++) { set.add(uniqueConfigs[i]); EXPECT_EQ(set.size(), i + 1); } } // [EGL 1.5] section 3.4: // EGL_CONFIG_ID is a unique integer identifying different EGLConfigs. Configuration IDs // must be small positive integers starting at 1 and ID assignment should be compact; // that is, if there are N EGLConfigs defined by the EGL implementation, their // configuration IDs should be in the range [1, N]. TEST(ConfigSetTest, IDs) { egl::ConfigSet set; std::set ids; std::vector uniqueConfigs = GenerateUniqueConfigs(16); for (size_t i = 0; i < uniqueConfigs.size(); i++) { EGLint id = set.add(uniqueConfigs[i]); // Check that the config that was inserted has the ID that was returned // by ConfigSet::add EXPECT_EQ(id, set.get(id).configID); ids.insert(id); } // Verify configCount unique IDs EXPECT_EQ(ids.size(), set.size()); // Check that there are no gaps and the IDs are in the range [1, N]. EXPECT_EQ(*std::min_element(ids.begin(), ids.end()), 1); EXPECT_EQ(*std::max_element(ids.begin(), ids.end()), static_cast(set.size())); } TEST(ConfigSetTest, Filtering_BitSizes) { egl::ConfigSet set; struct VariableConfigBitSize { EGLint Name; EGLint(egl::Config::*ConfigMember); }; VariableConfigBitSize testMembers[] = { { EGL_RED_SIZE, &egl::Config::redSize }, { EGL_GREEN_SIZE, &egl::Config::greenSize }, { EGL_BLUE_SIZE, &egl::Config::blueSize }, { EGL_ALPHA_SIZE, &egl::Config::alphaSize }, { EGL_DEPTH_SIZE, &egl::Config::depthSize }, { EGL_STENCIL_SIZE, &egl::Config::stencilSize }, }; // Generate configsPerType configs with varying bit sizes of each type size_t configsPerType = 4; for (size_t i = 0; i < ArraySize(testMembers); i++) { for (size_t j = 0; j < configsPerType; j++) { egl::Config config = GenerateGenericConfig(); // Set all the other tested members of this config to 0 for (size_t k = 0; k < ArraySize(testMembers); k++) { config.*(testMembers[k].ConfigMember) = 0; } // Set the tested member of this config to i so it ranges from // [1, configsPerType] config.*(testMembers[i].ConfigMember) = static_cast(j) + 1; set.add(config); } } // for each tested member, filter by it's type and verify that the correct number // of results are returned for (size_t i = 0; i < ArraySize(testMembers); i++) { // Start with a filter of 1 to not grab the other members for (EGLint j = 0; j < static_cast(configsPerType); j++) { egl::AttributeMap filter; filter.insert(testMembers[i].Name, j + 1); std::vector filteredConfigs = set.filter(filter); EXPECT_EQ(filteredConfigs.size(), configsPerType - j); } } } // Verify the sorting, [EGL 1.5] section 3.4.1.2 pg 30: // [configs are sorted] by larger total number of color bits (for an RGB // color buffer this is the sum of EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE, // and EGL_ALPHA_SIZE; for a luminance color buffer, the sum of EGL_LUMINANCE_SIZE // and EGL_ALPHA_SIZE).If the requested number of bits in attrib list for a // particular color component is 0 or EGL_DONT_CARE, then the number of bits // for that component is not considered. TEST(ConfigSetTest, Sorting_BitSizes) { egl::ConfigSet set; size_t testConfigCount = 64; for (size_t i = 0; i < testConfigCount; i++) { egl::Config config = GenerateGenericConfig(); // Give random-ish bit sizes to the config config.redSize = (i * 2) % 3; config.greenSize = (i + 5) % 7; config.blueSize = (i + 7) % 11; config.alphaSize = (i + 13) % 17; set.add(config); } egl::AttributeMap greaterThan1BitFilter; greaterThan1BitFilter.insert(EGL_RED_SIZE, 1); greaterThan1BitFilter.insert(EGL_GREEN_SIZE, 1); greaterThan1BitFilter.insert(EGL_BLUE_SIZE, 1); greaterThan1BitFilter.insert(EGL_ALPHA_SIZE, 1); std::vector filteredConfigs = set.filter(greaterThan1BitFilter); for (size_t i = 1; i < filteredConfigs.size(); i++) { const egl::Config &prevConfig = *filteredConfigs[i - 1]; size_t prevBitCount = prevConfig.redSize + prevConfig.greenSize + prevConfig.blueSize + prevConfig.alphaSize; const egl::Config &curConfig = *filteredConfigs[i]; size_t curBitCount = curConfig.redSize + curConfig.greenSize + curConfig.blueSize + curConfig.alphaSize; EXPECT_GE(prevBitCount, curBitCount); } }