2360 lines
99 KiB
C++
2360 lines
99 KiB
C++
#include "renderer_gl/opengl_capabilities.h"
|
|
#include "renderer_gl/shader_bindings.h"
|
|
#include "test_harness.h"
|
|
|
|
#include <array>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <limits>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
|
|
struct RecordedOpenGlStateCall {
|
|
enum class Kind {
|
|
enable,
|
|
disable,
|
|
blend_func,
|
|
blend_equation_separate,
|
|
};
|
|
|
|
Kind kind = Kind::enable;
|
|
std::uint32_t first = 0;
|
|
std::uint32_t second = 0;
|
|
};
|
|
|
|
struct RecordedOpenGlBindingCall {
|
|
enum class Kind {
|
|
bind_framebuffer,
|
|
use_program,
|
|
active_texture,
|
|
bind_texture,
|
|
bind_sampler,
|
|
};
|
|
|
|
Kind kind = Kind::bind_framebuffer;
|
|
std::uint32_t first = 0;
|
|
std::uint32_t second = 0;
|
|
};
|
|
|
|
struct RecordedOpenGlTextureImageCall {
|
|
std::uint32_t target = 0;
|
|
std::int32_t level = 0;
|
|
std::int32_t internal_format = 0;
|
|
std::int32_t x = 0;
|
|
std::int32_t y = 0;
|
|
std::int32_t width = 0;
|
|
std::int32_t height = 0;
|
|
std::int32_t border = 0;
|
|
std::uint32_t pixel_format = 0;
|
|
std::uint32_t component_type = 0;
|
|
const void* data = nullptr;
|
|
bool sub_image = false;
|
|
};
|
|
|
|
struct RecordedOpenGlFramebufferAttachmentCall {
|
|
std::uint32_t target = 0;
|
|
std::uint32_t attachment = 0;
|
|
std::uint32_t texture_target = 0;
|
|
std::uint32_t texture = 0;
|
|
std::int32_t level = 0;
|
|
};
|
|
|
|
struct RecordedOpenGlReadPixelsCall {
|
|
std::int32_t x = 0;
|
|
std::int32_t y = 0;
|
|
std::int32_t width = 0;
|
|
std::int32_t height = 0;
|
|
std::uint32_t pixel_format = 0;
|
|
std::uint32_t component_type = 0;
|
|
void* pixels = nullptr;
|
|
};
|
|
|
|
struct RecordedOpenGlBlitFramebufferCall {
|
|
std::int32_t source_x0 = 0;
|
|
std::int32_t source_y0 = 0;
|
|
std::int32_t source_x1 = 0;
|
|
std::int32_t source_y1 = 0;
|
|
std::int32_t destination_x0 = 0;
|
|
std::int32_t destination_y0 = 0;
|
|
std::int32_t destination_x1 = 0;
|
|
std::int32_t destination_y1 = 0;
|
|
std::uint32_t mask = 0;
|
|
std::uint32_t filter = 0;
|
|
};
|
|
|
|
std::vector<RecordedOpenGlStateCall> recorded_state_calls;
|
|
std::vector<std::uint32_t> recorded_string_queries;
|
|
std::vector<pp::renderer::gl::OpenGlDefaultClear> recorded_clear_calls;
|
|
std::vector<pp::renderer::gl::OpenGlViewportRect> recorded_viewport_calls;
|
|
std::vector<pp::renderer::gl::OpenGlScissorRect> recorded_scissor_calls;
|
|
std::vector<std::uint32_t> recorded_integer_queries;
|
|
std::vector<std::uint32_t> recorded_float_queries;
|
|
std::vector<std::uint32_t> recorded_active_texture_calls;
|
|
std::vector<RecordedOpenGlBindingCall> recorded_binding_calls;
|
|
std::vector<std::uint32_t> recorded_generated_texture_counts;
|
|
std::vector<std::uint32_t> recorded_deleted_textures;
|
|
std::vector<RecordedOpenGlTextureImageCall> recorded_texture_image_calls;
|
|
std::vector<std::uint32_t> recorded_mipmap_targets;
|
|
std::vector<std::uint32_t> recorded_generated_framebuffer_counts;
|
|
std::vector<std::uint32_t> recorded_deleted_framebuffers;
|
|
std::vector<RecordedOpenGlFramebufferAttachmentCall> recorded_framebuffer_attachment_calls;
|
|
std::vector<std::uint32_t> recorded_framebuffer_status_queries;
|
|
std::vector<RecordedOpenGlReadPixelsCall> recorded_read_pixels_calls;
|
|
std::vector<RecordedOpenGlBlitFramebufferCall> recorded_blit_framebuffer_calls;
|
|
std::uint32_t next_texture_id = 91U;
|
|
std::uint32_t next_framebuffer_id = 44U;
|
|
std::uint32_t configured_framebuffer_status = 0x8CD5U;
|
|
|
|
void record_enable(std::uint32_t state) noexcept
|
|
{
|
|
recorded_state_calls.push_back(RecordedOpenGlStateCall {
|
|
.kind = RecordedOpenGlStateCall::Kind::enable,
|
|
.first = state,
|
|
});
|
|
}
|
|
|
|
void record_disable(std::uint32_t state) noexcept
|
|
{
|
|
recorded_state_calls.push_back(RecordedOpenGlStateCall {
|
|
.kind = RecordedOpenGlStateCall::Kind::disable,
|
|
.first = state,
|
|
});
|
|
}
|
|
|
|
void record_blend_func(std::uint32_t source_factor, std::uint32_t destination_factor) noexcept
|
|
{
|
|
recorded_state_calls.push_back(RecordedOpenGlStateCall {
|
|
.kind = RecordedOpenGlStateCall::Kind::blend_func,
|
|
.first = source_factor,
|
|
.second = destination_factor,
|
|
});
|
|
}
|
|
|
|
void record_blend_equation_separate(std::uint32_t color_equation, std::uint32_t alpha_equation) noexcept
|
|
{
|
|
recorded_state_calls.push_back(RecordedOpenGlStateCall {
|
|
.kind = RecordedOpenGlStateCall::Kind::blend_equation_separate,
|
|
.first = color_equation,
|
|
.second = alpha_equation,
|
|
});
|
|
}
|
|
|
|
const char* record_string_query(std::uint32_t name) noexcept
|
|
{
|
|
recorded_string_queries.push_back(name);
|
|
switch (name) {
|
|
case 0x1F02U:
|
|
return "test-version";
|
|
case 0x1F00U:
|
|
return "test-vendor";
|
|
case 0x1F01U:
|
|
return "test-renderer";
|
|
case 0x8B8CU:
|
|
return "test-glsl";
|
|
default:
|
|
return "unexpected";
|
|
}
|
|
}
|
|
|
|
void record_clear_color(float r, float g, float b, float a) noexcept
|
|
{
|
|
recorded_clear_calls.push_back(pp::renderer::gl::OpenGlDefaultClear {
|
|
.color = { r, g, b, a },
|
|
});
|
|
}
|
|
|
|
void record_clear(std::uint32_t mask) noexcept
|
|
{
|
|
recorded_clear_calls.push_back(pp::renderer::gl::OpenGlDefaultClear {
|
|
.mask = mask,
|
|
});
|
|
}
|
|
|
|
void record_viewport(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height) noexcept
|
|
{
|
|
recorded_viewport_calls.push_back(pp::renderer::gl::OpenGlViewportRect {
|
|
.x = x,
|
|
.y = y,
|
|
.width = width,
|
|
.height = height,
|
|
});
|
|
}
|
|
|
|
void record_scissor(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height) noexcept
|
|
{
|
|
recorded_scissor_calls.push_back(pp::renderer::gl::OpenGlScissorRect {
|
|
.enabled = 1U,
|
|
.x = x,
|
|
.y = y,
|
|
.width = width,
|
|
.height = height,
|
|
});
|
|
}
|
|
|
|
std::uint8_t record_is_enabled(std::uint32_t state) noexcept
|
|
{
|
|
if (state == 0x0BE2U) {
|
|
return 1U;
|
|
}
|
|
if (state == 0x0B71U) {
|
|
return 0U;
|
|
}
|
|
if (state == 0x0C11U) {
|
|
return 1U;
|
|
}
|
|
return 0U;
|
|
}
|
|
|
|
void record_get_integer(std::uint32_t name, std::int32_t* value) noexcept
|
|
{
|
|
recorded_integer_queries.push_back(name);
|
|
switch (name) {
|
|
case 0x0BA2U:
|
|
value[0] = 2;
|
|
value[1] = 4;
|
|
value[2] = 640;
|
|
value[3] = 320;
|
|
break;
|
|
case 0x8B8DU:
|
|
*value = 42;
|
|
break;
|
|
case 0x8CA6U:
|
|
*value = 7;
|
|
break;
|
|
case 0x8CAAU:
|
|
*value = 9;
|
|
break;
|
|
case 0x84E0U:
|
|
*value = 0x84C4;
|
|
break;
|
|
case 0x8514U:
|
|
*value = 88;
|
|
break;
|
|
case 0x8069U:
|
|
*value = 100 + static_cast<std::int32_t>(recorded_active_texture_calls.size());
|
|
break;
|
|
case 0x8919U:
|
|
*value = 200 + static_cast<std::int32_t>(recorded_active_texture_calls.size());
|
|
break;
|
|
default:
|
|
*value = -1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void record_get_float(std::uint32_t name, float* value) noexcept
|
|
{
|
|
recorded_float_queries.push_back(name);
|
|
if (name == 0x0C22U) {
|
|
value[0] = 0.25F;
|
|
value[1] = 0.5F;
|
|
value[2] = 0.75F;
|
|
value[3] = 1.0F;
|
|
}
|
|
}
|
|
|
|
void record_active_texture(std::uint32_t texture_unit) noexcept
|
|
{
|
|
recorded_active_texture_calls.push_back(texture_unit);
|
|
}
|
|
|
|
void record_bind_framebuffer(std::uint32_t target, std::uint32_t framebuffer) noexcept
|
|
{
|
|
recorded_binding_calls.push_back(RecordedOpenGlBindingCall {
|
|
.kind = RecordedOpenGlBindingCall::Kind::bind_framebuffer,
|
|
.first = target,
|
|
.second = framebuffer,
|
|
});
|
|
}
|
|
|
|
void record_use_program(std::uint32_t program) noexcept
|
|
{
|
|
recorded_binding_calls.push_back(RecordedOpenGlBindingCall {
|
|
.kind = RecordedOpenGlBindingCall::Kind::use_program,
|
|
.first = program,
|
|
});
|
|
}
|
|
|
|
void record_bind_texture(std::uint32_t target, std::uint32_t texture) noexcept
|
|
{
|
|
recorded_binding_calls.push_back(RecordedOpenGlBindingCall {
|
|
.kind = RecordedOpenGlBindingCall::Kind::bind_texture,
|
|
.first = target,
|
|
.second = texture,
|
|
});
|
|
}
|
|
|
|
void record_bind_sampler(std::uint32_t unit, std::uint32_t sampler) noexcept
|
|
{
|
|
recorded_binding_calls.push_back(RecordedOpenGlBindingCall {
|
|
.kind = RecordedOpenGlBindingCall::Kind::bind_sampler,
|
|
.first = unit,
|
|
.second = sampler,
|
|
});
|
|
}
|
|
|
|
void record_gen_textures(std::uint32_t count, std::uint32_t* ids) noexcept
|
|
{
|
|
recorded_generated_texture_counts.push_back(count);
|
|
for (std::uint32_t i = 0U; i < count; ++i) {
|
|
ids[i] = next_texture_id + i;
|
|
}
|
|
}
|
|
|
|
void record_delete_textures(std::uint32_t count, const std::uint32_t* ids) noexcept
|
|
{
|
|
for (std::uint32_t i = 0U; i < count; ++i) {
|
|
recorded_deleted_textures.push_back(ids[i]);
|
|
}
|
|
}
|
|
|
|
void record_tex_image_2d(
|
|
std::uint32_t target,
|
|
std::int32_t level,
|
|
std::int32_t internal_format,
|
|
std::int32_t width,
|
|
std::int32_t height,
|
|
std::int32_t border,
|
|
std::uint32_t pixel_format,
|
|
std::uint32_t component_type,
|
|
const void* data) noexcept
|
|
{
|
|
recorded_texture_image_calls.push_back(RecordedOpenGlTextureImageCall {
|
|
.target = target,
|
|
.level = level,
|
|
.internal_format = internal_format,
|
|
.width = width,
|
|
.height = height,
|
|
.border = border,
|
|
.pixel_format = pixel_format,
|
|
.component_type = component_type,
|
|
.data = data,
|
|
});
|
|
}
|
|
|
|
void record_tex_sub_image_2d(
|
|
std::uint32_t target,
|
|
std::int32_t level,
|
|
std::int32_t x,
|
|
std::int32_t y,
|
|
std::int32_t width,
|
|
std::int32_t height,
|
|
std::uint32_t pixel_format,
|
|
std::uint32_t component_type,
|
|
const void* data) noexcept
|
|
{
|
|
recorded_texture_image_calls.push_back(RecordedOpenGlTextureImageCall {
|
|
.target = target,
|
|
.level = level,
|
|
.x = x,
|
|
.y = y,
|
|
.width = width,
|
|
.height = height,
|
|
.pixel_format = pixel_format,
|
|
.component_type = component_type,
|
|
.data = data,
|
|
.sub_image = true,
|
|
});
|
|
}
|
|
|
|
void record_generate_mipmap(std::uint32_t target) noexcept
|
|
{
|
|
recorded_mipmap_targets.push_back(target);
|
|
}
|
|
|
|
void record_gen_framebuffers(std::uint32_t count, std::uint32_t* ids) noexcept
|
|
{
|
|
recorded_generated_framebuffer_counts.push_back(count);
|
|
for (std::uint32_t i = 0U; i < count; ++i) {
|
|
ids[i] = next_framebuffer_id + i;
|
|
}
|
|
}
|
|
|
|
void record_delete_framebuffers(std::uint32_t count, const std::uint32_t* ids) noexcept
|
|
{
|
|
for (std::uint32_t i = 0U; i < count; ++i) {
|
|
recorded_deleted_framebuffers.push_back(ids[i]);
|
|
}
|
|
}
|
|
|
|
void record_framebuffer_texture_2d(
|
|
std::uint32_t target,
|
|
std::uint32_t attachment,
|
|
std::uint32_t texture_target,
|
|
std::uint32_t texture,
|
|
std::int32_t level) noexcept
|
|
{
|
|
recorded_framebuffer_attachment_calls.push_back(RecordedOpenGlFramebufferAttachmentCall {
|
|
.target = target,
|
|
.attachment = attachment,
|
|
.texture_target = texture_target,
|
|
.texture = texture,
|
|
.level = level,
|
|
});
|
|
}
|
|
|
|
std::uint32_t record_check_framebuffer_status(std::uint32_t target) noexcept
|
|
{
|
|
recorded_framebuffer_status_queries.push_back(target);
|
|
return configured_framebuffer_status;
|
|
}
|
|
|
|
void record_read_pixels(
|
|
std::int32_t x,
|
|
std::int32_t y,
|
|
std::int32_t width,
|
|
std::int32_t height,
|
|
std::uint32_t pixel_format,
|
|
std::uint32_t component_type,
|
|
void* pixels) noexcept
|
|
{
|
|
recorded_read_pixels_calls.push_back(RecordedOpenGlReadPixelsCall {
|
|
.x = x,
|
|
.y = y,
|
|
.width = width,
|
|
.height = height,
|
|
.pixel_format = pixel_format,
|
|
.component_type = component_type,
|
|
.pixels = pixels,
|
|
});
|
|
}
|
|
|
|
void record_blit_framebuffer(
|
|
std::int32_t source_x0,
|
|
std::int32_t source_y0,
|
|
std::int32_t source_x1,
|
|
std::int32_t source_y1,
|
|
std::int32_t destination_x0,
|
|
std::int32_t destination_y0,
|
|
std::int32_t destination_x1,
|
|
std::int32_t destination_y1,
|
|
std::uint32_t mask,
|
|
std::uint32_t filter) noexcept
|
|
{
|
|
recorded_blit_framebuffer_calls.push_back(RecordedOpenGlBlitFramebufferCall {
|
|
.source_x0 = source_x0,
|
|
.source_y0 = source_y0,
|
|
.source_x1 = source_x1,
|
|
.source_y1 = source_y1,
|
|
.destination_x0 = destination_x0,
|
|
.destination_y0 = destination_y0,
|
|
.destination_x1 = destination_x1,
|
|
.destination_y1 = destination_y1,
|
|
.mask = mask,
|
|
.filter = filter,
|
|
});
|
|
}
|
|
|
|
void detects_common_extension_capabilities(pp::tests::Harness& h)
|
|
{
|
|
constexpr std::array<std::string_view, 2> extensions {
|
|
"GL_EXT_shader_framebuffer_fetch",
|
|
"GL_ARB_map_buffer_alignment",
|
|
};
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::extension_count_query() == 0x821DU);
|
|
PP_EXPECT(h, pp::renderer::gl::extension_string_name() == 0x1F03U);
|
|
PP_EXPECT(h, pp::renderer::gl::no_error_code() == 0U);
|
|
PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0U) == std::string_view("GL_NO_ERROR"));
|
|
PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0x0500U) == std::string_view("GL_INVALID_ENUM"));
|
|
PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0x0501U) == std::string_view("GL_INVALID_VALUE"));
|
|
PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0x0502U) == std::string_view("GL_INVALID_OPERATION"));
|
|
PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0x0505U) == std::string_view("GL_OUT_OF_MEMORY"));
|
|
PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0x0506U)
|
|
== std::string_view("GL_INVALID_FRAMEBUFFER_OPERATION"));
|
|
PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0xffffffffU) == std::string_view("Unknown"));
|
|
|
|
const auto capabilities = pp::renderer::gl::detect_opengl_capabilities(
|
|
extensions,
|
|
pp::renderer::gl::OpenGlRuntime {});
|
|
|
|
PP_EXPECT(h, capabilities.framebuffer_fetch);
|
|
PP_EXPECT(h, capabilities.map_buffer_alignment);
|
|
PP_EXPECT(h, !capabilities.float32_textures);
|
|
PP_EXPECT(h, !capabilities.float16_textures);
|
|
|
|
const auto features = pp::renderer::gl::render_device_features(capabilities);
|
|
PP_EXPECT(h, features.framebuffer_fetch);
|
|
PP_EXPECT(h, !features.explicit_texture_transitions);
|
|
PP_EXPECT(h, features.texture_copy);
|
|
PP_EXPECT(h, features.render_target_blit);
|
|
PP_EXPECT(h, features.frame_capture);
|
|
PP_EXPECT(h, !features.float16_render_targets);
|
|
PP_EXPECT(h, !features.float32_render_targets);
|
|
}
|
|
|
|
void treats_desktop_gl_float_rendering_as_core(pp::tests::Harness& h)
|
|
{
|
|
const auto capabilities = pp::renderer::gl::detect_opengl_capabilities(
|
|
{},
|
|
pp::renderer::gl::OpenGlRuntime { .desktop_gl = true });
|
|
|
|
PP_EXPECT(h, capabilities.float32_textures);
|
|
PP_EXPECT(h, capabilities.float32_linear);
|
|
PP_EXPECT(h, capabilities.float16_textures);
|
|
|
|
const auto features = pp::renderer::gl::render_device_features(capabilities);
|
|
PP_EXPECT(h, features.float16_render_targets);
|
|
PP_EXPECT(h, features.float32_render_targets);
|
|
}
|
|
|
|
void detects_gles_texture_float_extensions(pp::tests::Harness& h)
|
|
{
|
|
constexpr std::array<std::string_view, 3> extensions {
|
|
"GL_OES_texture_float",
|
|
"GL_OES_texture_float_linear",
|
|
"GL_EXT_color_buffer_half_float",
|
|
};
|
|
|
|
const auto capabilities = pp::renderer::gl::detect_opengl_capabilities(
|
|
extensions,
|
|
pp::renderer::gl::OpenGlRuntime { .gles = true });
|
|
|
|
PP_EXPECT(h, capabilities.float32_textures);
|
|
PP_EXPECT(h, capabilities.float32_linear);
|
|
PP_EXPECT(h, capabilities.float16_textures);
|
|
}
|
|
|
|
void ignores_gles_texture_extensions_for_webgl_runtime(pp::tests::Harness& h)
|
|
{
|
|
constexpr std::array<std::string_view, 3> extensions {
|
|
"GL_OES_texture_float",
|
|
"GL_OES_texture_float_linear",
|
|
"GL_EXT_color_buffer_half_float",
|
|
};
|
|
|
|
const auto capabilities = pp::renderer::gl::detect_opengl_capabilities(
|
|
extensions,
|
|
pp::renderer::gl::OpenGlRuntime { .gles = true, .web = true });
|
|
|
|
PP_EXPECT(h, !capabilities.float32_textures);
|
|
PP_EXPECT(h, !capabilities.float32_linear);
|
|
PP_EXPECT(h, !capabilities.float16_textures);
|
|
}
|
|
|
|
void selects_texture_upload_type_from_internal_format(pp::tests::Harness& h)
|
|
{
|
|
constexpr std::uint32_t gl_unsigned_byte = 0x1401U;
|
|
constexpr std::uint32_t gl_float = 0x1406U;
|
|
constexpr std::uint32_t gl_half_float = 0x140BU;
|
|
constexpr std::uint32_t gl_rgba8 = 0x8058U;
|
|
constexpr std::uint32_t gl_rgba32f = 0x8814U;
|
|
constexpr std::uint32_t gl_rgba16f = 0x881AU;
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::texture_upload_type_for_internal_format(gl_rgba8) == gl_unsigned_byte);
|
|
PP_EXPECT(h, pp::renderer::gl::texture_upload_type_for_internal_format(gl_rgba32f) == gl_float);
|
|
PP_EXPECT(h, pp::renderer::gl::texture_upload_type_for_internal_format(gl_rgba16f) == gl_half_float);
|
|
PP_EXPECT(h, pp::renderer::gl::texture_upload_type_for_internal_format(0U) == gl_unsigned_byte);
|
|
PP_EXPECT(h, pp::renderer::gl::unsigned_byte_component_type() == gl_unsigned_byte);
|
|
PP_EXPECT(h, pp::renderer::gl::rgba_pixel_format() == 0x1908U);
|
|
}
|
|
|
|
void maps_image_channel_count_to_texture_format(pp::tests::Harness& h)
|
|
{
|
|
constexpr std::uint32_t gl_red = 0x1903U;
|
|
constexpr std::uint32_t gl_rgb = 0x1907U;
|
|
constexpr std::uint32_t gl_rgba = 0x1908U;
|
|
constexpr std::uint32_t gl_rg = 0x8227U;
|
|
constexpr std::uint32_t gl_r8 = 0x8229U;
|
|
constexpr std::uint32_t gl_rg8 = 0x822BU;
|
|
constexpr std::uint32_t gl_rgb8 = 0x8051U;
|
|
constexpr std::uint32_t gl_rgba8 = 0x8058U;
|
|
|
|
const auto r = pp::renderer::gl::texture_format_for_channel_count(1U);
|
|
const auto rg = pp::renderer::gl::texture_format_for_channel_count(2U);
|
|
const auto rgb = pp::renderer::gl::texture_format_for_channel_count(3U);
|
|
const auto rgba = pp::renderer::gl::texture_format_for_channel_count(4U);
|
|
const auto invalid = pp::renderer::gl::texture_format_for_channel_count(5U);
|
|
|
|
PP_EXPECT(h, r.internal_format == gl_r8);
|
|
PP_EXPECT(h, r.pixel_format == gl_red);
|
|
PP_EXPECT(h, rg.internal_format == gl_rg8);
|
|
PP_EXPECT(h, rg.pixel_format == gl_rg);
|
|
PP_EXPECT(h, rgb.internal_format == gl_rgb8);
|
|
PP_EXPECT(h, rgb.pixel_format == gl_rgb);
|
|
PP_EXPECT(h, rgba.internal_format == gl_rgba8);
|
|
PP_EXPECT(h, rgba.pixel_format == gl_rgba);
|
|
PP_EXPECT(h, invalid.channel_count == 0U);
|
|
PP_EXPECT(h, invalid.internal_format == 0U);
|
|
PP_EXPECT(h, invalid.pixel_format == 0U);
|
|
}
|
|
|
|
void maps_renderer_texture_formats_to_opengl_tokens(pp::tests::Harness& h)
|
|
{
|
|
const auto rgba8 = pp::renderer::gl::texture_format_for_renderer_format(pp::renderer::TextureFormat::rgba8);
|
|
const auto r8 = pp::renderer::gl::texture_format_for_renderer_format(pp::renderer::TextureFormat::r8);
|
|
const auto depth_stencil = pp::renderer::gl::texture_format_for_renderer_format(
|
|
pp::renderer::TextureFormat::depth24_stencil8);
|
|
const auto invalid = pp::renderer::gl::texture_format_for_renderer_format(
|
|
static_cast<pp::renderer::TextureFormat>(255U));
|
|
|
|
PP_EXPECT(h, rgba8.internal_format == 0x8058U);
|
|
PP_EXPECT(h, rgba8.pixel_format == 0x1908U);
|
|
PP_EXPECT(h, rgba8.component_type == 0x1401U);
|
|
PP_EXPECT(h, rgba8.bytes_per_pixel == 4U);
|
|
PP_EXPECT(h, r8.internal_format == 0x8229U);
|
|
PP_EXPECT(h, r8.pixel_format == 0x1903U);
|
|
PP_EXPECT(h, r8.component_type == 0x1401U);
|
|
PP_EXPECT(h, r8.bytes_per_pixel == 1U);
|
|
PP_EXPECT(h, depth_stencil.internal_format == 0x88F0U);
|
|
PP_EXPECT(h, depth_stencil.pixel_format == 0x84F9U);
|
|
PP_EXPECT(h, depth_stencil.component_type == 0x84FAU);
|
|
PP_EXPECT(h, depth_stencil.bytes_per_pixel == 4U);
|
|
PP_EXPECT(h, invalid.internal_format == 0U);
|
|
PP_EXPECT(h, invalid.pixel_format == 0U);
|
|
PP_EXPECT(h, invalid.component_type == 0U);
|
|
PP_EXPECT(h, invalid.bytes_per_pixel == 0U);
|
|
}
|
|
|
|
void maps_readback_formats(pp::tests::Harness& h)
|
|
{
|
|
const auto rgba8 = pp::renderer::gl::rgba8_readback_format();
|
|
const auto rgba32f = pp::renderer::gl::rgba32f_readback_format();
|
|
|
|
PP_EXPECT(h, rgba8.pixel_format == 0x1908U);
|
|
PP_EXPECT(h, rgba8.component_type == 0x1401U);
|
|
PP_EXPECT(h, rgba8.bytes_per_pixel == 4U);
|
|
PP_EXPECT(h, pp::renderer::gl::readback_byte_count(rgba8, 3U, 5U) == 60U);
|
|
PP_EXPECT(h, pp::renderer::gl::readback_byte_count(rgba8, 0U, 5U) == 0U);
|
|
|
|
PP_EXPECT(h, rgba32f.pixel_format == 0x1908U);
|
|
PP_EXPECT(h, rgba32f.component_type == 0x1406U);
|
|
PP_EXPECT(h, rgba32f.bytes_per_pixel == 16U);
|
|
PP_EXPECT(h, pp::renderer::gl::readback_byte_count(rgba32f, 3U, 5U) == 240U);
|
|
|
|
const auto invalid_format = pp::renderer::gl::OpenGlReadbackFormat {
|
|
.pixel_format = rgba8.pixel_format,
|
|
.component_type = rgba8.component_type,
|
|
.bytes_per_pixel = 0U,
|
|
};
|
|
const auto overflowing_format = pp::renderer::gl::OpenGlReadbackFormat {
|
|
.pixel_format = rgba8.pixel_format,
|
|
.component_type = rgba8.component_type,
|
|
.bytes_per_pixel = std::numeric_limits<std::uint32_t>::max(),
|
|
};
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::readback_byte_count(invalid_format, 1U, 1U) == 0U);
|
|
PP_EXPECT(h, pp::renderer::gl::readback_byte_count(
|
|
overflowing_format,
|
|
std::numeric_limits<std::uint32_t>::max(),
|
|
std::numeric_limits<std::uint32_t>::max())
|
|
== 0U);
|
|
}
|
|
|
|
void maps_pixel_buffer_parameters(pp::tests::Harness& h)
|
|
{
|
|
PP_EXPECT(h, pp::renderer::gl::pixel_pack_buffer_target() == 0x88EBU);
|
|
PP_EXPECT(h, pp::renderer::gl::pixel_unpack_buffer_target() == 0x88ECU);
|
|
PP_EXPECT(h, pp::renderer::gl::pixel_buffer_stream_read_usage() == 0x88E1U);
|
|
PP_EXPECT(h, pp::renderer::gl::pixel_buffer_map_read_access() == 0x0001U);
|
|
}
|
|
|
|
void names_framebuffer_status_codes(pp::tests::Harness& h)
|
|
{
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_complete_status() == 0x8CD5U);
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CD5U) == std::string_view("GL_FRAMEBUFFER_COMPLETE"));
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8219U) == std::string_view("GL_FRAMEBUFFER_UNDEFINED"));
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CD6U)
|
|
== std::string_view("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"));
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CD7U)
|
|
== std::string_view("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"));
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CDBU)
|
|
== std::string_view("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"));
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CDCU)
|
|
== std::string_view("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"));
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CDDU)
|
|
== std::string_view("GL_FRAMEBUFFER_UNSUPPORTED"));
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8D56U)
|
|
== std::string_view("GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"));
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0U) == std::string_view("UNKNOWN"));
|
|
}
|
|
|
|
void maps_framebuffer_render_target_parameters(pp::tests::Harness& h)
|
|
{
|
|
PP_EXPECT(h, pp::renderer::gl::texture_2d_target() == 0x0DE1U);
|
|
PP_EXPECT(h, pp::renderer::gl::renderbuffer_target() == 0x8D41U);
|
|
PP_EXPECT(h, pp::renderer::gl::depth_component24_format() == 0x81A6U);
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_target() == 0x8D40U);
|
|
PP_EXPECT(h, pp::renderer::gl::draw_framebuffer_target() == 0x8CA9U);
|
|
PP_EXPECT(h, pp::renderer::gl::read_framebuffer_target() == 0x8CA8U);
|
|
PP_EXPECT(h, pp::renderer::gl::draw_framebuffer_binding_query() == 0x8CA6U);
|
|
PP_EXPECT(h, pp::renderer::gl::read_framebuffer_binding_query() == 0x8CAAU);
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_color_attachment() == 0x8CE0U);
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_depth_attachment() == 0x8D00U);
|
|
PP_EXPECT(h, pp::renderer::gl::default_framebuffer_id() == 0U);
|
|
}
|
|
|
|
void maps_framebuffer_blit_parameters(pp::tests::Harness& h)
|
|
{
|
|
const auto nearest = pp::renderer::gl::blit_filter_for_renderer_filter(pp::renderer::BlitFilter::nearest);
|
|
const auto linear = pp::renderer::gl::blit_filter_for_renderer_filter(pp::renderer::BlitFilter::linear);
|
|
const auto invalid = pp::renderer::gl::blit_filter_for_renderer_filter(
|
|
static_cast<pp::renderer::BlitFilter>(255U));
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_color_buffer_mask() == 0x00004000U);
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_depth_buffer_mask() == 0x00000100U);
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_stencil_buffer_mask() == 0x00000400U);
|
|
PP_EXPECT(h, pp::renderer::gl::color_write_mask_query() == 0x0C23U);
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_blit_filter(true) == 0x2601U);
|
|
PP_EXPECT(h, pp::renderer::gl::framebuffer_blit_filter(false) == 0x2600U);
|
|
PP_EXPECT(h, nearest.supported);
|
|
PP_EXPECT(h, nearest.value == 0x2600U);
|
|
PP_EXPECT(h, linear.supported);
|
|
PP_EXPECT(h, linear.value == 0x2601U);
|
|
PP_EXPECT(h, !invalid.supported);
|
|
PP_EXPECT(h, invalid.value == 0U);
|
|
}
|
|
|
|
void maps_render_pass_clear_masks(pp::tests::Harness& h)
|
|
{
|
|
const auto no_clear = pp::renderer::gl::clear_mask_for_render_pass(pp::renderer::RenderPassDesc {
|
|
.clear_color_enabled = false,
|
|
.clear_color = {},
|
|
.clear_depth_enabled = false,
|
|
.clear_stencil_enabled = false,
|
|
});
|
|
const auto color_only = pp::renderer::gl::clear_mask_for_render_pass(pp::renderer::RenderPassDesc {
|
|
.clear_color_enabled = true,
|
|
.clear_color = {},
|
|
.clear_depth_enabled = false,
|
|
.clear_stencil_enabled = false,
|
|
});
|
|
const auto depth_only = pp::renderer::gl::clear_mask_for_render_pass(pp::renderer::RenderPassDesc {
|
|
.clear_color_enabled = false,
|
|
.clear_color = {},
|
|
.clear_depth_enabled = true,
|
|
.clear_stencil_enabled = false,
|
|
});
|
|
const auto stencil_only = pp::renderer::gl::clear_mask_for_render_pass(pp::renderer::RenderPassDesc {
|
|
.clear_color_enabled = false,
|
|
.clear_color = {},
|
|
.clear_depth_enabled = false,
|
|
.clear_stencil_enabled = true,
|
|
});
|
|
const auto all_buffers = pp::renderer::gl::clear_mask_for_render_pass(pp::renderer::RenderPassDesc {
|
|
.clear_color_enabled = true,
|
|
.clear_color = {},
|
|
.clear_depth_enabled = true,
|
|
.clear_stencil_enabled = true,
|
|
});
|
|
|
|
PP_EXPECT(h, no_clear == 0U);
|
|
PP_EXPECT(h, color_only == 0x00004000U);
|
|
PP_EXPECT(h, depth_only == 0x00000100U);
|
|
PP_EXPECT(h, stencil_only == 0x00000400U);
|
|
PP_EXPECT(h, all_buffers == 0x00004500U);
|
|
}
|
|
|
|
void maps_render_pass_clear_values(pp::tests::Harness& h)
|
|
{
|
|
const auto values = pp::renderer::gl::clear_values_for_render_pass(pp::renderer::RenderPassDesc {
|
|
.clear_color_enabled = true,
|
|
.clear_color = {
|
|
.r = 0.125F,
|
|
.g = 0.25F,
|
|
.b = 0.5F,
|
|
.a = 1.0F,
|
|
},
|
|
.clear_depth_enabled = true,
|
|
.clear_depth = 0.625F,
|
|
.clear_stencil_enabled = true,
|
|
.clear_stencil = 7U,
|
|
});
|
|
const auto disabled_values = pp::renderer::gl::clear_values_for_render_pass(pp::renderer::RenderPassDesc {
|
|
.clear_color_enabled = false,
|
|
.clear_color = {
|
|
.r = 1.0F,
|
|
.g = 0.75F,
|
|
.b = 0.5F,
|
|
.a = 0.25F,
|
|
},
|
|
.clear_depth_enabled = false,
|
|
.clear_depth = 0.125F,
|
|
.clear_stencil_enabled = false,
|
|
.clear_stencil = 13U,
|
|
});
|
|
|
|
PP_EXPECT(h, values.color[0] == 0.125F);
|
|
PP_EXPECT(h, values.color[1] == 0.25F);
|
|
PP_EXPECT(h, values.color[2] == 0.5F);
|
|
PP_EXPECT(h, values.color[3] == 1.0F);
|
|
PP_EXPECT(h, values.depth == 0.625F);
|
|
PP_EXPECT(h, values.stencil == 7U);
|
|
PP_EXPECT(h, disabled_values.color[0] == 1.0F);
|
|
PP_EXPECT(h, disabled_values.color[1] == 0.75F);
|
|
PP_EXPECT(h, disabled_values.color[2] == 0.5F);
|
|
PP_EXPECT(h, disabled_values.color[3] == 0.25F);
|
|
PP_EXPECT(h, disabled_values.depth == 0.125F);
|
|
PP_EXPECT(h, disabled_values.stencil == 13U);
|
|
}
|
|
|
|
void maps_renderer_primitive_topologies_to_draw_modes(pp::tests::Harness& h)
|
|
{
|
|
PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_renderer_topology(
|
|
pp::renderer::PrimitiveTopology::triangles)
|
|
== 0x0004U);
|
|
PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_renderer_topology(
|
|
pp::renderer::PrimitiveTopology::triangle_strip)
|
|
== 0x0005U);
|
|
PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_renderer_topology(
|
|
pp::renderer::PrimitiveTopology::lines)
|
|
== 0x0001U);
|
|
PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_renderer_topology(
|
|
static_cast<pp::renderer::PrimitiveTopology>(255U))
|
|
== 0U);
|
|
}
|
|
|
|
void maps_shape_index_and_primitive_modes(pp::tests::Harness& h)
|
|
{
|
|
constexpr std::uint32_t gl_points = 0x0000U;
|
|
constexpr std::uint32_t gl_lines = 0x0001U;
|
|
constexpr std::uint32_t gl_triangles = 0x0004U;
|
|
constexpr std::uint32_t gl_unsigned_short = 0x1403U;
|
|
constexpr std::uint32_t gl_unsigned_int = 0x1405U;
|
|
constexpr std::uint32_t gl_float = 0x1406U;
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::index_type_for_index_size(2U) == gl_unsigned_short);
|
|
PP_EXPECT(h, pp::renderer::gl::index_type_for_index_size(4U) == gl_unsigned_int);
|
|
PP_EXPECT(h, pp::renderer::gl::index_type_for_index_size(1U) == 0U);
|
|
PP_EXPECT(h, pp::renderer::gl::index_type_for_index_size(8U) == 0U);
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_fill_count(1U) == gl_points);
|
|
PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_fill_count(2U) == gl_lines);
|
|
PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_fill_count(3U) == gl_triangles);
|
|
PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_fill_count(99U) == gl_triangles);
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_stroke_count(1U) == gl_points);
|
|
PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_stroke_count(2U) == gl_lines);
|
|
PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_stroke_count(99U) == gl_lines);
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::array_buffer_target() == 0x8892U);
|
|
PP_EXPECT(h, pp::renderer::gl::element_array_buffer_target() == 0x8893U);
|
|
PP_EXPECT(h, pp::renderer::gl::static_draw_buffer_usage() == 0x88E4U);
|
|
PP_EXPECT(h, pp::renderer::gl::vertex_attribute_float_component_type() == gl_float);
|
|
PP_EXPECT(h, pp::renderer::gl::vertex_attribute_not_normalized() == 0U);
|
|
}
|
|
|
|
void maps_panopainter_cube_faces_to_texture_targets(pp::tests::Harness& h)
|
|
{
|
|
const auto targets = pp::renderer::gl::panopainter_cube_face_texture_targets();
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::texture_cube_map_target() == 0x8513U);
|
|
PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(0U) == 0x8515U);
|
|
PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(1U) == 0x8516U);
|
|
PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(2U) == 0x8517U);
|
|
PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(3U) == 0x8518U);
|
|
PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(4U) == 0x8519U);
|
|
PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(5U) == 0x851AU);
|
|
PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(6U) == 0U);
|
|
|
|
PP_EXPECT(h, targets.size() == 6U);
|
|
PP_EXPECT(h, targets[0] == 0x851AU);
|
|
PP_EXPECT(h, targets[1] == 0x8516U);
|
|
PP_EXPECT(h, targets[2] == 0x8519U);
|
|
PP_EXPECT(h, targets[3] == 0x8515U);
|
|
PP_EXPECT(h, targets[4] == 0x8518U);
|
|
PP_EXPECT(h, targets[5] == 0x8517U);
|
|
PP_EXPECT(h, pp::renderer::gl::cube_face_texture_target(0U) == 0x851AU);
|
|
PP_EXPECT(h, pp::renderer::gl::cube_face_texture_target(5U) == 0x8517U);
|
|
PP_EXPECT(h, pp::renderer::gl::cube_face_texture_target(6U) == 0U);
|
|
}
|
|
|
|
void exposes_default_render_target_texture_parameters(pp::tests::Harness& h)
|
|
{
|
|
const auto parameters = pp::renderer::gl::default_render_target_texture_parameters();
|
|
|
|
PP_EXPECT(h, parameters.size() == 4U);
|
|
PP_EXPECT(h, parameters[0].name == 0x2800U);
|
|
PP_EXPECT(h, parameters[0].value == 0x2601U);
|
|
PP_EXPECT(h, parameters[1].name == 0x2801U);
|
|
PP_EXPECT(h, parameters[1].value == 0x2601U);
|
|
PP_EXPECT(h, parameters[2].name == 0x2802U);
|
|
PP_EXPECT(h, parameters[2].value == 0x812FU);
|
|
PP_EXPECT(h, parameters[3].name == 0x2803U);
|
|
PP_EXPECT(h, parameters[3].value == 0x812FU);
|
|
}
|
|
|
|
void maps_sampler_parameters(pp::tests::Harness& h)
|
|
{
|
|
const auto parameters = pp::renderer::gl::sampler_parameters_for_filter_wrap(0x2601U, 0x812FU);
|
|
|
|
PP_EXPECT(h, parameters.size() == 5U);
|
|
PP_EXPECT(h, parameters[0].name == 0x2802U);
|
|
PP_EXPECT(h, parameters[0].value == 0x812FU);
|
|
PP_EXPECT(h, parameters[1].name == 0x2803U);
|
|
PP_EXPECT(h, parameters[1].value == 0x812FU);
|
|
PP_EXPECT(h, parameters[2].name == 0x8072U);
|
|
PP_EXPECT(h, parameters[2].value == 0x812FU);
|
|
PP_EXPECT(h, parameters[3].name == 0x2801U);
|
|
PP_EXPECT(h, parameters[3].value == 0x2601U);
|
|
PP_EXPECT(h, parameters[4].name == 0x2800U);
|
|
PP_EXPECT(h, parameters[4].value == 0x2601U);
|
|
|
|
const auto filters = pp::renderer::gl::sampler_filter_parameters(0x2600U, 0x2601U);
|
|
PP_EXPECT(h, filters.size() == 2U);
|
|
PP_EXPECT(h, filters[0].name == 0x2801U);
|
|
PP_EXPECT(h, filters[0].value == 0x2600U);
|
|
PP_EXPECT(h, filters[1].name == 0x2800U);
|
|
PP_EXPECT(h, filters[1].value == 0x2601U);
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::sampler_border_color_parameter_name() == 0x1004U);
|
|
}
|
|
|
|
void maps_renderer_sampler_tokens(pp::tests::Harness& h)
|
|
{
|
|
const auto nearest = pp::renderer::gl::sampler_filter_for_renderer_filter(
|
|
pp::renderer::SamplerFilter::nearest);
|
|
const auto linear = pp::renderer::gl::sampler_filter_for_renderer_filter(
|
|
pp::renderer::SamplerFilter::linear);
|
|
const auto invalid_filter = pp::renderer::gl::sampler_filter_for_renderer_filter(
|
|
static_cast<pp::renderer::SamplerFilter>(255U));
|
|
const auto clamp_to_edge = pp::renderer::gl::sampler_address_mode_for_renderer_mode(
|
|
pp::renderer::SamplerAddressMode::clamp_to_edge);
|
|
const auto repeat = pp::renderer::gl::sampler_address_mode_for_renderer_mode(
|
|
pp::renderer::SamplerAddressMode::repeat);
|
|
const auto mirrored_repeat = pp::renderer::gl::sampler_address_mode_for_renderer_mode(
|
|
pp::renderer::SamplerAddressMode::mirrored_repeat);
|
|
const auto clamp_to_border = pp::renderer::gl::sampler_address_mode_for_renderer_mode(
|
|
pp::renderer::SamplerAddressMode::clamp_to_border);
|
|
const auto invalid_mode = pp::renderer::gl::sampler_address_mode_for_renderer_mode(
|
|
static_cast<pp::renderer::SamplerAddressMode>(255U));
|
|
const auto nearest_nearest = pp::renderer::gl::sampler_min_filter_for_renderer_filters(
|
|
pp::renderer::SamplerFilter::nearest,
|
|
pp::renderer::SamplerFilter::nearest);
|
|
const auto linear_nearest = pp::renderer::gl::sampler_min_filter_for_renderer_filters(
|
|
pp::renderer::SamplerFilter::linear,
|
|
pp::renderer::SamplerFilter::nearest);
|
|
const auto nearest_linear = pp::renderer::gl::sampler_min_filter_for_renderer_filters(
|
|
pp::renderer::SamplerFilter::nearest,
|
|
pp::renderer::SamplerFilter::linear);
|
|
const auto linear_linear = pp::renderer::gl::sampler_min_filter_for_renderer_filters(
|
|
pp::renderer::SamplerFilter::linear,
|
|
pp::renderer::SamplerFilter::linear);
|
|
const auto invalid_min_filter = pp::renderer::gl::sampler_min_filter_for_renderer_filters(
|
|
static_cast<pp::renderer::SamplerFilter>(255U),
|
|
pp::renderer::SamplerFilter::linear);
|
|
const auto invalid_mip_filter = pp::renderer::gl::sampler_min_filter_for_renderer_filters(
|
|
pp::renderer::SamplerFilter::linear,
|
|
static_cast<pp::renderer::SamplerFilter>(255U));
|
|
|
|
PP_EXPECT(h, nearest.supported);
|
|
PP_EXPECT(h, nearest.value == 0x2600U);
|
|
PP_EXPECT(h, linear.supported);
|
|
PP_EXPECT(h, linear.value == 0x2601U);
|
|
PP_EXPECT(h, !invalid_filter.supported);
|
|
PP_EXPECT(h, invalid_filter.value == 0U);
|
|
PP_EXPECT(h, clamp_to_edge.supported);
|
|
PP_EXPECT(h, clamp_to_edge.value == 0x812FU);
|
|
PP_EXPECT(h, repeat.supported);
|
|
PP_EXPECT(h, repeat.value == 0x2901U);
|
|
PP_EXPECT(h, mirrored_repeat.supported);
|
|
PP_EXPECT(h, mirrored_repeat.value == 0x8370U);
|
|
PP_EXPECT(h, clamp_to_border.supported);
|
|
PP_EXPECT(h, clamp_to_border.value == 0x812DU);
|
|
PP_EXPECT(h, !invalid_mode.supported);
|
|
PP_EXPECT(h, invalid_mode.value == 0U);
|
|
PP_EXPECT(h, nearest_nearest.supported);
|
|
PP_EXPECT(h, nearest_nearest.value == 0x2700U);
|
|
PP_EXPECT(h, linear_nearest.supported);
|
|
PP_EXPECT(h, linear_nearest.value == 0x2701U);
|
|
PP_EXPECT(h, nearest_linear.supported);
|
|
PP_EXPECT(h, nearest_linear.value == 0x2702U);
|
|
PP_EXPECT(h, linear_linear.supported);
|
|
PP_EXPECT(h, linear_linear.value == 0x2703U);
|
|
PP_EXPECT(h, !invalid_min_filter.supported);
|
|
PP_EXPECT(h, invalid_min_filter.value == 0U);
|
|
PP_EXPECT(h, !invalid_mip_filter.supported);
|
|
PP_EXPECT(h, invalid_mip_filter.value == 0U);
|
|
}
|
|
|
|
void maps_renderer_sampler_states(pp::tests::Harness& h)
|
|
{
|
|
const auto default_sampler = pp::renderer::gl::sampler_state_for_renderer_sampler_desc(
|
|
pp::renderer::SamplerDesc {});
|
|
const auto mixed_sampler = pp::renderer::gl::sampler_state_for_renderer_sampler_desc(
|
|
pp::renderer::SamplerDesc {
|
|
.min_filter = pp::renderer::SamplerFilter::nearest,
|
|
.mag_filter = pp::renderer::SamplerFilter::linear,
|
|
.mip_filter = pp::renderer::SamplerFilter::linear,
|
|
.address_u = pp::renderer::SamplerAddressMode::repeat,
|
|
.address_v = pp::renderer::SamplerAddressMode::mirrored_repeat,
|
|
.address_w = pp::renderer::SamplerAddressMode::clamp_to_border,
|
|
});
|
|
const auto invalid_filter = pp::renderer::gl::sampler_state_for_renderer_sampler_desc(
|
|
pp::renderer::SamplerDesc {
|
|
.min_filter = static_cast<pp::renderer::SamplerFilter>(255U),
|
|
});
|
|
const auto invalid_address = pp::renderer::gl::sampler_state_for_renderer_sampler_desc(
|
|
pp::renderer::SamplerDesc {
|
|
.address_w = static_cast<pp::renderer::SamplerAddressMode>(255U),
|
|
});
|
|
|
|
PP_EXPECT(h, default_sampler.supported);
|
|
PP_EXPECT(h, default_sampler.min_filter == 0x2703U);
|
|
PP_EXPECT(h, default_sampler.mag_filter == 0x2601U);
|
|
PP_EXPECT(h, default_sampler.wrap_s == 0x812FU);
|
|
PP_EXPECT(h, default_sampler.wrap_t == 0x812FU);
|
|
PP_EXPECT(h, default_sampler.wrap_r == 0x812FU);
|
|
PP_EXPECT(h, mixed_sampler.supported);
|
|
PP_EXPECT(h, mixed_sampler.min_filter == 0x2702U);
|
|
PP_EXPECT(h, mixed_sampler.mag_filter == 0x2601U);
|
|
PP_EXPECT(h, mixed_sampler.wrap_s == 0x2901U);
|
|
PP_EXPECT(h, mixed_sampler.wrap_t == 0x8370U);
|
|
PP_EXPECT(h, mixed_sampler.wrap_r == 0x812DU);
|
|
PP_EXPECT(h, !invalid_filter.supported);
|
|
PP_EXPECT(h, invalid_filter.min_filter == 0U);
|
|
PP_EXPECT(h, !invalid_address.supported);
|
|
PP_EXPECT(h, invalid_address.wrap_r == 0U);
|
|
}
|
|
|
|
void exposes_shader_attribute_binding_catalog(pp::tests::Harness& h)
|
|
{
|
|
const auto bindings = pp::renderer::gl::panopainter_shader_attribute_bindings();
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::vertex_shader_stage() == 0x8B31U);
|
|
PP_EXPECT(h, pp::renderer::gl::fragment_shader_stage() == 0x8B30U);
|
|
PP_EXPECT(h, pp::renderer::gl::shader_compile_status_query() == 0x8B81U);
|
|
PP_EXPECT(h, pp::renderer::gl::program_link_status_query() == 0x8B82U);
|
|
PP_EXPECT(h, pp::renderer::gl::active_uniform_count_query() == 0x8B86U);
|
|
PP_EXPECT(h, pp::renderer::gl::matrix_uniform_not_transposed() == 0U);
|
|
|
|
PP_EXPECT(h, bindings.size() == 5U);
|
|
PP_EXPECT(h, pp::renderer::gl::validate_shader_attribute_bindings(bindings).ok());
|
|
PP_EXPECT(h, std::strcmp(bindings[0].name, "pos") == 0);
|
|
PP_EXPECT(h, bindings[0].location == 0U);
|
|
PP_EXPECT(h, std::strcmp(bindings[1].name, "uvs") == 0);
|
|
PP_EXPECT(h, bindings[1].location == 1U);
|
|
PP_EXPECT(h, std::strcmp(bindings[2].name, "uvs2") == 0);
|
|
PP_EXPECT(h, bindings[2].location == 2U);
|
|
PP_EXPECT(h, std::strcmp(bindings[3].name, "col") == 0);
|
|
PP_EXPECT(h, bindings[3].location == 3U);
|
|
PP_EXPECT(h, std::strcmp(bindings[4].name, "nor") == 0);
|
|
PP_EXPECT(h, bindings[4].location == 3U);
|
|
}
|
|
|
|
void maps_app_initialization_parameters(pp::tests::Harness& h)
|
|
{
|
|
PP_EXPECT(h, pp::renderer::gl::debug_severity_notification() == 0x826BU);
|
|
PP_EXPECT(h, pp::renderer::gl::debug_severity_low() == 0x9148U);
|
|
PP_EXPECT(h, pp::renderer::gl::debug_severity_medium() == 0x9147U);
|
|
PP_EXPECT(h, pp::renderer::gl::debug_severity_high() == 0x9146U);
|
|
PP_EXPECT(h, pp::renderer::gl::debug_output_state() == 0x92E0U);
|
|
PP_EXPECT(h, pp::renderer::gl::debug_output_synchronous_state() == 0x8242U);
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::version_string_name() == 0x1F02U);
|
|
PP_EXPECT(h, pp::renderer::gl::vendor_string_name() == 0x1F00U);
|
|
PP_EXPECT(h, pp::renderer::gl::renderer_string_name() == 0x1F01U);
|
|
PP_EXPECT(h, pp::renderer::gl::shading_language_version_string_name() == 0x8B8CU);
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::viewport_query() == 0x0BA2U);
|
|
PP_EXPECT(h, pp::renderer::gl::color_clear_value_query() == 0x0C22U);
|
|
PP_EXPECT(h, pp::renderer::gl::current_program_query() == 0x8B8DU);
|
|
PP_EXPECT(h, pp::renderer::gl::active_texture_query() == 0x84E0U);
|
|
PP_EXPECT(h, pp::renderer::gl::texture_binding_2d_query() == 0x8069U);
|
|
PP_EXPECT(h, pp::renderer::gl::texture_binding_cube_map_query() == 0x8514U);
|
|
PP_EXPECT(h, pp::renderer::gl::sampler_binding_query() == 0x8919U);
|
|
PP_EXPECT(h, pp::renderer::gl::blend_state() == 0x0BE2U);
|
|
PP_EXPECT(h, pp::renderer::gl::depth_test_state() == 0x0B71U);
|
|
PP_EXPECT(h, pp::renderer::gl::scissor_test_state() == 0x0C11U);
|
|
PP_EXPECT(h, pp::renderer::gl::program_point_size_state() == 0x8642U);
|
|
PP_EXPECT(h, pp::renderer::gl::line_smooth_state() == 0x0B20U);
|
|
PP_EXPECT(h, pp::renderer::gl::source_alpha_blend_factor() == 0x0302U);
|
|
PP_EXPECT(h, pp::renderer::gl::one_minus_source_alpha_blend_factor() == 0x0303U);
|
|
PP_EXPECT(h, pp::renderer::gl::add_blend_equation() == 0x8006U);
|
|
PP_EXPECT(h, pp::renderer::gl::max_blend_equation() == 0x8008U);
|
|
|
|
const auto initial_state = pp::renderer::gl::panopainter_initial_state();
|
|
PP_EXPECT(h, !initial_state.depth_test_enabled);
|
|
PP_EXPECT(h, initial_state.depth_test_state == 0x0B71U);
|
|
PP_EXPECT(h, initial_state.source_color_factor == 0x0302U);
|
|
PP_EXPECT(h, initial_state.destination_color_factor == 0x0303U);
|
|
PP_EXPECT(h, initial_state.color_equation == 0x8006U);
|
|
PP_EXPECT(h, initial_state.alpha_equation == 0x8008U);
|
|
|
|
PP_EXPECT(h, pp::renderer::gl::rgba8_internal_format() == 0x8058U);
|
|
PP_EXPECT(h, pp::renderer::gl::rgba16f_internal_format() == 0x881AU);
|
|
PP_EXPECT(h, pp::renderer::gl::rgba32f_internal_format() == 0x8814U);
|
|
PP_EXPECT(h, pp::renderer::gl::color_write_disabled() == 0U);
|
|
PP_EXPECT(h, pp::renderer::gl::color_write_enabled() == 1U);
|
|
PP_EXPECT(h, pp::renderer::gl::linear_texture_filter() == 0x2601U);
|
|
PP_EXPECT(h, pp::renderer::gl::linear_mipmap_linear_texture_filter() == 0x2703U);
|
|
PP_EXPECT(h, pp::renderer::gl::nearest_texture_filter() == 0x2600U);
|
|
PP_EXPECT(h, pp::renderer::gl::repeat_texture_wrap() == 0x2901U);
|
|
PP_EXPECT(h, pp::renderer::gl::clamp_to_edge_texture_wrap() == 0x812FU);
|
|
PP_EXPECT(h, pp::renderer::gl::clamp_to_border_texture_wrap() == 0x812DU);
|
|
PP_EXPECT(h, pp::renderer::gl::active_texture_unit(0U) == 0x84C0U);
|
|
PP_EXPECT(h, pp::renderer::gl::active_texture_unit(4U) == 0x84C4U);
|
|
}
|
|
|
|
void applies_app_initialization_state(pp::tests::Harness& h)
|
|
{
|
|
recorded_state_calls.clear();
|
|
|
|
const auto status = pp::renderer::gl::apply_panopainter_initial_state(
|
|
pp::renderer::gl::OpenGlStateDispatch {
|
|
.enable = record_enable,
|
|
.disable = record_disable,
|
|
.blend_func = record_blend_func,
|
|
.blend_equation_separate = record_blend_equation_separate,
|
|
});
|
|
|
|
PP_EXPECT(h, status.ok());
|
|
PP_EXPECT(h, recorded_state_calls.size() == 3U);
|
|
PP_EXPECT(h, recorded_state_calls[0].kind == RecordedOpenGlStateCall::Kind::disable);
|
|
PP_EXPECT(h, recorded_state_calls[0].first == 0x0B71U);
|
|
PP_EXPECT(h, recorded_state_calls[1].kind == RecordedOpenGlStateCall::Kind::blend_func);
|
|
PP_EXPECT(h, recorded_state_calls[1].first == 0x0302U);
|
|
PP_EXPECT(h, recorded_state_calls[1].second == 0x0303U);
|
|
PP_EXPECT(h, recorded_state_calls[2].kind == RecordedOpenGlStateCall::Kind::blend_equation_separate);
|
|
PP_EXPECT(h, recorded_state_calls[2].first == 0x8006U);
|
|
PP_EXPECT(h, recorded_state_calls[2].second == 0x8008U);
|
|
}
|
|
|
|
void rejects_incomplete_app_initialization_state_dispatch(pp::tests::Harness& h)
|
|
{
|
|
const auto status = pp::renderer::gl::apply_panopainter_initial_state(
|
|
pp::renderer::gl::OpenGlStateDispatch {
|
|
.enable = record_enable,
|
|
.disable = record_disable,
|
|
.blend_func = record_blend_func,
|
|
});
|
|
|
|
PP_EXPECT(h, !status.ok());
|
|
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void snapshots_legacy_gl_state(pp::tests::Harness& h)
|
|
{
|
|
recorded_integer_queries.clear();
|
|
recorded_float_queries.clear();
|
|
recorded_active_texture_calls.clear();
|
|
|
|
const auto result = pp::renderer::gl::snapshot_opengl_state(
|
|
pp::renderer::gl::OpenGlStateSnapshotDispatch {
|
|
.is_enabled = record_is_enabled,
|
|
.get_integer = record_get_integer,
|
|
.get_float = record_get_float,
|
|
.active_texture = record_active_texture,
|
|
});
|
|
|
|
PP_EXPECT(h, result.ok());
|
|
const auto& state = result.value();
|
|
PP_EXPECT(h, state.blend_enabled == 1U);
|
|
PP_EXPECT(h, state.depth_test_enabled == 0U);
|
|
PP_EXPECT(h, state.scissor_test_enabled == 1U);
|
|
PP_EXPECT(h, state.viewport[0] == 2);
|
|
PP_EXPECT(h, state.viewport[1] == 4);
|
|
PP_EXPECT(h, state.viewport[2] == 640);
|
|
PP_EXPECT(h, state.viewport[3] == 320);
|
|
PP_EXPECT(h, state.clear_color[0] == 0.25F);
|
|
PP_EXPECT(h, state.clear_color[1] == 0.5F);
|
|
PP_EXPECT(h, state.clear_color[2] == 0.75F);
|
|
PP_EXPECT(h, state.clear_color[3] == 1.0F);
|
|
PP_EXPECT(h, state.program == 42);
|
|
PP_EXPECT(h, state.draw_framebuffer == 7);
|
|
PP_EXPECT(h, state.read_framebuffer == 9);
|
|
PP_EXPECT(h, state.active_texture == 0x84C4);
|
|
PP_EXPECT(h, state.cube_map_binding == 88);
|
|
PP_EXPECT(h, state.texture_2d_bindings[0] == 101);
|
|
PP_EXPECT(h, state.texture_2d_bindings[9] == 110);
|
|
PP_EXPECT(h, state.sampler_bindings[0] == 201);
|
|
PP_EXPECT(h, state.sampler_bindings[9] == 210);
|
|
PP_EXPECT(h, recorded_float_queries.size() == 1U);
|
|
PP_EXPECT(h, recorded_active_texture_calls.size() == 10U);
|
|
PP_EXPECT(h, recorded_active_texture_calls[0] == 0x84C0U);
|
|
PP_EXPECT(h, recorded_active_texture_calls[9] == 0x84C9U);
|
|
}
|
|
|
|
void rejects_incomplete_gl_state_snapshot_dispatch(pp::tests::Harness& h)
|
|
{
|
|
const auto result = pp::renderer::gl::snapshot_opengl_state(
|
|
pp::renderer::gl::OpenGlStateSnapshotDispatch {
|
|
.is_enabled = record_is_enabled,
|
|
.get_integer = record_get_integer,
|
|
.get_float = record_get_float,
|
|
});
|
|
|
|
PP_EXPECT(h, !result.ok());
|
|
PP_EXPECT(h, result.status().code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void restores_legacy_gl_state(pp::tests::Harness& h)
|
|
{
|
|
recorded_state_calls.clear();
|
|
recorded_viewport_calls.clear();
|
|
recorded_clear_calls.clear();
|
|
recorded_active_texture_calls.clear();
|
|
recorded_binding_calls.clear();
|
|
|
|
pp::renderer::gl::OpenGlSavedState state {};
|
|
state.blend_enabled = 1U;
|
|
state.depth_test_enabled = 0U;
|
|
state.scissor_test_enabled = 1U;
|
|
state.viewport = { 3, 6, 800, 600 };
|
|
state.clear_color = { 0.1F, 0.2F, 0.3F, 0.4F };
|
|
state.program = 12;
|
|
state.draw_framebuffer = 21;
|
|
state.read_framebuffer = 22;
|
|
state.active_texture = 0x84C7;
|
|
state.cube_map_binding = 77;
|
|
for (std::size_t i = 0; i < state.texture_2d_bindings.size(); ++i) {
|
|
state.texture_2d_bindings[i] = 300 + static_cast<std::int32_t>(i);
|
|
state.sampler_bindings[i] = 400 + static_cast<std::int32_t>(i);
|
|
}
|
|
|
|
const auto status = pp::renderer::gl::restore_opengl_state(
|
|
state,
|
|
pp::renderer::gl::OpenGlStateRestoreDispatch {
|
|
.enable = record_enable,
|
|
.disable = record_disable,
|
|
.viewport = record_viewport,
|
|
.clear_color = record_clear_color,
|
|
.bind_framebuffer = record_bind_framebuffer,
|
|
.use_program = record_use_program,
|
|
.active_texture = record_active_texture,
|
|
.bind_texture = record_bind_texture,
|
|
.bind_sampler = record_bind_sampler,
|
|
});
|
|
|
|
PP_EXPECT(h, status.ok());
|
|
PP_EXPECT(h, recorded_state_calls.size() == 3U);
|
|
PP_EXPECT(h, recorded_state_calls[0].kind == RecordedOpenGlStateCall::Kind::enable);
|
|
PP_EXPECT(h, recorded_state_calls[0].first == 0x0BE2U);
|
|
PP_EXPECT(h, recorded_state_calls[1].kind == RecordedOpenGlStateCall::Kind::disable);
|
|
PP_EXPECT(h, recorded_state_calls[1].first == 0x0B71U);
|
|
PP_EXPECT(h, recorded_state_calls[2].kind == RecordedOpenGlStateCall::Kind::enable);
|
|
PP_EXPECT(h, recorded_state_calls[2].first == 0x0C11U);
|
|
PP_EXPECT(h, recorded_viewport_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_viewport_calls[0].width == 800);
|
|
PP_EXPECT(h, recorded_clear_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_clear_calls[0].color[2] == 0.3F);
|
|
PP_EXPECT(h, recorded_binding_calls.size() == 24U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].kind == RecordedOpenGlBindingCall::Kind::bind_framebuffer);
|
|
PP_EXPECT(h, recorded_binding_calls[0].first == 0x8CA9U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].second == 21U);
|
|
PP_EXPECT(h, recorded_binding_calls[1].kind == RecordedOpenGlBindingCall::Kind::bind_framebuffer);
|
|
PP_EXPECT(h, recorded_binding_calls[1].first == 0x8CA8U);
|
|
PP_EXPECT(h, recorded_binding_calls[1].second == 22U);
|
|
PP_EXPECT(h, recorded_binding_calls[2].kind == RecordedOpenGlBindingCall::Kind::use_program);
|
|
PP_EXPECT(h, recorded_binding_calls[2].first == 12U);
|
|
PP_EXPECT(h, recorded_active_texture_calls.size() == 11U);
|
|
PP_EXPECT(h, recorded_active_texture_calls[0] == 0x84C0U);
|
|
PP_EXPECT(h, recorded_active_texture_calls[9] == 0x84C9U);
|
|
PP_EXPECT(h, recorded_active_texture_calls[10] == 0x84C7U);
|
|
PP_EXPECT(h, recorded_binding_calls[3].kind == RecordedOpenGlBindingCall::Kind::bind_texture);
|
|
PP_EXPECT(h, recorded_binding_calls[3].first == 0x0DE1U);
|
|
PP_EXPECT(h, recorded_binding_calls[3].second == 300U);
|
|
PP_EXPECT(h, recorded_binding_calls[23].kind == RecordedOpenGlBindingCall::Kind::bind_texture);
|
|
PP_EXPECT(h, recorded_binding_calls[23].first == 0x8513U);
|
|
PP_EXPECT(h, recorded_binding_calls[23].second == 77U);
|
|
}
|
|
|
|
void rejects_incomplete_gl_state_restore_dispatch(pp::tests::Harness& h)
|
|
{
|
|
const auto status = pp::renderer::gl::restore_opengl_state(
|
|
pp::renderer::gl::OpenGlSavedState {},
|
|
pp::renderer::gl::OpenGlStateRestoreDispatch {
|
|
.enable = record_enable,
|
|
.disable = record_disable,
|
|
.viewport = record_viewport,
|
|
});
|
|
|
|
PP_EXPECT(h, !status.ok());
|
|
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void queries_app_runtime_info(pp::tests::Harness& h)
|
|
{
|
|
recorded_string_queries.clear();
|
|
|
|
const auto result = pp::renderer::gl::query_opengl_runtime_info(
|
|
pp::renderer::gl::OpenGlRuntimeInfoDispatch {
|
|
.get_string = record_string_query,
|
|
});
|
|
|
|
PP_EXPECT(h, result.ok());
|
|
PP_EXPECT(h, recorded_string_queries.size() == 4U);
|
|
PP_EXPECT(h, recorded_string_queries[0] == 0x1F02U);
|
|
PP_EXPECT(h, recorded_string_queries[1] == 0x1F00U);
|
|
PP_EXPECT(h, recorded_string_queries[2] == 0x1F01U);
|
|
PP_EXPECT(h, recorded_string_queries[3] == 0x8B8CU);
|
|
PP_EXPECT(h, std::strcmp(result.value().version, "test-version") == 0);
|
|
PP_EXPECT(h, std::strcmp(result.value().vendor, "test-vendor") == 0);
|
|
PP_EXPECT(h, std::strcmp(result.value().renderer, "test-renderer") == 0);
|
|
PP_EXPECT(h, std::strcmp(result.value().shading_language_version, "test-glsl") == 0);
|
|
}
|
|
|
|
void rejects_incomplete_app_runtime_info_dispatch(pp::tests::Harness& h)
|
|
{
|
|
const auto result = pp::renderer::gl::query_opengl_runtime_info(pp::renderer::gl::OpenGlRuntimeInfoDispatch {});
|
|
|
|
PP_EXPECT(h, !result.ok());
|
|
PP_EXPECT(h, result.status().code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void clears_app_default_target(pp::tests::Harness& h)
|
|
{
|
|
recorded_clear_calls.clear();
|
|
|
|
const auto clear = pp::renderer::gl::panopainter_default_clear();
|
|
PP_EXPECT(h, clear.color[0] == 0.1F);
|
|
PP_EXPECT(h, clear.color[1] == 0.1F);
|
|
PP_EXPECT(h, clear.color[2] == 0.1F);
|
|
PP_EXPECT(h, clear.color[3] == 1.0F);
|
|
PP_EXPECT(h, clear.mask == 0x00004000U);
|
|
|
|
const auto status = pp::renderer::gl::clear_panopainter_default_target(
|
|
pp::renderer::gl::OpenGlClearDispatch {
|
|
.clear_color = record_clear_color,
|
|
.clear = record_clear,
|
|
});
|
|
|
|
PP_EXPECT(h, status.ok());
|
|
PP_EXPECT(h, recorded_clear_calls.size() == 2U);
|
|
PP_EXPECT(h, recorded_clear_calls[0].color[0] == 0.1F);
|
|
PP_EXPECT(h, recorded_clear_calls[0].color[1] == 0.1F);
|
|
PP_EXPECT(h, recorded_clear_calls[0].color[2] == 0.1F);
|
|
PP_EXPECT(h, recorded_clear_calls[0].color[3] == 1.0F);
|
|
PP_EXPECT(h, recorded_clear_calls[0].mask == 0U);
|
|
PP_EXPECT(h, recorded_clear_calls[1].mask == 0x00004000U);
|
|
}
|
|
|
|
void rejects_incomplete_app_clear_dispatch(pp::tests::Harness& h)
|
|
{
|
|
const auto status = pp::renderer::gl::clear_panopainter_default_target(
|
|
pp::renderer::gl::OpenGlClearDispatch {
|
|
.clear_color = record_clear_color,
|
|
});
|
|
|
|
PP_EXPECT(h, !status.ok());
|
|
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void applies_viewport_dispatch(pp::tests::Harness& h)
|
|
{
|
|
recorded_viewport_calls.clear();
|
|
|
|
const auto status = pp::renderer::gl::apply_opengl_viewport(
|
|
pp::renderer::gl::OpenGlViewportRect {
|
|
.x = 8,
|
|
.y = 16,
|
|
.width = 1024,
|
|
.height = 512,
|
|
},
|
|
pp::renderer::gl::OpenGlViewportDispatch {
|
|
.viewport = record_viewport,
|
|
});
|
|
|
|
PP_EXPECT(h, status.ok());
|
|
PP_EXPECT(h, recorded_viewport_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_viewport_calls[0].x == 8);
|
|
PP_EXPECT(h, recorded_viewport_calls[0].y == 16);
|
|
PP_EXPECT(h, recorded_viewport_calls[0].width == 1024);
|
|
PP_EXPECT(h, recorded_viewport_calls[0].height == 512);
|
|
}
|
|
|
|
void rejects_incomplete_viewport_dispatch(pp::tests::Harness& h)
|
|
{
|
|
const auto status = pp::renderer::gl::apply_opengl_viewport(
|
|
pp::renderer::gl::OpenGlViewportRect {
|
|
.width = 1,
|
|
.height = 1,
|
|
},
|
|
pp::renderer::gl::OpenGlViewportDispatch {});
|
|
|
|
PP_EXPECT(h, !status.ok());
|
|
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void applies_scissor_dispatch(pp::tests::Harness& h)
|
|
{
|
|
recorded_state_calls.clear();
|
|
recorded_scissor_calls.clear();
|
|
|
|
const auto enabled_status = pp::renderer::gl::apply_opengl_scissor_rect(
|
|
pp::renderer::gl::OpenGlScissorRect {
|
|
.enabled = 1U,
|
|
.x = 4,
|
|
.y = 12,
|
|
.width = 320,
|
|
.height = 200,
|
|
},
|
|
pp::renderer::gl::OpenGlScissorDispatch {
|
|
.enable = record_enable,
|
|
.disable = record_disable,
|
|
.scissor = record_scissor,
|
|
});
|
|
|
|
const auto disabled_status = pp::renderer::gl::apply_opengl_scissor_rect(
|
|
pp::renderer::gl::OpenGlScissorRect {},
|
|
pp::renderer::gl::OpenGlScissorDispatch {
|
|
.enable = record_enable,
|
|
.disable = record_disable,
|
|
.scissor = record_scissor,
|
|
});
|
|
|
|
PP_EXPECT(h, enabled_status.ok());
|
|
PP_EXPECT(h, disabled_status.ok());
|
|
PP_EXPECT(h, recorded_state_calls.size() == 2U);
|
|
PP_EXPECT(h, recorded_state_calls[0].kind == RecordedOpenGlStateCall::Kind::enable);
|
|
PP_EXPECT(h, recorded_state_calls[0].first == 0x0C11U);
|
|
PP_EXPECT(h, recorded_state_calls[1].kind == RecordedOpenGlStateCall::Kind::disable);
|
|
PP_EXPECT(h, recorded_state_calls[1].first == 0x0C11U);
|
|
PP_EXPECT(h, recorded_scissor_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_scissor_calls[0].x == 4);
|
|
PP_EXPECT(h, recorded_scissor_calls[0].y == 12);
|
|
PP_EXPECT(h, recorded_scissor_calls[0].width == 320);
|
|
PP_EXPECT(h, recorded_scissor_calls[0].height == 200);
|
|
}
|
|
|
|
void rejects_incomplete_scissor_dispatch(pp::tests::Harness& h)
|
|
{
|
|
const auto status = pp::renderer::gl::apply_opengl_scissor_rect(
|
|
pp::renderer::gl::OpenGlScissorRect {
|
|
.enabled = 1U,
|
|
},
|
|
pp::renderer::gl::OpenGlScissorDispatch {
|
|
.enable = record_enable,
|
|
.disable = record_disable,
|
|
});
|
|
|
|
PP_EXPECT(h, !status.ok());
|
|
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void applies_scissor_test_dispatch(pp::tests::Harness& h)
|
|
{
|
|
recorded_state_calls.clear();
|
|
|
|
const auto enabled_status = pp::renderer::gl::apply_opengl_scissor_test(
|
|
true,
|
|
pp::renderer::gl::OpenGlScissorTestDispatch {
|
|
.enable = record_enable,
|
|
.disable = record_disable,
|
|
});
|
|
const auto disabled_status = pp::renderer::gl::apply_opengl_scissor_test(
|
|
false,
|
|
pp::renderer::gl::OpenGlScissorTestDispatch {
|
|
.enable = record_enable,
|
|
.disable = record_disable,
|
|
});
|
|
|
|
PP_EXPECT(h, enabled_status.ok());
|
|
PP_EXPECT(h, disabled_status.ok());
|
|
PP_EXPECT(h, recorded_state_calls.size() == 2U);
|
|
PP_EXPECT(h, recorded_state_calls[0].kind == RecordedOpenGlStateCall::Kind::enable);
|
|
PP_EXPECT(h, recorded_state_calls[0].first == 0x0C11U);
|
|
PP_EXPECT(h, recorded_state_calls[1].kind == RecordedOpenGlStateCall::Kind::disable);
|
|
PP_EXPECT(h, recorded_state_calls[1].first == 0x0C11U);
|
|
}
|
|
|
|
void rejects_incomplete_scissor_test_dispatch(pp::tests::Harness& h)
|
|
{
|
|
const auto status = pp::renderer::gl::apply_opengl_scissor_test(
|
|
true,
|
|
pp::renderer::gl::OpenGlScissorTestDispatch {
|
|
.enable = record_enable,
|
|
});
|
|
|
|
PP_EXPECT(h, !status.ok());
|
|
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void applies_generic_capability_dispatch(pp::tests::Harness& h)
|
|
{
|
|
recorded_state_calls.clear();
|
|
|
|
const auto enabled_status = pp::renderer::gl::apply_opengl_capability(
|
|
0x0BE2U,
|
|
true,
|
|
pp::renderer::gl::OpenGlCapabilityDispatch {
|
|
.enable = record_enable,
|
|
.disable = record_disable,
|
|
});
|
|
const auto disabled_status = pp::renderer::gl::apply_opengl_capability(
|
|
0x0B71U,
|
|
false,
|
|
pp::renderer::gl::OpenGlCapabilityDispatch {
|
|
.enable = record_enable,
|
|
.disable = record_disable,
|
|
});
|
|
|
|
PP_EXPECT(h, enabled_status.ok());
|
|
PP_EXPECT(h, disabled_status.ok());
|
|
PP_EXPECT(h, recorded_state_calls.size() == 2U);
|
|
PP_EXPECT(h, recorded_state_calls[0].kind == RecordedOpenGlStateCall::Kind::enable);
|
|
PP_EXPECT(h, recorded_state_calls[0].first == 0x0BE2U);
|
|
PP_EXPECT(h, recorded_state_calls[1].kind == RecordedOpenGlStateCall::Kind::disable);
|
|
PP_EXPECT(h, recorded_state_calls[1].first == 0x0B71U);
|
|
}
|
|
|
|
void rejects_incomplete_generic_capability_dispatch(pp::tests::Harness& h)
|
|
{
|
|
const auto status = pp::renderer::gl::apply_opengl_capability(
|
|
0x0BE2U,
|
|
true,
|
|
pp::renderer::gl::OpenGlCapabilityDispatch {
|
|
.enable = record_enable,
|
|
});
|
|
|
|
PP_EXPECT(h, !status.ok());
|
|
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void applies_buffer_clear_dispatch(pp::tests::Harness& h)
|
|
{
|
|
recorded_clear_calls.clear();
|
|
|
|
const auto status = pp::renderer::gl::clear_opengl_buffers(
|
|
0x00000100U,
|
|
pp::renderer::gl::OpenGlBufferClearDispatch {
|
|
.clear = record_clear,
|
|
});
|
|
|
|
PP_EXPECT(h, status.ok());
|
|
PP_EXPECT(h, recorded_clear_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_clear_calls[0].mask == 0x00000100U);
|
|
}
|
|
|
|
void rejects_incomplete_buffer_clear_dispatch(pp::tests::Harness& h)
|
|
{
|
|
const auto status = pp::renderer::gl::clear_opengl_buffers(
|
|
0x00000100U,
|
|
pp::renderer::gl::OpenGlBufferClearDispatch {});
|
|
|
|
PP_EXPECT(h, !status.ok());
|
|
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void allocates_texture_2d_through_dispatch(pp::tests::Harness& h)
|
|
{
|
|
recorded_generated_texture_counts.clear();
|
|
recorded_binding_calls.clear();
|
|
recorded_texture_image_calls.clear();
|
|
next_texture_id = 91U;
|
|
const std::array<std::uint8_t, 4> pixels { 1U, 2U, 3U, 4U };
|
|
|
|
const auto texture = pp::renderer::gl::allocate_opengl_texture_2d(
|
|
pp::renderer::gl::OpenGlTexture2DAllocation {
|
|
.width = 8,
|
|
.height = 4,
|
|
.internal_format = 0x8058,
|
|
.pixel_format = 0x1908U,
|
|
.component_type = 0x1401U,
|
|
.data = pixels.data(),
|
|
},
|
|
pp::renderer::gl::OpenGlTexture2DAllocationDispatch {
|
|
.gen_textures = record_gen_textures,
|
|
.bind_texture = record_bind_texture,
|
|
.tex_image_2d = record_tex_image_2d,
|
|
});
|
|
|
|
PP_EXPECT(h, texture.ok());
|
|
PP_EXPECT(h, texture.value() == 91U);
|
|
PP_EXPECT(h, recorded_generated_texture_counts.size() == 1U);
|
|
PP_EXPECT(h, recorded_generated_texture_counts[0] == 1U);
|
|
PP_EXPECT(h, recorded_binding_calls.size() == 2U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].kind == RecordedOpenGlBindingCall::Kind::bind_texture);
|
|
PP_EXPECT(h, recorded_binding_calls[0].first == 0x0DE1U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].second == 91U);
|
|
PP_EXPECT(h, recorded_binding_calls[1].second == 0U);
|
|
PP_EXPECT(h, recorded_texture_image_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_texture_image_calls[0].target == 0x0DE1U);
|
|
PP_EXPECT(h, recorded_texture_image_calls[0].width == 8);
|
|
PP_EXPECT(h, recorded_texture_image_calls[0].height == 4);
|
|
PP_EXPECT(h, recorded_texture_image_calls[0].data == pixels.data());
|
|
}
|
|
|
|
void rejects_invalid_texture_2d_allocation(pp::tests::Harness& h)
|
|
{
|
|
const auto missing_dispatch = pp::renderer::gl::allocate_opengl_texture_2d(
|
|
pp::renderer::gl::OpenGlTexture2DAllocation {
|
|
.width = 1,
|
|
.height = 1,
|
|
.internal_format = 0x8058,
|
|
.pixel_format = 0x1908U,
|
|
.component_type = 0x1401U,
|
|
},
|
|
pp::renderer::gl::OpenGlTexture2DAllocationDispatch {
|
|
.gen_textures = record_gen_textures,
|
|
.bind_texture = record_bind_texture,
|
|
});
|
|
const auto invalid_dimensions = pp::renderer::gl::allocate_opengl_texture_2d(
|
|
pp::renderer::gl::OpenGlTexture2DAllocation {
|
|
.width = 0,
|
|
.height = 1,
|
|
.internal_format = 0x8058,
|
|
.pixel_format = 0x1908U,
|
|
.component_type = 0x1401U,
|
|
},
|
|
pp::renderer::gl::OpenGlTexture2DAllocationDispatch {
|
|
.gen_textures = record_gen_textures,
|
|
.bind_texture = record_bind_texture,
|
|
.tex_image_2d = record_tex_image_2d,
|
|
});
|
|
|
|
PP_EXPECT(h, !missing_dispatch.ok());
|
|
PP_EXPECT(h, missing_dispatch.status().code == pp::foundation::StatusCode::invalid_argument);
|
|
PP_EXPECT(h, !invalid_dimensions.ok());
|
|
PP_EXPECT(h, invalid_dimensions.status().code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void deletes_and_binds_texture_2d_through_dispatch(pp::tests::Harness& h)
|
|
{
|
|
recorded_deleted_textures.clear();
|
|
recorded_binding_calls.clear();
|
|
|
|
const auto delete_status = pp::renderer::gl::delete_opengl_texture_2d(
|
|
27U,
|
|
pp::renderer::gl::OpenGlTexture2DDeleteDispatch {
|
|
.delete_textures = record_delete_textures,
|
|
});
|
|
const auto bind_status = pp::renderer::gl::bind_opengl_texture_2d(
|
|
27U,
|
|
pp::renderer::gl::OpenGlTexture2DBindDispatch {
|
|
.bind_texture = record_bind_texture,
|
|
});
|
|
|
|
PP_EXPECT(h, delete_status.ok());
|
|
PP_EXPECT(h, recorded_deleted_textures.size() == 1U);
|
|
PP_EXPECT(h, recorded_deleted_textures[0] == 27U);
|
|
PP_EXPECT(h, bind_status.ok());
|
|
PP_EXPECT(h, recorded_binding_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].first == 0x0DE1U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].second == 27U);
|
|
}
|
|
|
|
void updates_texture_2d_through_dispatch(pp::tests::Harness& h)
|
|
{
|
|
recorded_binding_calls.clear();
|
|
recorded_texture_image_calls.clear();
|
|
const std::array<std::uint8_t, 4> pixels { 9U, 8U, 7U, 6U };
|
|
|
|
const auto status = pp::renderer::gl::update_opengl_texture_2d(
|
|
pp::renderer::gl::OpenGlTexture2DUpdate {
|
|
.texture_id = 31U,
|
|
.width = 2,
|
|
.height = 2,
|
|
.pixel_format = 0x1908U,
|
|
.component_type = 0x1401U,
|
|
.data = pixels.data(),
|
|
},
|
|
pp::renderer::gl::OpenGlTexture2DUpdateDispatch {
|
|
.bind_texture = record_bind_texture,
|
|
.tex_sub_image_2d = record_tex_sub_image_2d,
|
|
});
|
|
|
|
PP_EXPECT(h, status.ok());
|
|
PP_EXPECT(h, recorded_binding_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].second == 31U);
|
|
PP_EXPECT(h, recorded_texture_image_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_texture_image_calls[0].sub_image);
|
|
PP_EXPECT(h, recorded_texture_image_calls[0].width == 2);
|
|
PP_EXPECT(h, recorded_texture_image_calls[0].height == 2);
|
|
PP_EXPECT(h, recorded_texture_image_calls[0].data == pixels.data());
|
|
}
|
|
|
|
void generates_texture_2d_mipmaps_through_dispatch(pp::tests::Harness& h)
|
|
{
|
|
recorded_binding_calls.clear();
|
|
recorded_mipmap_targets.clear();
|
|
|
|
const auto status = pp::renderer::gl::generate_opengl_texture_2d_mipmaps(
|
|
41U,
|
|
pp::renderer::gl::OpenGlTexture2DMipmapDispatch {
|
|
.bind_texture = record_bind_texture,
|
|
.generate_mipmap = record_generate_mipmap,
|
|
});
|
|
|
|
PP_EXPECT(h, status.ok());
|
|
PP_EXPECT(h, recorded_binding_calls.size() == 2U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].second == 41U);
|
|
PP_EXPECT(h, recorded_binding_calls[1].second == 0U);
|
|
PP_EXPECT(h, recorded_mipmap_targets.size() == 1U);
|
|
PP_EXPECT(h, recorded_mipmap_targets[0] == 0x0DE1U);
|
|
}
|
|
|
|
void reads_back_texture_2d_through_framebuffer_dispatch(pp::tests::Harness& h)
|
|
{
|
|
recorded_generated_framebuffer_counts.clear();
|
|
recorded_deleted_framebuffers.clear();
|
|
recorded_binding_calls.clear();
|
|
recorded_framebuffer_attachment_calls.clear();
|
|
recorded_framebuffer_status_queries.clear();
|
|
recorded_read_pixels_calls.clear();
|
|
next_framebuffer_id = 44U;
|
|
configured_framebuffer_status = 0x8CD5U;
|
|
std::array<std::uint8_t, 16> pixels {};
|
|
|
|
const auto result = pp::renderer::gl::readback_opengl_texture_2d(
|
|
pp::renderer::gl::OpenGlTexture2DReadback {
|
|
.texture_id = 56U,
|
|
.width = 2,
|
|
.height = 2,
|
|
.format = pp::renderer::gl::rgba8_readback_format(),
|
|
.pixels = pixels.data(),
|
|
},
|
|
pp::renderer::gl::OpenGlTexture2DReadbackDispatch {
|
|
.bind_texture = record_bind_texture,
|
|
.gen_framebuffers = record_gen_framebuffers,
|
|
.get_integer = record_get_integer,
|
|
.bind_framebuffer = record_bind_framebuffer,
|
|
.framebuffer_texture_2d = record_framebuffer_texture_2d,
|
|
.check_framebuffer_status = record_check_framebuffer_status,
|
|
.read_pixels = record_read_pixels,
|
|
.delete_framebuffers = record_delete_framebuffers,
|
|
});
|
|
|
|
PP_EXPECT(h, result.ok());
|
|
PP_EXPECT(h, result.value().pixels_read);
|
|
PP_EXPECT(h, result.value().framebuffer_status == 0x8CD5U);
|
|
PP_EXPECT(h, recorded_generated_framebuffer_counts.size() == 1U);
|
|
PP_EXPECT(h, recorded_generated_framebuffer_counts[0] == 1U);
|
|
PP_EXPECT(h, recorded_binding_calls.size() == 3U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].kind == RecordedOpenGlBindingCall::Kind::bind_texture);
|
|
PP_EXPECT(h, recorded_binding_calls[0].second == 56U);
|
|
PP_EXPECT(h, recorded_binding_calls[1].kind == RecordedOpenGlBindingCall::Kind::bind_framebuffer);
|
|
PP_EXPECT(h, recorded_binding_calls[1].first == 0x8D40U);
|
|
PP_EXPECT(h, recorded_binding_calls[1].second == 44U);
|
|
PP_EXPECT(h, recorded_binding_calls[2].kind == RecordedOpenGlBindingCall::Kind::bind_framebuffer);
|
|
PP_EXPECT(h, recorded_binding_calls[2].second == 7U);
|
|
PP_EXPECT(h, recorded_framebuffer_attachment_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_framebuffer_attachment_calls[0].attachment == 0x8CE0U);
|
|
PP_EXPECT(h, recorded_framebuffer_attachment_calls[0].texture == 56U);
|
|
PP_EXPECT(h, recorded_read_pixels_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_read_pixels_calls[0].pixels == pixels.data());
|
|
PP_EXPECT(h, recorded_deleted_framebuffers.size() == 1U);
|
|
PP_EXPECT(h, recorded_deleted_framebuffers[0] == 44U);
|
|
}
|
|
|
|
void reports_incomplete_texture_2d_readback_framebuffer(pp::tests::Harness& h)
|
|
{
|
|
recorded_deleted_framebuffers.clear();
|
|
recorded_read_pixels_calls.clear();
|
|
next_framebuffer_id = 45U;
|
|
configured_framebuffer_status = 0x8CD6U;
|
|
std::array<std::uint8_t, 16> pixels {};
|
|
|
|
const auto result = pp::renderer::gl::readback_opengl_texture_2d(
|
|
pp::renderer::gl::OpenGlTexture2DReadback {
|
|
.texture_id = 57U,
|
|
.width = 2,
|
|
.height = 2,
|
|
.format = pp::renderer::gl::rgba8_readback_format(),
|
|
.pixels = pixels.data(),
|
|
},
|
|
pp::renderer::gl::OpenGlTexture2DReadbackDispatch {
|
|
.bind_texture = record_bind_texture,
|
|
.gen_framebuffers = record_gen_framebuffers,
|
|
.get_integer = record_get_integer,
|
|
.bind_framebuffer = record_bind_framebuffer,
|
|
.framebuffer_texture_2d = record_framebuffer_texture_2d,
|
|
.check_framebuffer_status = record_check_framebuffer_status,
|
|
.read_pixels = record_read_pixels,
|
|
.delete_framebuffers = record_delete_framebuffers,
|
|
});
|
|
|
|
PP_EXPECT(h, result.ok());
|
|
PP_EXPECT(h, !result.value().pixels_read);
|
|
PP_EXPECT(h, result.value().framebuffer_status == 0x8CD6U);
|
|
PP_EXPECT(h, recorded_read_pixels_calls.empty());
|
|
PP_EXPECT(h, recorded_deleted_framebuffers.back() == 45U);
|
|
}
|
|
|
|
void rejects_incomplete_texture_2d_readback_dispatch(pp::tests::Harness& h)
|
|
{
|
|
std::array<std::uint8_t, 4> pixels {};
|
|
const auto result = pp::renderer::gl::readback_opengl_texture_2d(
|
|
pp::renderer::gl::OpenGlTexture2DReadback {
|
|
.texture_id = 1U,
|
|
.width = 1,
|
|
.height = 1,
|
|
.format = pp::renderer::gl::rgba8_readback_format(),
|
|
.pixels = pixels.data(),
|
|
},
|
|
pp::renderer::gl::OpenGlTexture2DReadbackDispatch {
|
|
.bind_texture = record_bind_texture,
|
|
.gen_framebuffers = record_gen_framebuffers,
|
|
});
|
|
|
|
PP_EXPECT(h, !result.ok());
|
|
PP_EXPECT(h, result.status().code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void blits_framebuffers_through_dispatch(pp::tests::Harness& h)
|
|
{
|
|
recorded_integer_queries.clear();
|
|
recorded_binding_calls.clear();
|
|
recorded_blit_framebuffer_calls.clear();
|
|
|
|
const auto status = pp::renderer::gl::blit_opengl_framebuffer(
|
|
pp::renderer::gl::OpenGlFramebufferBlit {
|
|
.source_framebuffer = 13U,
|
|
.destination_framebuffer = 17U,
|
|
.source_rect = pp::renderer::gl::OpenGlFramebufferRect {
|
|
.x0 = 1,
|
|
.y0 = 2,
|
|
.x1 = 65,
|
|
.y1 = 34,
|
|
},
|
|
.destination_rect = pp::renderer::gl::OpenGlFramebufferRect {
|
|
.x0 = 3,
|
|
.y0 = 4,
|
|
.x1 = 131,
|
|
.y1 = 68,
|
|
},
|
|
.mask = 0x00004000U,
|
|
.filter = 0x2601U,
|
|
},
|
|
pp::renderer::gl::OpenGlFramebufferBlitDispatch {
|
|
.get_integer = record_get_integer,
|
|
.bind_framebuffer = record_bind_framebuffer,
|
|
.blit_framebuffer = record_blit_framebuffer,
|
|
});
|
|
|
|
PP_EXPECT(h, status.ok());
|
|
PP_EXPECT(h, recorded_integer_queries.size() == 2U);
|
|
PP_EXPECT(h, recorded_integer_queries[0] == 0x8CA6U);
|
|
PP_EXPECT(h, recorded_integer_queries[1] == 0x8CAAU);
|
|
PP_EXPECT(h, recorded_binding_calls.size() == 4U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].kind == RecordedOpenGlBindingCall::Kind::bind_framebuffer);
|
|
PP_EXPECT(h, recorded_binding_calls[0].first == 0x8CA9U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].second == 17U);
|
|
PP_EXPECT(h, recorded_binding_calls[1].first == 0x8CA8U);
|
|
PP_EXPECT(h, recorded_binding_calls[1].second == 13U);
|
|
PP_EXPECT(h, recorded_binding_calls[2].first == 0x8CA9U);
|
|
PP_EXPECT(h, recorded_binding_calls[2].second == 7U);
|
|
PP_EXPECT(h, recorded_binding_calls[3].first == 0x8CA8U);
|
|
PP_EXPECT(h, recorded_binding_calls[3].second == 9U);
|
|
PP_EXPECT(h, recorded_blit_framebuffer_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_blit_framebuffer_calls[0].source_x0 == 1);
|
|
PP_EXPECT(h, recorded_blit_framebuffer_calls[0].source_y1 == 34);
|
|
PP_EXPECT(h, recorded_blit_framebuffer_calls[0].destination_x1 == 131);
|
|
PP_EXPECT(h, recorded_blit_framebuffer_calls[0].mask == 0x00004000U);
|
|
PP_EXPECT(h, recorded_blit_framebuffer_calls[0].filter == 0x2601U);
|
|
}
|
|
|
|
void rejects_invalid_framebuffer_blits(pp::tests::Harness& h)
|
|
{
|
|
const auto missing_dispatch = pp::renderer::gl::blit_opengl_framebuffer(
|
|
pp::renderer::gl::OpenGlFramebufferBlit {
|
|
.source_rect = pp::renderer::gl::OpenGlFramebufferRect { .x1 = 1, .y1 = 1 },
|
|
.destination_rect = pp::renderer::gl::OpenGlFramebufferRect { .x1 = 1, .y1 = 1 },
|
|
.mask = 0x00004000U,
|
|
.filter = 0x2601U,
|
|
},
|
|
pp::renderer::gl::OpenGlFramebufferBlitDispatch {
|
|
.get_integer = record_get_integer,
|
|
.bind_framebuffer = record_bind_framebuffer,
|
|
});
|
|
const auto empty_source = pp::renderer::gl::blit_opengl_framebuffer(
|
|
pp::renderer::gl::OpenGlFramebufferBlit {
|
|
.source_rect = pp::renderer::gl::OpenGlFramebufferRect { .x1 = 0, .y1 = 1 },
|
|
.destination_rect = pp::renderer::gl::OpenGlFramebufferRect { .x1 = 1, .y1 = 1 },
|
|
.mask = 0x00004000U,
|
|
.filter = 0x2601U,
|
|
},
|
|
pp::renderer::gl::OpenGlFramebufferBlitDispatch {
|
|
.get_integer = record_get_integer,
|
|
.bind_framebuffer = record_bind_framebuffer,
|
|
.blit_framebuffer = record_blit_framebuffer,
|
|
});
|
|
|
|
PP_EXPECT(h, !missing_dispatch.ok());
|
|
PP_EXPECT(h, missing_dispatch.code == pp::foundation::StatusCode::invalid_argument);
|
|
PP_EXPECT(h, !empty_source.ok());
|
|
PP_EXPECT(h, empty_source.code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void reads_back_framebuffer_through_dispatch(pp::tests::Harness& h)
|
|
{
|
|
recorded_integer_queries.clear();
|
|
recorded_binding_calls.clear();
|
|
recorded_read_pixels_calls.clear();
|
|
std::array<std::uint8_t, 16> pixels {};
|
|
|
|
const auto status = pp::renderer::gl::readback_opengl_framebuffer(
|
|
pp::renderer::gl::OpenGlFramebufferReadback {
|
|
.framebuffer = 23U,
|
|
.x = 2,
|
|
.y = 3,
|
|
.width = 4,
|
|
.height = 5,
|
|
.format = pp::renderer::gl::rgba8_readback_format(),
|
|
.pixels = pixels.data(),
|
|
},
|
|
pp::renderer::gl::OpenGlFramebufferReadbackDispatch {
|
|
.get_integer = record_get_integer,
|
|
.bind_framebuffer = record_bind_framebuffer,
|
|
.read_pixels = record_read_pixels,
|
|
});
|
|
|
|
PP_EXPECT(h, status.ok());
|
|
PP_EXPECT(h, recorded_integer_queries.size() == 1U);
|
|
PP_EXPECT(h, recorded_integer_queries[0] == 0x8CAAU);
|
|
PP_EXPECT(h, recorded_binding_calls.size() == 2U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].first == 0x8CA8U);
|
|
PP_EXPECT(h, recorded_binding_calls[0].second == 23U);
|
|
PP_EXPECT(h, recorded_binding_calls[1].first == 0x8CA8U);
|
|
PP_EXPECT(h, recorded_binding_calls[1].second == 9U);
|
|
PP_EXPECT(h, recorded_read_pixels_calls.size() == 1U);
|
|
PP_EXPECT(h, recorded_read_pixels_calls[0].x == 2);
|
|
PP_EXPECT(h, recorded_read_pixels_calls[0].y == 3);
|
|
PP_EXPECT(h, recorded_read_pixels_calls[0].width == 4);
|
|
PP_EXPECT(h, recorded_read_pixels_calls[0].height == 5);
|
|
PP_EXPECT(h, recorded_read_pixels_calls[0].pixels == pixels.data());
|
|
}
|
|
|
|
void rejects_invalid_framebuffer_readbacks(pp::tests::Harness& h)
|
|
{
|
|
std::array<std::uint8_t, 4> pixels {};
|
|
const auto missing_dispatch = pp::renderer::gl::readback_opengl_framebuffer(
|
|
pp::renderer::gl::OpenGlFramebufferReadback {
|
|
.width = 1,
|
|
.height = 1,
|
|
.format = pp::renderer::gl::rgba8_readback_format(),
|
|
.pixels = pixels.data(),
|
|
},
|
|
pp::renderer::gl::OpenGlFramebufferReadbackDispatch {
|
|
.get_integer = record_get_integer,
|
|
.bind_framebuffer = record_bind_framebuffer,
|
|
});
|
|
const auto missing_pixels = pp::renderer::gl::readback_opengl_framebuffer(
|
|
pp::renderer::gl::OpenGlFramebufferReadback {
|
|
.width = 1,
|
|
.height = 1,
|
|
.format = pp::renderer::gl::rgba8_readback_format(),
|
|
},
|
|
pp::renderer::gl::OpenGlFramebufferReadbackDispatch {
|
|
.get_integer = record_get_integer,
|
|
.bind_framebuffer = record_bind_framebuffer,
|
|
.read_pixels = record_read_pixels,
|
|
});
|
|
|
|
PP_EXPECT(h, !missing_dispatch.ok());
|
|
PP_EXPECT(h, missing_dispatch.code == pp::foundation::StatusCode::invalid_argument);
|
|
PP_EXPECT(h, !missing_pixels.ok());
|
|
PP_EXPECT(h, missing_pixels.code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void maps_renderer_viewports_and_scissors(pp::tests::Harness& h)
|
|
{
|
|
const auto viewport = pp::renderer::gl::viewport_for_renderer_viewport(
|
|
pp::renderer::Viewport {
|
|
.x = 4,
|
|
.y = 8,
|
|
.width = 640U,
|
|
.height = 320U,
|
|
.min_depth = 0.25F,
|
|
.max_depth = 0.75F,
|
|
});
|
|
const auto disabled_scissor = pp::renderer::gl::scissor_rect_for_renderer_scissor(
|
|
pp::renderer::ScissorRect {});
|
|
const auto enabled_scissor = pp::renderer::gl::scissor_rect_for_renderer_scissor(
|
|
pp::renderer::ScissorRect {
|
|
.enabled = true,
|
|
.x = 12,
|
|
.y = 16,
|
|
.width = 128U,
|
|
.height = 64U,
|
|
});
|
|
|
|
PP_EXPECT(h, viewport.x == 4);
|
|
PP_EXPECT(h, viewport.y == 8);
|
|
PP_EXPECT(h, viewport.width == 640);
|
|
PP_EXPECT(h, viewport.height == 320);
|
|
PP_EXPECT(h, viewport.min_depth == 0.25F);
|
|
PP_EXPECT(h, viewport.max_depth == 0.75F);
|
|
PP_EXPECT(h, disabled_scissor.enabled == 0U);
|
|
PP_EXPECT(h, disabled_scissor.width == 0);
|
|
PP_EXPECT(h, disabled_scissor.height == 0);
|
|
PP_EXPECT(h, enabled_scissor.enabled == 1U);
|
|
PP_EXPECT(h, enabled_scissor.x == 12);
|
|
PP_EXPECT(h, enabled_scissor.y == 16);
|
|
PP_EXPECT(h, enabled_scissor.width == 128);
|
|
PP_EXPECT(h, enabled_scissor.height == 64);
|
|
}
|
|
|
|
void maps_renderer_blend_state_tokens(pp::tests::Harness& h)
|
|
{
|
|
const auto zero = pp::renderer::gl::blend_factor_for_renderer_factor(pp::renderer::BlendFactor::zero);
|
|
const auto one = pp::renderer::gl::blend_factor_for_renderer_factor(pp::renderer::BlendFactor::one);
|
|
const auto source_alpha = pp::renderer::gl::blend_factor_for_renderer_factor(
|
|
pp::renderer::BlendFactor::source_alpha);
|
|
const auto one_minus_source_alpha = pp::renderer::gl::blend_factor_for_renderer_factor(
|
|
pp::renderer::BlendFactor::one_minus_source_alpha);
|
|
const auto destination_alpha = pp::renderer::gl::blend_factor_for_renderer_factor(
|
|
pp::renderer::BlendFactor::destination_alpha);
|
|
const auto one_minus_destination_alpha = pp::renderer::gl::blend_factor_for_renderer_factor(
|
|
pp::renderer::BlendFactor::one_minus_destination_alpha);
|
|
const auto invalid_factor = pp::renderer::gl::blend_factor_for_renderer_factor(
|
|
static_cast<pp::renderer::BlendFactor>(255U));
|
|
|
|
const auto add = pp::renderer::gl::blend_equation_for_renderer_op(pp::renderer::BlendOp::add);
|
|
const auto subtract = pp::renderer::gl::blend_equation_for_renderer_op(pp::renderer::BlendOp::subtract);
|
|
const auto reverse_subtract = pp::renderer::gl::blend_equation_for_renderer_op(
|
|
pp::renderer::BlendOp::reverse_subtract);
|
|
const auto invalid_op = pp::renderer::gl::blend_equation_for_renderer_op(
|
|
static_cast<pp::renderer::BlendOp>(255U));
|
|
|
|
PP_EXPECT(h, zero.supported);
|
|
PP_EXPECT(h, zero.value == 0U);
|
|
PP_EXPECT(h, one.supported);
|
|
PP_EXPECT(h, one.value == 1U);
|
|
PP_EXPECT(h, source_alpha.supported);
|
|
PP_EXPECT(h, source_alpha.value == 0x0302U);
|
|
PP_EXPECT(h, one_minus_source_alpha.supported);
|
|
PP_EXPECT(h, one_minus_source_alpha.value == 0x0303U);
|
|
PP_EXPECT(h, destination_alpha.supported);
|
|
PP_EXPECT(h, destination_alpha.value == 0x0304U);
|
|
PP_EXPECT(h, one_minus_destination_alpha.supported);
|
|
PP_EXPECT(h, one_minus_destination_alpha.value == 0x0305U);
|
|
PP_EXPECT(h, !invalid_factor.supported);
|
|
PP_EXPECT(h, invalid_factor.value == 0U);
|
|
|
|
PP_EXPECT(h, add.supported);
|
|
PP_EXPECT(h, add.value == 0x8006U);
|
|
PP_EXPECT(h, subtract.supported);
|
|
PP_EXPECT(h, subtract.value == 0x800AU);
|
|
PP_EXPECT(h, reverse_subtract.supported);
|
|
PP_EXPECT(h, reverse_subtract.value == 0x800BU);
|
|
PP_EXPECT(h, !invalid_op.supported);
|
|
PP_EXPECT(h, invalid_op.value == 0U);
|
|
}
|
|
|
|
void maps_renderer_color_write_masks(pp::tests::Harness& h)
|
|
{
|
|
const auto default_mask = pp::renderer::gl::color_write_mask_for_renderer_blend_state(
|
|
pp::renderer::BlendState {});
|
|
const auto mixed_mask = pp::renderer::gl::color_write_mask_for_renderer_blend_state(
|
|
pp::renderer::BlendState { .write_r = true, .write_g = false, .write_b = true, .write_a = false });
|
|
const auto disabled_mask = pp::renderer::gl::color_write_mask_for_renderer_blend_state(
|
|
pp::renderer::BlendState { .write_r = false, .write_g = false, .write_b = false, .write_a = false });
|
|
|
|
PP_EXPECT(h, default_mask.r == 1U);
|
|
PP_EXPECT(h, default_mask.g == 1U);
|
|
PP_EXPECT(h, default_mask.b == 1U);
|
|
PP_EXPECT(h, default_mask.a == 1U);
|
|
PP_EXPECT(h, mixed_mask.r == 1U);
|
|
PP_EXPECT(h, mixed_mask.g == 0U);
|
|
PP_EXPECT(h, mixed_mask.b == 1U);
|
|
PP_EXPECT(h, mixed_mask.a == 0U);
|
|
PP_EXPECT(h, disabled_mask.r == 0U);
|
|
PP_EXPECT(h, disabled_mask.g == 0U);
|
|
PP_EXPECT(h, disabled_mask.b == 0U);
|
|
PP_EXPECT(h, disabled_mask.a == 0U);
|
|
}
|
|
|
|
void maps_renderer_blend_states(pp::tests::Harness& h)
|
|
{
|
|
const auto disabled = pp::renderer::gl::blend_state_for_renderer_blend_state(
|
|
pp::renderer::BlendState {});
|
|
const auto alpha_blend = pp::renderer::gl::blend_state_for_renderer_blend_state(
|
|
pp::renderer::BlendState {
|
|
.enabled = true,
|
|
.source_color = pp::renderer::BlendFactor::source_alpha,
|
|
.destination_color = pp::renderer::BlendFactor::one_minus_source_alpha,
|
|
.color_op = pp::renderer::BlendOp::add,
|
|
.source_alpha = pp::renderer::BlendFactor::one,
|
|
.destination_alpha = pp::renderer::BlendFactor::one_minus_destination_alpha,
|
|
.alpha_op = pp::renderer::BlendOp::reverse_subtract,
|
|
.write_r = true,
|
|
.write_g = false,
|
|
.write_b = true,
|
|
.write_a = false,
|
|
});
|
|
const auto invalid_factor = pp::renderer::gl::blend_state_for_renderer_blend_state(
|
|
pp::renderer::BlendState {
|
|
.enabled = true,
|
|
.source_color = static_cast<pp::renderer::BlendFactor>(255U),
|
|
});
|
|
const auto invalid_op = pp::renderer::gl::blend_state_for_renderer_blend_state(
|
|
pp::renderer::BlendState {
|
|
.enabled = true,
|
|
.color_op = static_cast<pp::renderer::BlendOp>(255U),
|
|
});
|
|
|
|
PP_EXPECT(h, disabled.supported);
|
|
PP_EXPECT(h, disabled.enabled == 0U);
|
|
PP_EXPECT(h, disabled.source_color_factor == 1U);
|
|
PP_EXPECT(h, disabled.destination_color_factor == 0U);
|
|
PP_EXPECT(h, disabled.color_equation == 0x8006U);
|
|
PP_EXPECT(h, disabled.source_alpha_factor == 1U);
|
|
PP_EXPECT(h, disabled.destination_alpha_factor == 0U);
|
|
PP_EXPECT(h, disabled.alpha_equation == 0x8006U);
|
|
PP_EXPECT(h, disabled.color_write_mask.r == 1U);
|
|
PP_EXPECT(h, disabled.color_write_mask.g == 1U);
|
|
PP_EXPECT(h, disabled.color_write_mask.b == 1U);
|
|
PP_EXPECT(h, disabled.color_write_mask.a == 1U);
|
|
|
|
PP_EXPECT(h, alpha_blend.supported);
|
|
PP_EXPECT(h, alpha_blend.enabled == 1U);
|
|
PP_EXPECT(h, alpha_blend.source_color_factor == 0x0302U);
|
|
PP_EXPECT(h, alpha_blend.destination_color_factor == 0x0303U);
|
|
PP_EXPECT(h, alpha_blend.color_equation == 0x8006U);
|
|
PP_EXPECT(h, alpha_blend.source_alpha_factor == 1U);
|
|
PP_EXPECT(h, alpha_blend.destination_alpha_factor == 0x0305U);
|
|
PP_EXPECT(h, alpha_blend.alpha_equation == 0x800BU);
|
|
PP_EXPECT(h, alpha_blend.color_write_mask.r == 1U);
|
|
PP_EXPECT(h, alpha_blend.color_write_mask.g == 0U);
|
|
PP_EXPECT(h, alpha_blend.color_write_mask.b == 1U);
|
|
PP_EXPECT(h, alpha_blend.color_write_mask.a == 0U);
|
|
|
|
PP_EXPECT(h, !invalid_factor.supported);
|
|
PP_EXPECT(h, invalid_factor.enabled == 1U);
|
|
PP_EXPECT(h, invalid_factor.source_color_factor == 0U);
|
|
PP_EXPECT(h, !invalid_op.supported);
|
|
PP_EXPECT(h, invalid_op.color_equation == 0U);
|
|
}
|
|
|
|
void maps_renderer_depth_compare_tokens(pp::tests::Harness& h)
|
|
{
|
|
const auto never = pp::renderer::gl::compare_function_for_renderer_compare_op(
|
|
pp::renderer::CompareOp::never);
|
|
const auto less = pp::renderer::gl::compare_function_for_renderer_compare_op(
|
|
pp::renderer::CompareOp::less);
|
|
const auto equal = pp::renderer::gl::compare_function_for_renderer_compare_op(
|
|
pp::renderer::CompareOp::equal);
|
|
const auto less_or_equal = pp::renderer::gl::compare_function_for_renderer_compare_op(
|
|
pp::renderer::CompareOp::less_or_equal);
|
|
const auto greater = pp::renderer::gl::compare_function_for_renderer_compare_op(
|
|
pp::renderer::CompareOp::greater);
|
|
const auto not_equal = pp::renderer::gl::compare_function_for_renderer_compare_op(
|
|
pp::renderer::CompareOp::not_equal);
|
|
const auto greater_or_equal = pp::renderer::gl::compare_function_for_renderer_compare_op(
|
|
pp::renderer::CompareOp::greater_or_equal);
|
|
const auto always = pp::renderer::gl::compare_function_for_renderer_compare_op(
|
|
pp::renderer::CompareOp::always);
|
|
const auto invalid = pp::renderer::gl::compare_function_for_renderer_compare_op(
|
|
static_cast<pp::renderer::CompareOp>(255U));
|
|
|
|
PP_EXPECT(h, never.supported);
|
|
PP_EXPECT(h, never.value == 0x0200U);
|
|
PP_EXPECT(h, less.supported);
|
|
PP_EXPECT(h, less.value == 0x0201U);
|
|
PP_EXPECT(h, equal.supported);
|
|
PP_EXPECT(h, equal.value == 0x0202U);
|
|
PP_EXPECT(h, less_or_equal.supported);
|
|
PP_EXPECT(h, less_or_equal.value == 0x0203U);
|
|
PP_EXPECT(h, greater.supported);
|
|
PP_EXPECT(h, greater.value == 0x0204U);
|
|
PP_EXPECT(h, not_equal.supported);
|
|
PP_EXPECT(h, not_equal.value == 0x0205U);
|
|
PP_EXPECT(h, greater_or_equal.supported);
|
|
PP_EXPECT(h, greater_or_equal.value == 0x0206U);
|
|
PP_EXPECT(h, always.supported);
|
|
PP_EXPECT(h, always.value == 0x0207U);
|
|
PP_EXPECT(h, !invalid.supported);
|
|
PP_EXPECT(h, invalid.value == 0U);
|
|
}
|
|
|
|
void maps_renderer_depth_states(pp::tests::Harness& h)
|
|
{
|
|
const auto disabled = pp::renderer::gl::depth_state_for_renderer_depth_state(
|
|
pp::renderer::DepthState {});
|
|
const auto read_write = pp::renderer::gl::depth_state_for_renderer_depth_state(
|
|
pp::renderer::DepthState {
|
|
.test_enabled = true,
|
|
.write_enabled = true,
|
|
.compare = pp::renderer::CompareOp::greater,
|
|
});
|
|
const auto invalid_compare = pp::renderer::gl::depth_state_for_renderer_depth_state(
|
|
pp::renderer::DepthState {
|
|
.test_enabled = true,
|
|
.write_enabled = false,
|
|
.compare = static_cast<pp::renderer::CompareOp>(255U),
|
|
});
|
|
|
|
PP_EXPECT(h, disabled.supported);
|
|
PP_EXPECT(h, disabled.test_enabled == 0U);
|
|
PP_EXPECT(h, disabled.write_enabled == 0U);
|
|
PP_EXPECT(h, disabled.compare_function == 0x0203U);
|
|
PP_EXPECT(h, read_write.supported);
|
|
PP_EXPECT(h, read_write.test_enabled == 1U);
|
|
PP_EXPECT(h, read_write.write_enabled == 1U);
|
|
PP_EXPECT(h, read_write.compare_function == 0x0204U);
|
|
PP_EXPECT(h, !invalid_compare.supported);
|
|
PP_EXPECT(h, invalid_compare.test_enabled == 1U);
|
|
PP_EXPECT(h, invalid_compare.write_enabled == 0U);
|
|
PP_EXPECT(h, invalid_compare.compare_function == 0U);
|
|
}
|
|
|
|
void maps_windows_wgl_core_context_parameters(pp::tests::Harness& h)
|
|
{
|
|
const auto config = pp::renderer::gl::windows_wgl_core_context_3_3_config();
|
|
|
|
PP_EXPECT(h, config.context_attributes.size() == 9U);
|
|
PP_EXPECT(h, config.context_attributes[0] == 0x2091);
|
|
PP_EXPECT(h, config.context_attributes[1] == 3);
|
|
PP_EXPECT(h, config.context_attributes[2] == 0x2092);
|
|
PP_EXPECT(h, config.context_attributes[3] == 3);
|
|
PP_EXPECT(h, config.context_attributes[4] == 0x2094);
|
|
PP_EXPECT(h, config.context_attributes[5] == 0x0002);
|
|
PP_EXPECT(h, config.context_attributes[6] == 0x9126);
|
|
PP_EXPECT(h, config.context_attributes[7] == 0x00000001);
|
|
PP_EXPECT(h, config.context_attributes[8] == 0);
|
|
|
|
PP_EXPECT(h, config.pixel_format_attributes.size() == 15U);
|
|
PP_EXPECT(h, config.pixel_format_attributes[0] == 0x2001);
|
|
PP_EXPECT(h, config.pixel_format_attributes[1] == 1);
|
|
PP_EXPECT(h, config.pixel_format_attributes[2] == 0x2010);
|
|
PP_EXPECT(h, config.pixel_format_attributes[3] == 1);
|
|
PP_EXPECT(h, config.pixel_format_attributes[4] == 0x2011);
|
|
PP_EXPECT(h, config.pixel_format_attributes[5] == 1);
|
|
PP_EXPECT(h, config.pixel_format_attributes[6] == 0x2003);
|
|
PP_EXPECT(h, config.pixel_format_attributes[7] == 0x2027);
|
|
PP_EXPECT(h, config.pixel_format_attributes[8] == 0x2013);
|
|
PP_EXPECT(h, config.pixel_format_attributes[9] == 0x202B);
|
|
PP_EXPECT(h, config.pixel_format_attributes[10] == 0x2014);
|
|
PP_EXPECT(h, config.pixel_format_attributes[11] == 24);
|
|
PP_EXPECT(h, config.pixel_format_attributes[12] == 0x2022);
|
|
PP_EXPECT(h, config.pixel_format_attributes[13] == 16);
|
|
PP_EXPECT(h, config.pixel_format_attributes[14] == 0);
|
|
}
|
|
|
|
void rejects_invalid_shader_attribute_binding_catalogs(pp::tests::Harness& h)
|
|
{
|
|
const std::array<pp::renderer::gl::OpenGlAttributeBinding, 0> empty {};
|
|
const std::array unnamed {
|
|
pp::renderer::gl::OpenGlAttributeBinding { .name = "", .location = 0 },
|
|
};
|
|
const std::array null_named {
|
|
pp::renderer::gl::OpenGlAttributeBinding { .name = nullptr, .location = 0 },
|
|
};
|
|
const std::array duplicate_name {
|
|
pp::renderer::gl::OpenGlAttributeBinding { .name = "pos", .location = 0 },
|
|
pp::renderer::gl::OpenGlAttributeBinding { .name = "pos", .location = 1 },
|
|
};
|
|
const std::array duplicate_location {
|
|
pp::renderer::gl::OpenGlAttributeBinding { .name = "col", .location = 3 },
|
|
pp::renderer::gl::OpenGlAttributeBinding { .name = "nor", .location = 3 },
|
|
};
|
|
|
|
PP_EXPECT(h, !pp::renderer::gl::validate_shader_attribute_bindings(empty).ok());
|
|
PP_EXPECT(h, !pp::renderer::gl::validate_shader_attribute_bindings(unnamed).ok());
|
|
PP_EXPECT(h, !pp::renderer::gl::validate_shader_attribute_bindings(null_named).ok());
|
|
PP_EXPECT(h, !pp::renderer::gl::validate_shader_attribute_bindings(duplicate_name).ok());
|
|
PP_EXPECT(h, pp::renderer::gl::validate_shader_attribute_bindings(duplicate_location).ok());
|
|
}
|
|
|
|
void exposes_shader_uniform_catalog(pp::tests::Harness& h)
|
|
{
|
|
const auto uniforms = pp::renderer::gl::panopainter_shader_uniform_names();
|
|
|
|
PP_EXPECT(h, uniforms.size() == 43U);
|
|
PP_EXPECT(h, pp::renderer::gl::validate_shader_uniform_names(uniforms).ok());
|
|
PP_EXPECT(h, std::strcmp(uniforms[0].name, "mvp") == 0);
|
|
PP_EXPECT(h, uniforms[0].id == pp::renderer::gl::shader_uniform_id("mvp"));
|
|
PP_EXPECT(h, uniforms[0].id == 40696U);
|
|
PP_EXPECT(h, std::strcmp(uniforms[1].name, "tex") == 0);
|
|
PP_EXPECT(h, uniforms[1].id == pp::renderer::gl::shader_uniform_id("tex"));
|
|
PP_EXPECT(h, uniforms[1].id == 48854U);
|
|
PP_EXPECT(h, pp::renderer::gl::shader_uniform_id("pattern_contr") == 54920U);
|
|
PP_EXPECT(h, pp::renderer::gl::shader_uniform_id("draw_outline") == 36178U);
|
|
}
|
|
|
|
void rejects_invalid_shader_uniform_catalogs(pp::tests::Harness& h)
|
|
{
|
|
const std::array<pp::renderer::gl::OpenGlUniformName, 0> empty {};
|
|
const std::array unnamed {
|
|
pp::renderer::gl::OpenGlUniformName { .name = "", .id = 0 },
|
|
};
|
|
const std::array null_named {
|
|
pp::renderer::gl::OpenGlUniformName { .name = nullptr, .id = 0 },
|
|
};
|
|
const std::array mismatched_hash {
|
|
pp::renderer::gl::OpenGlUniformName { .name = "mvp", .id = 1 },
|
|
};
|
|
const std::array duplicate_name {
|
|
pp::renderer::gl::OpenGlUniformName {
|
|
.name = "mvp",
|
|
.id = pp::renderer::gl::shader_uniform_id("mvp"),
|
|
},
|
|
pp::renderer::gl::OpenGlUniformName {
|
|
.name = "mvp",
|
|
.id = pp::renderer::gl::shader_uniform_id("mvp"),
|
|
},
|
|
};
|
|
|
|
PP_EXPECT(h, !pp::renderer::gl::validate_shader_uniform_names(empty).ok());
|
|
PP_EXPECT(h, !pp::renderer::gl::validate_shader_uniform_names(unnamed).ok());
|
|
PP_EXPECT(h, !pp::renderer::gl::validate_shader_uniform_names(null_named).ok());
|
|
PP_EXPECT(h, !pp::renderer::gl::validate_shader_uniform_names(mismatched_hash).ok());
|
|
PP_EXPECT(h, !pp::renderer::gl::validate_shader_uniform_names(duplicate_name).ok());
|
|
}
|
|
|
|
}
|
|
|
|
int main()
|
|
{
|
|
pp::tests::Harness harness;
|
|
harness.run("detects_common_extension_capabilities", detects_common_extension_capabilities);
|
|
harness.run("treats_desktop_gl_float_rendering_as_core", treats_desktop_gl_float_rendering_as_core);
|
|
harness.run("detects_gles_texture_float_extensions", detects_gles_texture_float_extensions);
|
|
harness.run("ignores_gles_texture_extensions_for_webgl_runtime", ignores_gles_texture_extensions_for_webgl_runtime);
|
|
harness.run("selects_texture_upload_type_from_internal_format", selects_texture_upload_type_from_internal_format);
|
|
harness.run("maps_image_channel_count_to_texture_format", maps_image_channel_count_to_texture_format);
|
|
harness.run("maps_renderer_texture_formats_to_opengl_tokens", maps_renderer_texture_formats_to_opengl_tokens);
|
|
harness.run("maps_readback_formats", maps_readback_formats);
|
|
harness.run("maps_pixel_buffer_parameters", maps_pixel_buffer_parameters);
|
|
harness.run("names_framebuffer_status_codes", names_framebuffer_status_codes);
|
|
harness.run("maps_framebuffer_render_target_parameters", maps_framebuffer_render_target_parameters);
|
|
harness.run("maps_framebuffer_blit_parameters", maps_framebuffer_blit_parameters);
|
|
harness.run("maps_render_pass_clear_masks", maps_render_pass_clear_masks);
|
|
harness.run("maps_render_pass_clear_values", maps_render_pass_clear_values);
|
|
harness.run("maps_renderer_primitive_topologies_to_draw_modes", maps_renderer_primitive_topologies_to_draw_modes);
|
|
harness.run("maps_shape_index_and_primitive_modes", maps_shape_index_and_primitive_modes);
|
|
harness.run("maps_panopainter_cube_faces_to_texture_targets", maps_panopainter_cube_faces_to_texture_targets);
|
|
harness.run("exposes_default_render_target_texture_parameters", exposes_default_render_target_texture_parameters);
|
|
harness.run("maps_sampler_parameters", maps_sampler_parameters);
|
|
harness.run("maps_renderer_sampler_tokens", maps_renderer_sampler_tokens);
|
|
harness.run("maps_renderer_sampler_states", maps_renderer_sampler_states);
|
|
harness.run("exposes_shader_attribute_binding_catalog", exposes_shader_attribute_binding_catalog);
|
|
harness.run("maps_app_initialization_parameters", maps_app_initialization_parameters);
|
|
harness.run("applies_app_initialization_state", applies_app_initialization_state);
|
|
harness.run("rejects_incomplete_app_initialization_state_dispatch", rejects_incomplete_app_initialization_state_dispatch);
|
|
harness.run("snapshots_legacy_gl_state", snapshots_legacy_gl_state);
|
|
harness.run("rejects_incomplete_gl_state_snapshot_dispatch", rejects_incomplete_gl_state_snapshot_dispatch);
|
|
harness.run("restores_legacy_gl_state", restores_legacy_gl_state);
|
|
harness.run("rejects_incomplete_gl_state_restore_dispatch", rejects_incomplete_gl_state_restore_dispatch);
|
|
harness.run("queries_app_runtime_info", queries_app_runtime_info);
|
|
harness.run("rejects_incomplete_app_runtime_info_dispatch", rejects_incomplete_app_runtime_info_dispatch);
|
|
harness.run("clears_app_default_target", clears_app_default_target);
|
|
harness.run("rejects_incomplete_app_clear_dispatch", rejects_incomplete_app_clear_dispatch);
|
|
harness.run("applies_viewport_dispatch", applies_viewport_dispatch);
|
|
harness.run("rejects_incomplete_viewport_dispatch", rejects_incomplete_viewport_dispatch);
|
|
harness.run("applies_scissor_dispatch", applies_scissor_dispatch);
|
|
harness.run("rejects_incomplete_scissor_dispatch", rejects_incomplete_scissor_dispatch);
|
|
harness.run("applies_scissor_test_dispatch", applies_scissor_test_dispatch);
|
|
harness.run("rejects_incomplete_scissor_test_dispatch", rejects_incomplete_scissor_test_dispatch);
|
|
harness.run("applies_generic_capability_dispatch", applies_generic_capability_dispatch);
|
|
harness.run("rejects_incomplete_generic_capability_dispatch", rejects_incomplete_generic_capability_dispatch);
|
|
harness.run("applies_buffer_clear_dispatch", applies_buffer_clear_dispatch);
|
|
harness.run("rejects_incomplete_buffer_clear_dispatch", rejects_incomplete_buffer_clear_dispatch);
|
|
harness.run("allocates_texture_2d_through_dispatch", allocates_texture_2d_through_dispatch);
|
|
harness.run("rejects_invalid_texture_2d_allocation", rejects_invalid_texture_2d_allocation);
|
|
harness.run("deletes_and_binds_texture_2d_through_dispatch", deletes_and_binds_texture_2d_through_dispatch);
|
|
harness.run("updates_texture_2d_through_dispatch", updates_texture_2d_through_dispatch);
|
|
harness.run("generates_texture_2d_mipmaps_through_dispatch", generates_texture_2d_mipmaps_through_dispatch);
|
|
harness.run("reads_back_texture_2d_through_framebuffer_dispatch", reads_back_texture_2d_through_framebuffer_dispatch);
|
|
harness.run("reports_incomplete_texture_2d_readback_framebuffer", reports_incomplete_texture_2d_readback_framebuffer);
|
|
harness.run("rejects_incomplete_texture_2d_readback_dispatch", rejects_incomplete_texture_2d_readback_dispatch);
|
|
harness.run("blits_framebuffers_through_dispatch", blits_framebuffers_through_dispatch);
|
|
harness.run("rejects_invalid_framebuffer_blits", rejects_invalid_framebuffer_blits);
|
|
harness.run("reads_back_framebuffer_through_dispatch", reads_back_framebuffer_through_dispatch);
|
|
harness.run("rejects_invalid_framebuffer_readbacks", rejects_invalid_framebuffer_readbacks);
|
|
harness.run("maps_renderer_viewports_and_scissors", maps_renderer_viewports_and_scissors);
|
|
harness.run("maps_renderer_blend_state_tokens", maps_renderer_blend_state_tokens);
|
|
harness.run("maps_renderer_color_write_masks", maps_renderer_color_write_masks);
|
|
harness.run("maps_renderer_blend_states", maps_renderer_blend_states);
|
|
harness.run("maps_renderer_depth_compare_tokens", maps_renderer_depth_compare_tokens);
|
|
harness.run("maps_renderer_depth_states", maps_renderer_depth_states);
|
|
harness.run("maps_windows_wgl_core_context_parameters", maps_windows_wgl_core_context_parameters);
|
|
harness.run("rejects_invalid_shader_attribute_binding_catalogs", rejects_invalid_shader_attribute_binding_catalogs);
|
|
harness.run("exposes_shader_uniform_catalog", exposes_shader_uniform_catalog);
|
|
harness.run("rejects_invalid_shader_uniform_catalogs", rejects_invalid_shader_uniform_catalogs);
|
|
return harness.finish();
|
|
}
|