225 lines
6.1 KiB
C++
225 lines
6.1 KiB
C++
#include "../test_harness.h"
|
|
|
|
#if defined(_WIN32)
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#ifndef NOMINMAX
|
|
#define NOMINMAX
|
|
#endif
|
|
#include <windows.h>
|
|
#include <GL/gl.h>
|
|
#endif
|
|
|
|
#include <array>
|
|
#include <cstdint>
|
|
#include <iostream>
|
|
|
|
namespace {
|
|
|
|
#if defined(_WIN32)
|
|
|
|
class HiddenWglContext {
|
|
public:
|
|
HiddenWglContext()
|
|
{
|
|
instance_ = GetModuleHandleW(nullptr);
|
|
|
|
WNDCLASSW window_class {};
|
|
window_class.style = CS_OWNDC;
|
|
window_class.lpfnWndProc = DefWindowProcW;
|
|
window_class.hInstance = instance_;
|
|
window_class.lpszClassName = class_name_;
|
|
|
|
registered_ = RegisterClassW(&window_class) != 0 || GetLastError() == ERROR_CLASS_ALREADY_EXISTS;
|
|
if (!registered_) {
|
|
skip_reason_ = "RegisterClassW failed";
|
|
return;
|
|
}
|
|
|
|
window_ = CreateWindowExW(
|
|
WS_EX_TOOLWINDOW,
|
|
class_name_,
|
|
L"PanoPainter GPU readback test",
|
|
WS_POPUP,
|
|
0,
|
|
0,
|
|
16,
|
|
16,
|
|
nullptr,
|
|
nullptr,
|
|
instance_,
|
|
nullptr);
|
|
if (window_ == nullptr) {
|
|
skip_reason_ = "CreateWindowExW failed";
|
|
return;
|
|
}
|
|
ShowWindow(window_, SW_SHOWNA);
|
|
UpdateWindow(window_);
|
|
|
|
device_context_ = GetDC(window_);
|
|
if (device_context_ == nullptr) {
|
|
skip_reason_ = "GetDC failed";
|
|
return;
|
|
}
|
|
|
|
PIXELFORMATDESCRIPTOR pixel_format {};
|
|
pixel_format.nSize = sizeof(pixel_format);
|
|
pixel_format.nVersion = 1;
|
|
pixel_format.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
|
pixel_format.iPixelType = PFD_TYPE_RGBA;
|
|
pixel_format.cColorBits = 24;
|
|
pixel_format.cAlphaBits = 8;
|
|
pixel_format.cDepthBits = 24;
|
|
pixel_format.iLayerType = PFD_MAIN_PLANE;
|
|
|
|
const int format = ChoosePixelFormat(device_context_, &pixel_format);
|
|
if (format == 0 || SetPixelFormat(device_context_, format, &pixel_format) == FALSE) {
|
|
skip_reason_ = "OpenGL pixel format setup failed";
|
|
return;
|
|
}
|
|
|
|
render_context_ = wglCreateContext(device_context_);
|
|
if (render_context_ == nullptr) {
|
|
skip_reason_ = "wglCreateContext failed";
|
|
return;
|
|
}
|
|
|
|
if (wglMakeCurrent(device_context_, render_context_) == FALSE) {
|
|
skip_reason_ = "wglMakeCurrent failed";
|
|
return;
|
|
}
|
|
|
|
ready_ = true;
|
|
}
|
|
|
|
HiddenWglContext(const HiddenWglContext&) = delete;
|
|
HiddenWglContext& operator=(const HiddenWglContext&) = delete;
|
|
|
|
~HiddenWglContext()
|
|
{
|
|
if (render_context_ != nullptr) {
|
|
wglMakeCurrent(nullptr, nullptr);
|
|
wglDeleteContext(render_context_);
|
|
}
|
|
if (window_ != nullptr && device_context_ != nullptr) {
|
|
ReleaseDC(window_, device_context_);
|
|
}
|
|
if (window_ != nullptr) {
|
|
DestroyWindow(window_);
|
|
}
|
|
if (registered_) {
|
|
UnregisterClassW(class_name_, instance_);
|
|
}
|
|
}
|
|
|
|
[[nodiscard]] bool ready() const noexcept
|
|
{
|
|
return ready_;
|
|
}
|
|
|
|
[[nodiscard]] const char* skip_reason() const noexcept
|
|
{
|
|
return skip_reason_;
|
|
}
|
|
|
|
private:
|
|
static constexpr const wchar_t* class_name_ = L"PanoPainterGpuReadbackTestWindow";
|
|
|
|
HINSTANCE instance_ = nullptr;
|
|
HWND window_ = nullptr;
|
|
HDC device_context_ = nullptr;
|
|
HGLRC render_context_ = nullptr;
|
|
const char* skip_reason_ = "OpenGL context unavailable";
|
|
bool registered_ = false;
|
|
bool ready_ = false;
|
|
};
|
|
|
|
#endif
|
|
|
|
void opengl_clear_readback_matches_fixture(pp::tests::Harness& h)
|
|
{
|
|
#if defined(_WIN32)
|
|
HiddenWglContext context;
|
|
if (!context.ready()) {
|
|
std::cout << "[skip] desktop GPU OpenGL readback unavailable: " << context.skip_reason() << "\n";
|
|
return;
|
|
}
|
|
|
|
glViewport(0, 0, 1, 1);
|
|
glDrawBuffer(GL_BACK);
|
|
glReadBuffer(GL_BACK);
|
|
glClearColor(1.0F, 0.0F, 0.0F, 1.0F);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
glFinish();
|
|
|
|
std::array<std::uint8_t, 4> pixel {};
|
|
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel.data());
|
|
|
|
constexpr std::array<std::uint8_t, 4> expected {
|
|
255,
|
|
0,
|
|
0,
|
|
255,
|
|
};
|
|
if (pixel != expected) {
|
|
std::cout << "readback rgba: "
|
|
<< static_cast<int>(pixel[0]) << ", "
|
|
<< static_cast<int>(pixel[1]) << ", "
|
|
<< static_cast<int>(pixel[2]) << ", "
|
|
<< static_cast<int>(pixel[3]) << "\n";
|
|
}
|
|
PP_EXPECT(h, pixel == expected);
|
|
#else
|
|
std::cout << "[skip] desktop GPU OpenGL readback unavailable: no platform context helper\n";
|
|
#endif
|
|
}
|
|
|
|
void opengl_preview_readback_matches_fixture(pp::tests::Harness& h)
|
|
{
|
|
#if defined(_WIN32)
|
|
HiddenWglContext context;
|
|
if (!context.ready()) {
|
|
std::cout << "[skip] desktop GPU preview OpenGL readback unavailable: " << context.skip_reason() << "\n";
|
|
return;
|
|
}
|
|
|
|
glViewport(0, 0, 1, 1);
|
|
glDrawBuffer(GL_BACK);
|
|
glReadBuffer(GL_BACK);
|
|
glClearColor(0.0F, 1.0F, 0.0F, 1.0F);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
glFinish();
|
|
|
|
std::array<std::uint8_t, 4> pixel {};
|
|
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel.data());
|
|
|
|
constexpr std::array<std::uint8_t, 4> expected {
|
|
0,
|
|
255,
|
|
0,
|
|
255,
|
|
};
|
|
if (pixel != expected) {
|
|
std::cout << "preview readback rgba: "
|
|
<< static_cast<int>(pixel[0]) << ", "
|
|
<< static_cast<int>(pixel[1]) << ", "
|
|
<< static_cast<int>(pixel[2]) << ", "
|
|
<< static_cast<int>(pixel[3]) << "\n";
|
|
}
|
|
PP_EXPECT(h, pixel == expected);
|
|
#else
|
|
std::cout << "[skip] desktop GPU preview OpenGL readback unavailable: no platform context helper\n";
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
int main()
|
|
{
|
|
pp::tests::Harness harness;
|
|
harness.run("opengl_clear_readback_matches_fixture", opengl_clear_readback_matches_fixture);
|
|
harness.run("opengl_preview_readback_matches_fixture", opengl_preview_readback_matches_fixture);
|
|
return harness.finish();
|
|
}
|