Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp
4566 views
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 DEALINGS
21
* IN THE SOFTWARE.
22
*/
23
24
#include "d3d12_wgl_public.h"
25
26
#include <Windows.h>
27
#include <dxgi1_4.h>
28
#include <directx/d3d12.h>
29
#include <wrl.h>
30
31
#include "util/u_memory.h"
32
#include "util/u_inlines.h"
33
#include "frontend/api.h"
34
#include "frontend/winsys_handle.h"
35
36
#include "stw_device.h"
37
#include "stw_pixelformat.h"
38
#include "stw_winsys.h"
39
40
#include "d3d12/d3d12_format.h"
41
#include "d3d12/d3d12_resource.h"
42
#include "d3d12/d3d12_screen.h"
43
44
using Microsoft::WRL::ComPtr;
45
constexpr uint32_t num_buffers = 2;
46
47
struct d3d12_wgl_framebuffer {
48
struct stw_winsys_framebuffer base;
49
50
struct d3d12_screen *screen;
51
enum pipe_format pformat;
52
HWND window;
53
ComPtr<IDXGISwapChain3> swapchain;
54
struct pipe_resource *buffers[num_buffers];
55
};
56
57
static struct d3d12_wgl_framebuffer *
58
d3d12_wgl_framebuffer(struct stw_winsys_framebuffer *fb)
59
{
60
return (struct d3d12_wgl_framebuffer *)fb;
61
}
62
63
static void
64
d3d12_wgl_framebuffer_destroy(struct stw_winsys_framebuffer *fb,
65
pipe_context *ctx)
66
{
67
struct d3d12_wgl_framebuffer *framebuffer = d3d12_wgl_framebuffer(fb);
68
struct pipe_fence_handle *fence = NULL;
69
70
if (ctx) {
71
/* Ensure all resources are flushed */
72
ctx->flush(ctx, &fence, PIPE_FLUSH_HINT_FINISH);
73
if (fence) {
74
ctx->screen->fence_finish(ctx->screen, ctx, fence, PIPE_TIMEOUT_INFINITE);
75
ctx->screen->fence_reference(ctx->screen, &fence, NULL);
76
}
77
}
78
79
for (int i = 0; i < num_buffers; ++i) {
80
if (framebuffer->buffers[i]) {
81
d3d12_resource_release(d3d12_resource(framebuffer->buffers[i]));
82
pipe_resource_reference(&framebuffer->buffers[i], NULL);
83
}
84
}
85
86
delete framebuffer;
87
}
88
89
static void
90
d3d12_wgl_framebuffer_resize(stw_winsys_framebuffer *fb,
91
pipe_context *ctx,
92
pipe_resource *templ)
93
{
94
struct d3d12_wgl_framebuffer *framebuffer = d3d12_wgl_framebuffer(fb);
95
struct d3d12_dxgi_screen *screen = d3d12_dxgi_screen(framebuffer->screen);
96
97
DXGI_SWAP_CHAIN_DESC1 desc = {};
98
desc.BufferCount = num_buffers;
99
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
100
desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
101
desc.Format = d3d12_get_format(templ->format);
102
desc.Width = templ->width0;
103
desc.Height = templ->height0;
104
desc.SampleDesc.Count = 1;
105
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
106
107
framebuffer->pformat = templ->format;
108
109
if (!framebuffer->swapchain) {
110
ComPtr<IDXGISwapChain1> swapchain1;
111
if (FAILED(screen->factory->CreateSwapChainForHwnd(
112
screen->base.cmdqueue,
113
framebuffer->window,
114
&desc,
115
nullptr,
116
nullptr,
117
&swapchain1))) {
118
debug_printf("D3D12: failed to create swapchain");
119
return;
120
}
121
122
swapchain1.As(&framebuffer->swapchain);
123
124
screen->factory->MakeWindowAssociation(framebuffer->window,
125
DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_PRINT_SCREEN);
126
}
127
else {
128
struct pipe_fence_handle *fence = NULL;
129
130
/* Ensure all resources are flushed */
131
ctx->flush(ctx, &fence, PIPE_FLUSH_HINT_FINISH);
132
if (fence) {
133
ctx->screen->fence_finish(ctx->screen, ctx, fence, PIPE_TIMEOUT_INFINITE);
134
ctx->screen->fence_reference(ctx->screen, &fence, NULL);
135
}
136
137
for (int i = 0; i < num_buffers; ++i) {
138
if (framebuffer->buffers[i]) {
139
d3d12_resource_release(d3d12_resource(framebuffer->buffers[i]));
140
pipe_resource_reference(&framebuffer->buffers[i], NULL);
141
}
142
}
143
if (FAILED(framebuffer->swapchain->ResizeBuffers(num_buffers, desc.Width, desc.Height, desc.Format, desc.Flags))) {
144
debug_printf("D3D12: failed to resize swapchain");
145
}
146
}
147
}
148
149
static boolean
150
d3d12_wgl_framebuffer_present(stw_winsys_framebuffer *fb)
151
{
152
auto framebuffer = d3d12_wgl_framebuffer(fb);
153
if (!framebuffer->swapchain) {
154
debug_printf("D3D12: Cannot present; no swapchain");
155
return false;
156
}
157
158
if (stw_dev->swap_interval < 1)
159
return S_OK == framebuffer->swapchain->Present(0, DXGI_PRESENT_ALLOW_TEARING);
160
else
161
return S_OK == framebuffer->swapchain->Present(stw_dev->swap_interval, 0);
162
}
163
164
static struct pipe_resource *
165
d3d12_wgl_framebuffer_get_resource(struct stw_winsys_framebuffer *pframebuffer,
166
st_attachment_type statt)
167
{
168
auto framebuffer = d3d12_wgl_framebuffer(pframebuffer);
169
auto pscreen = &framebuffer->screen->base;
170
171
if (!framebuffer->swapchain)
172
return nullptr;
173
174
UINT index = framebuffer->swapchain->GetCurrentBackBufferIndex();
175
if (statt == ST_ATTACHMENT_FRONT_LEFT)
176
index = !index;
177
178
if (framebuffer->buffers[index]) {
179
pipe_reference(NULL, &framebuffer->buffers[index]->reference);
180
return framebuffer->buffers[index];
181
}
182
183
ID3D12Resource *res;
184
framebuffer->swapchain->GetBuffer(index, IID_PPV_ARGS(&res));
185
if (!res)
186
return nullptr;
187
188
struct winsys_handle handle;
189
memset(&handle, 0, sizeof(handle));
190
handle.type = WINSYS_HANDLE_TYPE_D3D12_RES;
191
handle.com_obj = res;
192
193
D3D12_RESOURCE_DESC res_desc = res->GetDesc();
194
195
struct pipe_resource templ;
196
memset(&templ, 0, sizeof(templ));
197
templ.target = PIPE_TEXTURE_2D;
198
templ.format = framebuffer->pformat;
199
templ.width0 = res_desc.Width;
200
templ.height0 = res_desc.Height;
201
templ.depth0 = 1;
202
templ.array_size = res_desc.DepthOrArraySize;
203
templ.nr_samples = res_desc.SampleDesc.Count;
204
templ.last_level = res_desc.MipLevels - 1;
205
templ.bind = PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET;
206
templ.usage = PIPE_USAGE_DEFAULT;
207
templ.flags = 0;
208
209
pipe_resource_reference(&framebuffer->buffers[index],
210
pscreen->resource_from_handle(pscreen, &templ, &handle,
211
PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE));
212
return framebuffer->buffers[index];
213
}
214
215
struct stw_winsys_framebuffer *
216
d3d12_wgl_create_framebuffer(struct pipe_screen *screen,
217
HDC hDC,
218
int iPixelFormat)
219
{
220
const struct stw_pixelformat_info *pfi =
221
stw_pixelformat_get_info(iPixelFormat);
222
if (!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER) ||
223
(pfi->pfd.dwFlags & PFD_SUPPORT_GDI))
224
return NULL;
225
226
struct d3d12_wgl_framebuffer *fb = CALLOC_STRUCT(d3d12_wgl_framebuffer);
227
if (!fb)
228
return NULL;
229
230
new (fb) struct d3d12_wgl_framebuffer();
231
232
fb->window = WindowFromDC(hDC);
233
fb->screen = d3d12_screen(screen);
234
fb->base.destroy = d3d12_wgl_framebuffer_destroy;
235
fb->base.resize = d3d12_wgl_framebuffer_resize;
236
fb->base.present = d3d12_wgl_framebuffer_present;
237
fb->base.get_resource = d3d12_wgl_framebuffer_get_resource;
238
239
return &fb->base;
240
}
241
242