diff options
author | Jesse Natalie <jenatali@ntdev.microsoft.com> | 2020-04-25 16:26:56 -0400 |
---|---|---|
committer | Erik Faye-Lund <erik.faye-lund@collabora.com> | 2020-11-18 11:18:37 +0100 |
commit | be4475c4a73dc71c8868f5508064feb6bdec0a22 (patch) | |
tree | 6d38f808e0647cf7715521186a40464ddd30c7c6 /src/gallium/winsys/d3d12 | |
parent | e74b3e570a6a4d42577912e9d37ca60771df2c9d (diff) |
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>
Diffstat (limited to 'src/gallium/winsys/d3d12')
-rw-r--r-- | src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp | 198 | ||||
-rw-r--r-- | src/gallium/winsys/d3d12/wgl/d3d12_wgl_public.h | 5 | ||||
-rw-r--r-- | src/gallium/winsys/d3d12/wgl/d3d12_wgl_winsys.c | 2 | ||||
-rw-r--r-- | src/gallium/winsys/d3d12/wgl/meson.build | 2 |
4 files changed, 205 insertions, 2 deletions
diff --git a/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp b/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp new file mode 100644 index 00000000000..b625e6dd7e4 --- /dev/null +++ b/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp @@ -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; +} diff --git a/src/gallium/winsys/d3d12/wgl/d3d12_wgl_public.h b/src/gallium/winsys/d3d12/wgl/d3d12_wgl_public.h index c24e111e1b0..aa0191274ea 100644 --- a/src/gallium/winsys/d3d12/wgl/d3d12_wgl_public.h +++ b/src/gallium/winsys/d3d12/wgl/d3d12_wgl_public.h @@ -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 diff --git a/src/gallium/winsys/d3d12/wgl/d3d12_wgl_winsys.c b/src/gallium/winsys/d3d12/wgl/d3d12_wgl_winsys.c index 7e84501f780..cf098daa738 100644 --- a/src/gallium/winsys/d3d12/wgl/d3d12_wgl_winsys.c +++ b/src/gallium/winsys/d3d12/wgl/d3d12_wgl_winsys.c @@ -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; } diff --git a/src/gallium/winsys/d3d12/wgl/meson.build b/src/gallium/winsys/d3d12/wgl/meson.build index 9f41560b811..8f05beeb885 100644 --- a/src/gallium/winsys/d3d12/wgl/meson.build +++ b/src/gallium/winsys/d3d12/wgl/meson.build @@ -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', ) |