Path: blob/21.2-virgl/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp
4566 views
/*1* Copyright © Microsoft Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "d3d12_wgl_public.h"2425#include <Windows.h>26#include <dxgi1_4.h>27#include <directx/d3d12.h>28#include <wrl.h>2930#include "util/u_memory.h"31#include "util/u_inlines.h"32#include "frontend/api.h"33#include "frontend/winsys_handle.h"3435#include "stw_device.h"36#include "stw_pixelformat.h"37#include "stw_winsys.h"3839#include "d3d12/d3d12_format.h"40#include "d3d12/d3d12_resource.h"41#include "d3d12/d3d12_screen.h"4243using Microsoft::WRL::ComPtr;44constexpr uint32_t num_buffers = 2;4546struct d3d12_wgl_framebuffer {47struct stw_winsys_framebuffer base;4849struct d3d12_screen *screen;50enum pipe_format pformat;51HWND window;52ComPtr<IDXGISwapChain3> swapchain;53struct pipe_resource *buffers[num_buffers];54};5556static struct d3d12_wgl_framebuffer *57d3d12_wgl_framebuffer(struct stw_winsys_framebuffer *fb)58{59return (struct d3d12_wgl_framebuffer *)fb;60}6162static void63d3d12_wgl_framebuffer_destroy(struct stw_winsys_framebuffer *fb,64pipe_context *ctx)65{66struct d3d12_wgl_framebuffer *framebuffer = d3d12_wgl_framebuffer(fb);67struct pipe_fence_handle *fence = NULL;6869if (ctx) {70/* Ensure all resources are flushed */71ctx->flush(ctx, &fence, PIPE_FLUSH_HINT_FINISH);72if (fence) {73ctx->screen->fence_finish(ctx->screen, ctx, fence, PIPE_TIMEOUT_INFINITE);74ctx->screen->fence_reference(ctx->screen, &fence, NULL);75}76}7778for (int i = 0; i < num_buffers; ++i) {79if (framebuffer->buffers[i]) {80d3d12_resource_release(d3d12_resource(framebuffer->buffers[i]));81pipe_resource_reference(&framebuffer->buffers[i], NULL);82}83}8485delete framebuffer;86}8788static void89d3d12_wgl_framebuffer_resize(stw_winsys_framebuffer *fb,90pipe_context *ctx,91pipe_resource *templ)92{93struct d3d12_wgl_framebuffer *framebuffer = d3d12_wgl_framebuffer(fb);94struct d3d12_dxgi_screen *screen = d3d12_dxgi_screen(framebuffer->screen);9596DXGI_SWAP_CHAIN_DESC1 desc = {};97desc.BufferCount = num_buffers;98desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;99desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;100desc.Format = d3d12_get_format(templ->format);101desc.Width = templ->width0;102desc.Height = templ->height0;103desc.SampleDesc.Count = 1;104desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;105106framebuffer->pformat = templ->format;107108if (!framebuffer->swapchain) {109ComPtr<IDXGISwapChain1> swapchain1;110if (FAILED(screen->factory->CreateSwapChainForHwnd(111screen->base.cmdqueue,112framebuffer->window,113&desc,114nullptr,115nullptr,116&swapchain1))) {117debug_printf("D3D12: failed to create swapchain");118return;119}120121swapchain1.As(&framebuffer->swapchain);122123screen->factory->MakeWindowAssociation(framebuffer->window,124DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_PRINT_SCREEN);125}126else {127struct pipe_fence_handle *fence = NULL;128129/* Ensure all resources are flushed */130ctx->flush(ctx, &fence, PIPE_FLUSH_HINT_FINISH);131if (fence) {132ctx->screen->fence_finish(ctx->screen, ctx, fence, PIPE_TIMEOUT_INFINITE);133ctx->screen->fence_reference(ctx->screen, &fence, NULL);134}135136for (int i = 0; i < num_buffers; ++i) {137if (framebuffer->buffers[i]) {138d3d12_resource_release(d3d12_resource(framebuffer->buffers[i]));139pipe_resource_reference(&framebuffer->buffers[i], NULL);140}141}142if (FAILED(framebuffer->swapchain->ResizeBuffers(num_buffers, desc.Width, desc.Height, desc.Format, desc.Flags))) {143debug_printf("D3D12: failed to resize swapchain");144}145}146}147148static boolean149d3d12_wgl_framebuffer_present(stw_winsys_framebuffer *fb)150{151auto framebuffer = d3d12_wgl_framebuffer(fb);152if (!framebuffer->swapchain) {153debug_printf("D3D12: Cannot present; no swapchain");154return false;155}156157if (stw_dev->swap_interval < 1)158return S_OK == framebuffer->swapchain->Present(0, DXGI_PRESENT_ALLOW_TEARING);159else160return S_OK == framebuffer->swapchain->Present(stw_dev->swap_interval, 0);161}162163static struct pipe_resource *164d3d12_wgl_framebuffer_get_resource(struct stw_winsys_framebuffer *pframebuffer,165st_attachment_type statt)166{167auto framebuffer = d3d12_wgl_framebuffer(pframebuffer);168auto pscreen = &framebuffer->screen->base;169170if (!framebuffer->swapchain)171return nullptr;172173UINT index = framebuffer->swapchain->GetCurrentBackBufferIndex();174if (statt == ST_ATTACHMENT_FRONT_LEFT)175index = !index;176177if (framebuffer->buffers[index]) {178pipe_reference(NULL, &framebuffer->buffers[index]->reference);179return framebuffer->buffers[index];180}181182ID3D12Resource *res;183framebuffer->swapchain->GetBuffer(index, IID_PPV_ARGS(&res));184if (!res)185return nullptr;186187struct winsys_handle handle;188memset(&handle, 0, sizeof(handle));189handle.type = WINSYS_HANDLE_TYPE_D3D12_RES;190handle.com_obj = res;191192D3D12_RESOURCE_DESC res_desc = res->GetDesc();193194struct pipe_resource templ;195memset(&templ, 0, sizeof(templ));196templ.target = PIPE_TEXTURE_2D;197templ.format = framebuffer->pformat;198templ.width0 = res_desc.Width;199templ.height0 = res_desc.Height;200templ.depth0 = 1;201templ.array_size = res_desc.DepthOrArraySize;202templ.nr_samples = res_desc.SampleDesc.Count;203templ.last_level = res_desc.MipLevels - 1;204templ.bind = PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET;205templ.usage = PIPE_USAGE_DEFAULT;206templ.flags = 0;207208pipe_resource_reference(&framebuffer->buffers[index],209pscreen->resource_from_handle(pscreen, &templ, &handle,210PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE));211return framebuffer->buffers[index];212}213214struct stw_winsys_framebuffer *215d3d12_wgl_create_framebuffer(struct pipe_screen *screen,216HDC hDC,217int iPixelFormat)218{219const struct stw_pixelformat_info *pfi =220stw_pixelformat_get_info(iPixelFormat);221if (!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER) ||222(pfi->pfd.dwFlags & PFD_SUPPORT_GDI))223return NULL;224225struct d3d12_wgl_framebuffer *fb = CALLOC_STRUCT(d3d12_wgl_framebuffer);226if (!fb)227return NULL;228229new (fb) struct d3d12_wgl_framebuffer();230231fb->window = WindowFromDC(hDC);232fb->screen = d3d12_screen(screen);233fb->base.destroy = d3d12_wgl_framebuffer_destroy;234fb->base.resize = d3d12_wgl_framebuffer_resize;235fb->base.present = d3d12_wgl_framebuffer_present;236fb->base.get_resource = d3d12_wgl_framebuffer_get_resource;237238return &fb->base;239}240241242