@@ -43,16 +43,16 @@ PropertyMap properties;
|
||||
} // namespace
|
||||
|
||||
TEST(Buckets, CircleBucket) {
|
||||
gl::HeadlessBackend backend({ 512, 256 });
|
||||
gfx::BackendScope scope { backend };
|
||||
gl::HeadlessBackend backend({512, 256});
|
||||
gfx::BackendScope scope{backend};
|
||||
|
||||
gl::Context context{ backend };
|
||||
gl::Context context{backend};
|
||||
CircleBucket bucket{{}, MapMode::Static, 1.0};
|
||||
ASSERT_FALSE(bucket.hasData());
|
||||
ASSERT_FALSE(bucket.needsUpload());
|
||||
|
||||
// CircleBucket::addFeature() is a no-op.
|
||||
GeometryCollection point { { { 0, 0 } } };
|
||||
GeometryCollection point{{{0, 0}}};
|
||||
bucket.addFeature(StubGeometryTileFeature{{}, FeatureType::Point, point, properties},
|
||||
point,
|
||||
{},
|
||||
@@ -74,16 +74,16 @@ TEST(Buckets, CircleBucket) {
|
||||
}
|
||||
|
||||
TEST(Buckets, FillBucket) {
|
||||
gl::HeadlessBackend backend({ 512, 256 });
|
||||
gfx::BackendScope scope { backend };
|
||||
gl::HeadlessBackend backend({512, 256});
|
||||
gfx::BackendScope scope{backend};
|
||||
FillBucket::PossiblyEvaluatedLayoutProperties layout;
|
||||
|
||||
gl::Context context{ backend };
|
||||
FillBucket bucket { layout, {}, 5.0f, 1};
|
||||
gl::Context context{backend};
|
||||
FillBucket bucket{layout, {}, 5.0f, 1};
|
||||
ASSERT_FALSE(bucket.hasData());
|
||||
ASSERT_FALSE(bucket.needsUpload());
|
||||
|
||||
GeometryCollection polygon { { { 0, 0 }, { 0, 1 }, { 1, 1 } } };
|
||||
GeometryCollection polygon{{{0, 0}, {0, 1}, {1, 1}}};
|
||||
bucket.addFeature(StubGeometryTileFeature{{}, FeatureType::Polygon, polygon, properties},
|
||||
polygon,
|
||||
{},
|
||||
@@ -100,17 +100,17 @@ TEST(Buckets, FillBucket) {
|
||||
}
|
||||
|
||||
TEST(Buckets, LineBucket) {
|
||||
gl::HeadlessBackend backend({ 512, 256 });
|
||||
gfx::BackendScope scope { backend };
|
||||
gl::HeadlessBackend backend({512, 256});
|
||||
gfx::BackendScope scope{backend};
|
||||
LineBucket::PossiblyEvaluatedLayoutProperties layout;
|
||||
|
||||
gl::Context context{ backend };
|
||||
LineBucket bucket { layout, {}, 10.0f, 1 };
|
||||
gl::Context context{backend};
|
||||
LineBucket bucket{layout, {}, 10.0f, 1};
|
||||
ASSERT_FALSE(bucket.hasData());
|
||||
ASSERT_FALSE(bucket.needsUpload());
|
||||
|
||||
// Ignore invalid feature type.
|
||||
GeometryCollection point { { { 0, 0 } } };
|
||||
GeometryCollection point{{{0, 0}}};
|
||||
bucket.addFeature(StubGeometryTileFeature{{}, FeatureType::Point, point, properties},
|
||||
point,
|
||||
{},
|
||||
@@ -119,7 +119,7 @@ TEST(Buckets, LineBucket) {
|
||||
CanonicalTileID(0, 0, 0));
|
||||
ASSERT_FALSE(bucket.hasData());
|
||||
|
||||
GeometryCollection line { { { 0, 0 }, { 1, 1 } } };
|
||||
GeometryCollection line{{{0, 0}, {1, 1}}};
|
||||
bucket.addFeature(StubGeometryTileFeature{{}, FeatureType::LineString, line, properties},
|
||||
line,
|
||||
{},
|
||||
@@ -136,8 +136,8 @@ TEST(Buckets, LineBucket) {
|
||||
}
|
||||
|
||||
TEST(Buckets, SymbolBucket) {
|
||||
gl::HeadlessBackend backend({ 512, 256 });
|
||||
gfx::BackendScope scope { backend };
|
||||
gl::HeadlessBackend backend({512, 256});
|
||||
gfx::BackendScope scope{backend};
|
||||
|
||||
auto layout = makeMutable<style::SymbolLayoutProperties::PossiblyEvaluated>();
|
||||
bool iconsNeedLinear = false;
|
||||
@@ -146,7 +146,7 @@ TEST(Buckets, SymbolBucket) {
|
||||
std::vector<SymbolInstance> symbolInstances;
|
||||
std::vector<SortKeyRange> symbolRanges;
|
||||
|
||||
gl::Context context{ backend };
|
||||
gl::Context context{backend};
|
||||
SymbolBucket bucket{std::move(layout),
|
||||
{},
|
||||
16.0f,
|
||||
@@ -172,7 +172,7 @@ TEST(Buckets, SymbolBucket) {
|
||||
ASSERT_FALSE(bucket.needsUpload());
|
||||
|
||||
// SymbolBucket::addFeature() is a no-op.
|
||||
GeometryCollection point { { { 0, 0 } } };
|
||||
GeometryCollection point{{{0, 0}}};
|
||||
bucket.addFeature(StubGeometryTileFeature{{}, FeatureType::Point, std::move(point), properties},
|
||||
point,
|
||||
{},
|
||||
@@ -194,14 +194,14 @@ TEST(Buckets, SymbolBucket) {
|
||||
}
|
||||
|
||||
TEST(Buckets, RasterBucket) {
|
||||
gl::HeadlessBackend backend({ 512, 256 });
|
||||
gfx::BackendScope scope { backend };
|
||||
gl::HeadlessBackend backend({512, 256});
|
||||
gfx::BackendScope scope{backend};
|
||||
|
||||
gl::Context context{ backend };
|
||||
PremultipliedImage rgba({ 1, 1 });
|
||||
gl::Context context{backend};
|
||||
PremultipliedImage rgba({1, 1});
|
||||
|
||||
// RasterBucket::hasData() is always true.
|
||||
RasterBucket bucket = { std::move(rgba) };
|
||||
RasterBucket bucket = {std::move(rgba)};
|
||||
ASSERT_TRUE(bucket.hasData());
|
||||
ASSERT_TRUE(bucket.needsUpload());
|
||||
|
||||
@@ -215,7 +215,7 @@ TEST(Buckets, RasterBucket) {
|
||||
}
|
||||
|
||||
TEST(Buckets, RasterBucketMaskEmpty) {
|
||||
RasterBucket bucket{ nullptr };
|
||||
RasterBucket bucket{nullptr};
|
||||
bucket.setMask({});
|
||||
EXPECT_EQ((std::vector<RasterLayoutVertex>{}), bucket.vertices.vector());
|
||||
EXPECT_EQ((std::vector<uint16_t>{}), bucket.indices.vector());
|
||||
@@ -225,8 +225,8 @@ TEST(Buckets, RasterBucketMaskEmpty) {
|
||||
}
|
||||
|
||||
TEST(Buckets, RasterBucketMaskNoChildren) {
|
||||
RasterBucket bucket{ nullptr };
|
||||
bucket.setMask({ CanonicalTileID{ 0, 0, 0 } });
|
||||
RasterBucket bucket{nullptr};
|
||||
bucket.setMask({CanonicalTileID{0, 0, 0}});
|
||||
|
||||
// A mask of 0/0/0 doesn't produce buffers since we're instead using the global shared buffers.
|
||||
EXPECT_EQ((std::vector<RasterLayoutVertex>{}), bucket.vertices.vector());
|
||||
@@ -234,121 +234,149 @@ TEST(Buckets, RasterBucketMaskNoChildren) {
|
||||
EXPECT_EQ((SegmentVector<RasterAttributes>{}), bucket.segments);
|
||||
}
|
||||
|
||||
TEST(Buckets, RasterBucketMaskTwoChildren) {
|
||||
RasterBucket bucket{ nullptr };
|
||||
bucket.setMask(
|
||||
{ CanonicalTileID{ 1, 0, 0 }, CanonicalTileID{ 1, 1, 1 } });
|
||||
TEST(Buckets, RasterBucketMaskTwoChildren) {
|
||||
RasterBucket bucket{nullptr};
|
||||
bucket.setMask({CanonicalTileID{1, 0, 0}, CanonicalTileID{1, 1, 1}});
|
||||
|
||||
EXPECT_EQ(
|
||||
(std::vector<RasterLayoutVertex>{
|
||||
// 1/0/1
|
||||
RasterProgram::layoutVertex({ 0, 0 }, { 0, 0 }),
|
||||
RasterProgram::layoutVertex({ 4096, 0 }, { 4096, 0 }),
|
||||
RasterProgram::layoutVertex({ 0, 4096 }, { 0, 4096 }),
|
||||
RasterProgram::layoutVertex({ 4096, 4096 }, { 4096, 4096 }),
|
||||
EXPECT_EQ((std::vector<RasterLayoutVertex>{
|
||||
// 1/0/1
|
||||
RasterProgram::layoutVertex({0, 0}, {0, 0}),
|
||||
RasterProgram::layoutVertex({4096, 0}, {4096, 0}),
|
||||
RasterProgram::layoutVertex({0, 4096}, {0, 4096}),
|
||||
RasterProgram::layoutVertex({4096, 4096}, {4096, 4096}),
|
||||
|
||||
// 1/1/1
|
||||
RasterProgram::layoutVertex({ 4096, 4096 }, { 4096, 4096 }),
|
||||
RasterProgram::layoutVertex({ 8192, 4096 }, { 8192, 4096 }),
|
||||
RasterProgram::layoutVertex({ 4096, 8192 }, { 4096, 8192 }),
|
||||
RasterProgram::layoutVertex({ 8192, 8192 }, { 8192, 8192 }),
|
||||
}),
|
||||
bucket.vertices.vector());
|
||||
// 1/1/1
|
||||
RasterProgram::layoutVertex({4096, 4096}, {4096, 4096}),
|
||||
RasterProgram::layoutVertex({8192, 4096}, {8192, 4096}),
|
||||
RasterProgram::layoutVertex({4096, 8192}, {4096, 8192}),
|
||||
RasterProgram::layoutVertex({8192, 8192}, {8192, 8192}),
|
||||
}),
|
||||
bucket.vertices.vector());
|
||||
|
||||
EXPECT_EQ(
|
||||
(std::vector<uint16_t>{
|
||||
// 1/0/1
|
||||
0, 1, 2,
|
||||
1, 2, 3,
|
||||
EXPECT_EQ((std::vector<uint16_t>{
|
||||
// 1/0/1
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
|
||||
// 1/1/1
|
||||
4, 5, 6,
|
||||
5, 6, 7,
|
||||
}),
|
||||
bucket.indices.vector());
|
||||
// 1/1/1
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
}),
|
||||
bucket.indices.vector());
|
||||
|
||||
SegmentVector<RasterAttributes> expectedSegments;
|
||||
expectedSegments.emplace_back(0, 0, 8, 12);
|
||||
EXPECT_EQ(expectedSegments, bucket.segments);
|
||||
}
|
||||
|
||||
SegmentVector<RasterAttributes> expectedSegments;
|
||||
expectedSegments.emplace_back(0, 0, 8, 12);
|
||||
EXPECT_EQ(expectedSegments, bucket.segments);
|
||||
}
|
||||
TEST(Buckets, RasterBucketMaskComplex) {
|
||||
RasterBucket bucket{nullptr};
|
||||
bucket.setMask({CanonicalTileID{1, 0, 1},
|
||||
CanonicalTileID{1, 1, 0},
|
||||
CanonicalTileID{2, 2, 3},
|
||||
CanonicalTileID{2, 3, 2},
|
||||
CanonicalTileID{3, 6, 7},
|
||||
CanonicalTileID{3, 7, 6}});
|
||||
|
||||
TEST(Buckets, RasterBucketMaskComplex) {
|
||||
RasterBucket bucket{ nullptr };
|
||||
bucket.setMask(
|
||||
{ CanonicalTileID{ 1, 0, 1 }, CanonicalTileID{ 1, 1, 0 }, CanonicalTileID{ 2, 2, 3 },
|
||||
CanonicalTileID{ 2, 3, 2 }, CanonicalTileID{ 3, 6, 7 }, CanonicalTileID{ 3, 7, 6 } });
|
||||
EXPECT_EQ((std::vector<RasterLayoutVertex>{
|
||||
// 1/0/1
|
||||
RasterProgram::layoutVertex({0, 4096}, {0, 4096}),
|
||||
RasterProgram::layoutVertex({4096, 4096}, {4096, 4096}),
|
||||
RasterProgram::layoutVertex({0, 8192}, {0, 8192}),
|
||||
RasterProgram::layoutVertex({4096, 8192}, {4096, 8192}),
|
||||
|
||||
EXPECT_EQ(
|
||||
(std::vector<RasterLayoutVertex>{
|
||||
// 1/0/1
|
||||
RasterProgram::layoutVertex({ 0, 4096 }, { 0, 4096 }),
|
||||
RasterProgram::layoutVertex({ 4096, 4096 }, { 4096, 4096 }),
|
||||
RasterProgram::layoutVertex({ 0, 8192 }, { 0, 8192 }),
|
||||
RasterProgram::layoutVertex({ 4096, 8192 }, { 4096, 8192 }),
|
||||
// 1/1/0
|
||||
RasterProgram::layoutVertex({4096, 0}, {4096, 0}),
|
||||
RasterProgram::layoutVertex({8192, 0}, {8192, 0}),
|
||||
RasterProgram::layoutVertex({4096, 4096}, {4096, 4096}),
|
||||
RasterProgram::layoutVertex({8192, 4096}, {8192, 4096}),
|
||||
|
||||
// 1/1/0
|
||||
RasterProgram::layoutVertex({ 4096, 0 }, { 4096, 0 }),
|
||||
RasterProgram::layoutVertex({ 8192, 0 }, { 8192, 0 }),
|
||||
RasterProgram::layoutVertex({ 4096, 4096 }, { 4096, 4096 }),
|
||||
RasterProgram::layoutVertex({ 8192, 4096 }, { 8192, 4096 }),
|
||||
// 2/2/3
|
||||
RasterProgram::layoutVertex({4096, 6144}, {4096, 6144}),
|
||||
RasterProgram::layoutVertex({6144, 6144}, {6144, 6144}),
|
||||
RasterProgram::layoutVertex({4096, 8192}, {4096, 8192}),
|
||||
RasterProgram::layoutVertex({6144, 8192}, {6144, 8192}),
|
||||
|
||||
// 2/2/3
|
||||
RasterProgram::layoutVertex({ 4096, 6144 }, { 4096, 6144 }),
|
||||
RasterProgram::layoutVertex({ 6144, 6144 }, { 6144, 6144 }),
|
||||
RasterProgram::layoutVertex({ 4096, 8192 }, { 4096, 8192 }),
|
||||
RasterProgram::layoutVertex({ 6144, 8192 }, { 6144, 8192 }),
|
||||
// 2/3/2
|
||||
RasterProgram::layoutVertex({6144, 4096}, {6144, 4096}),
|
||||
RasterProgram::layoutVertex({8192, 4096}, {8192, 4096}),
|
||||
RasterProgram::layoutVertex({6144, 6144}, {6144, 6144}),
|
||||
RasterProgram::layoutVertex({8192, 6144}, {8192, 6144}),
|
||||
|
||||
// 2/3/2
|
||||
RasterProgram::layoutVertex({ 6144, 4096 }, { 6144, 4096 }),
|
||||
RasterProgram::layoutVertex({ 8192, 4096 }, { 8192, 4096 }),
|
||||
RasterProgram::layoutVertex({ 6144, 6144 }, { 6144, 6144 }),
|
||||
RasterProgram::layoutVertex({ 8192, 6144 }, { 8192, 6144 }),
|
||||
// 3/6/7
|
||||
RasterProgram::layoutVertex({6144, 7168}, {6144, 7168}),
|
||||
RasterProgram::layoutVertex({7168, 7168}, {7168, 7168}),
|
||||
RasterProgram::layoutVertex({6144, 8192}, {6144, 8192}),
|
||||
RasterProgram::layoutVertex({7168, 8192}, {7168, 8192}),
|
||||
|
||||
// 3/6/7
|
||||
RasterProgram::layoutVertex({ 6144, 7168 }, { 6144, 7168 }),
|
||||
RasterProgram::layoutVertex({ 7168, 7168 }, { 7168, 7168 }),
|
||||
RasterProgram::layoutVertex({ 6144, 8192 }, { 6144, 8192 }),
|
||||
RasterProgram::layoutVertex({ 7168, 8192 }, { 7168, 8192 }),
|
||||
// 3/7/6
|
||||
RasterProgram::layoutVertex({7168, 6144}, {7168, 6144}),
|
||||
RasterProgram::layoutVertex({8192, 6144}, {8192, 6144}),
|
||||
RasterProgram::layoutVertex({7168, 7168}, {7168, 7168}),
|
||||
RasterProgram::layoutVertex({8192, 7168}, {8192, 7168}),
|
||||
}),
|
||||
bucket.vertices.vector());
|
||||
|
||||
// 3/7/6
|
||||
RasterProgram::layoutVertex({ 7168, 6144 }, { 7168, 6144 }),
|
||||
RasterProgram::layoutVertex({ 8192, 6144 }, { 8192, 6144 }),
|
||||
RasterProgram::layoutVertex({ 7168, 7168 }, { 7168, 7168 }),
|
||||
RasterProgram::layoutVertex({ 8192, 7168 }, { 8192, 7168 }),
|
||||
}),
|
||||
bucket.vertices.vector());
|
||||
EXPECT_EQ((std::vector<uint16_t>{
|
||||
// 1/0/1
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
|
||||
EXPECT_EQ(
|
||||
(std::vector<uint16_t>{
|
||||
// 1/0/1
|
||||
0, 1, 2,
|
||||
1, 2, 3,
|
||||
// 1/1/0
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
|
||||
// 1/1/0
|
||||
4, 5, 6,
|
||||
5, 6, 7,
|
||||
// 2/2/3
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
|
||||
// 2/2/3
|
||||
8, 9, 10,
|
||||
9, 10, 11,
|
||||
// 2/3/2
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
|
||||
// 2/3/2
|
||||
12, 13, 14,
|
||||
13, 14, 15,
|
||||
// 3/6/7
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
|
||||
// 3/6/7
|
||||
16, 17, 18,
|
||||
17, 18, 19,
|
||||
// 3/7/6
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
}),
|
||||
bucket.indices.vector());
|
||||
|
||||
// 3/7/6
|
||||
20, 21, 22,
|
||||
21, 22, 23,
|
||||
}),
|
||||
bucket.indices.vector());
|
||||
|
||||
|
||||
SegmentVector<RasterAttributes> expectedSegments;
|
||||
expectedSegments.emplace_back(0, 0, 24, 36);
|
||||
EXPECT_EQ(expectedSegments, bucket.segments);
|
||||
}
|
||||
SegmentVector<RasterAttributes> expectedSegments;
|
||||
expectedSegments.emplace_back(0, 0, 24, 36);
|
||||
EXPECT_EQ(expectedSegments, bucket.segments);
|
||||
}
|
||||
|
||||
@@ -73,13 +73,10 @@ struct Buffer {
|
||||
Buffer(std::vector<GLfloat> data) {
|
||||
MBGL_CHECK_ERROR(glGenBuffers(1, &buffer));
|
||||
MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, buffer));
|
||||
MBGL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.data(),
|
||||
GL_STATIC_DRAW));
|
||||
MBGL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.data(), GL_STATIC_DRAW));
|
||||
}
|
||||
|
||||
~Buffer() {
|
||||
MBGL_CHECK_ERROR(glDeleteBuffers(1, &buffer));
|
||||
}
|
||||
~Buffer() { MBGL_CHECK_ERROR(glDeleteBuffers(1, &buffer)); }
|
||||
|
||||
GLuint buffer = 0;
|
||||
};
|
||||
@@ -98,20 +95,20 @@ TEST(GLContextMode, Shared) {
|
||||
MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()),
|
||||
ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets"));
|
||||
map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
|
||||
map.jumpTo(CameraOptions().withCenter(LatLng { 37.8, -122.5 }).withZoom(10.0));
|
||||
map.jumpTo(CameraOptions().withCenter(LatLng{37.8, -122.5}).withZoom(10.0));
|
||||
|
||||
// Set transparent background layer.
|
||||
auto layer = map.getStyle().getLayer("background");
|
||||
ASSERT_STREQ("background", layer->getTypeInfo()->type);
|
||||
static_cast<BackgroundLayer*>(layer)->setBackgroundColor( { { 1.0f, 0.0f, 0.0f, 0.5f } } );
|
||||
static_cast<BackgroundLayer*>(layer)->setBackgroundColor({{1.0f, 0.0f, 0.0f, 0.5f}});
|
||||
|
||||
{
|
||||
// Custom rendering outside of GL Native render loop.
|
||||
gfx::BackendScope scope { *frontend.getBackend() };
|
||||
gfx::BackendScope scope{*frontend.getBackend()};
|
||||
frontend.getBackend()->getDefaultRenderable().getResource<gl::RenderableResource>().bind();
|
||||
|
||||
Shader paintShader(vertexShaderSource, fragmentShaderSource);
|
||||
Buffer triangleBuffer({ 0, 0.5, 0.5, -0.5, -0.5, -0.5 });
|
||||
Buffer triangleBuffer({0, 0.5, 0.5, -0.5, -0.5, -0.5});
|
||||
MBGL_CHECK_ERROR(glUseProgram(paintShader.program));
|
||||
MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, triangleBuffer.buffer));
|
||||
MBGL_CHECK_ERROR(glEnableVertexAttribArray(paintShader.a_pos));
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
using namespace mbgl::platform;
|
||||
|
||||
TEST(GLFunctions, OpenGLES) {
|
||||
|
||||
/* OpenGL ES 2.0 */
|
||||
|
||||
EXPECT_NE(glActiveTexture, nullptr);
|
||||
|
||||
@@ -18,7 +18,10 @@ static bool setFlag = false;
|
||||
struct MockGLObject {
|
||||
using Type = bool;
|
||||
static const Type Default;
|
||||
static Type Get() { getFlag = true; return true; }
|
||||
static Type Get() {
|
||||
getFlag = true;
|
||||
return true;
|
||||
}
|
||||
static void Set(const Type&) { setFlag = true; }
|
||||
};
|
||||
|
||||
@@ -45,10 +48,10 @@ TEST(GLObject, Value) {
|
||||
}
|
||||
|
||||
TEST(GLObject, Store) {
|
||||
gl::HeadlessBackend backend { { 256, 256 } };
|
||||
gfx::BackendScope scope { backend };
|
||||
gl::HeadlessBackend backend{{256, 256}};
|
||||
gfx::BackendScope scope{backend};
|
||||
|
||||
gl::Context context{ backend };
|
||||
gl::Context context{backend};
|
||||
EXPECT_TRUE(context.empty());
|
||||
|
||||
gl::UniqueTexture texture = context.createUniqueTexture();
|
||||
|
||||
Reference in New Issue
Block a user