Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
51
libs/drape/drape_tests/CMakeLists.txt
Normal file
51
libs/drape/drape_tests/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
project(drape_tests)
|
||||
|
||||
set(DRAPE_TESTABLE_SRC_PREFIXED ${DRAPE_TESTABLE_SRC})
|
||||
list(TRANSFORM DRAPE_TESTABLE_SRC_PREFIXED PREPEND "../")
|
||||
|
||||
set(SRC
|
||||
${DRAPE_TESTABLE_SRC_PREFIXED}
|
||||
attribute_provides_tests.cpp
|
||||
batcher_tests.cpp
|
||||
bingind_info_tests.cpp
|
||||
buffer_tests.cpp
|
||||
dummy_texture.hpp
|
||||
font_texture_tests.cpp
|
||||
gl_functions.cpp
|
||||
gl_mock_functions.cpp
|
||||
gl_mock_functions.hpp
|
||||
glyph_mng_tests.cpp
|
||||
glyph_packer_test.cpp
|
||||
harfbuzz_shaping_test.cpp
|
||||
img.cpp
|
||||
img.hpp
|
||||
memory_comparer.hpp
|
||||
object_pool_tests.cpp
|
||||
pointers_tests.cpp
|
||||
static_texture_tests.cpp
|
||||
stipple_pen_tests.cpp
|
||||
texture_of_colors_tests.cpp
|
||||
testing_graphics_context.hpp
|
||||
uniform_value_tests.cpp
|
||||
vertex_buffer_tests.cpp
|
||||
)
|
||||
|
||||
omim_add_test(${PROJECT_NAME} ${SRC})
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE GTEST_DONT_DEFINE_TEST WITH_GL_MOCK
|
||||
)
|
||||
|
||||
if (WITH_SYSTEM_PROVIDED_3PARTY)
|
||||
find_package(GTest REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} GTest::gtest)
|
||||
else()
|
||||
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../../../3party/googletest" "${CMAKE_CURRENT_BINARY_DIR}/googletest")
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${OMIM_ROOT}/3party/glm)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
qt_tstfrm
|
||||
gmock
|
||||
${DRAPE_LINK_LIBRARIES}
|
||||
)
|
||||
201
libs/drape/drape_tests/attribute_provides_tests.cpp
Normal file
201
libs/drape/drape_tests/attribute_provides_tests.cpp
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "drape/attribute_provider.hpp"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using namespace dp;
|
||||
|
||||
UNIT_TEST(InitStreamsTest)
|
||||
{
|
||||
int const VERTEX_COUNT = 10;
|
||||
AttributeProvider provider(3, VERTEX_COUNT);
|
||||
float positions[2 * VERTEX_COUNT];
|
||||
float depth[VERTEX_COUNT];
|
||||
float normals[2 * VERTEX_COUNT];
|
||||
|
||||
for (int i = 0; i < VERTEX_COUNT; ++i)
|
||||
{
|
||||
positions[2 * i] = (float)i;
|
||||
positions[(2 * i) + 1] = 0.0f;
|
||||
depth[i] = (float)i;
|
||||
normals[2 * i] = (float)i;
|
||||
normals[(2 * i) + 1] = 0.0;
|
||||
}
|
||||
|
||||
{
|
||||
BindingInfo zeroStreamBinding(1);
|
||||
BindingDecl & decl = zeroStreamBinding.GetBindingDecl(0);
|
||||
decl.m_attributeName = "position";
|
||||
decl.m_componentCount = 2;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
provider.InitStream(0, zeroStreamBinding, make_ref(positions));
|
||||
}
|
||||
|
||||
{
|
||||
BindingInfo firstStreamBinding(1);
|
||||
BindingDecl & decl = firstStreamBinding.GetBindingDecl(0);
|
||||
decl.m_attributeName = "depth";
|
||||
decl.m_componentCount = 1;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
provider.InitStream(1, firstStreamBinding, make_ref(depth));
|
||||
}
|
||||
|
||||
{
|
||||
BindingInfo secondStreamBinding(1);
|
||||
BindingDecl & decl = secondStreamBinding.GetBindingDecl(0);
|
||||
decl.m_attributeName = "normal";
|
||||
decl.m_componentCount = 2;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
provider.InitStream(2, secondStreamBinding, make_ref(normals));
|
||||
}
|
||||
|
||||
TEST_EQUAL(provider.IsDataExists(), true, ());
|
||||
TEST_EQUAL(provider.GetVertexCount(), 10, ());
|
||||
TEST_EQUAL(provider.GetRawPointer(0), (void *)positions, ());
|
||||
TEST_EQUAL(provider.GetRawPointer(1), (void *)depth, ());
|
||||
TEST_EQUAL(provider.GetRawPointer(2), (void *)normals, ());
|
||||
|
||||
provider.Advance(1);
|
||||
|
||||
TEST_EQUAL(provider.IsDataExists(), true, ());
|
||||
TEST_EQUAL(provider.GetVertexCount(), 9, ());
|
||||
TEST_EQUAL(provider.GetRawPointer(0), (void *)(&positions[2]), ());
|
||||
TEST_EQUAL(provider.GetRawPointer(1), (void *)(&depth[1]), ());
|
||||
TEST_EQUAL(provider.GetRawPointer(2), (void *)(&normals[2]), ());
|
||||
|
||||
provider.Advance(9);
|
||||
TEST_EQUAL(provider.IsDataExists(), false, ());
|
||||
TEST_EQUAL(provider.GetVertexCount(), 0, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(InterleavedStreamTest)
|
||||
{
|
||||
int const VERTEX_COUNT = 10;
|
||||
AttributeProvider provider(1, 10);
|
||||
float data[5 * VERTEX_COUNT];
|
||||
|
||||
for (int i = 0; i < VERTEX_COUNT; ++i)
|
||||
{
|
||||
data[(5 * i)] = (float)i;
|
||||
data[(5 * i) + 1] = 0.0;
|
||||
data[(5 * i) + 2] = (float)i;
|
||||
data[(5 * i) + 3] = (float)i;
|
||||
data[(5 * i) + 4] = 0.0;
|
||||
}
|
||||
|
||||
BindingInfo binding(3);
|
||||
{
|
||||
BindingDecl & decl = binding.GetBindingDecl(0);
|
||||
decl.m_attributeName = "position";
|
||||
decl.m_componentCount = 2;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 5 * sizeof(float);
|
||||
}
|
||||
{
|
||||
BindingDecl & decl = binding.GetBindingDecl(1);
|
||||
decl.m_attributeName = "depth";
|
||||
decl.m_componentCount = 1;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 2 * sizeof(float);
|
||||
decl.m_stride = 5 * sizeof(float);
|
||||
}
|
||||
{
|
||||
BindingDecl & decl = binding.GetBindingDecl(2);
|
||||
decl.m_attributeName = "normal";
|
||||
decl.m_componentCount = 2;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 3 * sizeof(float);
|
||||
decl.m_stride = 5 * sizeof(float);
|
||||
}
|
||||
|
||||
provider.InitStream(0, binding, make_ref(data));
|
||||
|
||||
TEST_EQUAL(provider.IsDataExists(), true, ());
|
||||
TEST_EQUAL(provider.GetVertexCount(), 10, ());
|
||||
TEST_EQUAL(provider.GetRawPointer(0), (void *)data, ());
|
||||
|
||||
provider.Advance(1);
|
||||
|
||||
TEST_EQUAL(provider.IsDataExists(), true, ());
|
||||
TEST_EQUAL(provider.GetVertexCount(), 9, ());
|
||||
TEST_EQUAL(provider.GetRawPointer(0), (void *)(&data[5]), ());
|
||||
|
||||
provider.Advance(9);
|
||||
TEST_EQUAL(provider.IsDataExists(), false, ());
|
||||
TEST_EQUAL(provider.GetVertexCount(), 0, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(MixedStreamsTest)
|
||||
{
|
||||
int const VERTEX_COUNT = 10;
|
||||
AttributeProvider provider(2, 10);
|
||||
float position[3 * VERTEX_COUNT];
|
||||
float normal[2 * VERTEX_COUNT];
|
||||
|
||||
for (int i = 0; i < VERTEX_COUNT; ++i)
|
||||
{
|
||||
position[3 * i] = (float)i; // x
|
||||
position[(3 * i) + 1] = 0.0; // y
|
||||
position[(3 * i) + 2] = (float)i; // z
|
||||
position[2 * i] = (float)i; // Nx
|
||||
position[(2 * i) + 1] = 0.0; // Ny
|
||||
}
|
||||
|
||||
{
|
||||
BindingInfo binding(2);
|
||||
{
|
||||
BindingDecl & decl = binding.GetBindingDecl(0);
|
||||
decl.m_attributeName = "position";
|
||||
decl.m_componentCount = 2;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 3 * sizeof(float);
|
||||
}
|
||||
|
||||
{
|
||||
BindingDecl & decl = binding.GetBindingDecl(1);
|
||||
decl.m_attributeName = "depth";
|
||||
decl.m_componentCount = 1;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 2 * sizeof(float);
|
||||
decl.m_stride = 3 * sizeof(float);
|
||||
}
|
||||
|
||||
provider.InitStream(0, binding, make_ref(position));
|
||||
}
|
||||
|
||||
{
|
||||
BindingInfo binding(1);
|
||||
BindingDecl & decl = binding.GetBindingDecl(0);
|
||||
decl.m_attributeName = "normal";
|
||||
decl.m_componentCount = 2;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
provider.InitStream(1, binding, make_ref(normal));
|
||||
}
|
||||
|
||||
TEST_EQUAL(provider.IsDataExists(), true, ());
|
||||
TEST_EQUAL(provider.GetVertexCount(), 10, ());
|
||||
TEST_EQUAL(provider.GetRawPointer(0), (void *)position, ());
|
||||
TEST_EQUAL(provider.GetRawPointer(1), (void *)normal, ());
|
||||
|
||||
provider.Advance(1);
|
||||
|
||||
TEST_EQUAL(provider.IsDataExists(), true, ());
|
||||
TEST_EQUAL(provider.GetVertexCount(), 9, ());
|
||||
TEST_EQUAL(provider.GetRawPointer(0), (void *)(&position[3]), ());
|
||||
TEST_EQUAL(provider.GetRawPointer(1), (void *)(&normal[2]), ());
|
||||
|
||||
provider.Advance(9);
|
||||
TEST_EQUAL(provider.IsDataExists(), false, ());
|
||||
TEST_EQUAL(provider.GetVertexCount(), 0, ());
|
||||
}
|
||||
355
libs/drape/drape_tests/batcher_tests.cpp
Normal file
355
libs/drape/drape_tests/batcher_tests.cpp
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "drape/drape_tests/gl_mock_functions.hpp"
|
||||
#include "drape/drape_tests/memory_comparer.hpp"
|
||||
#include "drape/drape_tests/testing_graphics_context.hpp"
|
||||
|
||||
#include "drape/batcher.hpp"
|
||||
#include "drape/gl_constants.hpp"
|
||||
#include "drape/index_storage.hpp"
|
||||
#include "drape/vertex_array_buffer.hpp"
|
||||
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using testing::_;
|
||||
using testing::AnyOf;
|
||||
using testing::IgnoreResult;
|
||||
using testing::InSequence;
|
||||
using testing::Invoke;
|
||||
using testing::Return;
|
||||
using namespace dp;
|
||||
using namespace std::placeholders;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct VAOAcceptor
|
||||
{
|
||||
virtual void FlushFullBucket(RenderState const & /* state */, drape_ptr<RenderBucket> && bucket)
|
||||
{
|
||||
m_vao.push_back(std::move(bucket));
|
||||
}
|
||||
|
||||
std::vector<drape_ptr<RenderBucket>> m_vao;
|
||||
};
|
||||
|
||||
class TestExtension : public dp::BaseRenderStateExtension
|
||||
{
|
||||
public:
|
||||
bool Less(ref_ptr<dp::BaseRenderStateExtension> other) const override { return false; }
|
||||
bool Equal(ref_ptr<dp::BaseRenderStateExtension> other) const override { return true; }
|
||||
};
|
||||
|
||||
class BatcherExpectations
|
||||
{
|
||||
public:
|
||||
BatcherExpectations() : m_indexBufferID(1), m_dataBufferID(2) {}
|
||||
|
||||
template <typename TBatcherCall>
|
||||
void RunTest(float * vertexes, void * indexes, uint32_t vertexCount, uint8_t vertexComponentCount,
|
||||
uint32_t indexCount, TBatcherCall const & fn)
|
||||
{
|
||||
uint32_t const vertexSize = vertexCount * vertexComponentCount;
|
||||
MemoryComparer const dataCmp(vertexes, vertexSize * sizeof(float));
|
||||
MemoryComparer const indexCmp(indexes, indexCount * dp::IndexStorage::SizeOfIndex());
|
||||
|
||||
ExpectBufferCreation(vertexSize, indexCount, indexCmp, dataCmp);
|
||||
|
||||
auto renderState = make_unique_dp<TestExtension>();
|
||||
auto state = RenderState(0, make_ref(renderState));
|
||||
|
||||
BindingInfo binding(1);
|
||||
BindingDecl & decl = binding.GetBindingDecl(0);
|
||||
decl.m_attributeName = "position";
|
||||
decl.m_componentCount = vertexComponentCount;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
|
||||
AttributeProvider provider(1, vertexCount);
|
||||
provider.InitStream(0, binding, make_ref(vertexes));
|
||||
|
||||
TestingGraphicsContext context;
|
||||
VAOAcceptor vaoAcceptor;
|
||||
Batcher batcher(65000, 65000);
|
||||
batcher.StartSession(std::bind(&VAOAcceptor::FlushFullBucket, &vaoAcceptor, _1, _2));
|
||||
fn(&batcher, state, make_ref(&provider));
|
||||
batcher.EndSession(make_ref(&context));
|
||||
|
||||
ExpectBufferDeletion();
|
||||
|
||||
for (size_t i = 0; i < vaoAcceptor.m_vao.size(); ++i)
|
||||
vaoAcceptor.m_vao[i].reset();
|
||||
}
|
||||
|
||||
void ExpectBufferCreation(uint32_t vertexCount, uint32_t indexCount, MemoryComparer const & indexCmp,
|
||||
MemoryComparer const & vertexCmp)
|
||||
{
|
||||
InSequence seq;
|
||||
|
||||
// data buffer creation
|
||||
EXPECTGL(glGenBuffer()).WillOnce(Return(m_dataBufferID));
|
||||
EXPECTGL(glBindBuffer(m_dataBufferID, gl_const::GLArrayBuffer));
|
||||
EXPECTGL(glBufferData(gl_const::GLArrayBuffer, vertexCount * sizeof(float), _, gl_const::GLDynamicDraw))
|
||||
.WillOnce(Invoke(&vertexCmp, &MemoryComparer::cmpSubBuffer));
|
||||
|
||||
// Index buffer creation
|
||||
EXPECTGL(glGenBuffer()).WillOnce(Return(m_indexBufferID));
|
||||
EXPECTGL(glBindBuffer(m_indexBufferID, gl_const::GLElementArrayBuffer));
|
||||
EXPECTGL(glBufferData(gl_const::GLElementArrayBuffer, indexCount * dp::IndexStorage::SizeOfIndex(), _,
|
||||
gl_const::GLDynamicDraw))
|
||||
.WillOnce(Invoke(&indexCmp, &MemoryComparer::cmpSubBuffer));
|
||||
|
||||
EXPECTGL(glBindBuffer(0, gl_const::GLElementArrayBuffer));
|
||||
EXPECTGL(glBindBuffer(0, gl_const::GLArrayBuffer));
|
||||
}
|
||||
|
||||
void ExpectBufferDeletion()
|
||||
{
|
||||
InSequence seq;
|
||||
EXPECTGL(glBindBuffer(0, gl_const::GLElementArrayBuffer));
|
||||
EXPECTGL(glDeleteBuffer(m_indexBufferID));
|
||||
EXPECTGL(glBindBuffer(0, gl_const::GLArrayBuffer));
|
||||
EXPECTGL(glDeleteBuffer(m_dataBufferID));
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_indexBufferID = 0;
|
||||
uint32_t m_dataBufferID = 0;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(BatchLists_Test)
|
||||
{
|
||||
TestingGraphicsContext context;
|
||||
uint32_t const kVerticesCount = 12;
|
||||
uint32_t const kFloatsCount = 3 * 12; // 3 component on each vertex.
|
||||
float data[kFloatsCount];
|
||||
for (uint32_t i = 0; i < kFloatsCount; ++i)
|
||||
data[i] = static_cast<float>(i);
|
||||
|
||||
std::vector<uint32_t> indexesRaw(kVerticesCount);
|
||||
for (uint32_t i = 0; i < kVerticesCount; ++i)
|
||||
indexesRaw[i] = i;
|
||||
dp::IndexStorage indexes(std::move(indexesRaw));
|
||||
|
||||
BatcherExpectations expectations;
|
||||
auto fn = [&context](Batcher * batcher, RenderState const & state, ref_ptr<AttributeProvider> p)
|
||||
{ batcher->InsertTriangleList(make_ref(&context), state, p); };
|
||||
expectations.RunTest(data, indexes.GetRaw(), kVerticesCount, 3, kVerticesCount, fn);
|
||||
}
|
||||
|
||||
UNIT_TEST(BatchListOfStript_4stride)
|
||||
{
|
||||
TestingGraphicsContext context;
|
||||
uint32_t const kVerticesCount = 12;
|
||||
uint32_t const kIndicesCount = 18;
|
||||
|
||||
float data[3 * kVerticesCount];
|
||||
for (uint32_t i = 0; i < kVerticesCount * 3; ++i)
|
||||
data[i] = static_cast<float>(i);
|
||||
|
||||
std::vector<uint32_t> indexesRaw = {0, 1, 2, 1, 3, 2, 4, 5, 6, 5, 7, 6, 8, 9, 10, 9, 11, 10};
|
||||
dp::IndexStorage indexes(std::move(indexesRaw));
|
||||
|
||||
BatcherExpectations expectations;
|
||||
auto fn = [&context](Batcher * batcher, RenderState const & state, ref_ptr<AttributeProvider> p)
|
||||
{ batcher->InsertListOfStrip(make_ref(&context), state, p, dp::Batcher::VertexPerQuad); };
|
||||
|
||||
expectations.RunTest(data, indexes.GetRaw(), kVerticesCount, 3, kIndicesCount, fn);
|
||||
}
|
||||
|
||||
UNIT_TEST(BatchListOfStript_5stride)
|
||||
{
|
||||
TestingGraphicsContext context;
|
||||
uint32_t const kVerticesCount = 15;
|
||||
uint32_t const kIndicesCount = 27;
|
||||
|
||||
float data[3 * kVerticesCount];
|
||||
for (uint32_t i = 0; i < kVerticesCount * 3; ++i)
|
||||
data[i] = static_cast<float>(i);
|
||||
|
||||
std::vector<uint32_t> indexesRaw = {0, 1, 2, 1, 3, 2, 2, 3, 4, 5, 6, 7, 6, 8,
|
||||
7, 7, 8, 9, 10, 11, 12, 11, 13, 12, 12, 13, 14};
|
||||
dp::IndexStorage indexes(std::move(indexesRaw));
|
||||
|
||||
BatcherExpectations expectations;
|
||||
auto fn = [&context](Batcher * batcher, RenderState const & state, ref_ptr<AttributeProvider> p)
|
||||
{ batcher->InsertListOfStrip(make_ref(&context), state, p, 5); };
|
||||
expectations.RunTest(data, indexes.GetRaw(), kVerticesCount, 3, kIndicesCount, fn);
|
||||
}
|
||||
|
||||
UNIT_TEST(BatchListOfStript_6stride)
|
||||
{
|
||||
TestingGraphicsContext context;
|
||||
uint32_t const kVerticesCount = 18;
|
||||
uint32_t const kIndicesCount = 36;
|
||||
|
||||
float data[3 * kVerticesCount];
|
||||
for (uint32_t i = 0; i < kVerticesCount * 3; ++i)
|
||||
data[i] = static_cast<float>(i);
|
||||
|
||||
std::vector<uint32_t> indexesRaw = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 5, 4, 6, 7, 8, 7, 9, 8,
|
||||
8, 9, 10, 9, 11, 10, 12, 13, 14, 13, 15, 14, 14, 15, 16, 15, 17, 16};
|
||||
dp::IndexStorage indexes(std::move(indexesRaw));
|
||||
|
||||
BatcherExpectations expectations;
|
||||
auto fn = [&context](Batcher * batcher, RenderState const & state, ref_ptr<AttributeProvider> p)
|
||||
{ batcher->InsertListOfStrip(make_ref(&context), state, p, 6); };
|
||||
expectations.RunTest(data, indexes.GetRaw(), kVerticesCount, 3, kIndicesCount, fn);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class PartialBatcherTest
|
||||
{
|
||||
public:
|
||||
struct BufferNode
|
||||
{
|
||||
BufferNode(uint32_t indexByteCount, uint32_t vertexByteCount, void * indexData, void * vertexData)
|
||||
: m_indexByteCount(indexByteCount)
|
||||
, m_vertexByteCount(vertexByteCount)
|
||||
, m_indexData(indexData)
|
||||
, m_vertexData(vertexData)
|
||||
, m_indexBufferID(0)
|
||||
, m_vertexBufferID(0)
|
||||
{}
|
||||
|
||||
uint32_t m_indexByteCount;
|
||||
uint32_t m_vertexByteCount;
|
||||
void * m_indexData;
|
||||
void * m_vertexData;
|
||||
uint32_t m_indexBufferID;
|
||||
uint32_t m_vertexBufferID;
|
||||
};
|
||||
|
||||
PartialBatcherTest() = default;
|
||||
|
||||
~PartialBatcherTest() { std::for_each(m_comparators.begin(), m_comparators.end(), base::DeleteFunctor()); }
|
||||
|
||||
void AddBufferNode(BufferNode const & node)
|
||||
{
|
||||
m_nodes.push_back(node);
|
||||
BufferNode & currentNode = m_nodes.back();
|
||||
currentNode.m_indexBufferID = m_bufferIDCounter++;
|
||||
currentNode.m_vertexBufferID = m_bufferIDCounter++;
|
||||
|
||||
// data buffer creation
|
||||
EXPECTGL(glGenBuffer()).WillOnce(Return(currentNode.m_vertexBufferID));
|
||||
EXPECTGL(glBindBuffer(currentNode.m_vertexBufferID, gl_const::GLArrayBuffer));
|
||||
|
||||
m_comparators.push_back(new MemoryComparer(currentNode.m_vertexData, currentNode.m_vertexByteCount));
|
||||
MemoryComparer * vertexComparer = m_comparators.back();
|
||||
|
||||
EXPECTGL(glBufferData(gl_const::GLArrayBuffer, currentNode.m_vertexByteCount, _, gl_const::GLDynamicDraw))
|
||||
.WillOnce(Invoke(vertexComparer, &MemoryComparer::cmpSubBuffer));
|
||||
|
||||
// Index buffer creation
|
||||
EXPECTGL(glGenBuffer()).WillOnce(Return(currentNode.m_indexBufferID));
|
||||
EXPECTGL(glBindBuffer(currentNode.m_indexBufferID, gl_const::GLElementArrayBuffer));
|
||||
|
||||
m_comparators.push_back(new MemoryComparer(currentNode.m_indexData, currentNode.m_indexByteCount));
|
||||
MemoryComparer * indexComparer = m_comparators.back();
|
||||
|
||||
EXPECTGL(glBufferData(gl_const::GLElementArrayBuffer, currentNode.m_indexByteCount, _, gl_const::GLDynamicDraw))
|
||||
.WillOnce(Invoke(indexComparer, &MemoryComparer::cmpSubBuffer));
|
||||
|
||||
EXPECTGL(glBindBuffer(0, gl_const::GLElementArrayBuffer));
|
||||
EXPECTGL(glBindBuffer(0, gl_const::GLArrayBuffer));
|
||||
}
|
||||
|
||||
void CloseExpection()
|
||||
{
|
||||
for (auto const & node : m_nodes)
|
||||
{
|
||||
EXPECTGL(glBindBuffer(0, gl_const::GLElementArrayBuffer));
|
||||
EXPECTGL(glDeleteBuffer(node.m_indexBufferID));
|
||||
EXPECTGL(glBindBuffer(0, gl_const::GLArrayBuffer));
|
||||
EXPECTGL(glDeleteBuffer(node.m_vertexBufferID));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_bufferIDCounter = 1;
|
||||
|
||||
std::vector<BufferNode> m_nodes;
|
||||
std::vector<MemoryComparer *> m_comparators;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(BatchListOfStript_partial)
|
||||
{
|
||||
TestingGraphicsContext context;
|
||||
uint32_t const VertexCount = 16;
|
||||
uint32_t const ComponentCount = 3;
|
||||
uint32_t const VertexArraySize = VertexCount * ComponentCount;
|
||||
uint32_t const IndexCount = 24;
|
||||
|
||||
uint32_t const FirstBufferVertexPortion = 12;
|
||||
uint32_t const SecondBufferVertexPortion = VertexCount - FirstBufferVertexPortion;
|
||||
uint32_t const FirstBufferIndexPortion = 18;
|
||||
uint32_t const SecondBufferIndexPortion = IndexCount - FirstBufferIndexPortion;
|
||||
|
||||
float vertexData[VertexArraySize];
|
||||
for (uint32_t i = 0; i < VertexArraySize; ++i)
|
||||
vertexData[i] = static_cast<float>(i);
|
||||
|
||||
std::vector<uint32_t> indexDataRaw = {0, 1, 2, 1, 3, 2, 4, 5, 6, 5, 7,
|
||||
6, 8, 9, 10, 9, 11, 10, 0, 1, 2, // start new buffer
|
||||
1, 3, 2};
|
||||
dp::IndexStorage indexData(std::move(indexDataRaw));
|
||||
|
||||
PartialBatcherTest::BufferNode node1(FirstBufferIndexPortion * dp::IndexStorage::SizeOfIndex(),
|
||||
FirstBufferVertexPortion * ComponentCount * sizeof(float), indexData.GetRaw(),
|
||||
vertexData);
|
||||
|
||||
PartialBatcherTest::BufferNode node2(SecondBufferIndexPortion * dp::IndexStorage::SizeOfIndex(),
|
||||
SecondBufferVertexPortion * ComponentCount * sizeof(float),
|
||||
indexData.GetRaw(FirstBufferIndexPortion),
|
||||
vertexData + FirstBufferVertexPortion * ComponentCount);
|
||||
|
||||
using IndexVertexCount = std::pair<uint32_t, uint32_t>;
|
||||
std::vector<IndexVertexCount> srcData;
|
||||
srcData.emplace_back(30, 12);
|
||||
srcData.emplace_back(30, 13);
|
||||
srcData.emplace_back(18, 30);
|
||||
srcData.emplace_back(19, 30);
|
||||
|
||||
for (size_t i = 0; i < srcData.size(); ++i)
|
||||
{
|
||||
InSequence seq;
|
||||
PartialBatcherTest test;
|
||||
test.AddBufferNode(node1);
|
||||
test.AddBufferNode(node2);
|
||||
test.CloseExpection();
|
||||
|
||||
auto renderState = make_unique_dp<TestExtension>();
|
||||
auto state = RenderState(0, make_ref(renderState));
|
||||
|
||||
BindingInfo binding(1);
|
||||
BindingDecl & decl = binding.GetBindingDecl(0);
|
||||
decl.m_attributeName = "position";
|
||||
decl.m_componentCount = ComponentCount;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
|
||||
AttributeProvider provider(1, VertexCount);
|
||||
provider.InitStream(0, binding, make_ref(vertexData));
|
||||
|
||||
VAOAcceptor vaoAcceptor;
|
||||
Batcher batcher(srcData[i].first, srcData[i].second);
|
||||
batcher.StartSession(std::bind(&VAOAcceptor::FlushFullBucket, &vaoAcceptor, _1, _2));
|
||||
batcher.InsertListOfStrip(make_ref(&context), state, make_ref(&provider), 4);
|
||||
batcher.EndSession(make_ref(&context));
|
||||
|
||||
for (size_t i = 0; i < vaoAcceptor.m_vao.size(); ++i)
|
||||
vaoAcceptor.m_vao[i].reset();
|
||||
}
|
||||
}
|
||||
31
libs/drape/drape_tests/bingind_info_tests.cpp
Normal file
31
libs/drape/drape_tests/bingind_info_tests.cpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "drape/binding_info.hpp"
|
||||
|
||||
using namespace dp;
|
||||
|
||||
UNIT_TEST(BindingInfoIDTest)
|
||||
{
|
||||
{
|
||||
BindingInfo info(1, 1);
|
||||
TEST_EQUAL(info.GetID(), 1, ());
|
||||
}
|
||||
|
||||
{
|
||||
BindingInfo info(1);
|
||||
TEST_EQUAL(info.GetID(), 0, ());
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(DynamicHandlingTest)
|
||||
{
|
||||
{
|
||||
BindingInfo info(1);
|
||||
TEST_EQUAL(info.IsDynamic(), false, ());
|
||||
}
|
||||
|
||||
{
|
||||
BindingInfo info(1, 1);
|
||||
TEST_EQUAL(info.IsDynamic(), true, ());
|
||||
}
|
||||
}
|
||||
111
libs/drape/drape_tests/buffer_tests.cpp
Normal file
111
libs/drape/drape_tests/buffer_tests.cpp
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "drape/drape_tests/gl_mock_functions.hpp"
|
||||
#include "drape/drape_tests/testing_graphics_context.hpp"
|
||||
|
||||
#include "drape/data_buffer.hpp"
|
||||
#include "drape/gpu_buffer.hpp"
|
||||
#include "drape/index_buffer.hpp"
|
||||
#include "drape/index_storage.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using namespace emul;
|
||||
using namespace dp;
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::InSequence;
|
||||
using ::testing::Return;
|
||||
|
||||
UNIT_TEST(CreateDestroyDataBufferTest)
|
||||
{
|
||||
TestingGraphicsContext context;
|
||||
InSequence s;
|
||||
EXPECTGL(glGenBuffer()).WillOnce(Return(1));
|
||||
EXPECTGL(glBindBuffer(1, gl_const::GLArrayBuffer));
|
||||
EXPECTGL(glBufferData(gl_const::GLArrayBuffer, 3 * 100 * sizeof(float), nullptr, gl_const::GLDynamicDraw));
|
||||
EXPECTGL(glBindBuffer(0, gl_const::GLArrayBuffer));
|
||||
EXPECTGL(glDeleteBuffer(1));
|
||||
|
||||
std::unique_ptr<DataBuffer> buffer(new DataBuffer(3 * sizeof(float), 100));
|
||||
buffer->MoveToGPU(make_ref(&context), GPUBuffer::ElementBuffer, 0);
|
||||
}
|
||||
|
||||
UNIT_TEST(CreateDestroyIndexBufferTest)
|
||||
{
|
||||
TestingGraphicsContext context;
|
||||
InSequence s;
|
||||
EXPECTGL(glGenBuffer()).WillOnce(Return(1));
|
||||
EXPECTGL(glBindBuffer(1, gl_const::GLElementArrayBuffer));
|
||||
EXPECTGL(glBufferData(gl_const::GLElementArrayBuffer, 100 * dp::IndexStorage::SizeOfIndex(), nullptr,
|
||||
gl_const::GLDynamicDraw));
|
||||
EXPECTGL(glBindBuffer(0, gl_const::GLElementArrayBuffer));
|
||||
EXPECTGL(glDeleteBuffer(1));
|
||||
|
||||
std::unique_ptr<IndexBuffer> buffer(new IndexBuffer(100));
|
||||
buffer->MoveToGPU(make_ref(&context), GPUBuffer::IndexBuffer, 0);
|
||||
}
|
||||
|
||||
UNIT_TEST(UploadDataTest)
|
||||
{
|
||||
float data[3 * 100];
|
||||
for (int i = 0; i < 3 * 100; ++i)
|
||||
data[i] = (float)i;
|
||||
|
||||
std::unique_ptr<DataBuffer> buffer(new DataBuffer(3 * sizeof(float), 100));
|
||||
|
||||
TestingGraphicsContext context;
|
||||
InSequence s;
|
||||
EXPECTGL(glGenBuffer()).WillOnce(Return(1));
|
||||
EXPECTGL(glBindBuffer(1, gl_const::GLArrayBuffer));
|
||||
EXPECTGL(glBufferData(gl_const::GLArrayBuffer, 3 * 100 * sizeof(float), buffer->GetBuffer()->Data(),
|
||||
gl_const::GLDynamicDraw));
|
||||
EXPECTGL(glBindBuffer(0, gl_const::GLArrayBuffer));
|
||||
EXPECTGL(glDeleteBuffer(1));
|
||||
|
||||
buffer->GetBuffer()->UploadData(make_ref(&context), data, 100);
|
||||
buffer->MoveToGPU(make_ref(&context), GPUBuffer::ElementBuffer, 0);
|
||||
}
|
||||
|
||||
UNIT_TEST(ParticalUploadDataTest)
|
||||
{
|
||||
size_t const kPart1Size = 3 * 30;
|
||||
float part1Data[kPart1Size];
|
||||
for (size_t i = 0; i < kPart1Size; ++i)
|
||||
part1Data[i] = (float)i;
|
||||
|
||||
size_t const kPart2Size = 3 * 100;
|
||||
float part2Data[kPart2Size];
|
||||
for (size_t i = 0; i < kPart2Size; ++i)
|
||||
part2Data[i] = (float)i;
|
||||
|
||||
std::unique_ptr<DataBuffer> buffer(new DataBuffer(3 * sizeof(float), 100));
|
||||
|
||||
TestingGraphicsContext context;
|
||||
InSequence s;
|
||||
EXPECTGL(glGenBuffer()).WillOnce(Return(1));
|
||||
EXPECTGL(glBindBuffer(1, gl_const::GLArrayBuffer));
|
||||
EXPECTGL(glBufferData(gl_const::GLArrayBuffer, 3 * 100 * sizeof(float), buffer->GetBuffer()->Data(),
|
||||
gl_const::GLDynamicDraw));
|
||||
EXPECTGL(glBindBuffer(0, gl_const::GLArrayBuffer));
|
||||
EXPECTGL(glDeleteBuffer(1));
|
||||
|
||||
TEST_EQUAL(buffer->GetBuffer()->GetCapacity(), 100, ());
|
||||
TEST_EQUAL(buffer->GetBuffer()->GetAvailableSize(), 100, ());
|
||||
TEST_EQUAL(buffer->GetBuffer()->GetCurrentSize(), 0, ());
|
||||
|
||||
buffer->GetBuffer()->UploadData(make_ref(&context), part1Data, 30);
|
||||
TEST_EQUAL(buffer->GetBuffer()->GetCapacity(), 100, ());
|
||||
TEST_EQUAL(buffer->GetBuffer()->GetAvailableSize(), 70, ());
|
||||
TEST_EQUAL(buffer->GetBuffer()->GetCurrentSize(), 30, ());
|
||||
|
||||
buffer->GetBuffer()->UploadData(make_ref(&context), part2Data, 70);
|
||||
TEST_EQUAL(buffer->GetBuffer()->GetCapacity(), 100, ());
|
||||
TEST_EQUAL(buffer->GetBuffer()->GetAvailableSize(), 0, ());
|
||||
TEST_EQUAL(buffer->GetBuffer()->GetCurrentSize(), 100, ());
|
||||
|
||||
buffer->MoveToGPU(make_ref(&context), GPUBuffer::ElementBuffer, 0);
|
||||
}
|
||||
16
libs/drape/drape_tests/dummy_texture.hpp
Normal file
16
libs/drape/drape_tests/dummy_texture.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "drape/pointers.hpp"
|
||||
#include "drape/texture.hpp"
|
||||
|
||||
class DummyTexture : public dp::Texture
|
||||
{
|
||||
public:
|
||||
ref_ptr<ResourceInfo> FindResource(Key const & key)
|
||||
{
|
||||
bool dummy = false;
|
||||
return FindResource(key, dummy);
|
||||
}
|
||||
|
||||
virtual ref_ptr<ResourceInfo> FindResource(Key const & /*key*/, bool & /*newResource*/) { return nullptr; }
|
||||
};
|
||||
137
libs/drape/drape_tests/font_texture_tests.cpp
Normal file
137
libs/drape/drape_tests/font_texture_tests.cpp
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/* This test crashes with ASSERT_NOT_EQUAL(CurrentApiVersion, dp::ApiVersion::Invalid, ()); in gl_functions.cpp
|
||||
#include "drape/drape_tests/dummy_texture.hpp"
|
||||
#include "drape/drape_tests/gl_mock_functions.hpp"
|
||||
#include "drape/drape_tests/img.hpp"
|
||||
#include "drape/drape_tests/testing_graphics_context.hpp"
|
||||
|
||||
#include "base/file_name_utils.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
#include "qt_tstfrm/test_main_loop.hpp"
|
||||
#include "testing/testing.hpp"
|
||||
|
||||
#include "drape/drape_routine.hpp"
|
||||
#include "drape/font_constants.hpp"
|
||||
#include "drape/font_texture.hpp"
|
||||
#include "drape/glyph_manager.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
using ::testing::InSequence;
|
||||
using ::testing::AnyNumber;
|
||||
using ::testing::Invoke;
|
||||
using namespace dp;
|
||||
using namespace std::placeholders;
|
||||
|
||||
namespace
|
||||
{
|
||||
class UploadedRender
|
||||
{
|
||||
public:
|
||||
explicit UploadedRender(QPoint const & pen) : m_pen(pen) {}
|
||||
|
||||
void glMemoryToQImage(int x, int y, int w, int h, glConst f, glConst t, void const * memory)
|
||||
{
|
||||
TEST(f == gl_const::GLAlpha || f == gl_const::GLAlpha8 || f == gl_const::GLRed, ());
|
||||
TEST(t == gl_const::GLUnsignedByteType, ());
|
||||
|
||||
uint8_t const * image = reinterpret_cast<uint8_t const *>(memory);
|
||||
|
||||
QPoint p(m_pen);
|
||||
p.rx() += x;
|
||||
m_images.push_back(qMakePair(p, CreateImage(w, h, image)));
|
||||
m_pen.ry() += h;
|
||||
}
|
||||
|
||||
void Render(QPaintDevice * device)
|
||||
{
|
||||
QPainter p(device);
|
||||
for (auto const & d : m_images)
|
||||
p.drawImage(d.first, d.second);
|
||||
}
|
||||
|
||||
private:
|
||||
QPoint m_pen;
|
||||
QVector<QPair<QPoint, QImage>> m_images;
|
||||
};
|
||||
|
||||
class DummyGlyphIndex : public GlyphIndex
|
||||
{
|
||||
public:
|
||||
DummyGlyphIndex(m2::PointU size, ref_ptr<GlyphManager> mng)
|
||||
: GlyphIndex(size, mng)
|
||||
{}
|
||||
ref_ptr<Texture::ResourceInfo> MapResource(GlyphKey const & key)
|
||||
{
|
||||
bool dummy = false;
|
||||
return GlyphIndex::MapResource(key, dummy);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(UploadingGlyphs)
|
||||
{
|
||||
// Set QT_QPA_PLATFORM=offscreen env var to avoid running GUI on Linux
|
||||
DrapeRoutine::Init();
|
||||
EXPECTGL(glHasExtension(_)).Times(AnyNumber());
|
||||
EXPECTGL(glBindTexture(_)).Times(AnyNumber());
|
||||
EXPECTGL(glDeleteTexture(_)).Times(AnyNumber());
|
||||
EXPECTGL(glTexParameter(_, _)).Times(AnyNumber());
|
||||
EXPECTGL(glTexImage2D(_, _, _, _, _)).Times(AnyNumber());
|
||||
EXPECTGL(glGenTexture()).Times(AnyNumber());
|
||||
|
||||
UploadedRender r(QPoint(10, 10));
|
||||
dp::GlyphManager::Params args;
|
||||
args.m_uniBlocks = base::JoinPath("fonts", "unicode_blocks.txt");
|
||||
args.m_whitelist = base::JoinPath("fonts", "whitelist.txt");
|
||||
args.m_blacklist = base::JoinPath("fonts", "blacklist.txt");
|
||||
GetPlatform().GetFontNames(args.m_fonts);
|
||||
|
||||
uint32_t constexpr kTextureSize = 1024;
|
||||
GlyphManager mng(args);
|
||||
DummyGlyphIndex index(m2::PointU(kTextureSize, kTextureSize), make_ref(&mng));
|
||||
size_t count = 1; // invalid symbol glyph has been mapped internally.
|
||||
count += (index.MapResource(GlyphKey(0x58)) != nullptr) ? 1 : 0;
|
||||
count += (index.MapResource(GlyphKey(0x59)) != nullptr) ? 1 : 0;
|
||||
count += (index.MapResource(GlyphKey(0x61)) != nullptr) ? 1 : 0;
|
||||
while (index.GetPendingNodesCount() < count)
|
||||
;
|
||||
|
||||
TestingGraphicsContext context;
|
||||
Texture::Params p;
|
||||
p.m_allocator = GetDefaultAllocator(make_ref(&context));
|
||||
p.m_format = dp::TextureFormat::Red;
|
||||
p.m_width = p.m_height = kTextureSize;
|
||||
|
||||
DummyTexture tex;
|
||||
tex.Create(make_ref(&context), p);
|
||||
EXPECTGL(glTexSubImage2D(_, _, _, _, _, _, _))
|
||||
.WillRepeatedly(Invoke(&r, &UploadedRender::glMemoryToQImage));
|
||||
index.UploadResources(make_ref(&context), make_ref(&tex));
|
||||
|
||||
count = 0;
|
||||
count += (index.MapResource(GlyphKey(0x68)) != nullptr) ? 1 : 0;
|
||||
count += (index.MapResource(GlyphKey(0x30)) != nullptr) ? 1 : 0;
|
||||
count += (index.MapResource(GlyphKey(0x62)) != nullptr) ? 1 : 0;
|
||||
count += (index.MapResource(GlyphKey(0x65)) != nullptr) ? 1 : 0;
|
||||
count += (index.MapResource(GlyphKey(0x400)) != nullptr) ? 1 : 0;
|
||||
count += (index.MapResource(GlyphKey(0x401)) != nullptr) ? 1 : 0;
|
||||
// TODO: Fix this condition
|
||||
//while (index.GetPendingNodesCount() < count)
|
||||
// ;
|
||||
|
||||
EXPECTGL(glTexSubImage2D(_, _, _, _, _, _, _))
|
||||
.WillRepeatedly(Invoke(&r, &UploadedRender::glMemoryToQImage));
|
||||
index.UploadResources(make_ref(&context), make_ref(&tex));
|
||||
|
||||
RunTestLoop("UploadingGlyphs", std::bind(&UploadedRender::Render, &r, _1));
|
||||
DrapeRoutine::Shutdown();
|
||||
}
|
||||
*/
|
||||
374
libs/drape/drape_tests/gl_functions.cpp
Normal file
374
libs/drape/drape_tests/gl_functions.cpp
Normal file
|
|
@ -0,0 +1,374 @@
|
|||
#include "drape/gl_functions.hpp"
|
||||
#include "drape/drape_tests/gl_mock_functions.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
using namespace emul;
|
||||
|
||||
dp::ApiVersion GLFunctions::CurrentApiVersion = dp::ApiVersion::Invalid;
|
||||
dp::GLExtensionsList GLFunctions::ExtensionsList;
|
||||
|
||||
#define MOCK_CALL(f) GLMockFunctions::Instance().f;
|
||||
|
||||
void GLFunctions::Init(dp::ApiVersion apiVersion)
|
||||
{
|
||||
MOCK_CALL(Init(apiVersion));
|
||||
}
|
||||
|
||||
void GLFunctions::glFlush() {}
|
||||
|
||||
void GLFunctions::glFinish() {}
|
||||
|
||||
uint32_t GLFunctions::glGenVertexArray()
|
||||
{
|
||||
return MOCK_CALL(glGenVertexArray());
|
||||
}
|
||||
|
||||
void GLFunctions::glBindVertexArray(uint32_t vao)
|
||||
{
|
||||
MOCK_CALL(glBindVertexArray(vao));
|
||||
}
|
||||
|
||||
void GLFunctions::glDeleteVertexArray(uint32_t vao)
|
||||
{
|
||||
MOCK_CALL(glDeleteVertexArray(vao));
|
||||
}
|
||||
|
||||
uint32_t GLFunctions::glGenBuffer()
|
||||
{
|
||||
return MOCK_CALL(glGenBuffer());
|
||||
}
|
||||
|
||||
void GLFunctions::glBindBuffer(uint32_t vbo, glConst target)
|
||||
{
|
||||
MOCK_CALL(glBindBuffer(vbo, target));
|
||||
}
|
||||
|
||||
void GLFunctions::glDeleteBuffer(uint32_t vbo)
|
||||
{
|
||||
MOCK_CALL(glDeleteBuffer(vbo));
|
||||
}
|
||||
|
||||
void GLFunctions::glBufferData(glConst target, uint32_t size, void const * data, glConst usage)
|
||||
{
|
||||
MOCK_CALL(glBufferData(target, size, data, usage));
|
||||
}
|
||||
|
||||
void GLFunctions::glBufferSubData(glConst target, uint32_t size, void const * data, uint32_t offset)
|
||||
{
|
||||
MOCK_CALL(glBufferSubData(target, size, data, offset));
|
||||
}
|
||||
|
||||
uint32_t GLFunctions::glCreateShader(glConst type)
|
||||
{
|
||||
return MOCK_CALL(glCreateShader(type));
|
||||
}
|
||||
|
||||
void GLFunctions::glShaderSource(uint32_t shaderID, std::string const & src, std::string const & defines)
|
||||
{
|
||||
MOCK_CALL(glShaderSource(shaderID, src));
|
||||
}
|
||||
|
||||
bool GLFunctions::glCompileShader(uint32_t shaderID, std::string & errorLog)
|
||||
{
|
||||
return MOCK_CALL(glCompileShader(shaderID, errorLog));
|
||||
}
|
||||
|
||||
void GLFunctions::glDeleteShader(uint32_t shaderID)
|
||||
{
|
||||
MOCK_CALL(glDeleteShader(shaderID));
|
||||
}
|
||||
|
||||
uint32_t GLFunctions::glCreateProgram()
|
||||
{
|
||||
return MOCK_CALL(glCreateProgram());
|
||||
}
|
||||
|
||||
void GLFunctions::glAttachShader(uint32_t programID, uint32_t shaderID)
|
||||
{
|
||||
MOCK_CALL(glAttachShader(programID, shaderID));
|
||||
}
|
||||
|
||||
void GLFunctions::glDetachShader(uint32_t programID, uint32_t shaderID)
|
||||
{
|
||||
MOCK_CALL(glDetachShader(programID, shaderID));
|
||||
}
|
||||
|
||||
bool GLFunctions::glLinkProgram(uint32_t programID, std::string & errorLog)
|
||||
{
|
||||
return MOCK_CALL(glLinkProgram(programID, errorLog));
|
||||
}
|
||||
|
||||
void GLFunctions::glDeleteProgram(uint32_t programID)
|
||||
{
|
||||
MOCK_CALL(glDeleteProgram(programID));
|
||||
}
|
||||
|
||||
void GLFunctions::glUseProgram(uint32_t programID)
|
||||
{
|
||||
MOCK_CALL(glUseProgram(programID));
|
||||
}
|
||||
|
||||
int8_t GLFunctions::glGetAttribLocation(uint32_t programID, std::string const & name)
|
||||
{
|
||||
return MOCK_CALL(glGetAttribLocation(programID, name));
|
||||
}
|
||||
|
||||
void GLFunctions::glBindAttribLocation(uint32_t programID, uint8_t index, std::string const & name) {}
|
||||
|
||||
// Enable vertex attribute binding. To get attributeLocation need to call glGetAttributeLocation.
|
||||
void GLFunctions::glEnableVertexAttribute(int32_t attributeLocation)
|
||||
{
|
||||
MOCK_CALL(glEnableVertexAttribute(attributeLocation));
|
||||
}
|
||||
|
||||
void GLFunctions::glVertexAttributePointer(int32_t attrLocation, uint32_t count, glConst type, bool needNormalize,
|
||||
uint32_t stride, uint32_t offset)
|
||||
{
|
||||
MOCK_CALL(glVertexAttributePointer(attrLocation, count, type, needNormalize, stride, offset));
|
||||
}
|
||||
|
||||
int8_t GLFunctions::glGetUniformLocation(uint32_t programID, std::string const & name)
|
||||
{
|
||||
return MOCK_CALL(glGetUniformLocation(programID, name));
|
||||
}
|
||||
|
||||
void GLFunctions::glUniformValuei(int8_t location, int32_t v)
|
||||
{
|
||||
MOCK_CALL(glUniformValuei(location, v));
|
||||
}
|
||||
|
||||
void GLFunctions::glUniformValuei(int8_t location, int32_t v1, int32_t v2)
|
||||
{
|
||||
MOCK_CALL(glUniformValuei(location, v1, v2));
|
||||
}
|
||||
|
||||
void GLFunctions::glUniformValuei(int8_t location, int32_t v1, int32_t v2, int32_t v3)
|
||||
{
|
||||
MOCK_CALL(glUniformValuei(location, v1, v2, v3));
|
||||
}
|
||||
|
||||
void GLFunctions::glUniformValuei(int8_t location, int32_t v1, int32_t v2, int32_t v3, int32_t v4)
|
||||
{
|
||||
MOCK_CALL(glUniformValuei(location, v1, v2, v3, v4));
|
||||
}
|
||||
|
||||
void GLFunctions::glUniformValuef(int8_t location, float v)
|
||||
{
|
||||
MOCK_CALL(glUniformValuef(location, v));
|
||||
}
|
||||
|
||||
void GLFunctions::glUniformValuef(int8_t location, float v1, float v2)
|
||||
{
|
||||
MOCK_CALL(glUniformValuef(location, v1, v2));
|
||||
}
|
||||
|
||||
void GLFunctions::glUniformValuef(int8_t location, float v1, float v2, float v3)
|
||||
{
|
||||
MOCK_CALL(glUniformValuef(location, v1, v2, v3));
|
||||
}
|
||||
|
||||
void GLFunctions::glUniformValuef(int8_t location, float v1, float v2, float v3, float v4)
|
||||
{
|
||||
MOCK_CALL(glUniformValuef(location, v1, v2, v3, v4));
|
||||
}
|
||||
|
||||
void GLFunctions::glUniformMatrix4x4Value(int8_t location, float const * values)
|
||||
{
|
||||
MOCK_CALL(glUniformMatrix4x4Value(location, values));
|
||||
}
|
||||
|
||||
uint32_t GLFunctions::glGetCurrentProgram()
|
||||
{
|
||||
return MOCK_CALL(glGetCurrentProgram());
|
||||
}
|
||||
|
||||
bool GLFunctions::glHasExtension(std::string const & extName)
|
||||
{
|
||||
return MOCK_CALL(glHasExtension(extName));
|
||||
}
|
||||
|
||||
int32_t GLFunctions::glGetProgramiv(uint32_t program, glConst paramName)
|
||||
{
|
||||
return MOCK_CALL(glGetProgramiv(program, paramName));
|
||||
}
|
||||
|
||||
void GLFunctions::glGetActiveUniform(uint32_t programID, uint32_t uniformIndex, int32_t * uniformSize, glConst * type,
|
||||
std::string & name)
|
||||
{
|
||||
MOCK_CALL(glGetActiveUniform(programID, uniformIndex, uniformSize, type, name));
|
||||
}
|
||||
|
||||
void GLFunctions::glActiveTexture(glConst texBlock)
|
||||
{
|
||||
MOCK_CALL(glActiveTexture(texBlock));
|
||||
}
|
||||
|
||||
uint32_t GLFunctions::glGenTexture()
|
||||
{
|
||||
MOCK_CALL(glGenTexture());
|
||||
return 1;
|
||||
}
|
||||
|
||||
void GLFunctions::glDeleteTexture(uint32_t id)
|
||||
{
|
||||
MOCK_CALL(glDeleteTexture(id));
|
||||
}
|
||||
|
||||
void GLFunctions::glBindTexture(uint32_t textureID)
|
||||
{
|
||||
MOCK_CALL(glBindTexture(textureID));
|
||||
}
|
||||
|
||||
void GLFunctions::glTexImage2D(int width, int height, glConst layout, glConst pixelType, void const * data)
|
||||
{
|
||||
MOCK_CALL(glTexImage2D(width, height, layout, pixelType, data));
|
||||
}
|
||||
|
||||
void GLFunctions::glTexSubImage2D(int x, int y, int width, int height, glConst layout, glConst pixelType,
|
||||
void const * data)
|
||||
{
|
||||
MOCK_CALL(glTexSubImage2D(x, y, width, height, layout, pixelType, data));
|
||||
}
|
||||
|
||||
void GLFunctions::glTexParameter(glConst param, glConst value)
|
||||
{
|
||||
MOCK_CALL(glTexParameter(param, value));
|
||||
}
|
||||
|
||||
int32_t GLFunctions::glGetInteger(glConst pname)
|
||||
{
|
||||
return MOCK_CALL(glGetInteger(pname));
|
||||
}
|
||||
|
||||
std::string GLFunctions::glGetString(glConst pname)
|
||||
{
|
||||
return MOCK_CALL(glGetString(pname));
|
||||
}
|
||||
|
||||
int32_t GLFunctions::glGetMaxLineWidth()
|
||||
{
|
||||
return MOCK_CALL(glGetMaxLineWidth());
|
||||
}
|
||||
|
||||
void GLFunctions::glLineWidth(uint32_t value)
|
||||
{
|
||||
return MOCK_CALL(glLineWidth(value));
|
||||
}
|
||||
|
||||
void GLFunctions::glViewport(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
|
||||
{
|
||||
return MOCK_CALL(glViewport(x, y, w, h));
|
||||
}
|
||||
|
||||
void GLFunctions::glScissor(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
|
||||
{
|
||||
return MOCK_CALL(glScissor(x, y, w, h));
|
||||
}
|
||||
|
||||
void GLFunctions::glGenFramebuffer(uint32_t * fbo)
|
||||
{
|
||||
return MOCK_CALL(glGenFramebuffer(fbo));
|
||||
}
|
||||
|
||||
void GLFunctions::glBindFramebuffer(uint32_t fbo)
|
||||
{
|
||||
return MOCK_CALL(glBindFramebuffer(fbo));
|
||||
}
|
||||
|
||||
void GLFunctions::glDeleteFramebuffer(uint32_t * fbo)
|
||||
{
|
||||
return MOCK_CALL(glDeleteFramebuffer(fbo));
|
||||
}
|
||||
|
||||
void GLFunctions::glFramebufferTexture2D(glConst attachment, glConst texture)
|
||||
{
|
||||
return MOCK_CALL(glFramebufferTexture2D(attachment, texture));
|
||||
}
|
||||
|
||||
uint32_t GLFunctions::glCheckFramebufferStatus()
|
||||
{
|
||||
return MOCK_CALL(glCheckFramebufferStatus());
|
||||
}
|
||||
|
||||
void CheckGLError(base::SrcPoint const & /*srcPt*/) {}
|
||||
|
||||
void GLFunctions::glEnable(glConst mode) {}
|
||||
|
||||
void GLFunctions::glBlendEquation(glConst function) {}
|
||||
|
||||
void GLFunctions::glBlendFunc(glConst srcFactor, glConst dstFactor) {}
|
||||
|
||||
bool GLFunctions::CanEnableDebugMessages()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLFunctions::glDebugMessageCallback(TglDebugProc messageCallback, void * userParam) {}
|
||||
|
||||
void GLFunctions::glDebugMessageControl(glConst source, glConst type, glConst severity, int32_t count,
|
||||
uint32_t const * ids, uint8_t enabled)
|
||||
{}
|
||||
|
||||
void GLFunctions::glDisable(glConst mode) {}
|
||||
|
||||
void GLFunctions::glDepthFunc(glConst depthFunc) {}
|
||||
|
||||
void GLFunctions::glUniformValueiv(int8_t location, int32_t * v, uint32_t size) {}
|
||||
|
||||
void * GLFunctions::glMapBuffer(glConst, glConst)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void * GLFunctions::glMapBufferRange(glConst, uint32_t, uint32_t, glConst)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GLFunctions::glUnmapBuffer(glConst target) {}
|
||||
|
||||
void GLFunctions::glDrawElements(glConst primitive, uint32_t sizeOfIndex, uint32_t indexCount, uint32_t startIndex) {}
|
||||
|
||||
void GLFunctions::glDrawArrays(glConst mode, int32_t first, uint32_t count) {}
|
||||
|
||||
void GLFunctions::glPixelStore(glConst name, uint32_t value) {}
|
||||
|
||||
void GLFunctions::glStencilOpSeparate(glConst face, glConst sfail, glConst dpfail, glConst dppass) {}
|
||||
|
||||
void GLFunctions::glStencilFuncSeparate(glConst face, glConst func, int ref, uint32_t mask) {}
|
||||
|
||||
int32_t GLFunctions::glGetBufferParameter(glConst target, glConst name)
|
||||
{
|
||||
return MOCK_CALL(glGetBufferParameter(target, name));
|
||||
}
|
||||
|
||||
void GLFunctions::glCullFace(glConst face)
|
||||
{
|
||||
MOCK_CALL(glCullFace(face));
|
||||
}
|
||||
|
||||
void GLFunctions::glFrontFace(glConst mode)
|
||||
{
|
||||
MOCK_CALL(glFrontFace(mode));
|
||||
}
|
||||
|
||||
void GLFunctions::glDepthMask(bool needWriteToDepthBuffer)
|
||||
{
|
||||
MOCK_CALL(glDepthMask(needWriteToDepthBuffer));
|
||||
}
|
||||
|
||||
void GLFunctions::glClear(uint32_t clearBits)
|
||||
{
|
||||
MOCK_CALL(glClear(clearBits));
|
||||
}
|
||||
|
||||
void GLFunctions::glClearColor(float r, float g, float b, float a)
|
||||
{
|
||||
MOCK_CALL(glClearColor(r, g, b, a));
|
||||
}
|
||||
|
||||
void GLFunctions::glClearDepthValue(double depth)
|
||||
{
|
||||
MOCK_CALL(glClearDepthValue(depth));
|
||||
}
|
||||
28
libs/drape/drape_tests/gl_mock_functions.cpp
Normal file
28
libs/drape/drape_tests/gl_mock_functions.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#include "drape/drape_tests/gl_mock_functions.hpp"
|
||||
|
||||
namespace emul
|
||||
{
|
||||
void GLMockFunctions::Init(int * argc, char ** argv)
|
||||
{
|
||||
::testing::InitGoogleMock(argc, argv);
|
||||
m_mock = new GLMockFunctions();
|
||||
}
|
||||
|
||||
void GLMockFunctions::Teardown()
|
||||
{
|
||||
delete m_mock;
|
||||
m_mock = NULL;
|
||||
}
|
||||
|
||||
GLMockFunctions & GLMockFunctions::Instance()
|
||||
{
|
||||
return *m_mock;
|
||||
}
|
||||
|
||||
void GLMockFunctions::ValidateAndClear()
|
||||
{
|
||||
::testing::Mock::VerifyAndClear(m_mock);
|
||||
}
|
||||
|
||||
GLMockFunctions * GLMockFunctions::m_mock;
|
||||
} // namespace emul
|
||||
109
libs/drape/drape_tests/gl_mock_functions.hpp
Normal file
109
libs/drape/drape_tests/gl_mock_functions.hpp
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#pragma once
|
||||
|
||||
#include "drape/drape_global.hpp"
|
||||
#include "drape/gl_constants.hpp"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace emul
|
||||
{
|
||||
class GLMockFunctions
|
||||
{
|
||||
public:
|
||||
static void Init(int * argc, char ** argv);
|
||||
static void Teardown();
|
||||
static GLMockFunctions & Instance();
|
||||
static void ValidateAndClear();
|
||||
|
||||
MOCK_METHOD1(Init, void(dp::ApiVersion));
|
||||
|
||||
// VAO
|
||||
MOCK_METHOD0(glGenVertexArray, uint32_t());
|
||||
MOCK_METHOD1(glBindVertexArray, void(uint32_t vao));
|
||||
MOCK_METHOD1(glDeleteVertexArray, void(uint32_t vao));
|
||||
|
||||
// VBO
|
||||
MOCK_METHOD0(glGenBuffer, uint32_t());
|
||||
MOCK_METHOD2(glBindBuffer, void(uint32_t vbo, glConst target));
|
||||
MOCK_METHOD1(glDeleteBuffer, void(uint32_t vbo));
|
||||
MOCK_METHOD4(glBufferData, void(glConst target, uint32_t size, void const * data, glConst usage));
|
||||
MOCK_METHOD4(glBufferSubData, void(glConst target, uint32_t size, void const * data, uint32_t offset));
|
||||
MOCK_METHOD2(glGetBufferParameter, int32_t(glConst target, glConst name));
|
||||
|
||||
MOCK_METHOD2(glGetUniformLocation, int8_t(uint32_t programID, std::string const & name));
|
||||
MOCK_METHOD2(glUniformValuei, void(int8_t location, int32_t v));
|
||||
MOCK_METHOD3(glUniformValuei, void(int8_t location, int32_t v1, int32_t v2));
|
||||
MOCK_METHOD4(glUniformValuei, void(int8_t location, int32_t v1, int32_t v2, int32_t v3));
|
||||
MOCK_METHOD5(glUniformValuei, void(int8_t location, int32_t v1, int32_t v2, int32_t v3, int32_t v4));
|
||||
|
||||
MOCK_METHOD2(glUniformValuef, void(int8_t location, float v));
|
||||
MOCK_METHOD3(glUniformValuef, void(int8_t location, float v1, float v2));
|
||||
MOCK_METHOD4(glUniformValuef, void(int8_t location, float v1, float v2, float v3));
|
||||
MOCK_METHOD5(glUniformValuef, void(int8_t location, float v1, float v2, float v3, float v4));
|
||||
MOCK_METHOD2(glUniformMatrix4x4Value, void(int8_t location, float const * values));
|
||||
MOCK_METHOD0(glGetCurrentProgram, uint32_t());
|
||||
|
||||
MOCK_METHOD1(glCreateShader, uint32_t(glConst type));
|
||||
MOCK_METHOD2(glShaderSource, void(uint32_t shaderID, std::string const & src));
|
||||
MOCK_METHOD2(glCompileShader, bool(uint32_t shaderID, std::string & errorLog));
|
||||
MOCK_METHOD1(glDeleteShader, void(uint32_t shaderID));
|
||||
|
||||
MOCK_METHOD0(glCreateProgram, uint32_t());
|
||||
MOCK_METHOD2(glAttachShader, void(uint32_t programID, uint32_t shaderID));
|
||||
MOCK_METHOD2(glDetachShader, void(uint32_t programID, uint32_t shaderID));
|
||||
MOCK_METHOD2(glLinkProgram, bool(uint32_t programID, std::string & errorLog));
|
||||
MOCK_METHOD1(glDeleteProgram, void(uint32_t programID));
|
||||
|
||||
MOCK_METHOD2(glGetAttribLocation, int32_t(uint32_t programID, std::string const & name));
|
||||
MOCK_METHOD1(glEnableVertexAttribute, void(int32_t attributeLocation));
|
||||
MOCK_METHOD6(glVertexAttributePointer, void(int32_t attrLocation, uint32_t count, glConst type, bool needNormalize,
|
||||
uint32_t stride, uint32_t offset));
|
||||
|
||||
MOCK_METHOD1(glUseProgram, void(uint32_t programID));
|
||||
MOCK_METHOD1(glHasExtension, bool(std::string const & extName));
|
||||
|
||||
MOCK_METHOD2(glGetProgramiv, int32_t(uint32_t, glConst));
|
||||
|
||||
MOCK_METHOD5(glGetActiveUniform, void(uint32_t, uint32_t, int32_t *, glConst *, std::string &));
|
||||
|
||||
// Texture functions
|
||||
MOCK_METHOD1(glActiveTexture, void(glConst));
|
||||
MOCK_METHOD0(glGenTexture, uint32_t());
|
||||
MOCK_METHOD1(glDeleteTexture, void(uint32_t));
|
||||
MOCK_METHOD1(glBindTexture, void(uint32_t));
|
||||
MOCK_METHOD5(glTexImage2D, void(int, int, glConst, glConst, void const *));
|
||||
MOCK_METHOD7(glTexSubImage2D, void(int, int, int, int, glConst, glConst, void const *));
|
||||
MOCK_METHOD2(glTexParameter, void(glConst, glConst));
|
||||
|
||||
MOCK_METHOD1(glGetInteger, int32_t(glConst));
|
||||
MOCK_METHOD1(glGetString, std::string(glConst));
|
||||
MOCK_METHOD0(glGetMaxLineWidth, int32_t());
|
||||
|
||||
MOCK_METHOD1(glLineWidth, void(uint32_t value));
|
||||
MOCK_METHOD4(glViewport, void(uint32_t x, uint32_t y, uint32_t w, uint32_t h));
|
||||
MOCK_METHOD4(glScissor, void(uint32_t x, uint32_t y, uint32_t w, uint32_t h));
|
||||
|
||||
// FBO
|
||||
MOCK_METHOD1(glGenFramebuffer, void(uint32_t * fbo));
|
||||
MOCK_METHOD1(glBindFramebuffer, void(uint32_t fbo));
|
||||
MOCK_METHOD1(glDeleteFramebuffer, void(uint32_t * fbo));
|
||||
MOCK_METHOD2(glFramebufferTexture2D, void(glConst attachment, glConst texture));
|
||||
MOCK_METHOD0(glCheckFramebufferStatus, uint32_t());
|
||||
|
||||
MOCK_METHOD1(glCullFace, void(glConst));
|
||||
MOCK_METHOD1(glFrontFace, void(glConst));
|
||||
|
||||
MOCK_METHOD1(glDepthMask, void(bool));
|
||||
|
||||
MOCK_METHOD1(glClear, void(uint32_t));
|
||||
MOCK_METHOD4(glClearColor, void(float, float, float, float));
|
||||
MOCK_METHOD1(glClearDepthValue, void(double));
|
||||
|
||||
private:
|
||||
static GLMockFunctions * m_mock;
|
||||
};
|
||||
} // namespace emul
|
||||
|
||||
#define EXPECTGL(x) EXPECT_CALL(emul::GLMockFunctions::Instance(), x)
|
||||
321
libs/drape/drape_tests/glyph_mng_tests.cpp
Normal file
321
libs/drape/drape_tests/glyph_mng_tests.cpp
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "drape/drape_tests/img.hpp"
|
||||
|
||||
#include "drape/font_constants.hpp"
|
||||
#include "drape/glyph_manager.hpp"
|
||||
#include "drape/harfbuzz_shaping.hpp"
|
||||
|
||||
#include "base/file_name_utils.hpp"
|
||||
|
||||
#include "qt_tstfrm/test_main_loop.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_MODULE_H
|
||||
#include <hb-ft.h>
|
||||
|
||||
namespace glyph_mng_tests
|
||||
{
|
||||
class GlyphRenderer
|
||||
{
|
||||
FT_Library m_freetypeLibrary;
|
||||
std::string m_utf8;
|
||||
int m_fontPixelSize;
|
||||
char const * m_lang;
|
||||
|
||||
static constexpr FT_Int kSdfSpread{dp::kSdfBorder};
|
||||
|
||||
public:
|
||||
GlyphRenderer()
|
||||
{
|
||||
// Initialize FreeType
|
||||
TEST_EQUAL(0, FT_Init_FreeType(&m_freetypeLibrary), ("Can't initialize FreeType"));
|
||||
for (auto const module : {"sdf", "bsdf"})
|
||||
TEST_EQUAL(0, FT_Property_Set(m_freetypeLibrary, module, "spread", &kSdfSpread), ());
|
||||
|
||||
dp::GlyphManager::Params args;
|
||||
args.m_uniBlocks = base::JoinPath("fonts", "unicode_blocks.txt");
|
||||
args.m_whitelist = base::JoinPath("fonts", "whitelist.txt");
|
||||
args.m_blacklist = base::JoinPath("fonts", "blacklist.txt");
|
||||
GetPlatform().GetFontNames(args.m_fonts);
|
||||
|
||||
m_mng = std::make_unique<dp::GlyphManager>(args);
|
||||
}
|
||||
|
||||
~GlyphRenderer() { FT_Done_FreeType(m_freetypeLibrary); }
|
||||
|
||||
void SetString(std::string const & s, int fontPixelSize, char const * lang)
|
||||
{
|
||||
m_utf8 = s;
|
||||
m_fontPixelSize = fontPixelSize;
|
||||
m_lang = lang;
|
||||
}
|
||||
|
||||
static float Smoothstep(float edge0, float edge1, float x)
|
||||
{
|
||||
x = std::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
|
||||
return x * x * (3 - 2 * x);
|
||||
}
|
||||
|
||||
static float PixelColorFromDistance(float distance)
|
||||
{
|
||||
// float const normalizedDistance = (distance - 128.f) / 128.f;
|
||||
float const normalizedDistance = distance / 255.f;
|
||||
static constexpr float kFontScale = 1.f;
|
||||
static constexpr float kSmoothing = 0.25f / (kSdfSpread * kFontScale);
|
||||
float const alpha = Smoothstep(0.5f - kSmoothing, 0.5f + kSmoothing, normalizedDistance);
|
||||
return 255.f * alpha;
|
||||
}
|
||||
|
||||
void RenderGlyphs(QPaintDevice * device) const
|
||||
{
|
||||
QPainter painter(device);
|
||||
painter.fillRect(QRectF(0.0, 0.0, device->width(), device->height()), Qt::white);
|
||||
|
||||
auto const shapedText = m_mng->ShapeText(m_utf8, m_fontPixelSize, m_lang);
|
||||
|
||||
std::cout << "Total width: " << shapedText.m_lineWidthInPixels << '\n';
|
||||
std::cout << "Max height: " << shapedText.m_maxLineHeightInPixels << '\n';
|
||||
|
||||
int constexpr kLineStartX = 10;
|
||||
int constexpr kLineMarginY = 50;
|
||||
QPoint pen(kLineStartX, kLineMarginY);
|
||||
|
||||
for (auto const & glyph : shapedText.m_glyphs)
|
||||
{
|
||||
constexpr bool kUseSdfBitmap = false;
|
||||
dp::GlyphImage img = m_mng->GetGlyphImage(glyph.m_key, m_fontPixelSize, kUseSdfBitmap);
|
||||
|
||||
auto const w = img.m_width;
|
||||
auto const h = img.m_height;
|
||||
// Spaces do not have images.
|
||||
if (w && h)
|
||||
{
|
||||
QPoint currentPen = pen;
|
||||
currentPen.rx() += glyph.m_xOffset;
|
||||
// Image is drawn at the top left origin, text metrics returns bottom left origin.
|
||||
currentPen.ry() -= glyph.m_yOffset + h;
|
||||
painter.drawImage(currentPen, CreateImage(w, h, img.m_data->data()), QRect(0, 0, w, h));
|
||||
}
|
||||
pen += QPoint(glyph.m_xAdvance, glyph.m_yAdvance /* 0 for horizontal texts */);
|
||||
|
||||
img.Destroy();
|
||||
}
|
||||
|
||||
pen.rx() = kLineStartX;
|
||||
pen.ry() += kLineMarginY;
|
||||
|
||||
for (auto const & glyph : shapedText.m_glyphs)
|
||||
{
|
||||
constexpr bool kUseSdfBitmap = true;
|
||||
auto img = m_mng->GetGlyphImage(glyph.m_key, m_fontPixelSize, kUseSdfBitmap);
|
||||
|
||||
auto const w = img.m_width;
|
||||
auto const h = img.m_height;
|
||||
// Spaces do not have images.
|
||||
if (w && h)
|
||||
{
|
||||
QPoint currentPen = pen;
|
||||
currentPen.rx() += glyph.m_xOffset;
|
||||
currentPen.ry() -= glyph.m_yOffset + h;
|
||||
painter.drawImage(currentPen, CreateImage(w, h, img.m_data->data()),
|
||||
QRect(dp::kSdfBorder, dp::kSdfBorder, w - 2 * dp::kSdfBorder, h - 2 * dp::kSdfBorder));
|
||||
}
|
||||
pen += QPoint(glyph.m_xAdvance, glyph.m_yAdvance /* 0 for horizontal texts */);
|
||||
|
||||
img.Destroy();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Manual rendering using HB functions.
|
||||
{
|
||||
pen.rx() = kLineStartX;
|
||||
pen.ry() += kLineMarginY;
|
||||
|
||||
auto const hbLanguage = hb_language_from_string(m_lang, -1);
|
||||
|
||||
auto const runs = harfbuzz_shaping::GetTextSegments(m_utf8);
|
||||
for (auto const & segment : runs.m_segments)
|
||||
{
|
||||
hb_buffer_t * buf = hb_buffer_create();
|
||||
hb_buffer_add_utf16(buf, reinterpret_cast<uint16_t const *>(runs.m_text.data()), runs.m_text.size(),
|
||||
segment.m_start, segment.m_length);
|
||||
hb_buffer_set_direction(buf, segment.m_direction);
|
||||
hb_buffer_set_script(buf, segment.m_script);
|
||||
hb_buffer_set_language(buf, hbLanguage);
|
||||
|
||||
// If direction, script, and language are not known.
|
||||
// hb_buffer_guess_segment_properties(buf);
|
||||
|
||||
std::string const lang = m_lang;
|
||||
std::string const fontFileName = lang == "ar" ? "00_NotoNaskhArabic-Regular.ttf" : "07_roboto_medium.ttf";
|
||||
|
||||
auto reader = GetPlatform().GetReader("fonts/" + fontFileName);
|
||||
auto fontFile = reader->GetName();
|
||||
FT_Face face;
|
||||
if (FT_New_Face(m_freetypeLibrary, fontFile.c_str(), 0, &face))
|
||||
{
|
||||
std::cerr << "Can't load font " << fontFile << '\n';
|
||||
return;
|
||||
}
|
||||
// Set character size
|
||||
FT_Set_Pixel_Sizes(face, 0, m_fontPixelSize);
|
||||
// This also works.
|
||||
// if (FT_Set_Char_Size(face, 0, m_fontPixelSize << 6, 0, 0)) {
|
||||
// std::cerr << "Can't set character size\n";
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Set no transform (identity)
|
||||
// FT_Set_Transform(face, nullptr, nullptr);
|
||||
|
||||
// Load font into HarfBuzz
|
||||
hb_font_t * font = hb_ft_font_create(face, nullptr);
|
||||
|
||||
// Shape!
|
||||
hb_shape(font, buf, nullptr, 0);
|
||||
|
||||
// Get the glyph and position information.
|
||||
unsigned int glyph_count;
|
||||
hb_glyph_info_t * glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count);
|
||||
hb_glyph_position_t * glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count);
|
||||
|
||||
for (unsigned int i = 0; i < glyph_count; i++)
|
||||
{
|
||||
hb_codepoint_t const glyphid = glyph_info[i].codepoint;
|
||||
|
||||
FT_Int32 const flags = FT_LOAD_RENDER;
|
||||
FT_Load_Glyph(face, glyphid, flags);
|
||||
FT_Render_Glyph(face->glyph, FT_RENDER_MODE_SDF);
|
||||
|
||||
FT_GlyphSlot slot = face->glyph;
|
||||
|
||||
FT_Bitmap const & ftBitmap = slot->bitmap;
|
||||
|
||||
auto const buffer = ftBitmap.buffer;
|
||||
auto const width = ftBitmap.width;
|
||||
auto const height = ftBitmap.rows;
|
||||
|
||||
for (unsigned h = 0; h < height; ++h)
|
||||
{
|
||||
for (unsigned w = 0; w < width; ++w)
|
||||
{
|
||||
auto curPixelAddr = buffer + h * width + w;
|
||||
float currPixel = *curPixelAddr;
|
||||
currPixel = PixelColorFromDistance(currPixel);
|
||||
*curPixelAddr = static_cast<unsigned char>(currPixel);
|
||||
}
|
||||
}
|
||||
|
||||
auto const bearing_x = slot->metrics.horiBearingX; // slot->bitmap_left;
|
||||
auto const bearing_y = slot->metrics.horiBearingY; // slot->bitmap_top;
|
||||
|
||||
auto const & glyphPos = glyph_pos[i];
|
||||
hb_position_t const x_offset = (glyphPos.x_offset + bearing_x) >> 6;
|
||||
hb_position_t const y_offset = (glyphPos.y_offset + bearing_y) >> 6;
|
||||
hb_position_t const x_advance = glyphPos.x_advance >> 6;
|
||||
hb_position_t const y_advance = glyphPos.y_advance >> 6;
|
||||
|
||||
// Empty images are possible for space characters.
|
||||
if (width != 0 && height != 0)
|
||||
{
|
||||
QPoint currentPen = pen;
|
||||
currentPen.rx() += x_offset;
|
||||
currentPen.ry() -= y_offset;
|
||||
painter.drawImage(currentPen, CreateImage(width, height, buffer),
|
||||
QRect(kSdfSpread, kSdfSpread, width - 2 * kSdfSpread, height - 2 * kSdfSpread));
|
||||
}
|
||||
pen += QPoint(x_advance, y_advance);
|
||||
}
|
||||
|
||||
// Tidy up.
|
||||
hb_buffer_destroy(buf);
|
||||
hb_font_destroy(font);
|
||||
FT_Done_Face(face);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// QT text renderer.
|
||||
{
|
||||
pen.rx() = kLineStartX;
|
||||
pen.ry() += kLineMarginY;
|
||||
|
||||
// QFont font("Noto Naskh Arabic");
|
||||
QFont font("Roboto");
|
||||
font.setPixelSize(m_fontPixelSize);
|
||||
// font.setWeight(QFont::Weight::Normal);
|
||||
painter.setFont(font);
|
||||
painter.drawText(pen, QString::fromUtf8(m_utf8.c_str(), m_utf8.size()));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<dp::GlyphManager> m_mng;
|
||||
};
|
||||
|
||||
// This unit test creates a window so can't be run in GUI-less Linux machine.
|
||||
// Make sure that the QT_QPA_PLATFORM=offscreen environment variable is set.
|
||||
UNIT_TEST(GlyphLoadingTest)
|
||||
{
|
||||
GlyphRenderer renderer;
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
constexpr int fontSize = 27;
|
||||
|
||||
renderer.SetString("Muḩāfaz̧at", fontSize, "en");
|
||||
RunTestLoop("Latin Extended", std::bind(&GlyphRenderer::RenderGlyphs, &renderer, _1));
|
||||
|
||||
renderer.SetString("Строка", fontSize, "ru");
|
||||
RunTestLoop("ru", std::bind(&GlyphRenderer::RenderGlyphs, &renderer, _1));
|
||||
|
||||
renderer.SetString("ØŒÆ", fontSize, "en");
|
||||
RunTestLoop("en", std::bind(&GlyphRenderer::RenderGlyphs, &renderer, _1));
|
||||
|
||||
renderer.SetString("𫝚 𫝛 𫝜", fontSize, "zh");
|
||||
RunTestLoop("CJK Surrogates", std::bind(&GlyphRenderer::RenderGlyphs, &renderer, _1));
|
||||
|
||||
renderer.SetString(
|
||||
"الحلّة گلها"
|
||||
" كسول الزنجبيل القط"
|
||||
"56"
|
||||
"عين علي (الحربية)"
|
||||
"123"
|
||||
" اَلْعَرَبِيَّةُ",
|
||||
fontSize, "ar");
|
||||
RunTestLoop("Arabic1", std::bind(&GlyphRenderer::RenderGlyphs, &renderer, _1));
|
||||
|
||||
renderer.SetString(
|
||||
"12345"
|
||||
"گُلها"
|
||||
"12345"
|
||||
"گُلها"
|
||||
"12345",
|
||||
fontSize, "ar");
|
||||
RunTestLoop("Arabic2", std::bind(&GlyphRenderer::RenderGlyphs, &renderer, _1));
|
||||
|
||||
renderer.SetString("മനക്കലപ്പടി", fontSize, "ml");
|
||||
RunTestLoop("Malay", std::bind(&GlyphRenderer::RenderGlyphs, &renderer, _1));
|
||||
|
||||
renderer.SetString(
|
||||
"Test 12 345 "
|
||||
"گُلها"
|
||||
"678 9000 Test",
|
||||
fontSize, "ar");
|
||||
RunTestLoop("Arabic Mixed", std::bind(&GlyphRenderer::RenderGlyphs, &renderer, _1));
|
||||
|
||||
renderer.SetString("NFKC Razdoĺny NFKD Razdoĺny", fontSize, "be");
|
||||
RunTestLoop("Polish", std::bind(&GlyphRenderer::RenderGlyphs, &renderer, _1));
|
||||
}
|
||||
|
||||
} // namespace glyph_mng_tests
|
||||
26
libs/drape/drape_tests/glyph_packer_test.cpp
Normal file
26
libs/drape/drape_tests/glyph_packer_test.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#include "drape/font_texture.hpp"
|
||||
#include "testing/testing.hpp"
|
||||
|
||||
UNIT_TEST(SimplePackTest)
|
||||
{
|
||||
dp::GlyphPacker packer(m2::PointU(32, 32));
|
||||
|
||||
m2::RectU r;
|
||||
|
||||
TEST(packer.PackGlyph(10, 13, r), ());
|
||||
TEST_EQUAL(r, m2::RectU(0, 0, 10, 13), ());
|
||||
|
||||
TEST(packer.PackGlyph(18, 8, r), ());
|
||||
TEST_EQUAL(r, m2::RectU(10, 0, 28, 8), ());
|
||||
|
||||
TEST(packer.PackGlyph(4, 15, r), ());
|
||||
TEST_EQUAL(r, m2::RectU(28, 0, 32, 15), ());
|
||||
|
||||
TEST(packer.PackGlyph(7, 10, r), ());
|
||||
TEST(!packer.IsFull(), ());
|
||||
TEST_EQUAL(r, m2::RectU(0, 15, 7, 25), ());
|
||||
|
||||
TEST(!packer.PackGlyph(12, 18, r), ());
|
||||
TEST(packer.IsFull(), ());
|
||||
TEST_EQUAL(r, m2::RectU(0, 15, 7, 25), ());
|
||||
}
|
||||
26
libs/drape/drape_tests/harfbuzz_shaping_test.cpp
Normal file
26
libs/drape/drape_tests/harfbuzz_shaping_test.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#include "drape/harfbuzz_shaping.hpp"
|
||||
#include "testing/testing.hpp"
|
||||
|
||||
namespace harfbuzz_shaping
|
||||
{
|
||||
|
||||
bool operator==(TextSegment const & s1, TextSegment const & s2)
|
||||
{
|
||||
return s1.m_start == s2.m_start && s1.m_length == s2.m_length && s1.m_script == s2.m_script &&
|
||||
s1.m_direction == s2.m_direction;
|
||||
}
|
||||
|
||||
UNIT_TEST(GetTextSegments)
|
||||
{
|
||||
auto const [text, segments] = GetTextSegments("Map data © OpenStreetMap");
|
||||
TEST(text == u"Map data © OpenStreetMap", ());
|
||||
|
||||
std::vector<TextSegment> const expected{
|
||||
{0, 3, HB_SCRIPT_LATIN, HB_DIRECTION_LTR}, {3, 1, HB_SCRIPT_COMMON, HB_DIRECTION_LTR},
|
||||
{4, 4, HB_SCRIPT_LATIN, HB_DIRECTION_LTR}, {8, 3, HB_SCRIPT_COMMON, HB_DIRECTION_LTR},
|
||||
{11, 13, HB_SCRIPT_LATIN, HB_DIRECTION_LTR},
|
||||
};
|
||||
|
||||
TEST_EQUAL(segments, expected, ());
|
||||
}
|
||||
} // namespace harfbuzz_shaping
|
||||
24
libs/drape/drape_tests/img.cpp
Normal file
24
libs/drape/drape_tests/img.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include "drape/drape_tests/img.hpp"
|
||||
|
||||
void cleanUpQImageMemory(void * mem)
|
||||
{
|
||||
free(mem);
|
||||
}
|
||||
|
||||
QImage CreateImage(uint32_t w, uint32_t h, uint8_t const * mem)
|
||||
{
|
||||
int pitch = 32 * (((w - 1) / 32) + 1);
|
||||
int byteCount = pitch * h;
|
||||
unsigned char * buf = (unsigned char *)malloc(byteCount);
|
||||
memset(buf, 0, byteCount);
|
||||
for (uint32_t i = 0; i < h; ++i)
|
||||
memcpy(buf + pitch * i, mem + w * i, w);
|
||||
|
||||
QImage img = QImage(buf, pitch, h, QImage::Format_Indexed8, &cleanUpQImageMemory, buf);
|
||||
|
||||
img.setColorCount(0xFF);
|
||||
for (int i = 0; i < 256; ++i)
|
||||
img.setColor(i, qRgb(255 - i, 255 - i, 255 - i));
|
||||
|
||||
return img;
|
||||
}
|
||||
5
libs/drape/drape_tests/img.hpp
Normal file
5
libs/drape/drape_tests/img.hpp
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <QtGui/QImage>
|
||||
|
||||
QImage CreateImage(uint32_t w, uint32_t h, uint8_t const * mem);
|
||||
49
libs/drape/drape_tests/memory_comparer.hpp
Normal file
49
libs/drape/drape_tests/memory_comparer.hpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include "base/logging.hpp"
|
||||
#include "drape/gl_constants.hpp"
|
||||
#include "testing/testing.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace dp
|
||||
{
|
||||
struct MemoryComparer
|
||||
{
|
||||
void * m_mem;
|
||||
int m_size;
|
||||
|
||||
MemoryComparer(void * memory, int size) : m_mem(memory), m_size(size) {}
|
||||
void cmpSubBuffer(glConst /*type*/, uint32_t size, void const * data, uint32_t /*offset*/) const
|
||||
{
|
||||
TEST_EQUAL(size, static_cast<uint32_t>(m_size), ());
|
||||
TEST_EQUAL(memcmp(m_mem, data, size), 0, ());
|
||||
}
|
||||
|
||||
void cmpSubImage(uint32_t /*x*/, uint32_t /*y*/, uint32_t width, uint32_t height, glConst layout, glConst pixelFormat,
|
||||
void const * data) const
|
||||
{
|
||||
uint32_t channelCount = 0;
|
||||
if (layout == gl_const::GLRGBA || layout == gl_const::GLRGBA8 || layout == gl_const::GLRGBA4)
|
||||
channelCount = 4;
|
||||
else if (layout == gl_const::GLRGB)
|
||||
channelCount = 3;
|
||||
else if (layout == gl_const::GLAlpha || layout == gl_const::GLAlpha8 || layout == gl_const::GLLuminance ||
|
||||
layout == gl_const::GLLuminance8 || layout == gl_const::GLAlphaLuminance || layout == gl_const::GLRed)
|
||||
{
|
||||
channelCount = 1;
|
||||
}
|
||||
else
|
||||
ASSERT(false, ());
|
||||
|
||||
ASSERT(gl_const::GL8BitOnChannel == pixelFormat, ());
|
||||
|
||||
TEST_EQUAL(static_cast<uint32_t>(m_size), width * height * channelCount, ());
|
||||
uint8_t * member = (uint8_t *)m_mem;
|
||||
uint8_t * input = (uint8_t *)data;
|
||||
|
||||
for (int i = 0; i < m_size; ++i)
|
||||
TEST_EQUAL(member[i], input[i], (i));
|
||||
}
|
||||
};
|
||||
} // namespace dp
|
||||
75
libs/drape/drape_tests/object_pool_tests.cpp
Normal file
75
libs/drape/drape_tests/object_pool_tests.cpp
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "drape/object_pool.hpp"
|
||||
|
||||
class vec2
|
||||
{
|
||||
public:
|
||||
class vec2Factory
|
||||
{
|
||||
public:
|
||||
vec2 * GetNew() const { return new vec2(); }
|
||||
};
|
||||
|
||||
public:
|
||||
float m_x, m_y;
|
||||
static int m_counter;
|
||||
|
||||
vec2() : m_x(0.0f), m_y(0.0f) { m_counter++; }
|
||||
~vec2() { m_counter--; }
|
||||
};
|
||||
|
||||
int vec2::m_counter = 0;
|
||||
|
||||
UNIT_TEST(ObjectPoolFilling)
|
||||
{
|
||||
vec2::vec2Factory factory;
|
||||
dp::ObjectPool<vec2, vec2::vec2Factory> pool(1, factory);
|
||||
vec2 *pt1, *pt2, *pt3;
|
||||
pt1 = pool.Get();
|
||||
pool.Return(pt1);
|
||||
pt2 = pool.Get();
|
||||
TEST_EQUAL(pt1, pt2, ());
|
||||
pt3 = pool.Get();
|
||||
|
||||
pool.Return(pt2);
|
||||
pool.Return(pt3);
|
||||
}
|
||||
|
||||
UNIT_TEST(ObjectPoolClearing_1)
|
||||
{
|
||||
vec2::m_counter = 0;
|
||||
vec2::vec2Factory factory;
|
||||
auto pool = new dp::ObjectPool<vec2, vec2::vec2Factory>(1, factory);
|
||||
vec2 *pt1, *pt2, *pt3;
|
||||
pt1 = pool->Get();
|
||||
pool->Return(pt1);
|
||||
pt2 = pool->Get();
|
||||
pt3 = pool->Get();
|
||||
|
||||
pool->Return(pt2);
|
||||
pool->Return(pt3);
|
||||
|
||||
delete pool;
|
||||
|
||||
TEST_EQUAL(vec2::m_counter, 0, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(ObjectPoolClearing_2)
|
||||
{
|
||||
vec2::m_counter = 0;
|
||||
vec2::vec2Factory factory;
|
||||
auto pool = new dp::ObjectPool<vec2, vec2::vec2Factory>(100, factory);
|
||||
vec2 *pt1, *pt2, *pt3;
|
||||
pt1 = pool->Get();
|
||||
pool->Return(pt1);
|
||||
pt2 = pool->Get();
|
||||
pt3 = pool->Get();
|
||||
|
||||
pool->Return(pt2);
|
||||
pool->Return(pt3);
|
||||
|
||||
delete pool;
|
||||
|
||||
TEST_EQUAL(vec2::m_counter, 0, ());
|
||||
}
|
||||
97
libs/drape/drape_tests/pointers_tests.cpp
Normal file
97
libs/drape/drape_tests/pointers_tests.cpp
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
#include "drape/pointers.hpp"
|
||||
#include "testing/testing.hpp"
|
||||
|
||||
#include "base/base.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace
|
||||
{
|
||||
class Tester
|
||||
{
|
||||
public:
|
||||
Tester() = default;
|
||||
};
|
||||
|
||||
#if defined(TRACK_POINTERS)
|
||||
bool g_assertRaised = false;
|
||||
bool OnAssertRaised(base::SrcPoint const & /* srcPoint */, std::string const & /* msg */)
|
||||
{
|
||||
g_assertRaised = true;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(PointersTrackingTest)
|
||||
{
|
||||
#if defined(TRACK_POINTERS)
|
||||
|
||||
DpPointerTracker::TAlivePointers const & alivePointers = DpPointerTracker::Instance().GetAlivePointers();
|
||||
|
||||
drape_ptr<Tester> ptr = make_unique_dp<Tester>();
|
||||
void * ptrAddress = ptr.get();
|
||||
std::string const ptrTypeName = typeid(Tester *).name();
|
||||
|
||||
// no references
|
||||
TEST(alivePointers.find(ptrAddress) == alivePointers.end(), ());
|
||||
|
||||
// create a reference
|
||||
ref_ptr<Tester> refPtr = make_ref(ptr);
|
||||
|
||||
DpPointerTracker::TAlivePointers::const_iterator found = alivePointers.find(ptrAddress);
|
||||
TEST(found != alivePointers.end(), ());
|
||||
TEST_EQUAL(found->second.first, 1, ());
|
||||
TEST_EQUAL(found->second.second, ptrTypeName, ());
|
||||
|
||||
// copy reference
|
||||
ref_ptr<Tester> refPtr2 = refPtr;
|
||||
|
||||
found = alivePointers.find(ptrAddress);
|
||||
TEST_EQUAL(found->second.first, 2, ());
|
||||
|
||||
// remove reference
|
||||
{
|
||||
ref_ptr<Tester> refPtrInScope = refPtr2;
|
||||
TEST_EQUAL(found->second.first, 3, ());
|
||||
}
|
||||
TEST_EQUAL(found->second.first, 2, ());
|
||||
|
||||
// move reference
|
||||
ref_ptr<Tester> refPtr3 = std::move(refPtr2);
|
||||
TEST_EQUAL(found->second.first, 2, ());
|
||||
|
||||
// assign reference
|
||||
ref_ptr<Tester> refPtr4;
|
||||
refPtr4 = refPtr3;
|
||||
TEST_EQUAL(found->second.first, 3, ());
|
||||
|
||||
// move-assign reference
|
||||
refPtr4 = std::move(refPtr3);
|
||||
TEST_EQUAL(found->second.first, 2, ());
|
||||
|
||||
// create another reference
|
||||
ref_ptr<Tester> refPtr5 = make_ref(ptr);
|
||||
TEST_EQUAL(found->second.first, 3, ());
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
UNIT_TEST(RefPointerExpiringTest)
|
||||
{
|
||||
#if defined(TRACK_POINTERS)
|
||||
g_assertRaised = false;
|
||||
base::AssertFailedFn prevFn = base::SetAssertFunction(OnAssertRaised);
|
||||
|
||||
drape_ptr<Tester> ptr = make_unique_dp<Tester>();
|
||||
ref_ptr<Tester> refPtr1 = make_ref(ptr);
|
||||
ref_ptr<Tester> refPtr2 = make_ref(ptr);
|
||||
ptr.reset();
|
||||
|
||||
base::SetAssertFunction(prevFn);
|
||||
|
||||
TEST(g_assertRaised, ());
|
||||
#endif
|
||||
}
|
||||
31
libs/drape/drape_tests/static_texture_tests.cpp
Normal file
31
libs/drape/drape_tests/static_texture_tests.cpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "indexer/map_style.hpp"
|
||||
#include "indexer/map_style_reader.hpp"
|
||||
|
||||
#include "drape/drape_tests/testing_graphics_context.hpp"
|
||||
#include "drape/static_texture.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
UNIT_TEST(CheckTrafficArrowTextures)
|
||||
{
|
||||
static std::vector<std::string> skinPaths = {"6plus", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"};
|
||||
static std::vector<MapStyle> styles = {MapStyle::MapStyleDefaultLight, MapStyle::MapStyleDefaultDark,
|
||||
MapStyle::MapStyleVehicleLight, MapStyle::MapStyleVehicleDark};
|
||||
|
||||
TestingGraphicsContext context;
|
||||
for (auto const & style : styles)
|
||||
{
|
||||
GetStyleReader().SetCurrentStyle(style);
|
||||
for (auto const & skinPath : skinPaths)
|
||||
{
|
||||
dp::StaticTexture texture(make_ref(&context), "traffic-arrow.png", skinPath, dp::TextureFormat::RGBA8, nullptr);
|
||||
TEST(texture.IsLoadingCorrect(), ());
|
||||
|
||||
dp::StaticTexture texture2(make_ref(&context), "area-hatching.png", skinPath, dp::TextureFormat::RGBA8, nullptr);
|
||||
TEST(texture2.IsLoadingCorrect(), ());
|
||||
}
|
||||
}
|
||||
}
|
||||
77
libs/drape/drape_tests/stipple_pen_tests.cpp
Normal file
77
libs/drape/drape_tests/stipple_pen_tests.cpp
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "drape/drape_tests/dummy_texture.hpp"
|
||||
#include "drape/drape_tests/memory_comparer.hpp"
|
||||
|
||||
#include "drape/stipple_pen_resource.hpp"
|
||||
#include "drape/texture.hpp"
|
||||
#include "drape/tm_read_resources.hpp"
|
||||
|
||||
namespace stipple_pen_tests
|
||||
{
|
||||
using namespace dp;
|
||||
|
||||
namespace
|
||||
{
|
||||
void TestPacker(StipplePenPacker & packer, uint32_t width, m2::RectU const & expect)
|
||||
{
|
||||
TEST_EQUAL(packer.PackResource({width, 1}), expect, ());
|
||||
}
|
||||
|
||||
bool IsRectsEqual(m2::RectF const & r1, m2::RectF const & r2)
|
||||
{
|
||||
return AlmostEqualULPs(r1.minX(), r2.minX()) && AlmostEqualULPs(r1.minY(), r2.minY()) &&
|
||||
AlmostEqualULPs(r1.maxX(), r2.maxX()) && AlmostEqualULPs(r1.maxY(), r2.maxY());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(StippleTest_Pack)
|
||||
{
|
||||
StipplePenPacker packer(m2::PointU(512, 8));
|
||||
TestPacker(packer, 30, m2::RectU(0, 0, 30, 1));
|
||||
TestPacker(packer, 254, m2::RectU(0, 1, 254, 2));
|
||||
TestPacker(packer, 1, m2::RectU(0, 2, 1, 3));
|
||||
TestPacker(packer, 250, m2::RectU(0, 3, 250, 4));
|
||||
TestPacker(packer, 249, m2::RectU(0, 4, 249, 5));
|
||||
|
||||
m2::RectF mapped = packer.MapTextureCoords(m2::RectU(0, 0, 256, 1));
|
||||
TEST(IsRectsEqual(mapped, m2::RectF(0.5f / 512.0f, 0.5f / 8.0f, 255.5f / 512.0f, 0.5f / 8.0f)), ());
|
||||
}
|
||||
|
||||
UNIT_TEST(StippleTest_EqualPatterns)
|
||||
{
|
||||
using PatternT = std::array<double, 2>;
|
||||
std::vector<PatternT> patterns;
|
||||
|
||||
using namespace dp::impl;
|
||||
ParsePatternsList("./data/patterns.txt", [&patterns](buffer_vector<double, 8> const & p)
|
||||
{
|
||||
if (p.size() == 2)
|
||||
patterns.push_back({p[0], p[1]});
|
||||
});
|
||||
|
||||
auto const IsEqualPatterns = [](PatternT const & p1, PatternT const & p2)
|
||||
{
|
||||
for (double scale : {1, 2, 3})
|
||||
if ((PatternFloat2Pixel(scale * p1[0]) != PatternFloat2Pixel(scale * p2[0])) ||
|
||||
(PatternFloat2Pixel(scale * p1[1]) != PatternFloat2Pixel(scale * p2[1])))
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
auto const IsAlmostEqualPatterns = [](PatternT const & p1, PatternT const & p2)
|
||||
{
|
||||
double const scale = 3;
|
||||
return (fabs(scale * p1[0] - scale * p2[0]) + fabs(scale * p1[1] - scale * p2[1])) < 1;
|
||||
};
|
||||
|
||||
size_t const count = patterns.size();
|
||||
for (size_t i = 0; i < count - 1; ++i)
|
||||
{
|
||||
for (size_t j = i + 1; j < count; ++j)
|
||||
if (IsEqualPatterns(patterns[i], patterns[j]))
|
||||
LOG(LINFO, ("Equal:", patterns[i], patterns[j]));
|
||||
else if (IsAlmostEqualPatterns(patterns[i], patterns[j]))
|
||||
LOG(LINFO, ("Almost equal:", patterns[i], patterns[j]));
|
||||
}
|
||||
}
|
||||
} // namespace stipple_pen_tests
|
||||
43
libs/drape/drape_tests/testing_graphics_context.hpp
Normal file
43
libs/drape/drape_tests/testing_graphics_context.hpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include "drape/graphics_context.hpp"
|
||||
|
||||
// Testing context simulates OpenGLES3 API version.
|
||||
class TestingGraphicsContext : public dp::GraphicsContext
|
||||
{
|
||||
public:
|
||||
TestingGraphicsContext() = default;
|
||||
explicit TestingGraphicsContext(dp::ApiVersion apiVersion) : m_apiVersion(apiVersion) {}
|
||||
|
||||
void Present() override {}
|
||||
void MakeCurrent() override {}
|
||||
void SetFramebuffer(ref_ptr<dp::BaseFramebuffer> framebuffer) override {}
|
||||
void ForgetFramebuffer(ref_ptr<dp::BaseFramebuffer> framebuffer) override {}
|
||||
void ApplyFramebuffer(std::string const & framebufferLabel) override {}
|
||||
|
||||
void Init(dp::ApiVersion apiVersion) override {}
|
||||
dp::ApiVersion GetApiVersion() const override { return m_apiVersion; }
|
||||
std::string GetRendererName() const override { return {}; }
|
||||
std::string GetRendererVersion() const override { return {}; }
|
||||
|
||||
void PushDebugLabel(std::string const & label) override {}
|
||||
void PopDebugLabel() override {}
|
||||
|
||||
void SetClearColor(dp::Color const & color) override {}
|
||||
void Clear(uint32_t clearBits, uint32_t storeBits) override {}
|
||||
void Flush() override {}
|
||||
void SetViewport(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override {}
|
||||
void SetScissor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override {}
|
||||
void SetDepthTestEnabled(bool enabled) override {}
|
||||
void SetDepthTestFunction(dp::TestFunction depthFunction) override {}
|
||||
void SetStencilTestEnabled(bool enabled) override {}
|
||||
void SetStencilFunction(dp::StencilFace face, dp::TestFunction stencilFunction) override {}
|
||||
void SetStencilActions(dp::StencilFace face, dp::StencilAction stencilFailAction, dp::StencilAction depthFailAction,
|
||||
dp::StencilAction passAction) override
|
||||
{}
|
||||
void SetStencilReferenceValue(uint32_t stencilReferenceValue) override {}
|
||||
void SetCullingEnabled(bool enabled) override {}
|
||||
|
||||
private:
|
||||
dp::ApiVersion m_apiVersion = dp::ApiVersion::OpenGLES3;
|
||||
};
|
||||
346
libs/drape/drape_tests/texture_of_colors_tests.cpp
Normal file
346
libs/drape/drape_tests/texture_of_colors_tests.cpp
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "drape/drape_tests/dummy_texture.hpp"
|
||||
#include "drape/drape_tests/memory_comparer.hpp"
|
||||
#include "drape/drape_tests/testing_graphics_context.hpp"
|
||||
|
||||
#include "drape/gl_constants.hpp"
|
||||
#include "drape/texture.hpp"
|
||||
#include "drape/texture_of_colors.hpp"
|
||||
|
||||
#include "drape/drape_tests/gl_mock_functions.hpp"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using testing::_;
|
||||
using testing::AnyOf;
|
||||
using testing::IgnoreResult;
|
||||
using testing::InSequence;
|
||||
using testing::Invoke;
|
||||
using testing::Return;
|
||||
using namespace dp;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void TestRects(m2::RectF const & a, m2::RectF const & b)
|
||||
{
|
||||
TEST_ALMOST_EQUAL_ULPS(a.minX(), b.minX(), ());
|
||||
TEST_ALMOST_EQUAL_ULPS(a.maxX(), b.maxX(), ());
|
||||
TEST_ALMOST_EQUAL_ULPS(a.minY(), b.minY(), ());
|
||||
TEST_ALMOST_EQUAL_ULPS(a.maxY(), b.maxY(), ());
|
||||
}
|
||||
|
||||
void InitOpenGLTextures(int const w, int const h)
|
||||
{
|
||||
InSequence seq;
|
||||
EXPECTGL(glHasExtension(_)).WillRepeatedly(Return(true));
|
||||
EXPECTGL(glGenTexture()).WillOnce(Return(1));
|
||||
EXPECTGL(glBindTexture(1)).WillOnce(Return());
|
||||
EXPECTGL(glTexImage2D(w, h, AnyOf(gl_const::GLRGBA, gl_const::GLRGBA8), gl_const::GL8BitOnChannel, NULL));
|
||||
EXPECTGL(glTexParameter(gl_const::GLMinFilter, gl_const::GLLinear));
|
||||
EXPECTGL(glTexParameter(gl_const::GLMagFilter, gl_const::GLLinear));
|
||||
EXPECTGL(glTexParameter(gl_const::GLWrapS, gl_const::GLClampToEdge));
|
||||
EXPECTGL(glTexParameter(gl_const::GLWrapT, gl_const::GLClampToEdge));
|
||||
EXPECTGL(glBindTexture(0)).WillOnce(Return());
|
||||
}
|
||||
|
||||
class DummyColorPallete : public ColorPalette
|
||||
{
|
||||
typedef ColorPalette TBase;
|
||||
|
||||
public:
|
||||
explicit DummyColorPallete(m2::PointU const & size) : TBase(size) {}
|
||||
|
||||
ref_ptr<Texture::ResourceInfo> MapResource(ColorKey const & key)
|
||||
{
|
||||
bool dummy = false;
|
||||
return TBase::MapResource(key, dummy);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
UNIT_TEST(ColorPalleteMappingTests)
|
||||
{
|
||||
DummyColorPallete cp(m2::PointU(32, 16));
|
||||
|
||||
ref_ptr<Texture::ResourceInfo> info1 = cp.MapResource(dp::ColorKey(dp::Color(0, 0, 0, 0)));
|
||||
ref_ptr<Texture::ResourceInfo> info2 = cp.MapResource(dp::ColorKey(dp::Color(1, 1, 1, 1)));
|
||||
ref_ptr<Texture::ResourceInfo> info3 = cp.MapResource(dp::ColorKey(dp::Color(0, 0, 0, 0)));
|
||||
|
||||
TEST_NOT_EQUAL(info1, info2, ());
|
||||
TEST_EQUAL(info1, info3, ());
|
||||
|
||||
TestRects(info1->GetTexRect(), m2::RectF(1.0f / 32.0f, 1.0f / 16, 1.0f / 32.0f, 1.0f / 16));
|
||||
TestRects(info2->GetTexRect(), m2::RectF(3.0f / 32.0f, 1.0f / 16, 3.0f / 32.0f, 1.0f / 16));
|
||||
TestRects(info3->GetTexRect(), m2::RectF(1.0f / 32.0f, 1.0f / 16, 1.0f / 32.0f, 1.0f / 16));
|
||||
|
||||
for (int i = 2; i < 100; ++i)
|
||||
cp.MapResource(dp::ColorKey(dp::Color(i, i, i, i)));
|
||||
|
||||
TestRects(cp.MapResource(dp::ColorKey(dp::Color(54, 54, 54, 54)))->GetTexRect(),
|
||||
m2::RectF(13.0f / 32.0f, 7.0f / 16.0f, 13.0f / 32.0f, 7.0f / 16.0f));
|
||||
}
|
||||
|
||||
UNIT_TEST(ColorPalleteUploadingSingleRow)
|
||||
{
|
||||
int const width = 32;
|
||||
int const height = 16;
|
||||
InitOpenGLTextures(width, height);
|
||||
|
||||
TestingGraphicsContext context;
|
||||
Texture::Params p;
|
||||
p.m_allocator = GetDefaultAllocator(make_ref(&context));
|
||||
p.m_format = dp::TextureFormat::RGBA8;
|
||||
p.m_width = width;
|
||||
p.m_height = height;
|
||||
|
||||
DummyTexture texture;
|
||||
texture.Create(make_ref(&context), p);
|
||||
DummyColorPallete cp(m2::PointU(width, height));
|
||||
cp.UploadResources(make_ref(&context), make_ref(&texture));
|
||||
|
||||
{
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xFF, 0, 0, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0, 0xFF, 0, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0, 0, 0xFF, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0, 0, 0, 0xFF)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xAA, 0xBB, 0xCC, 0xDD)));
|
||||
|
||||
uint8_t memoryEtalon[] = {
|
||||
0xFF, 0x00, 0x00, 0x00, // 1 pixel (1st row)
|
||||
0xFF, 0x00, 0x00, 0x00, // 1 pixel (1st row)
|
||||
0x00, 0xFF, 0x00, 0x00, // 2 pixel (1st row)
|
||||
0x00, 0xFF, 0x00, 0x00, // 2 pixel (1st row)
|
||||
0x00, 0x00, 0xFF, 0x00, // 3 pixel (1st row)
|
||||
0x00, 0x00, 0xFF, 0x00, // 3 pixel (1st row)
|
||||
0x00, 0x00, 0x00, 0xFF, // 4 pixel (1st row)
|
||||
0x00, 0x00, 0x00, 0xFF, // 4 pixel (1st row)
|
||||
0xAA, 0xBB, 0xCC, 0xDD, // 5 pixel (1st row)
|
||||
0xAA, 0xBB, 0xCC, 0xDD, // 5 pixel (1st row)
|
||||
|
||||
0xFF, 0x00, 0x00, 0x00, // 1 pixel (2nd row)
|
||||
0xFF, 0x00, 0x00, 0x00, // 1 pixel (2nd row)
|
||||
0x00, 0xFF, 0x00, 0x00, // 2 pixel (2nd row)
|
||||
0x00, 0xFF, 0x00, 0x00, // 2 pixel (2nd row)
|
||||
0x00, 0x00, 0xFF, 0x00, // 3 pixel (2nd row)
|
||||
0x00, 0x00, 0xFF, 0x00, // 3 pixel (2nd row)
|
||||
0x00, 0x00, 0x00, 0xFF, // 4 pixel (2nd row)
|
||||
0x00, 0x00, 0x00, 0xFF, // 4 pixel (2nd row)
|
||||
0xAA, 0xBB, 0xCC, 0xDD, // 5 pixel (2nd row)
|
||||
0xAA, 0xBB, 0xCC, 0xDD // 5 pixel (2nd row)
|
||||
};
|
||||
|
||||
MemoryComparer cmp(memoryEtalon, ARRAY_SIZE(memoryEtalon));
|
||||
EXPECTGL(glTexSubImage2D(0, 0, 10, 2, AnyOf(gl_const::GLRGBA, gl_const::GLRGBA8), gl_const::GL8BitOnChannel, _))
|
||||
.WillOnce(Invoke(&cmp, &MemoryComparer::cmpSubImage));
|
||||
|
||||
cp.UploadResources(make_ref(&context), make_ref(&texture));
|
||||
}
|
||||
|
||||
{
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xFF, 0xAA, 0, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xAA, 0xFF, 0, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xAA, 0, 0xFF, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xAA, 0, 0, 0xFF)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0x00, 0xBB, 0xCC, 0xDD)));
|
||||
|
||||
uint8_t memoryEtalon[] = {
|
||||
0xFF, 0xAA, 0x00, 0x00, // 1 pixel (1st row)
|
||||
0xFF, 0xAA, 0x00, 0x00, // 1 pixel (1st row)
|
||||
0xAA, 0xFF, 0x00, 0x00, // 2 pixel (1st row)
|
||||
0xAA, 0xFF, 0x00, 0x00, // 2 pixel (1st row)
|
||||
0xAA, 0x00, 0xFF, 0x00, // 3 pixel (1st row)
|
||||
0xAA, 0x00, 0xFF, 0x00, // 3 pixel (1st row)
|
||||
0xAA, 0x00, 0x00, 0xFF, // 4 pixel (1st row)
|
||||
0xAA, 0x00, 0x00, 0xFF, // 4 pixel (1st row)
|
||||
0x00, 0xBB, 0xCC, 0xDD, // 5 pixel (1st row)
|
||||
0x00, 0xBB, 0xCC, 0xDD, // 5 pixel (1st row)
|
||||
|
||||
0xFF, 0xAA, 0x00, 0x00, // 1 pixel (2nd row)
|
||||
0xFF, 0xAA, 0x00, 0x00, // 1 pixel (2nd row)
|
||||
0xAA, 0xFF, 0x00, 0x00, // 2 pixel (2nd row)
|
||||
0xAA, 0xFF, 0x00, 0x00, // 2 pixel (2nd row)
|
||||
0xAA, 0x00, 0xFF, 0x00, // 3 pixel (2nd row)
|
||||
0xAA, 0x00, 0xFF, 0x00, // 3 pixel (2nd row)
|
||||
0xAA, 0x00, 0x00, 0xFF, // 4 pixel (2nd row)
|
||||
0xAA, 0x00, 0x00, 0xFF, // 4 pixel (2nd row)
|
||||
0x00, 0xBB, 0xCC, 0xDD, // 5 pixel (2nd row)
|
||||
0x00, 0xBB, 0xCC, 0xDD // 5 pixel (2nd row)
|
||||
};
|
||||
|
||||
MemoryComparer cmp(memoryEtalon, ARRAY_SIZE(memoryEtalon));
|
||||
EXPECTGL(glTexSubImage2D(10, 0, 10, 2, AnyOf(gl_const::GLRGBA, gl_const::GLRGBA8), gl_const::GL8BitOnChannel, _))
|
||||
.WillOnce(Invoke(&cmp, &MemoryComparer::cmpSubImage));
|
||||
|
||||
cp.UploadResources(make_ref(&context), make_ref(&texture));
|
||||
}
|
||||
|
||||
EXPECTGL(glDeleteTexture(1));
|
||||
}
|
||||
|
||||
UNIT_TEST(ColorPalleteUploadingPartialyRow)
|
||||
{
|
||||
int const width = 8;
|
||||
int const height = 8;
|
||||
InitOpenGLTextures(width, height);
|
||||
|
||||
TestingGraphicsContext context;
|
||||
Texture::Params p;
|
||||
p.m_allocator = GetDefaultAllocator(make_ref(&context));
|
||||
p.m_format = dp::TextureFormat::RGBA8;
|
||||
p.m_width = width;
|
||||
p.m_height = height;
|
||||
|
||||
DummyTexture texture;
|
||||
texture.Create(make_ref(&context), p);
|
||||
|
||||
DummyColorPallete cp(m2::PointU(width, height));
|
||||
|
||||
{
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xFF, 0, 0, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xFF, 0xFF, 0, 0)));
|
||||
|
||||
uint8_t memoryEtalon[] = {
|
||||
0xFF, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xFF, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xFF, 0xFF, 0x00, 0x00, // 2 pixel
|
||||
0xFF, 0xFF, 0x00, 0x00, // 2 pixel
|
||||
|
||||
0xFF, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xFF, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xFF, 0xFF, 0x00, 0x00, // 2 pixel
|
||||
0xFF, 0xFF, 0x00, 0x00 // 2 pixel
|
||||
};
|
||||
|
||||
MemoryComparer cmp(memoryEtalon, ARRAY_SIZE(memoryEtalon));
|
||||
EXPECTGL(glTexSubImage2D(0, 0, 4, 2, AnyOf(gl_const::GLRGBA, gl_const::GLRGBA8), gl_const::GL8BitOnChannel, _))
|
||||
.WillOnce(Invoke(&cmp, &MemoryComparer::cmpSubImage));
|
||||
|
||||
cp.UploadResources(make_ref(&context), make_ref(&texture));
|
||||
}
|
||||
|
||||
{
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xAA, 0, 0, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xAA, 0xAA, 0, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xAA, 0xAA, 0xAA, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xAA, 0xAA, 0xAA, 0xAA)));
|
||||
|
||||
uint8_t memoryEtalon1[] = {
|
||||
0xAA, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xAA, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xAA, 0xAA, 0x00, 0x00, // 2 pixel
|
||||
0xAA, 0xAA, 0x00, 0x00, // 2 pixel
|
||||
|
||||
0xAA, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xAA, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xAA, 0xAA, 0x00, 0x00, // 2 pixel
|
||||
0xAA, 0xAA, 0x00, 0x00 // 2 pixel
|
||||
};
|
||||
|
||||
uint8_t memoryEtalon2[] = {
|
||||
0xAA, 0xAA, 0xAA, 0x00, // 1 pixel
|
||||
0xAA, 0xAA, 0xAA, 0x00, // 1 pixel
|
||||
0xAA, 0xAA, 0xAA, 0xAA, // 2 pixel
|
||||
0xAA, 0xAA, 0xAA, 0xAA, // 2 pixel
|
||||
|
||||
0xAA, 0xAA, 0xAA, 0x00, // 1 pixel
|
||||
0xAA, 0xAA, 0xAA, 0x00, // 1 pixel
|
||||
0xAA, 0xAA, 0xAA, 0xAA, // 2 pixel
|
||||
0xAA, 0xAA, 0xAA, 0xAA // 2 pixel
|
||||
};
|
||||
|
||||
MemoryComparer cmp1(memoryEtalon1, ARRAY_SIZE(memoryEtalon1));
|
||||
EXPECTGL(glTexSubImage2D(4, 0, 4, 2, AnyOf(gl_const::GLRGBA, gl_const::GLRGBA8), gl_const::GL8BitOnChannel, _))
|
||||
.WillOnce(Invoke(&cmp1, &MemoryComparer::cmpSubImage));
|
||||
|
||||
MemoryComparer cmp2(memoryEtalon2, ARRAY_SIZE(memoryEtalon2));
|
||||
EXPECTGL(glTexSubImage2D(0, 2, 4, 2, AnyOf(gl_const::GLRGBA, gl_const::GLRGBA8), gl_const::GL8BitOnChannel, _))
|
||||
.WillOnce(Invoke(&cmp2, &MemoryComparer::cmpSubImage));
|
||||
|
||||
cp.UploadResources(make_ref(&context), make_ref(&texture));
|
||||
}
|
||||
|
||||
EXPECTGL(glDeleteTexture(1));
|
||||
}
|
||||
|
||||
UNIT_TEST(ColorPalleteUploadingMultiplyRow)
|
||||
{
|
||||
int const width = 4;
|
||||
int const height = 8;
|
||||
InitOpenGLTextures(width, height);
|
||||
|
||||
TestingGraphicsContext context;
|
||||
Texture::Params p;
|
||||
p.m_allocator = GetDefaultAllocator(make_ref(&context));
|
||||
p.m_format = dp::TextureFormat::RGBA8;
|
||||
p.m_width = width;
|
||||
p.m_height = height;
|
||||
|
||||
DummyTexture texture;
|
||||
texture.Create(make_ref(&context), p);
|
||||
|
||||
DummyColorPallete cp(m2::PointU(width, height));
|
||||
cp.SetIsDebug(true);
|
||||
|
||||
{
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xFF, 0, 0, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xAA, 0, 0, 0)));
|
||||
|
||||
uint8_t memoryEtalon[] = {
|
||||
0xFF, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xFF, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xAA, 0x00, 0x00, 0x00, // 2 pixel
|
||||
0xAA, 0x00, 0x00, 0x00, // 2 pixel
|
||||
|
||||
0xFF, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xFF, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xAA, 0x00, 0x00, 0x00, // 2 pixel
|
||||
0xAA, 0x00, 0x00, 0x00, // 2 pixel
|
||||
};
|
||||
|
||||
MemoryComparer cmp(memoryEtalon, ARRAY_SIZE(memoryEtalon));
|
||||
EXPECTGL(glTexSubImage2D(0, 0, 4, 2, AnyOf(gl_const::GLRGBA, gl_const::GLRGBA8), gl_const::GL8BitOnChannel, _))
|
||||
.WillOnce(Invoke(&cmp, &MemoryComparer::cmpSubImage));
|
||||
|
||||
cp.UploadResources(make_ref(&context), make_ref(&texture));
|
||||
}
|
||||
|
||||
{
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xCC, 0, 0, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xFF, 0xFF, 0, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xFF, 0xFF, 0xFF, 0)));
|
||||
cp.MapResource(dp::ColorKey(dp::Color(0xFF, 0xFF, 0xFF, 0xFF)));
|
||||
|
||||
uint8_t memoryEtalon1[] = {
|
||||
0xCC, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xCC, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xFF, 0xFF, 0x00, 0x00, // 2 pixel
|
||||
0xFF, 0xFF, 0x00, 0x00, // 2 pixel
|
||||
|
||||
0xCC, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xCC, 0x00, 0x00, 0x00, // 1 pixel
|
||||
0xFF, 0xFF, 0x00, 0x00, // 2 pixel
|
||||
0xFF, 0xFF, 0x00, 0x00, // 2 pixel
|
||||
|
||||
0xFF, 0xFF, 0xFF, 0x00, // 1 pixel
|
||||
0xFF, 0xFF, 0xFF, 0x00, // 1 pixel
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 2 pixel
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 2 pixel
|
||||
|
||||
0xFF, 0xFF, 0xFF, 0x00, // 1 pixel
|
||||
0xFF, 0xFF, 0xFF, 0x00, // 1 pixel
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 2 pixel
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 2 pixel
|
||||
};
|
||||
|
||||
MemoryComparer cmp1(memoryEtalon1, ARRAY_SIZE(memoryEtalon1));
|
||||
EXPECTGL(glTexSubImage2D(0, 2, 4, 4, AnyOf(gl_const::GLRGBA, gl_const::GLRGBA8), gl_const::GL8BitOnChannel, _))
|
||||
.WillOnce(Invoke(&cmp1, &MemoryComparer::cmpSubImage));
|
||||
|
||||
cp.UploadResources(make_ref(&context), make_ref(&texture));
|
||||
}
|
||||
|
||||
EXPECTGL(glDeleteTexture(1));
|
||||
}
|
||||
157
libs/drape/drape_tests/uniform_value_tests.cpp
Normal file
157
libs/drape/drape_tests/uniform_value_tests.cpp
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "drape/drape_global.hpp"
|
||||
#include "drape/gl_gpu_program.hpp"
|
||||
#include "drape/uniform_value.hpp"
|
||||
|
||||
#include "drape/drape_tests/gl_mock_functions.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::AnyOf;
|
||||
using ::testing::IgnoreResult;
|
||||
using ::testing::InSequence;
|
||||
using ::testing::Invoke;
|
||||
using ::testing::Return;
|
||||
using namespace dp;
|
||||
|
||||
namespace uniform_value_tests
|
||||
{
|
||||
template <typename T>
|
||||
class MemoryComparer
|
||||
{
|
||||
public:
|
||||
MemoryComparer(T const * memory, uint32_t size) : m_result(false), m_memory(memory), m_size(size) {}
|
||||
|
||||
void Compare(int32_t id, T const * memory) { m_result = memcmp(m_memory, memory, m_size) == 0; }
|
||||
|
||||
bool GetResult() const { return m_result; }
|
||||
|
||||
private:
|
||||
bool m_result;
|
||||
T const * m_memory;
|
||||
uint32_t m_size;
|
||||
};
|
||||
|
||||
void mock_glGetActiveUniform(uint32_t programID, uint32_t index, int32_t * size, glConst * type, std::string & name)
|
||||
{
|
||||
*size = 1;
|
||||
if (index < 9)
|
||||
{
|
||||
static std::pair<std::string, glConst> mockUniforms[9] = {
|
||||
{"position0", gl_const::GLIntType}, {"position1", gl_const::GLIntVec2},
|
||||
{"position2", gl_const::GLIntVec3}, {"position3", gl_const::GLIntVec4},
|
||||
{"position4", gl_const::GLFloatType}, {"position5", gl_const::GLFloatVec2},
|
||||
{"position6", gl_const::GLFloatVec3}, {"position7", gl_const::GLFloatVec4},
|
||||
{"viewModel", gl_const::GLFloatMat4}};
|
||||
name = mockUniforms[index].first;
|
||||
*type = mockUniforms[index].second;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(false, ("Undefined index:", index));
|
||||
}
|
||||
}
|
||||
|
||||
UNIT_TEST(UniformValueTest)
|
||||
{
|
||||
uint32_t constexpr VertexShaderID = 1;
|
||||
uint32_t constexpr FragmentShaderID = 2;
|
||||
uint32_t constexpr ProgramID = 2;
|
||||
int32_t constexpr positionLoc = 10;
|
||||
int32_t constexpr modelViewLoc = 11;
|
||||
|
||||
float matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
|
||||
|
||||
MemoryComparer<float> comparer(matrix, 16 * sizeof(float));
|
||||
|
||||
{
|
||||
InSequence seq;
|
||||
EXPECTGL(glCreateShader(gl_const::GLVertexShader)).WillOnce(Return(VertexShaderID));
|
||||
EXPECTGL(glShaderSource(VertexShaderID, _)).Times(1);
|
||||
EXPECTGL(glCompileShader(VertexShaderID, _)).WillOnce(Return(true));
|
||||
EXPECTGL(glCreateShader(gl_const::GLFragmentShader)).WillOnce(Return(FragmentShaderID));
|
||||
EXPECTGL(glShaderSource(FragmentShaderID, _)).Times(1);
|
||||
EXPECTGL(glCompileShader(FragmentShaderID, _)).WillOnce(Return(true));
|
||||
|
||||
EXPECTGL(glCreateProgram()).WillOnce(Return(ProgramID));
|
||||
EXPECTGL(glAttachShader(ProgramID, VertexShaderID));
|
||||
EXPECTGL(glAttachShader(ProgramID, FragmentShaderID));
|
||||
|
||||
EXPECTGL(glLinkProgram(ProgramID, _)).WillOnce(Return(true));
|
||||
|
||||
EXPECTGL(glGetProgramiv(ProgramID, gl_const::GLActiveUniforms)).WillOnce(Return(9));
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
EXPECTGL(glGetActiveUniform(ProgramID, _, _, _, _)).WillOnce(Invoke(mock_glGetActiveUniform));
|
||||
EXPECTGL(glGetUniformLocation(ProgramID, _)).WillOnce(Return(i == 8 ? modelViewLoc : positionLoc));
|
||||
}
|
||||
|
||||
EXPECTGL(glDetachShader(ProgramID, VertexShaderID));
|
||||
EXPECTGL(glDetachShader(ProgramID, FragmentShaderID));
|
||||
|
||||
EXPECTGL(glUseProgram(ProgramID));
|
||||
|
||||
EXPECTGL(glUniformValuei(positionLoc, 1));
|
||||
|
||||
EXPECTGL(glUniformValuei(positionLoc, 1, 2));
|
||||
|
||||
EXPECTGL(glUniformValuei(positionLoc, 1, 2, 3));
|
||||
|
||||
EXPECTGL(glUniformValuei(positionLoc, 1, 2, 3, 4));
|
||||
|
||||
EXPECTGL(glUniformValuef(positionLoc, 1.0f));
|
||||
|
||||
EXPECTGL(glUniformValuef(positionLoc, 1.0f, 2.0f));
|
||||
|
||||
EXPECTGL(glUniformValuef(positionLoc, 1.0f, 2.0f, 3.0f));
|
||||
|
||||
EXPECTGL(glUniformValuef(positionLoc, 1.0f, 2.0f, 3.0f, 4.0f));
|
||||
|
||||
EXPECTGL(glUniformMatrix4x4Value(modelViewLoc, _)).WillOnce(Invoke(&comparer, &MemoryComparer<float>::Compare));
|
||||
|
||||
EXPECTGL(glUseProgram(0));
|
||||
EXPECTGL(glDeleteProgram(ProgramID));
|
||||
EXPECTGL(glDeleteShader(AnyOf(VertexShaderID, FragmentShaderID))).Times(2);
|
||||
}
|
||||
|
||||
drape_ptr<Shader> vs = make_unique_dp<Shader>("", "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }", "",
|
||||
Shader::Type::VertexShader);
|
||||
|
||||
drape_ptr<Shader> fs = make_unique_dp<Shader>("", "void main() { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); }", "",
|
||||
Shader::Type::FragmentShader);
|
||||
|
||||
drape_ptr<GLGpuProgram> program = make_unique_dp<GLGpuProgram>("", make_ref(vs), make_ref(fs));
|
||||
|
||||
program->Bind();
|
||||
|
||||
UniformValue::ApplyRaw(positionLoc, 1);
|
||||
|
||||
UniformValue::ApplyRaw(positionLoc, glsl::ivec2(1, 2));
|
||||
|
||||
UniformValue::ApplyRaw(positionLoc, glsl::ivec3(1, 2, 3));
|
||||
|
||||
UniformValue::ApplyRaw(positionLoc, glsl::ivec4(1, 2, 3, 4));
|
||||
|
||||
UniformValue::ApplyRaw(positionLoc, 1.0f);
|
||||
|
||||
UniformValue::ApplyRaw(positionLoc, glsl::vec2(1.0f, 2.0f));
|
||||
|
||||
UniformValue::ApplyRaw(positionLoc, glsl::vec3(1.0f, 2.0f, 3.0f));
|
||||
|
||||
UniformValue::ApplyRaw(positionLoc, glsl::vec4(1.0f, 2.0f, 3.0f, 4.0f));
|
||||
|
||||
UniformValue::ApplyRaw(modelViewLoc, glsl::make_mat4(matrix));
|
||||
|
||||
program->Unbind();
|
||||
|
||||
program.reset();
|
||||
vs.reset();
|
||||
fs.reset();
|
||||
}
|
||||
} // namespace uniform_value_tests
|
||||
97
libs/drape/drape_tests/vertex_buffer_tests.cpp
Normal file
97
libs/drape/drape_tests/vertex_buffer_tests.cpp
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "drape/utils/vertex_decl.hpp"
|
||||
|
||||
#include "base/buffer_vector.hpp"
|
||||
|
||||
#include <boost/container/small_vector.hpp>
|
||||
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
namespace vertex_buffer_tests
|
||||
{
|
||||
#ifndef DEBUG
|
||||
std::vector<uint32_t> GenerateSizes(uint32_t min, uint32_t max)
|
||||
{
|
||||
std::vector<uint32_t> res;
|
||||
|
||||
std::uniform_int_distribution<uint64_t> randDist(min, max);
|
||||
std::random_device randDevice;
|
||||
std::mt19937 randEngine(randDevice());
|
||||
|
||||
for (size_t i = 0; i < 1000000; ++i)
|
||||
res.push_back(randDist(randEngine));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
UNIT_TEST(VertexBuffer_Benchmark)
|
||||
{
|
||||
using ValueT = gpu::TextOutlinedStaticVertex;
|
||||
// using ValueT = gpu::TextDynamicVertex
|
||||
ValueT objs[] = {
|
||||
{{1, 1}, {2, 2}, {3, 3}},
|
||||
{{4, 4}, {5, 5}, {6, 6}},
|
||||
{{7, 7}, {8, 8}, {9, 9}},
|
||||
};
|
||||
|
||||
// Very comfortable for buffer_vector<ValueT, kUpperBound>.
|
||||
uint32_t constexpr kUpperBound = 128;
|
||||
std::vector<uint32_t> sizes = GenerateSizes(16, kUpperBound);
|
||||
|
||||
uint64_t t1, t2, t3, t4;
|
||||
{
|
||||
base::Timer timer;
|
||||
for (uint32_t sz : sizes)
|
||||
{
|
||||
std::vector<ValueT> v;
|
||||
for (size_t i = 0; i < sz; ++i)
|
||||
v.push_back(objs[i % std::size(objs)]);
|
||||
}
|
||||
t1 = timer.ElapsedMilliseconds();
|
||||
}
|
||||
|
||||
{
|
||||
base::Timer timer;
|
||||
for (uint32_t sz : sizes)
|
||||
{
|
||||
buffer_vector<ValueT, kUpperBound> v;
|
||||
for (size_t i = 0; i < sz; ++i)
|
||||
v.push_back(objs[i % std::size(objs)]);
|
||||
}
|
||||
t2 = timer.ElapsedMilliseconds();
|
||||
}
|
||||
|
||||
{
|
||||
base::Timer timer;
|
||||
for (uint32_t sz : sizes)
|
||||
{
|
||||
boost::container::small_vector<ValueT, kUpperBound> v;
|
||||
for (size_t i = 0; i < sz; ++i)
|
||||
v.push_back(objs[i % std::size(objs)]);
|
||||
}
|
||||
t3 = timer.ElapsedMilliseconds();
|
||||
}
|
||||
|
||||
{
|
||||
base::Timer timer;
|
||||
for (uint32_t sz : sizes)
|
||||
{
|
||||
std::vector<ValueT> v;
|
||||
v.reserve(sz);
|
||||
for (size_t i = 0; i < sz; ++i)
|
||||
v.push_back(objs[i % std::size(objs)]);
|
||||
}
|
||||
t4 = timer.ElapsedMilliseconds();
|
||||
}
|
||||
|
||||
LOG(LINFO,
|
||||
("vector time:", t1, "buffer_vector time:", t2, "boost::small_vector time:", t3, "reserved vector time:", t4));
|
||||
TEST_LESS(t2, t1, ());
|
||||
TEST_LESS(t3, t2, ());
|
||||
// TODO: Fix this condition
|
||||
// TEST_LESS(t4, t3, ());
|
||||
}
|
||||
#endif
|
||||
} // namespace vertex_buffer_tests
|
||||
Loading…
Add table
Add a link
Reference in a new issue