1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <gtest/gtest.h> 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include <windows.h> 27bf215546Sopenharmony_ci#include <GL/gl.h> 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#undef GetMessage 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ciclass window 32bf215546Sopenharmony_ci{ 33bf215546Sopenharmony_cipublic: 34bf215546Sopenharmony_ci window(UINT width = 64, UINT height = 64); 35bf215546Sopenharmony_ci ~window(); 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci HWND get_hwnd() const { return _window; }; 38bf215546Sopenharmony_ci HDC get_hdc() const { return _hdc; }; 39bf215546Sopenharmony_ci bool valid() const { return _window && _hdc && _hglrc; } 40bf215546Sopenharmony_ci void show() { 41bf215546Sopenharmony_ci ShowWindow(_window, SW_SHOW); 42bf215546Sopenharmony_ci } 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci void recreate_attribs(const int *attribList); 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ciprivate: 47bf215546Sopenharmony_ci HWND _window = nullptr; 48bf215546Sopenharmony_ci HDC _hdc = nullptr; 49bf215546Sopenharmony_ci HGLRC _hglrc = nullptr; 50bf215546Sopenharmony_ci}; 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ciwindow::window(uint32_t width, uint32_t height) 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci _window = CreateWindowW( 55bf215546Sopenharmony_ci L"STATIC", 56bf215546Sopenharmony_ci L"OpenGLTestWindow", 57bf215546Sopenharmony_ci WS_OVERLAPPEDWINDOW, 58bf215546Sopenharmony_ci 0, 59bf215546Sopenharmony_ci 0, 60bf215546Sopenharmony_ci width, 61bf215546Sopenharmony_ci height, 62bf215546Sopenharmony_ci NULL, 63bf215546Sopenharmony_ci NULL, 64bf215546Sopenharmony_ci NULL, 65bf215546Sopenharmony_ci NULL 66bf215546Sopenharmony_ci ); 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci if (_window == nullptr) 69bf215546Sopenharmony_ci return; 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci _hdc = ::GetDC(_window); 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci PIXELFORMATDESCRIPTOR pfd = { 74bf215546Sopenharmony_ci sizeof(PIXELFORMATDESCRIPTOR), /* size */ 75bf215546Sopenharmony_ci 1, /* version */ 76bf215546Sopenharmony_ci PFD_SUPPORT_OPENGL | 77bf215546Sopenharmony_ci PFD_DRAW_TO_WINDOW | 78bf215546Sopenharmony_ci PFD_DOUBLEBUFFER, /* support double-buffering */ 79bf215546Sopenharmony_ci PFD_TYPE_RGBA, /* color type */ 80bf215546Sopenharmony_ci 8, /* prefered color depth */ 81bf215546Sopenharmony_ci 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ 82bf215546Sopenharmony_ci 0, /* no alpha buffer */ 83bf215546Sopenharmony_ci 0, /* alpha bits (ignored) */ 84bf215546Sopenharmony_ci 0, /* no accumulation buffer */ 85bf215546Sopenharmony_ci 0, 0, 0, 0, /* accum bits (ignored) */ 86bf215546Sopenharmony_ci 32, /* depth buffer */ 87bf215546Sopenharmony_ci 0, /* no stencil buffer */ 88bf215546Sopenharmony_ci 0, /* no auxiliary buffers */ 89bf215546Sopenharmony_ci PFD_MAIN_PLANE, /* main layer */ 90bf215546Sopenharmony_ci 0, /* reserved */ 91bf215546Sopenharmony_ci 0, 0, 0, /* no layer, visible, damage masks */ 92bf215546Sopenharmony_ci }; 93bf215546Sopenharmony_ci int pixel_format = ChoosePixelFormat(_hdc, &pfd); 94bf215546Sopenharmony_ci if (pixel_format == 0) 95bf215546Sopenharmony_ci return; 96bf215546Sopenharmony_ci if (!SetPixelFormat(_hdc, pixel_format, &pfd)) 97bf215546Sopenharmony_ci return; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci _hglrc = wglCreateContext(_hdc); 100bf215546Sopenharmony_ci if (!_hglrc) 101bf215546Sopenharmony_ci return; 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci wglMakeCurrent(_hdc, _hglrc); 104bf215546Sopenharmony_ci} 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_civoid window::recreate_attribs(const int *attribs) 107bf215546Sopenharmony_ci{ 108bf215546Sopenharmony_ci using pwglCreateContextAttribsARB = HGLRC(WINAPI*)(HDC, HGLRC, const int *); 109bf215546Sopenharmony_ci auto wglCreateContextAttribsARB = (pwglCreateContextAttribsARB)wglGetProcAddress("wglCreateContextAttribsARB"); 110bf215546Sopenharmony_ci if (!wglCreateContextAttribsARB) 111bf215546Sopenharmony_ci GTEST_FAIL() << "failed to get wglCreateContextAttribsARB"; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci wglMakeCurrent(nullptr, nullptr); 114bf215546Sopenharmony_ci wglDeleteContext(_hglrc); 115bf215546Sopenharmony_ci _hglrc = wglCreateContextAttribsARB(_hdc, nullptr, attribs); 116bf215546Sopenharmony_ci if (!_hglrc) 117bf215546Sopenharmony_ci return; 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci wglMakeCurrent(_hdc, _hglrc); 120bf215546Sopenharmony_ci} 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ciwindow::~window() 123bf215546Sopenharmony_ci{ 124bf215546Sopenharmony_ci if (_hglrc) { 125bf215546Sopenharmony_ci wglMakeCurrent(NULL, NULL); 126bf215546Sopenharmony_ci wglDeleteContext(_hglrc); 127bf215546Sopenharmony_ci } 128bf215546Sopenharmony_ci if (_hdc) 129bf215546Sopenharmony_ci ReleaseDC(_window, _hdc); 130bf215546Sopenharmony_ci if (_window) 131bf215546Sopenharmony_ci DestroyWindow(_window); 132bf215546Sopenharmony_ci} 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ciTEST(wgl, basic_create) 135bf215546Sopenharmony_ci{ 136bf215546Sopenharmony_ci window wnd; 137bf215546Sopenharmony_ci ASSERT_TRUE(wnd.valid()); 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci const char *version = (const char *)glGetString(GL_VERSION); 140bf215546Sopenharmony_ci ASSERT_NE(strstr(version, "Mesa"), nullptr); 141bf215546Sopenharmony_ci} 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci#ifdef GALLIUM_D3D12 144bf215546Sopenharmony_ci/* Fixture for tests for the d3d12 backend. Will be skipped if 145bf215546Sopenharmony_ci * the environment isn't set up to run them. 146bf215546Sopenharmony_ci */ 147bf215546Sopenharmony_ci#include <directx/d3d12.h> 148bf215546Sopenharmony_ci#include <dxguids/dxguids.h> 149bf215546Sopenharmony_ci#include <wrl/client.h> 150bf215546Sopenharmony_ci#include <memory> 151bf215546Sopenharmony_ciusing Microsoft::WRL::ComPtr; 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ciclass d3d12 : public ::testing::Test 154bf215546Sopenharmony_ci{ 155bf215546Sopenharmony_ci void SetUp() override; 156bf215546Sopenharmony_ci}; 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_civoid d3d12::SetUp() 159bf215546Sopenharmony_ci{ 160bf215546Sopenharmony_ci window wnd; 161bf215546Sopenharmony_ci ASSERT_TRUE(wnd.valid()); 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci const char *renderer = (const char *)glGetString(GL_RENDERER); 164bf215546Sopenharmony_ci if (!strstr(renderer, "D3D12")) 165bf215546Sopenharmony_ci GTEST_SKIP(); 166bf215546Sopenharmony_ci} 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_cistatic bool 169bf215546Sopenharmony_ciinfo_queue_has_swapchain(ID3D12DebugDevice *debug_device, ID3D12InfoQueue *info_queue) 170bf215546Sopenharmony_ci{ 171bf215546Sopenharmony_ci info_queue->PushEmptyStorageFilter(); 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci debug_device->ReportLiveDeviceObjects(D3D12_RLDO_DETAIL); 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci uint32_t num_messages = info_queue->GetNumStoredMessages(); 176bf215546Sopenharmony_ci for (uint32_t i = 0; i < num_messages; ++i) { 177bf215546Sopenharmony_ci SIZE_T message_size = 0; 178bf215546Sopenharmony_ci info_queue->GetMessage(i, nullptr, &message_size); 179bf215546Sopenharmony_ci EXPECT_GT(message_size, 0); 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci std::unique_ptr<byte[]> message_bytes(new byte[message_size]); 182bf215546Sopenharmony_ci D3D12_MESSAGE *message = (D3D12_MESSAGE *)message_bytes.get(); 183bf215546Sopenharmony_ci info_queue->GetMessage(i, message, &message_size); 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci if (strstr(message->pDescription, "SwapChain")) { 186bf215546Sopenharmony_ci info_queue->ClearStoredMessages(); 187bf215546Sopenharmony_ci info_queue->PopStorageFilter(); 188bf215546Sopenharmony_ci return true; 189bf215546Sopenharmony_ci } 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci info_queue->ClearStoredMessages(); 192bf215546Sopenharmony_ci info_queue->PopStorageFilter(); 193bf215546Sopenharmony_ci return false; 194bf215546Sopenharmony_ci} 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ciTEST_F(d3d12, swapchain_cleanup) 197bf215546Sopenharmony_ci{ 198bf215546Sopenharmony_ci ComPtr<ID3D12InfoQueue> info_queue; 199bf215546Sopenharmony_ci ComPtr<ID3D12DebugDevice> debug_device; 200bf215546Sopenharmony_ci if (FAILED(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&info_queue))) || 201bf215546Sopenharmony_ci FAILED(info_queue.As(&debug_device))) 202bf215546Sopenharmony_ci GTEST_SKIP(); 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci ASSERT_FALSE(info_queue_has_swapchain(debug_device.Get(), info_queue.Get())); 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci { 207bf215546Sopenharmony_ci window wnd; 208bf215546Sopenharmony_ci wnd.show(); 209bf215546Sopenharmony_ci glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 210bf215546Sopenharmony_ci glClear(GL_COLOR_BUFFER_BIT); 211bf215546Sopenharmony_ci SwapBuffers(wnd.get_hdc()); 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci ASSERT_TRUE(info_queue_has_swapchain(debug_device.Get(), info_queue.Get())); 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci ASSERT_FALSE(info_queue_has_swapchain(debug_device.Get(), info_queue.Get())); 217bf215546Sopenharmony_ci} 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 220bf215546Sopenharmony_ci#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 221bf215546Sopenharmony_ciusing pglGetGraphicsResetStatusARB = GLenum(APIENTRY*)(); 222bf215546Sopenharmony_ciTEST_F(d3d12, context_reset) 223bf215546Sopenharmony_ci{ 224bf215546Sopenharmony_ci ComPtr<ID3D12Device5> device; 225bf215546Sopenharmony_ci if (FAILED(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device)))) 226bf215546Sopenharmony_ci GTEST_SKIP(); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci const int attribs[] = { WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, WGL_LOSE_CONTEXT_ON_RESET_ARB, 0 }; 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci { 231bf215546Sopenharmony_ci window wnd; 232bf215546Sopenharmony_ci wnd.recreate_attribs(attribs); 233bf215546Sopenharmony_ci EXPECT_TRUE(wnd.valid()); 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci wnd.show(); 236bf215546Sopenharmony_ci glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 237bf215546Sopenharmony_ci glClear(GL_COLOR_BUFFER_BIT); 238bf215546Sopenharmony_ci SwapBuffers(wnd.get_hdc()); 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci auto glGetGraphicsResetStatusARB = (pglGetGraphicsResetStatusARB)wglGetProcAddress("glGetGraphicsResetStatusARB"); 241bf215546Sopenharmony_ci if (!glGetGraphicsResetStatusARB) 242bf215546Sopenharmony_ci GTEST_FAIL() << "Couldn't get reset function"; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci EXPECT_EQ(glGetGraphicsResetStatusARB(), NO_ERROR); 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci device->RemoveDevice(); 247bf215546Sopenharmony_ci device.Reset(); 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci EXPECT_NE(glGetGraphicsResetStatusARB(), NO_ERROR); 250bf215546Sopenharmony_ci } 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci { 253bf215546Sopenharmony_ci window wnd; 254bf215546Sopenharmony_ci EXPECT_TRUE(wnd.valid()); 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci wnd.recreate_attribs(attribs); 257bf215546Sopenharmony_ci EXPECT_TRUE(wnd.valid()); 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci wnd.show(); 260bf215546Sopenharmony_ci auto glGetGraphicsResetStatusARB = (pglGetGraphicsResetStatusARB)wglGetProcAddress("glGetGraphicsResetStatusARB"); 261bf215546Sopenharmony_ci EXPECT_EQ(glGetGraphicsResetStatusARB(), NO_ERROR); 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 264bf215546Sopenharmony_ci glClear(GL_COLOR_BUFFER_BIT); 265bf215546Sopenharmony_ci SwapBuffers(wnd.get_hdc()); 266bf215546Sopenharmony_ci } 267bf215546Sopenharmony_ci} 268bf215546Sopenharmony_ci#endif 269