wgl: Add support for Xbox GDK.

This patch is comprised of three main changes:
- Add a "shim" for GDI, since Xbox doesn't expose this library
- New framebuffer file, to support the Xbox "windowing" system
- Implement a custom WndProc hook for Xbox, since SetWindowsHookEx isn't supported either

Other than that, it's similar to the previous Xbox commits which mostly disable Win32-specific logic.

Co-authored-by: Ethan Lee <flibitijibibo@gmail.com>
Co-authored-by: David Jacewicz <david.jacewicz@protonmail.com>
Co-authored-by: tieuchanlong <tieuchanlong@gmail.com>
Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19022>
This commit is contained in:
Caleb Cornett
2023-01-11 10:48:49 -05:00
committed by Marge Bot
parent 75415e58e3
commit 882a78b8ad
21 changed files with 632 additions and 21 deletions

View File

@@ -25,27 +25,33 @@ if not with_shared_glapi
_c_args_wgl += '-D_GLAPI_NO_EXPORTS'
endif
files_libwgl = files(
'stw_context.c',
'stw_device.c',
'stw_ext_context.c',
'stw_ext_extensionsstring.c',
'stw_ext_interop.c',
'stw_ext_pbuffer.c',
'stw_ext_pixelformat.c',
'stw_ext_rendertexture.c',
'stw_ext_swapinterval.c',
'stw_framebuffer.c',
'stw_getprocaddress.c',
'stw_image.c',
'stw_nopfuncs.c',
'stw_nopfuncs.h',
'stw_pixelformat.c',
'stw_st.c',
'stw_tls.c',
)
if target_machine.system().startswith('Gaming.Xbox')
files_libwgl += files('stw_gdishim.c')
endif
libwgl = static_library(
'wgl',
files(
'stw_context.c',
'stw_device.c',
'stw_ext_context.c',
'stw_ext_extensionsstring.c',
'stw_ext_interop.c',
'stw_ext_pbuffer.c',
'stw_ext_pixelformat.c',
'stw_ext_rendertexture.c',
'stw_ext_swapinterval.c',
'stw_framebuffer.c',
'stw_getprocaddress.c',
'stw_image.c',
'stw_nopfuncs.c',
'stw_nopfuncs.h',
'stw_pixelformat.c',
'stw_st.c',
'stw_tls.c',
),
files_libwgl,
c_args : [
'-D_GDI32_', # prevent wgl* being declared __declspec(dllimport)
_c_args_wgl

View File

@@ -42,6 +42,7 @@
#include "util/u_atomic.h"
#include "hud/hud_context.h"
#include "stw_gdishim.h"
#include "gldrv.h"
#include "stw_device.h"
#include "stw_winsys.h"

View File

@@ -30,6 +30,7 @@
#include <windows.h>
#include <GL/gl.h>
#include <stw_gdishim.h>
#include <gldrv.h>
struct hud_context;

View File

@@ -40,6 +40,7 @@
#include "stw_device.h"
#include "stw_winsys.h"
#include "stw_pixelformat.h"
#include "stw_gdishim.h"
#include "gldrv.h"
#include "stw_tls.h"
#include "stw_framebuffer.h"
@@ -72,6 +73,7 @@ stw_get_param(struct pipe_frontend_screen *fscreen,
static int
get_refresh_rate(void)
{
#ifndef _GAMING_XBOX
DEVMODE devModes;
if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devModes)) {
@@ -82,6 +84,9 @@ get_refresh_rate(void)
/* reasonable default */
return 60;
}
#else
return 60;
#endif /* _GAMING_XBOX */
}
static bool

View File

@@ -35,6 +35,7 @@
#include "util/u_dynarray.h"
#include "util/xmlconfig.h"
#include <GL/gl.h>
#include "stw_gdishim.h"
#include "gldrv.h"
#include "stw_pixelformat.h"

View File

@@ -30,6 +30,7 @@
#include <GL/gl.h>
#include <GL/wglext.h>
#include "stw_gdishim.h"
#include "gldrv.h"
#include "stw_context.h"
#include "stw_device.h"

View File

@@ -48,6 +48,7 @@
static LRESULT CALLBACK
WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
#ifndef _GAMING_XBOX
MINMAXINFO *pMMI;
switch (uMsg) {
case WM_GETMINMAXINFO:
@@ -61,6 +62,7 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
default:
break;
}
#endif /* _GAMING_XBOX */
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
@@ -78,8 +80,10 @@ stw_pbuffer_create(const struct stw_pixelformat_info *pfi, int iWidth, int iHeig
WNDCLASS wc;
memset(&wc, 0, sizeof wc);
wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
#ifndef _GAMING_XBOX
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
#endif
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "wglpbuffer";
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;

View File

@@ -37,6 +37,7 @@
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
#include "stw_gdishim.h"
#include "gldrv.h"
#include "stw_context.h"
#include "stw_device.h"

View File

@@ -37,6 +37,7 @@
#include "frontend/api.h"
#include <GL/gl.h>
#include "stw_gdishim.h"
#include "gldrv.h"
#include "stw_framebuffer.h"
#include "stw_device.h"
@@ -178,11 +179,13 @@ stw_framebuffer_get_size(struct stw_framebuffer *fb)
client_pos.x = 0;
client_pos.y = 0;
#ifndef _GAMING_XBOX
if (ClientToScreen(fb->hWnd, &client_pos) &&
GetWindowRect(fb->hWnd, &window_rect)) {
fb->client_rect.left = client_pos.x - window_rect.left;
fb->client_rect.top = client_pos.y - window_rect.top;
}
#endif
fb->client_rect.right = fb->client_rect.left + fb->width;
fb->client_rect.bottom = fb->client_rect.top + fb->height;
@@ -204,6 +207,7 @@ stw_framebuffer_get_size(struct stw_framebuffer *fb)
}
#ifndef _GAMING_XBOX
/**
* @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx
* @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx
@@ -263,6 +267,40 @@ stw_call_window_proc(int nCode, WPARAM wParam, LPARAM lParam)
return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);
}
#else
LRESULT CALLBACK
stw_call_window_proc_xbox(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
WNDPROC prev_wndproc = NULL;
/* We check that the stw_dev object is initialized before we try to do
* anything with it. Otherwise, in multi-threaded programs there's a
* chance of executing this code before the stw_dev object is fully
* initialized.
*/
if (stw_dev && stw_dev->initialized) {
if (message == WM_DESTROY) {
stw_lock_framebuffers(stw_dev);
struct stw_framebuffer *fb = stw_framebuffer_from_hwnd_locked(hWnd);
if (fb) {
struct stw_context *current_context = stw_current_context();
struct st_context *st = current_context &&
current_context->current_framebuffer == fb ? current_context->st : NULL;
prev_wndproc = fb->prev_wndproc;
stw_framebuffer_release_locked(fb, st);
}
stw_unlock_framebuffers(stw_dev);
}
}
/* Pass the parameters up the chain, if applicable */
if (prev_wndproc)
return prev_wndproc(hWnd, message, wParam, lParam);
return 0;
}
#endif /* _GAMING_XBOX */
/**
@@ -286,6 +324,10 @@ stw_framebuffer_create(HWND hWnd, const struct stw_pixelformat_info *pfi, enum s
fb->winsys_framebuffer =
stw_dev->stw_winsys->create_framebuffer(stw_dev->screen, hWnd, pfi->iPixelFormat);
#ifdef _GAMING_XBOX
fb->prev_wndproc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)&stw_call_window_proc_xbox);
#endif
/*
* We often need a displayable pixel format to make GDI happy. Set it
* here (always 1, i.e., out first pixel format) where appropriate.

View File

@@ -132,6 +132,11 @@ struct stw_framebuffer
int swap_interval;
int64_t prev_swap_time;
#ifdef _GAMING_XBOX
/* For the WndProc hook chain */
WNDPROC prev_wndproc;
#endif
/**
* This is protected by stw_device::fb_mutex, not the mutex above.
*

View File

@@ -0,0 +1,75 @@
/*
* 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.
*/
/* Certain Win32-like platforms (i.e. Xbox GDK) do not support the GDI library.
* stw_gdishim acts as a shim layer to provide the APIs required for gallium.
*/
#include "stw_gdishim.h"
#include "stw_pixelformat.h"
#include "stw_framebuffer.h"
int GetPixelFormat(HDC hdc)
{
return stw_pixelformat_get(hdc);
}
int DescribePixelFormat(
HDC hdc,
int iPixelFormat,
UINT nBytes,
LPPIXELFORMATDESCRIPTOR ppfd
)
{
if (iPixelFormat >= stw_pixelformat_get_count(hdc))
return 0;
const struct stw_pixelformat_info* info = stw_pixelformat_get_info(iPixelFormat);
memcpy(ppfd, &info->pfd, nBytes);
return 1;
}
BOOL SetPixelFormat(
HDC hdc,
int format,
const PIXELFORMATDESCRIPTOR* ppfd
)
{
// TODO: can we support this?
#if 0
struct stw_framebuffer* fb;
fb = stw_framebuffer_from_hdc(hdc);
if (fb && fb->pfi) {
fb->pfi->iPixelFormat = format;
stw_framebuffer_unlock(fb);
return TRUE;
}
#endif
return FALSE;
}
void StretchDIBits(HDC hdc, unsigned int xDest, unsigned int yDest, unsigned int DestWidth, unsigned int DestHeight, unsigned int xSrc, unsigned int ySrc, unsigned int SrcWidth, unsigned int SrcHeight, void* lpBits, void* lpbmi, unsigned int iUsage, DWORD rop)
{
}

View File

@@ -0,0 +1,152 @@
/*
* 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.
*/
/* Certain Win32-like platforms (i.e. Xbox GDK) do not support the GDI library.
* stw_gdishim acts as a shim layer to provide the APIs required for gallium.
*/
#ifndef STW_GDISHIM_H
#define STW_GDISHIM_H
#ifdef _GAMING_XBOX
#include <windows.h>
/* Handles */
typedef void* HMONITOR;
/* Stubs */
#define WindowFromDC(hdc) (HWND)hdc
#define GetDC(hwnd) (HDC)hwnd
#define ReleaseDC(hwnd, hdc) 1
void StretchDIBits(HDC hdc, unsigned int xDest, unsigned int yDest, unsigned int DestWidth, unsigned int DestHeight, unsigned int xSrc, unsigned int ySrc, unsigned int SrcWidth, unsigned int SrcHeight, void* lpBits, void* lpbmi, unsigned int iUsage, DWORD rop);
/* Layer plane descriptor */
typedef struct tagLAYERPLANEDESCRIPTOR { // lpd
WORD nSize;
WORD nVersion;
DWORD dwFlags;
BYTE iPixelType;
BYTE cColorBits;
BYTE cRedBits;
BYTE cRedShift;
BYTE cGreenBits;
BYTE cGreenShift;
BYTE cBlueBits;
BYTE cBlueShift;
BYTE cAlphaBits;
BYTE cAlphaShift;
BYTE cAccumBits;
BYTE cAccumRedBits;
BYTE cAccumGreenBits;
BYTE cAccumBlueBits;
BYTE cAccumAlphaBits;
BYTE cDepthBits;
BYTE cStencilBits;
BYTE cAuxBuffers;
BYTE iLayerPlane;
BYTE bReserved;
COLORREF crTransparent;
} LAYERPLANEDESCRIPTOR, * PLAYERPLANEDESCRIPTOR, FAR* LPLAYERPLANEDESCRIPTOR;
/* WGL */
typedef struct _WGLSWAP
{
HDC hdc;
UINT uiFlags;
} WGLSWAP;
#define WGL_SWAPMULTIPLE_MAX 16
WINGDIAPI DWORD WINAPI
wglSwapMultipleBuffers(UINT n,
CONST WGLSWAP* ps);
WINGDIAPI BOOL WINAPI wglDeleteContext(HGLRC);
/* wglSwapLayerBuffers flags */
#define WGL_SWAP_MAIN_PLANE 0x00000001
/* Pixel format descriptor */
typedef struct tagPIXELFORMATDESCRIPTOR
{
WORD nSize;
WORD nVersion;
DWORD dwFlags;
BYTE iPixelType;
BYTE cColorBits;
BYTE cRedBits;
BYTE cRedShift;
BYTE cGreenBits;
BYTE cGreenShift;
BYTE cBlueBits;
BYTE cBlueShift;
BYTE cAlphaBits;
BYTE cAlphaShift;
BYTE cAccumBits;
BYTE cAccumRedBits;
BYTE cAccumGreenBits;
BYTE cAccumBlueBits;
BYTE cAccumAlphaBits;
BYTE cDepthBits;
BYTE cStencilBits;
BYTE cAuxBuffers;
BYTE iLayerType;
BYTE bReserved;
DWORD dwLayerMask;
DWORD dwVisibleMask;
DWORD dwDamageMask;
} PIXELFORMATDESCRIPTOR, * PPIXELFORMATDESCRIPTOR, FAR* LPPIXELFORMATDESCRIPTOR;
/* Bitmap Info */
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO, * LPBITMAPINFO, * PBITMAPINFO;
/* Glyph Info */
typedef struct tagGLYPHMETRICSFLOAT {
FLOAT gmfBlackBoxX;
FLOAT gmfBlackBoxY;
#ifndef _GAMING_XBOX
POINTFLOAT gmfptGlyphOrigin;
#else
FLOAT gmfptGlyphOriginX;
FLOAT gmfptGlyphOriginY;
#endif
FLOAT gmfCellIncX;
FLOAT gmfCellIncY;
} GLYPHMETRICSFLOAT, *PGLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT;
#endif /* _GAMING_XBOX */
#endif /* STW_PIXELFORMAT_H */

View File

@@ -35,6 +35,7 @@
#include "glapi/glapi.h"
#include "stw_device.h"
#include "stw_gdishim.h"
#include "gldrv.h"
#include "stw_nopfuncs.h"

View File

@@ -34,6 +34,7 @@
#include "util/u_memory.h"
#include <GL/gl.h>
#include "stw_gdishim.h"
#include "gldrv.h"
#include "stw_device.h"
#include "stw_framebuffer.h"

View File

@@ -73,6 +73,7 @@ stw_tls_init(void)
* XXX: Except for the current thread since it there is an explicit
* stw_tls_init_thread() call for it later on.
*/
#ifndef _GAMING_XBOX
if (1) {
DWORD dwCurrentProcessId = GetCurrentProcessId();
DWORD dwCurrentThreadId = GetCurrentThreadId();
@@ -103,6 +104,7 @@ stw_tls_init(void)
CloseHandle(hSnapshot);
}
}
#endif /* _GAMING_XBOX */
return TRUE;
}
@@ -127,10 +129,14 @@ stw_tls_data_create(DWORD dwThreadId)
data->dwThreadId = dwThreadId;
#ifndef _GAMING_XBOX
data->hCallWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC,
stw_call_window_proc,
NULL,
dwThreadId);
#else
data->hCallWndProcHook = NULL;
#endif
if (data->hCallWndProcHook == NULL) {
goto no_hook;
}
@@ -161,10 +167,12 @@ stw_tls_data_destroy(struct stw_tls_data *data)
debug_printf("%s(0x%04lx)\n", __func__, data->dwThreadId);
}
#ifndef _GAMING_XBOX
if (data->hCallWndProcHook) {
UnhookWindowsHookEx(data->hCallWndProcHook);
data->hCallWndProcHook = NULL;
}
#endif
free(data);
}

View File

@@ -42,6 +42,7 @@
#include <GL/gl.h>
#include "util/u_debug.h"
#include "stw_gdishim.h"
#include "gldrv.h"
#include "stw_context.h"
#include "stw_pixelformat.h"
@@ -223,6 +224,7 @@ wglUseFontBitmapsW(
DWORD count,
DWORD listBase )
{
#ifndef _GAMING_XBOX
GLYPHMETRICS gm;
MAT2 tra;
FIXED one, minus_one, zero;
@@ -273,6 +275,9 @@ wglUseFontBitmapsW(
free(buffer);
return result;
#else
return FALSE;
#endif /* _GAMING_XBOX */
}
WINGDIAPI BOOL APIENTRY

View File

@@ -0,0 +1,294 @@
/*
* 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 <new>
#include <windows.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_resource.h"
#include "d3d12/d3d12_screen.h"
constexpr uint32_t num_buffers = 2;
static int current_backbuffer_index = 0;
static bool has_signaled_first_time = false;
static int cached_interval = 1;
struct d3d12_wgl_framebuffer {
struct stw_winsys_framebuffer base;
struct d3d12_screen *screen;
enum pipe_format pformat;
ID3D12Resource *images[num_buffers];
D3D12_CPU_DESCRIPTOR_HANDLE rtvs[num_buffers];
ID3D12DescriptorHeap *rtvHeap;
pipe_resource *buffers[num_buffers];
};
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,
pipe_context *ctx)
{
struct d3d12_wgl_framebuffer *framebuffer = d3d12_wgl_framebuffer(fb);
struct pipe_fence_handle *fence = NULL;
if (ctx) {
/* 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);
}
}
framebuffer->rtvHeap->Release();
for (int i = 0; i < num_buffers; ++i) {
if (framebuffer->buffers[i]) {
d3d12_resource_release(d3d12_resource(framebuffer->buffers[i]));
pipe_resource_reference(&framebuffer->buffers[i], NULL);
}
}
delete framebuffer;
}
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);
if (framebuffer->rtvHeap == NULL) {
D3D12_DESCRIPTOR_HEAP_DESC descHeapDesc = {};
descHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
descHeapDesc.NumDescriptors = num_buffers;
framebuffer->screen->dev->CreateDescriptorHeap(&descHeapDesc,
IID_PPV_ARGS(&framebuffer->rtvHeap));
}
// Release the old images
for (int i = 0; i < num_buffers; i++) {
if (framebuffer->buffers[i]) {
d3d12_resource_release(d3d12_resource(framebuffer->buffers[i]));
pipe_resource_reference(&framebuffer->buffers[i], NULL);
}
}
D3D12_HEAP_PROPERTIES heapProps = {};
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
D3D12_RESOURCE_DESC resDesc;
resDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
resDesc.Width = templ->width0;
resDesc.Height = templ->height0;
resDesc.Alignment = 0;
resDesc.DepthOrArraySize = 1;
resDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
resDesc.Format = d3d12_get_format(templ->format);
resDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
resDesc.MipLevels = 1;
resDesc.SampleDesc.Count = 1;
resDesc.SampleDesc.Quality = 0;
D3D12_CLEAR_VALUE optimizedClearValue = {};
optimizedClearValue.Format = resDesc.Format;
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Format = resDesc.Format;
rtvDesc.Texture2D.MipSlice = 0;
rtvDesc.Texture2D.PlaneSlice = 0;
for (int i = 0; i < num_buffers; i++) {
if (FAILED(framebuffer->screen->dev->CreateCommittedResource(
&heapProps,
D3D12_HEAP_FLAG_ALLOW_DISPLAY,
&resDesc,
D3D12_RESOURCE_STATE_PRESENT,
&optimizedClearValue,
IID_PPV_ARGS(&framebuffer->images[i])
))) {
assert(0);
}
framebuffer->rtvs[i].ptr =
framebuffer->rtvHeap->GetCPUDescriptorHandleForHeapStart().ptr +
((int64_t)i * framebuffer->screen->dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV));
framebuffer->screen->dev->CreateRenderTargetView(
framebuffer->images[i],
&rtvDesc,
framebuffer->rtvs[i]
);
}
framebuffer->pformat = templ->format;
}
static boolean
d3d12_wgl_framebuffer_present(stw_winsys_framebuffer *fb, int interval)
{
auto framebuffer = d3d12_wgl_framebuffer(fb);
D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParams = {};
planeParams.Token = framebuffer->screen->frame_token;
planeParams.ResourceCount = 1;
planeParams.ppResources = &framebuffer->images[current_backbuffer_index];
D3D12XBOX_PRESENT_PARAMETERS presentParams = {};
presentParams.Flags = (interval == 0) ?
D3D12XBOX_PRESENT_FLAG_IMMEDIATE :
D3D12XBOX_PRESENT_FLAG_NONE;
if (cached_interval != interval) {
framebuffer->screen->dev->SetFrameIntervalX(
nullptr,
D3D12XBOX_FRAME_INTERVAL_60_HZ,
interval,
D3D12XBOX_FRAME_INTERVAL_FLAG_NONE
);
cached_interval = interval;
}
framebuffer->screen->cmdqueue->PresentX(1, &planeParams, &presentParams);
current_backbuffer_index = !current_backbuffer_index;
framebuffer->screen->frame_token = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL;
framebuffer->screen->dev->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE,
nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE,
&framebuffer->screen->frame_token);
return true;
}
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;
UINT index = current_backbuffer_index;
if (statt == ST_ATTACHMENT_FRONT_LEFT)
index = !index;
if (framebuffer->buffers[index]) {
pipe_reference(NULL, &framebuffer->buffers[index]->reference);
return framebuffer->buffers[index];
}
ID3D12Resource *res = framebuffer->images[index];
struct winsys_handle handle;
memset(&handle, 0, sizeof(handle));
handle.type = WINSYS_HANDLE_TYPE_D3D12_RES;
handle.format = framebuffer->pformat;
handle.com_obj = res;
D3D12_RESOURCE_DESC res_desc = GetDesc(res);
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;
pipe_resource_reference(&framebuffer->buffers[index],
pscreen->resource_from_handle(pscreen, &templ, &handle,
PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE));
return framebuffer->buffers[index];
}
struct stw_winsys_framebuffer*
d3d12_wgl_create_framebuffer(struct pipe_screen *screen,
HWND hWnd,
int iPixelFormat)
{
const struct stw_pixelformat_info *pfi =
stw_pixelformat_get_info(iPixelFormat);
if (!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER) ||
(pfi->pfd.dwFlags & PFD_SUPPORT_GDI))
return NULL;
struct d3d12_wgl_framebuffer *fb = CALLOC_STRUCT(d3d12_wgl_framebuffer);
if (!fb)
return NULL;
new (fb) struct d3d12_wgl_framebuffer();
fb->screen = d3d12_screen(screen);
fb->images[0] = NULL;
fb->images[1] = NULL;
fb->rtvHeap = NULL;
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;
// Xbox applications must manually handle Suspend/Resume events on the Command Queue.
// To allow the application to access the queue, we store a pointer in the HWND's user data.
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) fb->screen->cmdqueue);
// Schedule the frame interval and origin frame event
fb->screen->dev->SetFrameIntervalX(
nullptr,
D3D12XBOX_FRAME_INTERVAL_60_HZ,
cached_interval,
D3D12XBOX_FRAME_INTERVAL_FLAG_NONE
);
fb->screen->dev->ScheduleFrameEventX(
D3D12XBOX_FRAME_EVENT_ORIGIN,
0,
nullptr,
D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE
);
return &fb->base;
}

View File

@@ -19,10 +19,16 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
files_libd3d12winsys = files('d3d12_wgl_winsys.c')
if target_machine.system().startswith('Gaming.Xbox')
files_libd3d12winsys += files('d3d12_wgl_framebuffer_xbox.cpp')
else
files_libd3d12winsys += files('d3d12_wgl_framebuffer.cpp')
endif
libd3d12winsys = static_library(
'd3d12winsys',
files('d3d12_wgl_framebuffer.cpp', 'd3d12_wgl_winsys.c'),
files_libd3d12winsys,
include_directories : [inc_src, inc_wgl, inc_include, inc_gallium, inc_gallium_aux, inc_gallium_drivers],
dependencies : [dep_dxheaders, idep_nir_headers],
gnu_symbol_visibility : 'hidden',

View File

@@ -44,6 +44,7 @@
#include "util/u_memory.h"
#include "frontend/sw_winsys.h"
#include "gdi_sw_winsys.h"
#include "wgl/stw_gdishim.h"
struct gdi_sw_displaytarget

View File

@@ -22,6 +22,6 @@ libwsgdi = static_library(
'wsgdi',
'gdi_sw_winsys.c',
include_directories : [
inc_src, inc_include, inc_gallium, inc_gallium_aux, inc_gallium_drivers,
inc_src, inc_include, inc_gallium, inc_gallium_aux, inc_gallium_drivers, inc_frontends
],
)

View File

@@ -26,6 +26,7 @@ inc_gallium_aux = include_directories('gallium/auxiliary')
inc_amd_common = include_directories('amd/common')
inc_tool = include_directories('tool')
inc_virtio_gpu = include_directories('virtio/virtio-gpu')
inc_frontends = include_directories('gallium/frontends')
pps_datasources = []
pps_includes = []