d3d12: Implement winsys framebuffer
Reviewed-by: Charmaine Lee <charmainel@vmware.com> Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7535>
This commit is contained in:
committed by
Erik Faye-Lund
parent
e74b3e570a
commit
be4475c4a7
@@ -38,6 +38,9 @@
|
||||
|
||||
#define STW_MAX_PIXELFORMATS 256
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct pipe_screen;
|
||||
struct st_api;
|
||||
@@ -129,5 +132,8 @@ stw_unlock_framebuffers(struct stw_device *stw_dev)
|
||||
LeaveCriticalSection(&stw_dev->fb_mutex);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* STW_DEVICE_H_ */
|
||||
|
||||
@@ -91,6 +91,15 @@ gdi_get_pfd_flags(struct pipe_screen *screen)
|
||||
}
|
||||
|
||||
|
||||
static struct stw_winsys_framebuffer *
|
||||
gdi_create_framebuffer(struct pipe_screen *screen,
|
||||
HDC hDC,
|
||||
int iPixelFormat)
|
||||
{
|
||||
return d3d12_wgl_create_framebuffer(screen, hDC, iPixelFormat);
|
||||
}
|
||||
|
||||
|
||||
static const struct stw_winsys stw_winsys = {
|
||||
&gdi_screen_create,
|
||||
&gdi_present,
|
||||
@@ -98,7 +107,8 @@ static const struct stw_winsys stw_winsys = {
|
||||
NULL, /* shared_surface_open */
|
||||
NULL, /* shared_surface_close */
|
||||
NULL, /* compose */
|
||||
&gdi_get_pfd_flags
|
||||
&gdi_get_pfd_flags,
|
||||
&gdi_create_framebuffer
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -229,6 +229,19 @@ gdi_get_pfd_flags(struct pipe_screen *screen)
|
||||
}
|
||||
|
||||
|
||||
static struct stw_winsys_framebuffer *
|
||||
gdi_create_framebuffer(struct pipe_screen *screen,
|
||||
HDC hDC,
|
||||
int iPixelFormat)
|
||||
{
|
||||
#ifdef GALLIUM_D3D12
|
||||
if (use_d3d12)
|
||||
return d3d12_wgl_create_framebuffer(screen, hDC, iPixelFormat);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static const struct stw_winsys stw_winsys = {
|
||||
&gdi_screen_create,
|
||||
&gdi_present,
|
||||
@@ -241,6 +254,7 @@ static const struct stw_winsys stw_winsys = {
|
||||
NULL, /* shared_surface_close */
|
||||
NULL, /* compose */
|
||||
&gdi_get_pfd_flags,
|
||||
&gdi_create_framebuffer,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright © Microsoft Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "d3d12_wgl_public.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <dxgi1_4.h>
|
||||
#include <d3d12.h>
|
||||
#include <wrl.h>
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "frontend/api.h"
|
||||
#include "frontend/winsys_handle.h"
|
||||
|
||||
#include "stw_device.h"
|
||||
#include "stw_pixelformat.h"
|
||||
#include "stw_winsys.h"
|
||||
|
||||
#include "d3d12/d3d12_format.h"
|
||||
#include "d3d12/d3d12_screen.h"
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
struct d3d12_wgl_framebuffer {
|
||||
struct stw_winsys_framebuffer base;
|
||||
|
||||
struct d3d12_screen *screen;
|
||||
enum pipe_format pformat;
|
||||
HWND window;
|
||||
ComPtr<IDXGISwapChain3> swapchain;
|
||||
};
|
||||
|
||||
static struct d3d12_wgl_framebuffer *
|
||||
d3d12_wgl_framebuffer(struct stw_winsys_framebuffer *fb)
|
||||
{
|
||||
return (struct d3d12_wgl_framebuffer *)fb;
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_wgl_framebuffer_destroy(struct stw_winsys_framebuffer *fb)
|
||||
{
|
||||
FREE(fb);
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_wgl_framebuffer_resize(stw_winsys_framebuffer *fb,
|
||||
pipe_context *ctx,
|
||||
pipe_resource *templ)
|
||||
{
|
||||
struct d3d12_wgl_framebuffer *framebuffer = d3d12_wgl_framebuffer(fb);
|
||||
struct d3d12_screen *screen = framebuffer->screen;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 desc = {};
|
||||
desc.BufferCount = 2;
|
||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
|
||||
desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
||||
desc.Format = d3d12_get_format(templ->format);
|
||||
desc.Width = templ->width0;
|
||||
desc.Height = templ->height0;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||
|
||||
framebuffer->pformat = templ->format;
|
||||
|
||||
if (!framebuffer->swapchain) {
|
||||
ComPtr<IDXGISwapChain1> swapchain1;
|
||||
if (FAILED(screen->factory->CreateSwapChainForHwnd(
|
||||
screen->cmdqueue,
|
||||
framebuffer->window,
|
||||
&desc,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&swapchain1))) {
|
||||
debug_printf("D3D12: failed to create swapchain");
|
||||
return;
|
||||
}
|
||||
|
||||
swapchain1.As(&framebuffer->swapchain);
|
||||
}
|
||||
else {
|
||||
struct pipe_fence_handle *fence = NULL;
|
||||
|
||||
/* Ensure all resources are flushed */
|
||||
ctx->flush(ctx, &fence, PIPE_FLUSH_HINT_FINISH);
|
||||
if (fence) {
|
||||
ctx->screen->fence_finish(ctx->screen, ctx, fence, PIPE_TIMEOUT_INFINITE);
|
||||
ctx->screen->fence_reference(ctx->screen, &fence, NULL);
|
||||
}
|
||||
|
||||
if (FAILED(framebuffer->swapchain->ResizeBuffers(2, desc.Width, desc.Height, desc.Format, desc.Flags))) {
|
||||
debug_printf("D3D12: failed to resize swapchain");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static boolean
|
||||
d3d12_wgl_framebuffer_present(stw_winsys_framebuffer *fb)
|
||||
{
|
||||
auto framebuffer = d3d12_wgl_framebuffer(fb);
|
||||
if (!framebuffer->swapchain) {
|
||||
debug_printf("D3D12: Cannot present; no swapchain");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stw_dev->swap_interval < 1)
|
||||
return S_OK == framebuffer->swapchain->Present(0, DXGI_PRESENT_ALLOW_TEARING);
|
||||
else
|
||||
return S_OK == framebuffer->swapchain->Present(stw_dev->swap_interval, 0);
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
d3d12_wgl_framebuffer_get_resource(struct stw_winsys_framebuffer *pframebuffer,
|
||||
st_attachment_type statt)
|
||||
{
|
||||
auto framebuffer = d3d12_wgl_framebuffer(pframebuffer);
|
||||
auto pscreen = &framebuffer->screen->base;
|
||||
|
||||
if (!framebuffer->swapchain)
|
||||
return nullptr;
|
||||
|
||||
UINT index = framebuffer->swapchain->GetCurrentBackBufferIndex();
|
||||
if (statt == ST_ATTACHMENT_FRONT_LEFT)
|
||||
index = !index;
|
||||
|
||||
ID3D12Resource *res;
|
||||
framebuffer->swapchain->GetBuffer(index, IID_PPV_ARGS(&res));
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
struct winsys_handle handle;
|
||||
memset(&handle, 0, sizeof(handle));
|
||||
handle.type = WINSYS_HANDLE_TYPE_D3D12_RES;
|
||||
handle.com_obj = res;
|
||||
|
||||
D3D12_RESOURCE_DESC res_desc = res->GetDesc();
|
||||
|
||||
struct pipe_resource templ;
|
||||
memset(&templ, 0, sizeof(templ));
|
||||
templ.target = PIPE_TEXTURE_2D;
|
||||
templ.format = framebuffer->pformat;
|
||||
templ.width0 = res_desc.Width;
|
||||
templ.height0 = res_desc.Height;
|
||||
templ.depth0 = 1;
|
||||
templ.array_size = res_desc.DepthOrArraySize;
|
||||
templ.nr_samples = res_desc.SampleDesc.Count;
|
||||
templ.last_level = res_desc.MipLevels - 1;
|
||||
templ.bind = PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET;
|
||||
templ.usage = PIPE_USAGE_DEFAULT;
|
||||
templ.flags = 0;
|
||||
|
||||
return pscreen->resource_from_handle(pscreen, &templ, &handle,
|
||||
PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
|
||||
}
|
||||
|
||||
struct stw_winsys_framebuffer *
|
||||
d3d12_wgl_create_framebuffer(struct pipe_screen *screen,
|
||||
HDC hDC,
|
||||
int iPixelFormat)
|
||||
{
|
||||
const struct stw_pixelformat_info *pfi =
|
||||
stw_pixelformat_get_info(iPixelFormat);
|
||||
if (!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))
|
||||
return NULL;
|
||||
|
||||
struct d3d12_wgl_framebuffer *fb = CALLOC_STRUCT(d3d12_wgl_framebuffer);
|
||||
if (!fb)
|
||||
return NULL;
|
||||
|
||||
fb->window = WindowFromDC(hDC);
|
||||
fb->screen = d3d12_screen(screen);
|
||||
fb->base.destroy = d3d12_wgl_framebuffer_destroy;
|
||||
fb->base.resize = d3d12_wgl_framebuffer_resize;
|
||||
fb->base.present = d3d12_wgl_framebuffer_present;
|
||||
fb->base.get_resource = d3d12_wgl_framebuffer_get_resource;
|
||||
|
||||
return &fb->base;
|
||||
}
|
||||
@@ -46,6 +46,11 @@ d3d12_wgl_present(struct pipe_screen *screen,
|
||||
unsigned
|
||||
d3d12_wgl_get_pfd_flags(struct pipe_screen *screen);
|
||||
|
||||
struct stw_winsys_framebuffer *
|
||||
d3d12_wgl_create_framebuffer(struct pipe_screen *screen,
|
||||
HDC hDC,
|
||||
int iPixelFormat);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -53,5 +53,5 @@ unsigned
|
||||
d3d12_wgl_get_pfd_flags(struct pipe_screen *screen)
|
||||
{
|
||||
(void)screen;
|
||||
return stw_pfd_gdi_support;
|
||||
return stw_pfd_gdi_support | stw_pfd_double_buffer;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
libd3d12winsys = static_library(
|
||||
'd3d12winsys',
|
||||
files('d3d12_wgl_winsys.c'),
|
||||
files('d3d12_wgl_framebuffer.cpp', 'd3d12_wgl_winsys.c'),
|
||||
include_directories : [inc_src, inc_wgl, inc_include, inc_gallium, inc_gallium_aux, inc_gallium_drivers],
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user