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 private:
45    HWND _window = nullptr;
46    HDC _hdc = nullptr;
47    HGLRC _hglrc = nullptr;
48 };
49 
window(uint32_t width,uint32_t height)50 window::window(uint32_t width, uint32_t height)
51 {
52    _window = CreateWindowW(
53       L"STATIC",
54       L"OpenGLTestWindow",
55       WS_OVERLAPPEDWINDOW,
56       0,
57       0,
58       width,
59       height,
60       NULL,
61       NULL,
62       NULL,
63       NULL
64    );
65 
66    if (_window == nullptr)
67       return;
68 
69    _hdc = ::GetDC(_window);
70 
71    PIXELFORMATDESCRIPTOR pfd = {
72        sizeof(PIXELFORMATDESCRIPTOR),  /* size */
73        1,                              /* version */
74        PFD_SUPPORT_OPENGL |
75        PFD_DRAW_TO_WINDOW |
76        PFD_DOUBLEBUFFER,               /* support double-buffering */
77        PFD_TYPE_RGBA,                  /* color type */
78        8,                              /* prefered color depth */
79        0, 0, 0, 0, 0, 0,               /* color bits (ignored) */
80        0,                              /* no alpha buffer */
81        0,                              /* alpha bits (ignored) */
82        0,                              /* no accumulation buffer */
83        0, 0, 0, 0,                     /* accum bits (ignored) */
84        32,                             /* depth buffer */
85        0,                              /* no stencil buffer */
86        0,                              /* no auxiliary buffers */
87        PFD_MAIN_PLANE,                 /* main layer */
88        0,                              /* reserved */
89        0, 0, 0,                        /* no layer, visible, damage masks */
90    };
91    int pixel_format = ChoosePixelFormat(_hdc, &pfd);
92    if (pixel_format == 0)
93       return;
94    if (!SetPixelFormat(_hdc, pixel_format, &pfd))
95       return;
96 
97    _hglrc = wglCreateContext(_hdc);
98    if (!_hglrc)
99       return;
100 
101    wglMakeCurrent(_hdc, _hglrc);
102 }
103 
~window()104 window::~window()
105 {
106    if (_hglrc) {
107       wglMakeCurrent(NULL, NULL);
108       wglDeleteContext(_hglrc);
109    }
110    if (_hdc)
111       ReleaseDC(_window, _hdc);
112    if (_window)
113       DestroyWindow(_window);
114 }
115 
TEST(wgl,basic_create)116 TEST(wgl, basic_create)
117 {
118    window wnd;
119    ASSERT_TRUE(wnd.valid());
120 
121    const char *version = (const char *)glGetString(GL_VERSION);
122    ASSERT_NE(strstr(version, "Mesa"), nullptr);
123 }
124 
125 #ifdef GALLIUM_D3D12
126 /* Fixture for tests for the d3d12 backend. Will be skipped if
127  * the environment isn't set up to run them.
128  */
129 #include <directx/d3d12.h>
130 #include <wrl/client.h>
131 #include <memory>
132 using Microsoft::WRL::ComPtr;
133 
134 class d3d12 : public ::testing::Test
135 {
136    void SetUp() override;
137 };
138 
SetUp()139 void d3d12::SetUp()
140 {
141    window wnd;
142    ASSERT_TRUE(wnd.valid());
143 
144    const char *renderer = (const char *)glGetString(GL_RENDERER);
145    if (!strstr(renderer, "D3D12"))
146       GTEST_SKIP();
147 }
148 
149 static bool
info_queue_has_swapchain(ID3D12DebugDevice * debug_device,ID3D12InfoQueue * info_queue)150 info_queue_has_swapchain(ID3D12DebugDevice *debug_device, ID3D12InfoQueue *info_queue)
151 {
152    info_queue->PushEmptyStorageFilter();
153 
154    debug_device->ReportLiveDeviceObjects(D3D12_RLDO_DETAIL);
155 
156    uint32_t num_messages = info_queue->GetNumStoredMessages();
157    for (uint32_t i = 0; i < num_messages; ++i) {
158       SIZE_T message_size = 0;
159       info_queue->GetMessage(i, nullptr, &message_size);
160       EXPECT_GT(message_size, 0);
161 
162       std::unique_ptr<byte[]> message_bytes(new byte[message_size]);
163       D3D12_MESSAGE *message = (D3D12_MESSAGE *)message_bytes.get();
164       info_queue->GetMessage(i, message, &message_size);
165 
166       if (strstr(message->pDescription, "SwapChain")) {
167          info_queue->ClearStoredMessages();
168          info_queue->PopStorageFilter();
169          return true;
170       }
171    }
172    info_queue->ClearStoredMessages();
173    info_queue->PopStorageFilter();
174    return false;
175 }
176 
TEST_F(d3d12,swapchain_cleanup)177 TEST_F(d3d12, swapchain_cleanup)
178 {
179    ComPtr<ID3D12InfoQueue> info_queue;
180    ComPtr<ID3D12DebugDevice> debug_device;
181    if (FAILED(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&info_queue))) ||
182        FAILED(info_queue.As(&debug_device)))
183       GTEST_SKIP();
184 
185    ASSERT_FALSE(info_queue_has_swapchain(debug_device.Get(), info_queue.Get()));
186 
187    {
188       window wnd;
189       wnd.show();
190       glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
191       glClear(GL_COLOR_BUFFER_BIT);
192       SwapBuffers(wnd.get_hdc());
193 
194       ASSERT_TRUE(info_queue_has_swapchain(debug_device.Get(), info_queue.Get()));
195    }
196 
197    ASSERT_FALSE(info_queue_has_swapchain(debug_device.Get(), info_queue.Get()));
198 }
199 #endif
200