• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <GL/gl.h>
28 
29 #undef GetMessage
30 
31 class window
32 {
33 public:
34    window(UINT width = 64, UINT height = 64);
35    ~window();
36 
get_hwnd() const37    HWND get_hwnd() const { return _window; };
get_hdc() const38    HDC get_hdc() const { return _hdc; };
valid() const39    bool valid() const { return _window && _hdc && _hglrc; }
show()40    void show() {
41       ShowWindow(_window, SW_SHOW);
42    }
43 
44    void recreate_attribs(const int *attribList);
45 
46 private:
47    HWND _window = nullptr;
48    HDC _hdc = nullptr;
49    HGLRC _hglrc = nullptr;
50 };
51 
window(uint32_t width,uint32_t height)52 window::window(uint32_t width, uint32_t height)
53 {
54    _window = CreateWindowW(
55       L"STATIC",
56       L"OpenGLTestWindow",
57       WS_OVERLAPPEDWINDOW,
58       0,
59       0,
60       width,
61       height,
62       NULL,
63       NULL,
64       NULL,
65       NULL
66    );
67 
68    if (_window == nullptr)
69       return;
70 
71    _hdc = ::GetDC(_window);
72 
73    PIXELFORMATDESCRIPTOR pfd = {
74        sizeof(PIXELFORMATDESCRIPTOR),  /* size */
75        1,                              /* version */
76        PFD_SUPPORT_OPENGL |
77        PFD_DRAW_TO_WINDOW |
78        PFD_DOUBLEBUFFER,               /* support double-buffering */
79        PFD_TYPE_RGBA,                  /* color type */
80        8,                              /* prefered color depth */
81        0, 0, 0, 0, 0, 0,               /* color bits (ignored) */
82        0,                              /* no alpha buffer */
83        0,                              /* alpha bits (ignored) */
84        0,                              /* no accumulation buffer */
85        0, 0, 0, 0,                     /* accum bits (ignored) */
86        32,                             /* depth buffer */
87        0,                              /* no stencil buffer */
88        0,                              /* no auxiliary buffers */
89        PFD_MAIN_PLANE,                 /* main layer */
90        0,                              /* reserved */
91        0, 0, 0,                        /* no layer, visible, damage masks */
92    };
93    int pixel_format = ChoosePixelFormat(_hdc, &pfd);
94    if (pixel_format == 0)
95       return;
96    if (!SetPixelFormat(_hdc, pixel_format, &pfd))
97       return;
98 
99    _hglrc = wglCreateContext(_hdc);
100    if (!_hglrc)
101       return;
102 
103    wglMakeCurrent(_hdc, _hglrc);
104 }
105 
recreate_attribs(const int * attribs)106 void window::recreate_attribs(const int *attribs)
107 {
108    using pwglCreateContextAttribsARB = HGLRC(WINAPI*)(HDC, HGLRC, const int *);
109    auto wglCreateContextAttribsARB = (pwglCreateContextAttribsARB)wglGetProcAddress("wglCreateContextAttribsARB");
110    if (!wglCreateContextAttribsARB)
111       GTEST_FAIL() << "failed to get wglCreateContextAttribsARB";
112 
113    wglMakeCurrent(nullptr, nullptr);
114    wglDeleteContext(_hglrc);
115    _hglrc = wglCreateContextAttribsARB(_hdc, nullptr, attribs);
116    if (!_hglrc)
117       return;
118 
119    wglMakeCurrent(_hdc, _hglrc);
120 }
121 
~window()122 window::~window()
123 {
124    if (_hglrc) {
125       wglMakeCurrent(NULL, NULL);
126       wglDeleteContext(_hglrc);
127    }
128    if (_hdc)
129       ReleaseDC(_window, _hdc);
130    if (_window)
131       DestroyWindow(_window);
132 }
133 
TEST(wgl,basic_create)134 TEST(wgl, basic_create)
135 {
136    window wnd;
137    ASSERT_TRUE(wnd.valid());
138 
139    const char *version = (const char *)glGetString(GL_VERSION);
140    ASSERT_NE(strstr(version, "Mesa"), nullptr);
141 }
142 
143 #ifdef GALLIUM_D3D12
144 /* Fixture for tests for the d3d12 backend. Will be skipped if
145  * the environment isn't set up to run them.
146  */
147 #include <directx/d3d12.h>
148 #include <dxguids/dxguids.h>
149 #include <wrl/client.h>
150 #include <memory>
151 using Microsoft::WRL::ComPtr;
152 
153 class d3d12 : public ::testing::Test
154 {
155    void SetUp() override;
156 };
157 
SetUp()158 void d3d12::SetUp()
159 {
160    window wnd;
161    ASSERT_TRUE(wnd.valid());
162 
163    const char *renderer = (const char *)glGetString(GL_RENDERER);
164    if (!strstr(renderer, "D3D12"))
165       GTEST_SKIP();
166 }
167 
168 static bool
info_queue_has_swapchain(ID3D12DebugDevice * debug_device,ID3D12InfoQueue * info_queue)169 info_queue_has_swapchain(ID3D12DebugDevice *debug_device, ID3D12InfoQueue *info_queue)
170 {
171    info_queue->PushEmptyStorageFilter();
172 
173    debug_device->ReportLiveDeviceObjects(D3D12_RLDO_DETAIL);
174 
175    uint32_t num_messages = info_queue->GetNumStoredMessages();
176    for (uint32_t i = 0; i < num_messages; ++i) {
177       SIZE_T message_size = 0;
178       info_queue->GetMessage(i, nullptr, &message_size);
179       EXPECT_GT(message_size, 0);
180 
181       std::unique_ptr<byte[]> message_bytes(new byte[message_size]);
182       D3D12_MESSAGE *message = (D3D12_MESSAGE *)message_bytes.get();
183       info_queue->GetMessage(i, message, &message_size);
184 
185       if (strstr(message->pDescription, "SwapChain")) {
186          info_queue->ClearStoredMessages();
187          info_queue->PopStorageFilter();
188          return true;
189       }
190    }
191    info_queue->ClearStoredMessages();
192    info_queue->PopStorageFilter();
193    return false;
194 }
195 
TEST_F(d3d12,swapchain_cleanup)196 TEST_F(d3d12, swapchain_cleanup)
197 {
198    ComPtr<ID3D12InfoQueue> info_queue;
199    ComPtr<ID3D12DebugDevice> debug_device;
200    if (FAILED(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&info_queue))) ||
201        FAILED(info_queue.As(&debug_device)))
202       GTEST_SKIP();
203 
204    ASSERT_FALSE(info_queue_has_swapchain(debug_device.Get(), info_queue.Get()));
205 
206    {
207       window wnd;
208       wnd.show();
209       glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
210       glClear(GL_COLOR_BUFFER_BIT);
211       SwapBuffers(wnd.get_hdc());
212 
213       ASSERT_TRUE(info_queue_has_swapchain(debug_device.Get(), info_queue.Get()));
214    }
215 
216    ASSERT_FALSE(info_queue_has_swapchain(debug_device.Get(), info_queue.Get()));
217 }
218 
219 #define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
220 #define WGL_LOSE_CONTEXT_ON_RESET_ARB               0x8252
221 using pglGetGraphicsResetStatusARB = GLenum(APIENTRY*)();
TEST_F(d3d12,context_reset)222 TEST_F(d3d12, context_reset)
223 {
224    ComPtr<ID3D12Device5> device;
225    if (FAILED(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device))))
226       GTEST_SKIP();
227 
228    const int attribs[] = { WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, WGL_LOSE_CONTEXT_ON_RESET_ARB, 0 };
229 
230    {
231       window wnd;
232       wnd.recreate_attribs(attribs);
233       EXPECT_TRUE(wnd.valid());
234 
235       wnd.show();
236       glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
237       glClear(GL_COLOR_BUFFER_BIT);
238       SwapBuffers(wnd.get_hdc());
239 
240       auto glGetGraphicsResetStatusARB = (pglGetGraphicsResetStatusARB)wglGetProcAddress("glGetGraphicsResetStatusARB");
241       if (!glGetGraphicsResetStatusARB)
242          GTEST_FAIL() << "Couldn't get reset function";
243 
244       EXPECT_EQ(glGetGraphicsResetStatusARB(), NO_ERROR);
245 
246       device->RemoveDevice();
247       device.Reset();
248 
249       EXPECT_NE(glGetGraphicsResetStatusARB(), NO_ERROR);
250    }
251 
252    {
253       window wnd;
254       EXPECT_TRUE(wnd.valid());
255 
256       wnd.recreate_attribs(attribs);
257       EXPECT_TRUE(wnd.valid());
258 
259       wnd.show();
260       auto glGetGraphicsResetStatusARB = (pglGetGraphicsResetStatusARB)wglGetProcAddress("glGetGraphicsResetStatusARB");
261       EXPECT_EQ(glGetGraphicsResetStatusARB(), NO_ERROR);
262 
263       glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
264       glClear(GL_COLOR_BUFFER_BIT);
265       SwapBuffers(wnd.get_hdc());
266    }
267 }
268 #endif
269