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