update SDL3 to 3.1.6.

This commit is contained in:
Sasha Szpakowski
2024-11-16 00:44:49 -04:00
parent aecb572558
commit 8c4c8655aa
231 changed files with 16035 additions and 3495 deletions
+1 -1
View File
@@ -767,7 +767,7 @@ static SDL_Sandbox SDL_DetectSandbox(void)
}
if (access("/run/host/container-manager", F_OK) == 0) {
return SDL_SANDBOX_UNKNOWN;
return SDL_SANDBOX_UNKNOWN_CONTAINER;
}
#elif defined(SDL_PLATFORM_MACOS)
+2
View File
@@ -442,9 +442,11 @@ SDL_PropertiesID SDL_GetAudioStreamProperties(SDL_AudioStream *stream)
SDL_InvalidParamError("stream");
return 0;
}
SDL_LockMutex(stream->lock);
if (stream->props == 0) {
stream->props = SDL_CreateProperties();
}
SDL_UnlockMutex(stream->lock);
return stream->props;
}
@@ -233,7 +233,7 @@ static bool EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
if ((SDL3 === undefined) || (SDL3.audio_recording === undefined)) { return; }
audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0);
SDL3.audio_recording.currentRecordingBuffer = audioProcessingEvent.inputBuffer;
dynCall('vi', $2, [$3]);
dynCall('ii', $2, [$3]);
};
SDL3.audio_recording.mediaStreamNode.connect(SDL3.audio_recording.scriptProcessorNode);
SDL3.audio_recording.scriptProcessorNode.connect(SDL3.audioContext.destination);
@@ -249,7 +249,7 @@ static bool EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
SDL3.audio_recording.silenceBuffer.getChannelData(0).fill(0.0);
var silence_callback = function() {
SDL3.audio_recording.currentRecordingBuffer = SDL3.audio_recording.silenceBuffer;
dynCall('vi', $2, [$3]);
dynCall('ii', $2, [$3]);
};
SDL3.audio_recording.silenceTimer = setInterval(silence_callback, ($1 / SDL3.audioContext.sampleRate) * 1000);
@@ -274,7 +274,7 @@ static bool EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
SDL3.audio_playback.silenceBuffer = undefined;
}
SDL3.audio_playback.currentPlaybackBuffer = e['outputBuffer'];
dynCall('vi', $2, [$3]);
dynCall('ii', $2, [$3]);
};
SDL3.audio_playback.scriptProcessorNode['connect'](SDL3.audioContext['destination']);
@@ -292,7 +292,7 @@ static bool EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device)
// the buffer that gets filled here just gets ignored, so the app can make progress
// and/or avoid flooding audio queues until we can actually play audio.
SDL3.audio_playback.currentPlaybackBuffer = SDL3.audio_playback.silenceBuffer;
dynCall('vi', $2, [$3]);
dynCall('ii', $2, [$3]);
SDL3.audio_playback.currentPlaybackBuffer = undefined;
};
+2 -2
View File
@@ -146,8 +146,8 @@ const char *SDL_GetAndroidInternalStoragePath(void)
return NULL;
}
SDL_DECLSPEC JNIEnv *SDLCALL SDL_GetAndroidJNIEnv(void);
JNIEnv *SDL_GetAndroidJNIEnv(void)
SDL_DECLSPEC void *SDLCALL SDL_GetAndroidJNIEnv(void);
void *SDL_GetAndroidJNIEnv(void)
{
SDL_Unsupported();
return NULL;
+2 -2
View File
@@ -2177,7 +2177,7 @@ bool Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *b
//////////////////////////////////////////////////////////////////////////////
*/
JNIEnv *SDL_GetAndroidJNIEnv(void)
void *SDL_GetAndroidJNIEnv(void)
{
return Android_JNI_GetEnv();
}
@@ -2400,7 +2400,7 @@ const char *SDL_GetAndroidCachePath(void)
// fileObj = context.getExternalFilesDir();
mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
"getCacheDir", "(Ljava/lang/String;)Ljava/io/File;");
"getCacheDir", "()Ljava/io/File;");
fileObject = (*env)->CallObjectMethod(env, context, mid, NULL);
if (!fileObject) {
SDL_SetError("Couldn't get cache directory");
+11 -4
View File
@@ -933,14 +933,18 @@ static bool SDL_EVDEV_device_added(const char *dev_path, int udev_class)
SDL_free(item);
return false;
}
} else if (udev_class & SDL_UDEV_DEVICE_MOUSE) {
}
if (udev_class & SDL_UDEV_DEVICE_MOUSE) {
if (!SDL_EVDEV_init_mouse(item, udev_class)) {
close(item->fd);
SDL_free(item->path);
SDL_free(item);
return false;
}
} else if (udev_class & SDL_UDEV_DEVICE_KEYBOARD) {
}
if (udev_class & SDL_UDEV_DEVICE_KEYBOARD) {
if (!SDL_EVDEV_init_keyboard(item, udev_class)) {
close(item->fd);
SDL_free(item->path);
@@ -981,11 +985,14 @@ static bool SDL_EVDEV_device_removed(const char *dev_path)
if (item == _this->last) {
_this->last = prev;
}
if (item->is_touchscreen) {
SDL_EVDEV_destroy_touchscreen(item);
} else if (item->udev_class & SDL_UDEV_DEVICE_MOUSE) {
}
if (item->udev_class & SDL_UDEV_DEVICE_MOUSE) {
SDL_EVDEV_destroy_mouse(item);
} else if (item->udev_class & SDL_UDEV_DEVICE_KEYBOARD) {
}
if (item->udev_class & SDL_UDEV_DEVICE_KEYBOARD) {
SDL_EVDEV_destroy_keyboard(item);
}
close(item->fd);
+7 -3
View File
@@ -487,9 +487,13 @@ static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
return;
}
devclass = device_class(dev);
if (!devclass) {
return;
if (type == SDL_UDEV_DEVICEADDED) {
devclass = device_class(dev);
if (!devclass) {
return;
}
} else {
// The device has been removed, the class isn't available
}
// Process callbacks
+4 -4
View File
@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,1,5,0
PRODUCTVERSION 3,1,5,0
FILEVERSION 3,1,6,0
PRODUCTVERSION 3,1,6,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x40004L
@@ -23,12 +23,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "SDL\0"
VALUE "FileVersion", "3, 1, 5, 0\0"
VALUE "FileVersion", "3, 1, 6, 0\0"
VALUE "InternalName", "SDL\0"
VALUE "LegalCopyright", "Copyright (C) 2024 Sam Lantinga\0"
VALUE "OriginalFilename", "SDL3.dll\0"
VALUE "ProductName", "Simple DirectMedia Layer\0"
VALUE "ProductVersion", "3, 1, 5, 0\0"
VALUE "ProductVersion", "3, 1, 6, 0\0"
END
END
BLOCK "VarFileInfo"
+1
View File
@@ -1183,6 +1183,7 @@ SDL3_0.0.0 {
SDL_GetDefaultLogOutputFunction;
SDL_RenderDebugText;
SDL_GetSandbox;
SDL_CancelGPUCommandBuffer;
# extra symbols go here (don't modify this line)
local: *;
};
@@ -1208,3 +1208,4 @@
#define SDL_GetDefaultLogOutputFunction SDL_GetDefaultLogOutputFunction_REAL
#define SDL_RenderDebugText SDL_RenderDebugText_REAL
#define SDL_GetSandbox SDL_GetSandbox_REAL
#define SDL_CancelGPUCommandBuffer SDL_CancelGPUCommandBuffer_REAL
+4 -3
View File
@@ -225,7 +225,7 @@ SDL_DYNAPI_PROC(void,SDL_GDKSuspendGPU,(SDL_GPUDevice *a),(a),)
SDL_DYNAPI_PROC(SDL_GLContext,SDL_GL_CreateContext,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_GL_DestroyContext,(SDL_GLContext a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_GL_ExtensionSupported,(const char *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_GL_GetAttribute,(SDL_GLattr a, int *b),(a,b),return)
SDL_DYNAPI_PROC(bool,SDL_GL_GetAttribute,(SDL_GLAttr a, int *b),(a,b),return)
SDL_DYNAPI_PROC(SDL_GLContext,SDL_GL_GetCurrentContext,(void),(),return)
SDL_DYNAPI_PROC(SDL_Window*,SDL_GL_GetCurrentWindow,(void),(),return)
SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_GL_GetProcAddress,(const char *a),(a),return)
@@ -233,7 +233,7 @@ SDL_DYNAPI_PROC(bool,SDL_GL_GetSwapInterval,(int *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_GL_LoadLibrary,(const char *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_GL_MakeCurrent,(SDL_Window *a, SDL_GLContext b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_GL_ResetAttributes,(void),(),)
SDL_DYNAPI_PROC(bool,SDL_GL_SetAttribute,(SDL_GLattr a, int b),(a,b),return)
SDL_DYNAPI_PROC(bool,SDL_GL_SetAttribute,(SDL_GLAttr a, int b),(a,b),return)
SDL_DYNAPI_PROC(bool,SDL_GL_SetSwapInterval,(int a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_GL_SwapWindow,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(void,SDL_GL_UnloadLibrary,(void),(),)
@@ -255,7 +255,7 @@ SDL_DYNAPI_PROC(const char*,SDL_GetAndroidCachePath,(void),(),return)
SDL_DYNAPI_PROC(const char*,SDL_GetAndroidExternalStoragePath,(void),(),return)
SDL_DYNAPI_PROC(Uint32,SDL_GetAndroidExternalStorageState,(void),(),return)
SDL_DYNAPI_PROC(const char*,SDL_GetAndroidInternalStoragePath,(void),(),return)
SDL_DYNAPI_PROC(JNIEnv*,SDL_GetAndroidJNIEnv,(void),(),return)
SDL_DYNAPI_PROC(void*,SDL_GetAndroidJNIEnv,(void),(),return)
SDL_DYNAPI_PROC(int,SDL_GetAndroidSDKVersion,(void),(),return)
SDL_DYNAPI_PROC(const char*,SDL_GetAppMetadataProperty,(const char *a),(a),return)
SDL_DYNAPI_PROC(SDL_AssertionHandler,SDL_GetAssertionHandler,(void **a),(a),return)
@@ -1214,3 +1214,4 @@ SDL_DYNAPI_PROC(bool,SDL_SetErrorV,(SDL_PRINTF_FORMAT_STRING const char *a,va_li
SDL_DYNAPI_PROC(SDL_LogOutputFunction,SDL_GetDefaultLogOutputFunction,(void),(),return)
SDL_DYNAPI_PROC(bool,SDL_RenderDebugText,(SDL_Renderer *a,float b,float c,const char *d),(a,b,c,d),return)
SDL_DYNAPI_PROC(SDL_Sandbox,SDL_GetSandbox,(void),(),return)
SDL_DYNAPI_PROC(bool,SDL_CancelGPUCommandBuffer,(SDL_GPUCommandBuffer *a),(a),return)
+1 -1
View File
@@ -687,7 +687,7 @@ bool SDL_SendKeyboardKeyIgnoreModifiers(Uint64 timestamp, SDL_KeyboardID keyboar
bool SDL_SendKeyboardKeyAutoRelease(Uint64 timestamp, SDL_Scancode scancode)
{
return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_AUTORELEASE, SDL_GLOBAL_KEYBOARD_ID, 0, scancode, false);
return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_AUTORELEASE, SDL_GLOBAL_KEYBOARD_ID, 0, scancode, true);
}
void SDL_ReleaseAutoReleaseKeys(void)
+2
View File
@@ -200,6 +200,8 @@ static void SDLCALL SDL_MouseRelativeCursorVisibleChanged(void *userdata, const
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
mouse->relative_mode_cursor_visible = SDL_GetStringBoolean(hint, false);
SDL_SetCursor(NULL); // Update cursor visibility
}
// Public functions
@@ -89,6 +89,9 @@ bool SDL_CreateDirectory(const char *path)
}
#else
const bool issep = (ch == '/');
if (issep && ((ptr - parents) == 0)) {
continue; // it's just the root directory, skip it.
}
#endif
if (issep) {
@@ -40,8 +40,7 @@ bool SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_Enume
DIR *dir = opendir(path);
if (!dir) {
SDL_SetError("Can't open directory: %s", strerror(errno));
return -1;
return SDL_SetError("Can't open directory: %s", strerror(errno));
}
struct dirent *ent;
@@ -75,7 +74,7 @@ bool SDL_SYS_RemovePath(const char *path)
bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath)
{
if (rename(oldpath, newpath) < 0) {
return SDL_SetError("Can't remove path: %s", strerror(errno));
return SDL_SetError("Can't rename path: %s", strerror(errno));
}
return true;
}
@@ -102,6 +102,7 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
* NULL, &wszPath);
*/
HRESULT hr = E_FAIL;
WCHAR path[MAX_PATH];
char *result = NULL;
WCHAR *worg = NULL;
@@ -117,8 +118,9 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
org = "";
}
if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) {
WIN_SetError("Couldn't locate our prefpath");
hr = SHGetFolderPathW(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path);
if (!SUCCEEDED(hr)) {
WIN_SetErrorFromHRESULT("Couldn't locate our prefpath", hr);
return NULL;
}
+31 -1
View File
@@ -1301,6 +1301,7 @@ SDL_GPUCommandBuffer *SDL_AcquireGPUCommandBuffer(
commandBufferHeader->compute_pipeline_bound = false;
commandBufferHeader->copy_pass.command_buffer = command_buffer;
commandBufferHeader->copy_pass.in_progress = false;
commandBufferHeader->swapchain_texture_acquired = false;
commandBufferHeader->submitted = false;
return command_buffer;
@@ -2666,6 +2667,8 @@ bool SDL_AcquireGPUSwapchainTexture(
Uint32 *swapchain_texture_width,
Uint32 *swapchain_texture_height)
{
CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
if (command_buffer == NULL) {
SDL_InvalidParamError("command_buffer");
return false;
@@ -2684,12 +2687,18 @@ bool SDL_AcquireGPUSwapchainTexture(
CHECK_ANY_PASS_IN_PROGRESS("Cannot acquire a swapchain texture during a pass!", false)
}
return COMMAND_BUFFER_DEVICE->AcquireSwapchainTexture(
bool result = COMMAND_BUFFER_DEVICE->AcquireSwapchainTexture(
command_buffer,
window,
swapchain_texture,
swapchain_texture_width,
swapchain_texture_height);
if (*swapchain_texture != NULL){
commandBufferHeader->swapchain_texture_acquired = true;
}
return result;
}
bool SDL_SubmitGPUCommandBuffer(
@@ -2746,6 +2755,27 @@ SDL_GPUFence *SDL_SubmitGPUCommandBufferAndAcquireFence(
command_buffer);
}
bool SDL_CancelGPUCommandBuffer(
SDL_GPUCommandBuffer *command_buffer)
{
CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
if (command_buffer == NULL) {
SDL_InvalidParamError("command_buffer");
return false;
}
if (COMMAND_BUFFER_DEVICE->debug_mode) {
if (commandBufferHeader->swapchain_texture_acquired) {
SDL_assert_release(!"Cannot cancel command buffer after a swapchain texture has been acquired!");
return false;
}
}
return COMMAND_BUFFER_DEVICE->Cancel(
command_buffer);
}
bool SDL_WaitForGPUIdle(
SDL_GPUDevice *device)
{
+5
View File
@@ -40,6 +40,7 @@ typedef struct CommandBufferCommonHeader
Pass compute_pass;
bool compute_pipeline_bound;
Pass copy_pass;
bool swapchain_texture_acquired;
bool submitted;
} CommandBufferCommonHeader;
@@ -810,6 +811,9 @@ struct SDL_GPUDevice
SDL_GPUFence *(*SubmitAndAcquireFence)(
SDL_GPUCommandBuffer *commandBuffer);
bool (*Cancel)(
SDL_GPUCommandBuffer *commandBuffer);
bool (*Wait)(
SDL_GPURenderer *driverData);
@@ -928,6 +932,7 @@ struct SDL_GPUDevice
ASSIGN_DRIVER_FUNC(AcquireSwapchainTexture, name) \
ASSIGN_DRIVER_FUNC(Submit, name) \
ASSIGN_DRIVER_FUNC(SubmitAndAcquireFence, name) \
ASSIGN_DRIVER_FUNC(Cancel, name) \
ASSIGN_DRIVER_FUNC(Wait, name) \
ASSIGN_DRIVER_FUNC(WaitForFences, name) \
ASSIGN_DRIVER_FUNC(QueryFence, name) \
+50 -27
View File
@@ -748,7 +748,7 @@ typedef struct D3D11CommandBuffer
// Fences
D3D11Fence *fence;
Uint8 autoReleaseFence;
bool autoReleaseFence;
// Reference Counting
D3D11Buffer **usedBuffers;
@@ -3280,15 +3280,10 @@ static SDL_GPUCommandBuffer *D3D11_AcquireCommandBuffer(
SDL_zeroa(commandBuffer->computeReadWriteStorageTextureSubresources);
SDL_zeroa(commandBuffer->computeReadWriteStorageBuffers);
bool acquireFenceResult = D3D11_INTERNAL_AcquireFence(commandBuffer);
commandBuffer->autoReleaseFence = 1;
commandBuffer->autoReleaseFence = true;
SDL_UnlockMutex(renderer->acquireCommandBufferLock);
if (!acquireFenceResult) {
return NULL;
}
return (SDL_GPUCommandBuffer *)commandBuffer;
}
@@ -4806,7 +4801,8 @@ static bool D3D11_INTERNAL_MapAndCopyTextureDownload(
static bool D3D11_INTERNAL_CleanCommandBuffer(
D3D11Renderer *renderer,
D3D11CommandBuffer *commandBuffer)
D3D11CommandBuffer *commandBuffer,
bool cancel)
{
Uint32 i, j;
bool result = true;
@@ -4817,17 +4813,21 @@ static bool D3D11_INTERNAL_CleanCommandBuffer(
D3D11TransferBuffer *transferBuffer = commandBuffer->usedTransferBuffers[i];
for (j = 0; j < transferBuffer->bufferDownloadCount; j += 1) {
result &= D3D11_INTERNAL_MapAndCopyBufferDownload(
renderer,
transferBuffer,
&transferBuffer->bufferDownloads[j]);
if (!cancel) {
result &= D3D11_INTERNAL_MapAndCopyBufferDownload(
renderer,
transferBuffer,
&transferBuffer->bufferDownloads[j]);
}
}
for (j = 0; j < transferBuffer->textureDownloadCount; j += 1) {
result &= D3D11_INTERNAL_MapAndCopyTextureDownload(
renderer,
transferBuffer,
&transferBuffer->textureDownloads[j]);
if (!cancel) {
result &= D3D11_INTERNAL_MapAndCopyTextureDownload(
renderer,
transferBuffer,
&transferBuffer->textureDownloads[j]);
}
}
transferBuffer->bufferDownloadCount = 0;
@@ -4887,10 +4887,12 @@ static bool D3D11_INTERNAL_CleanCommandBuffer(
SDL_UnlockMutex(renderer->acquireCommandBufferLock);
// Remove this command buffer from the submitted list
for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
if (renderer->submittedCommandBuffers[i] == commandBuffer) {
renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
renderer->submittedCommandBufferCount -= 1;
if (!cancel) {
for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
if (renderer->submittedCommandBuffers[i] == commandBuffer) {
renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
renderer->submittedCommandBufferCount -= 1;
}
}
}
@@ -5024,7 +5026,8 @@ static bool D3D11_WaitForFences(
if (res == S_OK) {
result &= D3D11_INTERNAL_CleanCommandBuffer(
renderer,
renderer->submittedCommandBuffers[i]);
renderer->submittedCommandBuffers[i],
false);
}
}
@@ -5696,6 +5699,11 @@ static bool D3D11_Submit(
SDL_LockMutex(renderer->contextLock);
if (!D3D11_INTERNAL_AcquireFence(d3d11CommandBuffer)) {
SDL_UnlockMutex(renderer->contextLock);
return false;
}
// Notify the command buffer completion query that we have completed recording
ID3D11DeviceContext_End(
renderer->immediateContext,
@@ -5778,7 +5786,8 @@ static bool D3D11_Submit(
if (res == S_OK) {
result &= D3D11_INTERNAL_CleanCommandBuffer(
renderer,
renderer->submittedCommandBuffers[i]);
renderer->submittedCommandBuffers[i],
false);
}
}
@@ -5793,12 +5802,26 @@ static SDL_GPUFence *D3D11_SubmitAndAcquireFence(
SDL_GPUCommandBuffer *commandBuffer)
{
D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
D3D11Fence *fence = d3d11CommandBuffer->fence;
d3d11CommandBuffer->autoReleaseFence = false;
if (!D3D11_Submit(commandBuffer)) {
return NULL;
}
return (SDL_GPUFence *)d3d11CommandBuffer->fence;
}
d3d11CommandBuffer->autoReleaseFence = 0;
D3D11_Submit(commandBuffer);
static bool D3D11_Cancel(
SDL_GPUCommandBuffer *commandBuffer)
{
D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
D3D11Renderer *renderer = d3d11CommandBuffer->renderer;
bool result;
return (SDL_GPUFence *)fence;
d3d11CommandBuffer->autoReleaseFence = false;
SDL_LockMutex(renderer->contextLock);
result = D3D11_INTERNAL_CleanCommandBuffer(renderer, d3d11CommandBuffer, true);
SDL_UnlockMutex(renderer->contextLock);
return result;
}
static bool D3D11_Wait(
@@ -5822,7 +5845,7 @@ static bool D3D11_Wait(
for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
commandBuffer = renderer->submittedCommandBuffers[i];
result &= D3D11_INTERNAL_CleanCommandBuffer(renderer, commandBuffer);
result &= D3D11_INTERNAL_CleanCommandBuffer(renderer, commandBuffer, false);
}
D3D11_INTERNAL_PerformPendingDestroys(renderer);
+183 -18
View File
@@ -248,6 +248,8 @@ static D3D12_BLEND_OP SDLToD3D12_BlendOp[] = {
};
SDL_COMPILE_TIME_ASSERT(SDLToD3D12_BlendOp, SDL_arraysize(SDLToD3D12_BlendOp) == SDL_GPU_BLENDOP_MAX_ENUM_VALUE);
// These are actually color formats.
// For some genius reason, D3D12 splits format capabilites for depth-stencil views.
static DXGI_FORMAT SDLToD3D12_TextureFormat[] = {
DXGI_FORMAT_UNKNOWN, // INVALID
DXGI_FORMAT_A8_UNORM, // A8_UNORM
@@ -307,6 +309,115 @@ static DXGI_FORMAT SDLToD3D12_TextureFormat[] = {
DXGI_FORMAT_BC2_UNORM_SRGB, // BC2_UNORM_SRGB
DXGI_FORMAT_BC3_UNORM_SRGB, // BC3_UNORM_SRGB
DXGI_FORMAT_BC7_UNORM_SRGB, // BC7_UNORM_SRGB
DXGI_FORMAT_R16_UNORM, // D16_UNORM
DXGI_FORMAT_R24_UNORM_X8_TYPELESS, // D24_UNORM
DXGI_FORMAT_R32_FLOAT, // D32_FLOAT
DXGI_FORMAT_R24_UNORM_X8_TYPELESS, // D24_UNORM_S8_UINT
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, // D32_FLOAT_S8_UINT
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_FLOAT
};
SDL_COMPILE_TIME_ASSERT(SDLToD3D12_TextureFormat, SDL_arraysize(SDLToD3D12_TextureFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
static DXGI_FORMAT SDLToD3D12_DepthFormat[] = {
DXGI_FORMAT_UNKNOWN, // INVALID
DXGI_FORMAT_UNKNOWN, // A8_UNORM
DXGI_FORMAT_UNKNOWN, // R8_UNORM
DXGI_FORMAT_UNKNOWN, // R8G8_UNORM
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UNORM
DXGI_FORMAT_UNKNOWN, // R16_UNORM
DXGI_FORMAT_UNKNOWN, // R16G16_UNORM
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_UNORM
DXGI_FORMAT_UNKNOWN, // R10G10B10A2_UNORM
DXGI_FORMAT_UNKNOWN, // B5G6R5_UNORM
DXGI_FORMAT_UNKNOWN, // B5G5R5A1_UNORM
DXGI_FORMAT_UNKNOWN, // B4G4R4A4_UNORM
DXGI_FORMAT_UNKNOWN, // B8G8R8A8_UNORM
DXGI_FORMAT_UNKNOWN, // BC1_UNORM
DXGI_FORMAT_UNKNOWN, // BC2_UNORM
DXGI_FORMAT_UNKNOWN, // BC3_UNORM
DXGI_FORMAT_UNKNOWN, // BC4_UNORM
DXGI_FORMAT_UNKNOWN, // BC5_UNORM
DXGI_FORMAT_UNKNOWN, // BC7_UNORM
DXGI_FORMAT_UNKNOWN, // BC6H_FLOAT
DXGI_FORMAT_UNKNOWN, // BC6H_UFLOAT
DXGI_FORMAT_UNKNOWN, // R8_SNORM
DXGI_FORMAT_UNKNOWN, // R8G8_SNORM
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_SNORM
DXGI_FORMAT_UNKNOWN, // R16_SNORM
DXGI_FORMAT_UNKNOWN, // R16G16_SNORM
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_SNORM
DXGI_FORMAT_UNKNOWN, // R16_FLOAT
DXGI_FORMAT_UNKNOWN, // R16G16_FLOAT
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_FLOAT
DXGI_FORMAT_UNKNOWN, // R32_FLOAT
DXGI_FORMAT_UNKNOWN, // R32G32_FLOAT
DXGI_FORMAT_UNKNOWN, // R32G32B32A32_FLOAT
DXGI_FORMAT_UNKNOWN, // R11G11B10_UFLOAT
DXGI_FORMAT_UNKNOWN, // R8_UINT
DXGI_FORMAT_UNKNOWN, // R8G8_UINT
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UINT
DXGI_FORMAT_UNKNOWN, // R16_UINT
DXGI_FORMAT_UNKNOWN, // R16G16_UINT
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_UINT
DXGI_FORMAT_UNKNOWN, // R32_UINT
DXGI_FORMAT_UNKNOWN, // R32G32_UINT
DXGI_FORMAT_UNKNOWN, // R32G32B32A32_UINT
DXGI_FORMAT_UNKNOWN, // R8_INT
DXGI_FORMAT_UNKNOWN, // R8G8_INT
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_INT
DXGI_FORMAT_UNKNOWN, // R16_INT
DXGI_FORMAT_UNKNOWN, // R16G16_INT
DXGI_FORMAT_UNKNOWN, // R16G16B16A16_INT
DXGI_FORMAT_UNKNOWN, // R32_INT
DXGI_FORMAT_UNKNOWN, // R32G32_INT
DXGI_FORMAT_UNKNOWN, // R32G32B32A32_INT
DXGI_FORMAT_UNKNOWN, // R8G8B8A8_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // B8G8R8A8_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // BC1_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // BC2_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // BC3_UNORM_SRGB
DXGI_FORMAT_UNKNOWN, // BC7_UNORM_SRGB
DXGI_FORMAT_D16_UNORM, // D16_UNORM
DXGI_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM
DXGI_FORMAT_D32_FLOAT, // D32_FLOAT
@@ -355,7 +466,7 @@ static DXGI_FORMAT SDLToD3D12_TextureFormat[] = {
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_FLOAT
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_FLOAT
};
SDL_COMPILE_TIME_ASSERT(SDLToD3D12_TextureFormat, SDL_arraysize(SDLToD3D12_TextureFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
SDL_COMPILE_TIME_ASSERT(SDLToD3D12_DepthFormat, SDL_arraysize(SDLToD3D12_DepthFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
static D3D12_COMPARISON_FUNC SDLToD3D12_CompareOp[] = {
D3D12_COMPARISON_FUNC_NEVER, // INVALID
@@ -2691,7 +2802,7 @@ static SDL_GPUGraphicsPipeline *D3D12_CreateGraphicsPipeline(
psoDesc.SampleDesc.Count = SDLToD3D12_SampleCount[createinfo->multisample_state.sample_count];
psoDesc.SampleDesc.Quality = (createinfo->multisample_state.sample_count > SDL_GPU_SAMPLECOUNT_1) ? D3D12_STANDARD_MULTISAMPLE_PATTERN : 0;
psoDesc.DSVFormat = SDLToD3D12_TextureFormat[createinfo->target_info.depth_stencil_format];
psoDesc.DSVFormat = SDLToD3D12_DepthFormat[createinfo->target_info.depth_stencil_format];
psoDesc.NumRenderTargets = createinfo->target_info.num_color_targets;
for (uint32_t i = 0; i < createinfo->target_info.num_color_targets; i += 1) {
psoDesc.RTVFormats[i] = SDLToD3D12_TextureFormat[createinfo->target_info.color_target_descriptions[i].format];
@@ -2846,6 +2957,7 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
D3D12_RESOURCE_FLAGS resourceFlags = (D3D12_RESOURCE_FLAGS)0;
D3D12_RESOURCE_STATES initialState = (D3D12_RESOURCE_STATES)0;
D3D12_CLEAR_VALUE clearValue;
DXGI_FORMAT format;
bool useClearValue = false;
bool needsUAV =
(createinfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) ||
@@ -2861,6 +2973,8 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
Uint32 depth = createinfo->type == SDL_GPU_TEXTURETYPE_3D ? createinfo->layer_count_or_depth : 1;
bool isMultisample = createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1;
format = SDLToD3D12_TextureFormat[createinfo->format];
if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
useClearValue = true;
@@ -2875,6 +2989,7 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
useClearValue = true;
clearValue.DepthStencil.Depth = SDL_GetFloatProperty(createinfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_DEPTH_FLOAT, 0);
clearValue.DepthStencil.Stencil = (UINT8)SDL_GetNumberProperty(createinfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_STENCIL_UINT8, 0);
format = SDLToD3D12_DepthFormat[createinfo->format];
}
if (needsUAV) {
@@ -2896,7 +3011,7 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
desc.Height = createinfo->height;
desc.DepthOrArraySize = (UINT16)createinfo->layer_count_or_depth;
desc.MipLevels = (UINT16)createinfo->num_levels;
desc.Format = SDLToD3D12_TextureFormat[createinfo->format];
desc.Format = format;
desc.SampleDesc.Count = SDLToD3D12_SampleCount[createinfo->sample_count];
desc.SampleDesc.Quality = isMultisample ? D3D12_STANDARD_MULTISAMPLE_PATTERN : 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // Apparently this is the most efficient choice
@@ -2908,7 +3023,7 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
desc.Height = createinfo->height;
desc.DepthOrArraySize = (UINT16)createinfo->layer_count_or_depth;
desc.MipLevels = (UINT16)createinfo->num_levels;
desc.Format = SDLToD3D12_TextureFormat[createinfo->format];
desc.Format = format;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
@@ -3065,7 +3180,7 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
&texture->subresources[subresourceIndex].dsvHandle);
dsvDesc.Format = SDLToD3D12_TextureFormat[createinfo->format];
dsvDesc.Format = SDLToD3D12_DepthFormat[createinfo->format];
dsvDesc.Flags = (D3D12_DSV_FLAGS)0;
if (isMultisample) {
@@ -4827,6 +4942,8 @@ static void D3D12_DrawPrimitivesIndirect(
offset,
NULL,
0);
D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, d3d12Buffer);
}
static void D3D12_DrawIndexedPrimitivesIndirect(
@@ -4848,6 +4965,8 @@ static void D3D12_DrawIndexedPrimitivesIndirect(
offset,
NULL,
0);
D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, d3d12Buffer);
}
static void D3D12_EndRenderPass(
@@ -5303,6 +5422,8 @@ static void D3D12_DispatchComputeIndirect(
offset,
NULL,
0);
D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, d3d12Buffer);
}
static void D3D12_EndComputePass(
@@ -7176,18 +7297,20 @@ static bool D3D12_INTERNAL_CopyTextureDownload(
static bool D3D12_INTERNAL_CleanCommandBuffer(
D3D12Renderer *renderer,
D3D12CommandBuffer *commandBuffer)
D3D12CommandBuffer *commandBuffer,
bool cancel)
{
Uint32 i;
HRESULT res;
bool result = true;
// Perform deferred texture data copies
for (i = 0; i < commandBuffer->textureDownloadCount; i += 1) {
result &= D3D12_INTERNAL_CopyTextureDownload(
commandBuffer,
commandBuffer->textureDownloads[i]);
if (!cancel) {
result &= D3D12_INTERNAL_CopyTextureDownload(
commandBuffer,
commandBuffer->textureDownloads[i]);
}
SDL_free(commandBuffer->textureDownloads[i]);
}
commandBuffer->textureDownloadCount = 0;
@@ -7280,10 +7403,12 @@ static bool D3D12_INTERNAL_CleanCommandBuffer(
SDL_UnlockMutex(renderer->acquireCommandBufferLock);
// Remove this command buffer from the submitted list
for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
if (renderer->submittedCommandBuffers[i] == commandBuffer) {
renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
renderer->submittedCommandBufferCount -= 1;
if (!cancel) {
for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
if (renderer->submittedCommandBuffers[i] == commandBuffer) {
renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
renderer->submittedCommandBufferCount -= 1;
}
}
}
@@ -7452,7 +7577,8 @@ static bool D3D12_Submit(
if (fenceValue == D3D12_FENCE_SIGNAL_VALUE) {
result &= D3D12_INTERNAL_CleanCommandBuffer(
renderer,
renderer->submittedCommandBuffers[i]);
renderer->submittedCommandBuffers[i],
false);
}
}
@@ -7468,10 +7594,32 @@ static SDL_GPUFence *D3D12_SubmitAndAcquireFence(
{
D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
d3d12CommandBuffer->autoReleaseFence = false;
D3D12_Submit(commandBuffer);
if (!D3D12_Submit(commandBuffer)) {
return NULL;
}
return (SDL_GPUFence *)d3d12CommandBuffer->inFlightFence;
}
static bool D3D12_Cancel(
SDL_GPUCommandBuffer *commandBuffer)
{
D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
D3D12Renderer *renderer = d3d12CommandBuffer->renderer;
bool result;
HRESULT res;
// Notify the command buffer that we have completed recording
res = ID3D12GraphicsCommandList_Close(d3d12CommandBuffer->graphicsCommandList);
CHECK_D3D12_ERROR_AND_RETURN("Failed to close command list!", false);
d3d12CommandBuffer->autoReleaseFence = false;
SDL_LockMutex(renderer->submitLock);
result = D3D12_INTERNAL_CleanCommandBuffer(renderer, d3d12CommandBuffer, true);
SDL_UnlockMutex(renderer->submitLock);
return result;
}
static bool D3D12_Wait(
SDL_GPURenderer *driverData)
{
@@ -7515,7 +7663,7 @@ static bool D3D12_Wait(
// Clean up
for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
result &= D3D12_INTERNAL_CleanCommandBuffer(renderer, renderer->submittedCommandBuffers[i]);
result &= D3D12_INTERNAL_CleanCommandBuffer(renderer, renderer->submittedCommandBuffers[i], false);
}
D3D12_INTERNAL_PerformPendingDestroys(renderer);
@@ -7571,7 +7719,8 @@ static bool D3D12_WaitForFences(
if (fenceValue == D3D12_FENCE_SIGNAL_VALUE) {
result &= D3D12_INTERNAL_CleanCommandBuffer(
renderer,
renderer->submittedCommandBuffers[i]);
renderer->submittedCommandBuffers[i],
false);
}
}
@@ -7640,6 +7789,22 @@ static bool D3D12_SupportsTextureFormat(
if ((usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET)) {
return false;
}
// Special case check for depth, because D3D12 is great.
formatSupport.Format = SDLToD3D12_DepthFormat[format];
formatSupport.Support1 = D3D12_FORMAT_SUPPORT1_NONE;
formatSupport.Support2 = D3D12_FORMAT_SUPPORT2_NONE;
res = ID3D12Device_CheckFeatureSupport(
renderer->device,
D3D12_FEATURE_FORMAT_SUPPORT,
&formatSupport,
sizeof(formatSupport));
if (FAILED(res)) {
// Format is apparently unknown
return false;
}
if ((usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL)) {
return false;
}
+340 -209
View File
@@ -76,140 +76,131 @@ static void METAL_INTERNAL_DestroyBlitResources(SDL_GPURenderer *driverData);
// Conversions
static MTLPixelFormat SDLToMetal_SurfaceFormat[] = {
MTLPixelFormatInvalid, // INVALID
MTLPixelFormatA8Unorm, // A8_UNORM
MTLPixelFormatR8Unorm, // R8_UNORM
MTLPixelFormatRG8Unorm, // R8G8_UNORM
MTLPixelFormatRGBA8Unorm, // R8G8B8A8_UNORM
MTLPixelFormatR16Unorm, // R16_UNORM
MTLPixelFormatRG16Unorm, // R16G16_UNORM
MTLPixelFormatRGBA16Unorm, // R16G16B16A16_UNORM
MTLPixelFormatRGB10A2Unorm, // A2R10G10B10_UNORM
MTLPixelFormatB5G6R5Unorm, // B5G6R5_UNORM
MTLPixelFormatBGR5A1Unorm, // B5G5R5A1_UNORM
MTLPixelFormatABGR4Unorm, // B4G4R4A4_UNORM
MTLPixelFormatBGRA8Unorm, // B8G8R8A8_UNORM
#define RETURN_FORMAT(availability, format) \
if (availability) { return format; } else { return MTLPixelFormatInvalid; }
static MTLPixelFormat SDLToMetal_TextureFormat(SDL_GPUTextureFormat format)
{
switch (format) {
case SDL_GPU_TEXTUREFORMAT_INVALID: return MTLPixelFormatInvalid;
case SDL_GPU_TEXTUREFORMAT_A8_UNORM: return MTLPixelFormatA8Unorm;
case SDL_GPU_TEXTUREFORMAT_R8_UNORM: return MTLPixelFormatR8Unorm;
case SDL_GPU_TEXTUREFORMAT_R8G8_UNORM: return MTLPixelFormatRG8Unorm;
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM: return MTLPixelFormatRGBA8Unorm;
case SDL_GPU_TEXTUREFORMAT_R16_UNORM: return MTLPixelFormatR16Unorm;
case SDL_GPU_TEXTUREFORMAT_R16G16_UNORM: return MTLPixelFormatRG16Unorm;
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM: return MTLPixelFormatRGBA16Unorm;
case SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM: return MTLPixelFormatRGB10A2Unorm;
case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatB5G6R5Unorm);
case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatBGR5A1Unorm);
case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatABGR4Unorm);
case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM: return MTLPixelFormatBGRA8Unorm;
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM: RETURN_FORMAT(@available(iOS 16.4, tvOS 16.4, *), MTLPixelFormatBC1_RGBA);
case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM: RETURN_FORMAT(@available(iOS 16.4, tvOS 16.4, *), MTLPixelFormatBC2_RGBA);
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM: RETURN_FORMAT(@available(iOS 16.4, tvOS 16.4, *), MTLPixelFormatBC3_RGBA);
case SDL_GPU_TEXTUREFORMAT_BC4_R_UNORM: RETURN_FORMAT(@available(iOS 16.4, tvOS 16.4, *), MTLPixelFormatBC4_RUnorm);
case SDL_GPU_TEXTUREFORMAT_BC5_RG_UNORM: RETURN_FORMAT(@available(iOS 16.4, tvOS 16.4, *), MTLPixelFormatBC5_RGUnorm);
case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM: RETURN_FORMAT(@available(iOS 16.4, tvOS 16.4, *), MTLPixelFormatBC7_RGBAUnorm);
case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT: RETURN_FORMAT(@available(iOS 16.4, tvOS 16.4, *), MTLPixelFormatBC6H_RGBFloat);
case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT: RETURN_FORMAT(@available(iOS 16.4, tvOS 16.4, *), MTLPixelFormatBC6H_RGBUfloat);
case SDL_GPU_TEXTUREFORMAT_R8_SNORM: return MTLPixelFormatR8Snorm;
case SDL_GPU_TEXTUREFORMAT_R8G8_SNORM: return MTLPixelFormatRG8Snorm;
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM: return MTLPixelFormatRGBA8Snorm;
case SDL_GPU_TEXTUREFORMAT_R16_SNORM: return MTLPixelFormatR16Snorm;
case SDL_GPU_TEXTUREFORMAT_R16G16_SNORM: return MTLPixelFormatRG16Snorm;
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_SNORM: return MTLPixelFormatRGBA16Snorm;
case SDL_GPU_TEXTUREFORMAT_R16_FLOAT: return MTLPixelFormatR16Float;
case SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT: return MTLPixelFormatRG16Float;
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT: return MTLPixelFormatRGBA16Float;
case SDL_GPU_TEXTUREFORMAT_R32_FLOAT: return MTLPixelFormatR32Float;
case SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT: return MTLPixelFormatRG32Float;
case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT: return MTLPixelFormatRGBA32Float;
case SDL_GPU_TEXTUREFORMAT_R11G11B10_UFLOAT: return MTLPixelFormatRG11B10Float;
case SDL_GPU_TEXTUREFORMAT_R8_UINT: return MTLPixelFormatR8Uint;
case SDL_GPU_TEXTUREFORMAT_R8G8_UINT: return MTLPixelFormatRG8Uint;
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT: return MTLPixelFormatRGBA8Uint;
case SDL_GPU_TEXTUREFORMAT_R16_UINT: return MTLPixelFormatR16Uint;
case SDL_GPU_TEXTUREFORMAT_R16G16_UINT: return MTLPixelFormatRG16Uint;
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT: return MTLPixelFormatRGBA16Uint;
case SDL_GPU_TEXTUREFORMAT_R32_UINT: return MTLPixelFormatR32Uint;
case SDL_GPU_TEXTUREFORMAT_R32G32_UINT: return MTLPixelFormatRG32Uint;
case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_UINT: return MTLPixelFormatRGBA32Uint;
case SDL_GPU_TEXTUREFORMAT_R8_INT: return MTLPixelFormatR8Sint;
case SDL_GPU_TEXTUREFORMAT_R8G8_INT: return MTLPixelFormatRG8Sint;
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_INT: return MTLPixelFormatRGBA8Sint;
case SDL_GPU_TEXTUREFORMAT_R16_INT: return MTLPixelFormatR16Sint;
case SDL_GPU_TEXTUREFORMAT_R16G16_INT: return MTLPixelFormatRG16Sint;
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_INT: return MTLPixelFormatRGBA16Sint;
case SDL_GPU_TEXTUREFORMAT_R32_INT: return MTLPixelFormatR32Sint;
case SDL_GPU_TEXTUREFORMAT_R32G32_INT: return MTLPixelFormatRG32Sint;
case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_INT: return MTLPixelFormatRGBA32Sint;
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB: return MTLPixelFormatRGBA8Unorm_sRGB;
case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB: return MTLPixelFormatBGRA8Unorm_sRGB;
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB: RETURN_FORMAT(@available(iOS 16.4, tvOS 16.4, *), MTLPixelFormatBC1_RGBA_sRGB);
case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB: RETURN_FORMAT(@available(iOS 16.4, tvOS 16.4, *), MTLPixelFormatBC2_RGBA_sRGB);
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB: RETURN_FORMAT(@available(iOS 16.4, tvOS 16.4, *), MTLPixelFormatBC3_RGBA_sRGB);
case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB: RETURN_FORMAT(@available(iOS 16.4, tvOS 16.4, *), MTLPixelFormatBC7_RGBAUnorm_sRGB);
case SDL_GPU_TEXTUREFORMAT_D16_UNORM: RETURN_FORMAT(@available(iOS 13.0, tvOS 13.0, *), MTLPixelFormatDepth16Unorm);
case SDL_GPU_TEXTUREFORMAT_D24_UNORM:
#ifdef SDL_PLATFORM_MACOS
MTLPixelFormatBC1_RGBA, // BC1_UNORM
MTLPixelFormatBC2_RGBA, // BC2_UNORM
MTLPixelFormatBC3_RGBA, // BC3_UNORM
MTLPixelFormatBC4_RUnorm, // BC4_UNORM
MTLPixelFormatBC5_RGUnorm, // BC5_UNORM
MTLPixelFormatBC7_RGBAUnorm, // BC7_UNORM
MTLPixelFormatBC6H_RGBFloat, // BC6H_FLOAT
MTLPixelFormatBC6H_RGBUfloat, // BC6H_UFLOAT
return MTLPixelFormatDepth24Unorm_Stencil8;
#else
MTLPixelFormatInvalid, // BC1_UNORM
MTLPixelFormatInvalid, // BC2_UNORM
MTLPixelFormatInvalid, // BC3_UNORM
MTLPixelFormatInvalid, // BC4_UNORM
MTLPixelFormatInvalid, // BC5_UNORM
MTLPixelFormatInvalid, // BC7_UNORM
MTLPixelFormatInvalid, // BC6H_FLOAT
MTLPixelFormatInvalid, // BC6H_UFLOAT
return MTLPixelFormatInvalid;
#endif
MTLPixelFormatR8Snorm, // R8_SNORM
MTLPixelFormatRG8Snorm, // R8G8_SNORM
MTLPixelFormatRGBA8Snorm, // R8G8B8A8_SNORM
MTLPixelFormatR16Snorm, // R16_SNORM
MTLPixelFormatRG16Snorm, // R16G16_SNORM
MTLPixelFormatRGBA16Snorm, // R16G16B16A16_SNORM
MTLPixelFormatR16Float, // R16_FLOAT
MTLPixelFormatRG16Float, // R16G16_FLOAT
MTLPixelFormatRGBA16Float, // R16G16B16A16_FLOAT
MTLPixelFormatR32Float, // R32_FLOAT
MTLPixelFormatRG32Float, // R32G32_FLOAT
MTLPixelFormatRGBA32Float, // R32G32B32A32_FLOAT
MTLPixelFormatRG11B10Float, // R11G11B10_UFLOAT
MTLPixelFormatR8Uint, // R8_UINT
MTLPixelFormatRG8Uint, // R8G8_UINT
MTLPixelFormatRGBA8Uint, // R8G8B8A8_UINT
MTLPixelFormatR16Uint, // R16_UINT
MTLPixelFormatRG16Uint, // R16G16_UINT
MTLPixelFormatRGBA16Uint, // R16G16B16A16_UINT
MTLPixelFormatR32Uint, // R32_UINT
MTLPixelFormatRG32Uint, // R32G32_UINT
MTLPixelFormatRGBA32Uint, // R32G32B32A32_UINT
MTLPixelFormatR8Sint, // R8_UINT
MTLPixelFormatRG8Sint, // R8G8_UINT
MTLPixelFormatRGBA8Sint, // R8G8B8A8_UINT
MTLPixelFormatR16Sint, // R16_UINT
MTLPixelFormatRG16Sint, // R16G16_UINT
MTLPixelFormatRGBA16Sint, // R16G16B16A16_UINT
MTLPixelFormatR32Sint, // R32_INT
MTLPixelFormatRG32Sint, // R32G32_INT
MTLPixelFormatRGBA32Sint, // R32G32B32A32_INT
MTLPixelFormatRGBA8Unorm_sRGB, // R8G8B8A8_UNORM_SRGB
MTLPixelFormatBGRA8Unorm_sRGB, // B8G8R8A8_UNORM_SRGB
case SDL_GPU_TEXTUREFORMAT_D32_FLOAT: return MTLPixelFormatDepth32Float;
case SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT:
#ifdef SDL_PLATFORM_MACOS
MTLPixelFormatBC1_RGBA_sRGB, // BC1_UNORM_SRGB
MTLPixelFormatBC2_RGBA_sRGB, // BC2_UNORM_SRGB
MTLPixelFormatBC3_RGBA_sRGB, // BC3_UNORM_SRGB
MTLPixelFormatBC7_RGBAUnorm_sRGB, // BC7_UNORM_SRGB
return MTLPixelFormatDepth24Unorm_Stencil8;
#else
MTLPixelFormatInvalid, // BC1_UNORM_SRGB
MTLPixelFormatInvalid, // BC2_UNORM_SRGB
MTLPixelFormatInvalid, // BC3_UNORM_SRGB
MTLPixelFormatInvalid, // BC7_UNORM_SRGB
return MTLPixelFormatInvalid;
#endif
MTLPixelFormatDepth16Unorm, // D16_UNORM
#ifdef SDL_PLATFORM_MACOS
MTLPixelFormatDepth24Unorm_Stencil8, // D24_UNORM
#else
MTLPixelFormatInvalid, // D24_UNORM
#endif
MTLPixelFormatDepth32Float, // D32_FLOAT
#ifdef SDL_PLATFORM_MACOS
MTLPixelFormatDepth24Unorm_Stencil8, // D24_UNORM_S8_UINT
#else
MTLPixelFormatInvalid, // D24_UNORM_S8_UINT
#endif
MTLPixelFormatDepth32Float_Stencil8, // D32_FLOAT_S8_UINT
MTLPixelFormatASTC_4x4_LDR, // ASTC_4x4_UNORM
MTLPixelFormatASTC_5x4_LDR, // ASTC_5x4_UNORM
MTLPixelFormatASTC_5x5_LDR, // ASTC_5x5_UNORM
MTLPixelFormatASTC_6x5_LDR, // ASTC_6x5_UNORM
MTLPixelFormatASTC_6x6_LDR, // ASTC_6x6_UNORM
MTLPixelFormatASTC_8x5_LDR, // ASTC_8x5_UNORM
MTLPixelFormatASTC_8x6_LDR, // ASTC_8x6_UNORM
MTLPixelFormatASTC_8x8_LDR, // ASTC_8x8_UNORM
MTLPixelFormatASTC_10x5_LDR, // ASTC_10x5_UNORM
MTLPixelFormatASTC_10x6_LDR, // ASTC_10x6_UNORM
MTLPixelFormatASTC_10x8_LDR, // ASTC_10x8_UNORM
MTLPixelFormatASTC_10x10_LDR, // ASTC_10x10_UNORM
MTLPixelFormatASTC_12x10_LDR, // ASTC_12x10_UNORM
MTLPixelFormatASTC_12x12_LDR, // ASTC_12x12_UNORM
MTLPixelFormatASTC_4x4_sRGB, // ASTC_4x4_UNORM_SRGB
MTLPixelFormatASTC_5x4_sRGB, // ASTC_5x4_UNORM_SRGB
MTLPixelFormatASTC_5x5_sRGB, // ASTC_5x5_UNORM_SRGB
MTLPixelFormatASTC_6x5_sRGB, // ASTC_6x5_UNORM_SRGB
MTLPixelFormatASTC_6x6_sRGB, // ASTC_6x6_UNORM_SRGB
MTLPixelFormatASTC_8x5_sRGB, // ASTC_8x5_UNORM_SRGB
MTLPixelFormatASTC_8x6_sRGB, // ASTC_8x6_UNORM_SRGB
MTLPixelFormatASTC_8x8_sRGB, // ASTC_8x8_UNORM_SRGB
MTLPixelFormatASTC_10x5_sRGB, // ASTC_10x5_UNORM_SRGB
MTLPixelFormatASTC_10x6_sRGB, // ASTC_10x6_UNORM_SRGB
MTLPixelFormatASTC_10x8_sRGB, // ASTC_10x8_UNORM_SRGB
MTLPixelFormatASTC_10x10_sRGB, // ASTC_10x10_UNORM_SRGB
MTLPixelFormatASTC_12x10_sRGB, // ASTC_12x10_UNORM_SRGB
MTLPixelFormatASTC_12x12_sRGB, // ASTC_12x12_UNORM_SRGB
MTLPixelFormatASTC_4x4_HDR, // ASTC_4x4_FLOAT
MTLPixelFormatASTC_5x4_HDR, // ASTC_5x4_FLOAT
MTLPixelFormatASTC_5x5_HDR, // ASTC_5x5_FLOAT
MTLPixelFormatASTC_6x5_HDR, // ASTC_6x5_FLOAT
MTLPixelFormatASTC_6x6_HDR, // ASTC_6x6_FLOAT
MTLPixelFormatASTC_8x5_HDR, // ASTC_8x5_FLOAT
MTLPixelFormatASTC_8x6_HDR, // ASTC_8x6_FLOAT
MTLPixelFormatASTC_8x8_HDR, // ASTC_8x8_FLOAT
MTLPixelFormatASTC_10x5_HDR, // ASTC_10x5_FLOAT
MTLPixelFormatASTC_10x6_HDR, // ASTC_10x6_FLOAT
MTLPixelFormatASTC_10x8_HDR, // ASTC_10x8_FLOAT
MTLPixelFormatASTC_10x10_HDR, // ASTC_10x10_FLOAT
MTLPixelFormatASTC_12x10_HDR, // ASTC_12x10_FLOAT
MTLPixelFormatASTC_12x12_HDR // ASTC_12x12_FLOAT
};
SDL_COMPILE_TIME_ASSERT(SDLToMetal_SurfaceFormat, SDL_arraysize(SDLToMetal_SurfaceFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
case SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT: return MTLPixelFormatDepth32Float_Stencil8;
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_4x4_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_5x4_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_5x5_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_6x5_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_6x6_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_8x5_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_8x6_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_8x8_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_10x5_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_10x6_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_10x8_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_10x10_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_12x10_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_12x12_LDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_4x4_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_5x4_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_5x5_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_6x5_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_6x6_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_8x5_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_8x6_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_8x8_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_10x5_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_10x6_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_10x8_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_10x10_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_12x10_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB: RETURN_FORMAT(@available(macOS 11.0, *), MTLPixelFormatASTC_12x12_sRGB);
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_4x4_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_5x4_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_5x5_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_6x5_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_6x6_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_8x5_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_8x6_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_8x8_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_10x5_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_10x6_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_10x8_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_10x10_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_12x10_HDR);
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT: RETURN_FORMAT(@available(macOS 11.0, iOS 13.0, tvOS 16.0, *), MTLPixelFormatASTC_12x12_HDR);
}
}
#undef RETURN_FORMAT
static MTLVertexFormat SDLToMetal_VertexFormat[] = {
MTLVertexFormatInvalid, // INVALID
@@ -391,7 +382,11 @@ static MTLTextureType SDLToMetal_TextureType(SDL_GPUTextureType textureType, boo
case SDL_GPU_TEXTURETYPE_CUBE:
return MTLTextureTypeCube;
case SDL_GPU_TEXTURETYPE_CUBE_ARRAY:
return MTLTextureTypeCubeArray;
if (@available(iOS 11.0, tvOS 11.0, *)) {
return MTLTextureTypeCubeArray;
} else {
return MTLTextureType2D; // FIXME: I guess...?
}
default:
return MTLTextureType2D;
}
@@ -451,6 +446,7 @@ typedef struct MetalTextureContainer
typedef struct MetalFence
{
SDL_AtomicInt complete;
SDL_AtomicInt referenceCount;
} MetalFence;
typedef struct MetalWindowData
@@ -458,9 +454,12 @@ typedef struct MetalWindowData
SDL_Window *window;
SDL_MetalView view;
CAMetalLayer *layer;
SDL_GPUPresentMode presentMode;
id<CAMetalDrawable> drawable;
MetalTexture texture;
MetalTextureContainer textureContainer;
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
Uint32 frameCounter;
} MetalWindowData;
typedef struct MetalShader
@@ -610,7 +609,7 @@ typedef struct MetalCommandBuffer
// Fences
MetalFence *fence;
Uint8 autoReleaseFence;
bool autoReleaseFence;
// Reference Counting
MetalBuffer **usedBuffers;
@@ -1089,7 +1088,7 @@ static SDL_GPUGraphicsPipeline *METAL_CreateGraphicsPipeline(
blendState->color_write_mask :
0xF;
pipelineDescriptor.colorAttachments[i].pixelFormat = SDLToMetal_SurfaceFormat[createinfo->target_info.color_target_descriptions[i].format];
pipelineDescriptor.colorAttachments[i].pixelFormat = SDLToMetal_TextureFormat(createinfo->target_info.color_target_descriptions[i].format);
pipelineDescriptor.colorAttachments[i].writeMask = SDLToMetal_ColorWriteMask(colorWriteMask);
pipelineDescriptor.colorAttachments[i].blendingEnabled = blendState->enable_blend;
pipelineDescriptor.colorAttachments[i].rgbBlendOperation = SDLToMetal_BlendOp[blendState->color_blend_op];
@@ -1107,10 +1106,10 @@ static SDL_GPUGraphicsPipeline *METAL_CreateGraphicsPipeline(
// Depth Stencil
if (createinfo->target_info.has_depth_stencil_target) {
pipelineDescriptor.depthAttachmentPixelFormat = SDLToMetal_SurfaceFormat[createinfo->target_info.depth_stencil_format];
pipelineDescriptor.depthAttachmentPixelFormat = SDLToMetal_TextureFormat(createinfo->target_info.depth_stencil_format);
if (createinfo->depth_stencil_state.enable_stencil_test) {
pipelineDescriptor.stencilAttachmentPixelFormat = SDLToMetal_SurfaceFormat[createinfo->target_info.depth_stencil_format];
pipelineDescriptor.stencilAttachmentPixelFormat = SDLToMetal_TextureFormat(createinfo->target_info.depth_stencil_format);
frontStencilDescriptor = [MTLStencilDescriptor new];
frontStencilDescriptor.stencilCompareFunction = SDLToMetal_CompareOp[createinfo->depth_stencil_state.front_stencil_state.compare_op];
@@ -1269,7 +1268,7 @@ static void METAL_InsertDebugLabel(
[metalCommandBuffer->computeEncoder insertDebugSignpost:label];
} else {
// Metal doesn't have insertDebugSignpost for command buffers...
if (@available(macOS 10.13, *)) {
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
[metalCommandBuffer->handle pushDebugGroup:label];
[metalCommandBuffer->handle popDebugGroup];
}
@@ -1292,7 +1291,7 @@ static void METAL_PushDebugGroup(
} else if (metalCommandBuffer->computeEncoder) {
[metalCommandBuffer->computeEncoder pushDebugGroup:label];
} else {
if (@available(macOS 10.13, *)) {
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
[metalCommandBuffer->handle pushDebugGroup:label];
}
}
@@ -1312,7 +1311,7 @@ static void METAL_PopDebugGroup(
} else if (metalCommandBuffer->computeEncoder) {
[metalCommandBuffer->computeEncoder popDebugGroup];
} else {
if (@available(macOS 10.13, *)) {
if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
[metalCommandBuffer->handle popDebugGroup];
}
}
@@ -1341,7 +1340,6 @@ static SDL_GPUSampler *METAL_CreateSampler(
samplerDesc.lodMaxClamp = createinfo->max_lod;
samplerDesc.maxAnisotropy = (NSUInteger)((createinfo->enable_anisotropy) ? createinfo->max_anisotropy : 1);
samplerDesc.compareFunction = (createinfo->enable_compare) ? SDLToMetal_CompareOp[createinfo->compare_op] : MTLCompareFunctionAlways;
samplerDesc.borderColor = MTLSamplerBorderColorTransparentBlack; // arbitrary, unused
sampler = [renderer->device newSamplerStateWithDescriptor:samplerDesc];
if (sampler == NULL) {
@@ -1394,10 +1392,10 @@ static MetalTexture *METAL_INTERNAL_CreateTexture(
MetalTexture *metalTexture;
textureDescriptor.textureType = SDLToMetal_TextureType(createinfo->type, createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1);
textureDescriptor.pixelFormat = SDLToMetal_SurfaceFormat[createinfo->format];
textureDescriptor.pixelFormat = SDLToMetal_TextureFormat(createinfo->format);
// This format isn't natively supported so let's swizzle!
if (createinfo->format == SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM) {
if (@available(macOS 10.15, *)) {
if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) {
textureDescriptor.swizzle = MTLTextureSwizzleChannelsMake(MTLTextureSwizzleBlue,
MTLTextureSwizzleGreen,
MTLTextureSwizzleRed,
@@ -2025,6 +2023,7 @@ static Uint8 METAL_INTERNAL_CreateFence(
fence = SDL_calloc(1, sizeof(MetalFence));
SDL_SetAtomicInt(&fence->complete, 0);
SDL_SetAtomicInt(&fence->referenceCount, 0);
// Add it to the available pool
// FIXME: Should this be EXPAND_IF_NEEDED?
@@ -2042,7 +2041,7 @@ static Uint8 METAL_INTERNAL_CreateFence(
return 1;
}
static Uint8 METAL_INTERNAL_AcquireFence(
static bool METAL_INTERNAL_AcquireFence(
MetalRenderer *renderer,
MetalCommandBuffer *commandBuffer)
{
@@ -2055,7 +2054,7 @@ static Uint8 METAL_INTERNAL_AcquireFence(
if (!METAL_INTERNAL_CreateFence(renderer)) {
SDL_UnlockMutex(renderer->fenceLock);
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create fence!");
return 0;
return false;
}
}
@@ -2067,8 +2066,9 @@ static Uint8 METAL_INTERNAL_AcquireFence(
// Associate the fence with the command buffer
commandBuffer->fence = fence;
SDL_SetAtomicInt(&fence->complete, 0); // FIXME: Is this right?
(void)SDL_AtomicIncRef(&commandBuffer->fence->referenceCount);
return 1;
return true;
}
static SDL_GPUCommandBuffer *METAL_AcquireCommandBuffer(
@@ -2105,8 +2105,7 @@ static SDL_GPUCommandBuffer *METAL_AcquireCommandBuffer(
commandBuffer->needComputeTextureBind = true;
commandBuffer->needComputeUniformBind = true;
METAL_INTERNAL_AcquireFence(renderer, commandBuffer);
commandBuffer->autoReleaseFence = 1;
commandBuffer->autoReleaseFence = true;
SDL_UnlockMutex(renderer->acquireCommandBufferLock);
@@ -2370,7 +2369,9 @@ static void METAL_BindGraphicsPipeline(
[metalCommandBuffer->renderEncoder setTriangleFillMode:SDLToMetal_PolygonMode[metalGraphicsPipeline->rasterizerState.fill_mode]];
[metalCommandBuffer->renderEncoder setCullMode:SDLToMetal_CullMode[metalGraphicsPipeline->rasterizerState.cull_mode]];
[metalCommandBuffer->renderEncoder setFrontFacingWinding:SDLToMetal_FrontFace[metalGraphicsPipeline->rasterizerState.front_face]];
[metalCommandBuffer->renderEncoder setDepthClipMode:SDLToMetal_DepthClipMode(metalGraphicsPipeline->rasterizerState.enable_depth_clip)];
if (@available(iOS 11.0, tvOS 11.0, *)) {
[metalCommandBuffer->renderEncoder setDepthClipMode:SDLToMetal_DepthClipMode(metalGraphicsPipeline->rasterizerState.enable_depth_clip)];
}
[metalCommandBuffer->renderEncoder
setDepthBias:((rast->enable_depth_bias) ? rast->depth_bias_constant_factor : 0)
slopeScale:((rast->enable_depth_bias) ? rast->depth_bias_slope_factor : 0)
@@ -3034,7 +3035,7 @@ static void METAL_BeginComputePass(
METAL_INTERNAL_TrackTexture(metalCommandBuffer, texture);
textureView = [texture->handle newTextureViewWithPixelFormat:SDLToMetal_SurfaceFormat[textureContainer->header.info.format]
textureView = [texture->handle newTextureViewWithPixelFormat:SDLToMetal_TextureFormat(textureContainer->header.info.format)
textureType:SDLToMetal_TextureType(textureContainer->header.info.type, false)
levels:NSMakeRange(storageTextureBindings[i].mip_level, 1)
slices:NSMakeRange(storageTextureBindings[i].layer, 1)];
@@ -3270,29 +3271,36 @@ static void METAL_ReleaseFence(
SDL_GPURenderer *driverData,
SDL_GPUFence *fence)
{
METAL_INTERNAL_ReleaseFenceToPool(
(MetalRenderer *)driverData,
(MetalFence *)fence);
MetalFence *metalFence = (MetalFence *)fence;
if (SDL_AtomicDecRef(&metalFence->referenceCount)) {
METAL_INTERNAL_ReleaseFenceToPool(
(MetalRenderer *)driverData,
(MetalFence *)fence);
}
}
// Cleanup
static void METAL_INTERNAL_CleanCommandBuffer(
MetalRenderer *renderer,
MetalCommandBuffer *commandBuffer)
MetalCommandBuffer *commandBuffer,
bool cancel)
{
Uint32 i;
// Reference Counting
for (i = 0; i < commandBuffer->usedBufferCount; i += 1) {
(void)SDL_AtomicDecRef(&commandBuffer->usedBuffers[i]->referenceCount);
// End any active passes
if (commandBuffer->renderEncoder) {
[commandBuffer->renderEncoder endEncoding];
commandBuffer->renderEncoder = nil;
}
commandBuffer->usedBufferCount = 0;
for (i = 0; i < commandBuffer->usedTextureCount; i += 1) {
(void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount);
if (commandBuffer->computeEncoder) {
[commandBuffer->computeEncoder endEncoding];
commandBuffer->computeEncoder = nil;
}
if (commandBuffer->blitEncoder) {
[commandBuffer->blitEncoder endEncoding];
commandBuffer->blitEncoder = nil;
}
commandBuffer->usedTextureCount = 0;
// Uniform buffers are now available
@@ -3307,6 +3315,18 @@ static void METAL_INTERNAL_CleanCommandBuffer(
SDL_UnlockMutex(renderer->acquireUniformBufferLock);
// Reference Counting
for (i = 0; i < commandBuffer->usedBufferCount; i += 1) {
(void)SDL_AtomicDecRef(&commandBuffer->usedBuffers[i]->referenceCount);
}
commandBuffer->usedBufferCount = 0;
for (i = 0; i < commandBuffer->usedTextureCount; i += 1) {
(void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount);
}
commandBuffer->usedTextureCount = 0;
// Reset presentation
commandBuffer->windowDataCount = 0;
@@ -3358,10 +3378,12 @@ static void METAL_INTERNAL_CleanCommandBuffer(
SDL_UnlockMutex(renderer->acquireCommandBufferLock);
// Remove this command buffer from the submitted list
for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
if (renderer->submittedCommandBuffers[i] == commandBuffer) {
renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
renderer->submittedCommandBufferCount -= 1;
if (!cancel) {
for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
if (renderer->submittedCommandBuffers[i] == commandBuffer) {
renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
renderer->submittedCommandBufferCount -= 1;
}
}
}
}
@@ -3487,17 +3509,26 @@ static Uint8 METAL_INTERNAL_CreateSwapchain(
windowData->view = SDL_Metal_CreateView(windowData->window);
windowData->drawable = nil;
windowData->presentMode = SDL_GPU_PRESENTMODE_VSYNC;
windowData->frameCounter = 0;
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
windowData->inFlightFences[i] = NULL;
}
windowData->layer = (__bridge CAMetalLayer *)(SDL_Metal_GetLayer(windowData->view));
windowData->layer.device = renderer->device;
#ifdef SDL_PLATFORM_MACOS
if (@available(macOS 10.13, *)) {
windowData->layer.displaySyncEnabled = (presentMode != SDL_GPU_PRESENTMODE_IMMEDIATE);
windowData->presentMode = presentMode;
}
#endif
windowData->layer.pixelFormat = SDLToMetal_SurfaceFormat[SwapchainCompositionToFormat[swapchainComposition]];
windowData->layer.pixelFormat = SDLToMetal_TextureFormat(SwapchainCompositionToFormat[swapchainComposition]);
#ifndef SDL_PLATFORM_TVOS
windowData->layer.wantsExtendedDynamicRangeContent = (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR);
if (@available(iOS 16.0, *)) {
windowData->layer.wantsExtendedDynamicRangeContent = (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR);
}
#endif
colorspace = CGColorSpaceCreateWithName(SwapchainCompositionToColorSpace[swapchainComposition]);
@@ -3612,6 +3643,13 @@ static void METAL_ReleaseWindow(
METAL_Wait(driverData);
SDL_Metal_DestroyView(windowData->view);
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
if (windowData->inFlightFences[i] != NULL) {
METAL_ReleaseFence(
(SDL_GPURenderer *)renderer,
windowData->inFlightFences[i]);
}
}
SDL_LockMutex(renderer->windowLock);
for (Uint32 i = 0; i < renderer->claimedWindowCount; i += 1) {
@@ -3655,10 +3693,6 @@ static bool METAL_AcquireSwapchainTexture(
SET_STRING_ERROR_AND_RETURN("Window is not claimed by this SDL_GpuDevice", false);
}
// Get the drawable and its underlying texture
windowData->drawable = [windowData->layer nextDrawable];
windowData->texture.handle = [windowData->drawable texture];
// Update the window size
drawableSize = windowData->layer.drawableSize;
windowData->textureContainer.header.info.width = (Uint32)drawableSize.width;
@@ -3670,6 +3704,39 @@ static bool METAL_AcquireSwapchainTexture(
*swapchainTextureHeight = (Uint32)drawableSize.height;
}
if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
if (windowData->presentMode == SDL_GPU_PRESENTMODE_VSYNC) {
// In VSYNC mode, block until the least recent presented frame is done
if (!METAL_WaitForFences(
(SDL_GPURenderer *)renderer,
true,
&windowData->inFlightFences[windowData->frameCounter],
1)) {
return false;
}
} else {
if (!METAL_QueryFence(
(SDL_GPURenderer *)metalCommandBuffer->renderer,
windowData->inFlightFences[windowData->frameCounter])) {
/*
* In IMMEDIATE mode, if the least recent fence is not signaled,
* return true to indicate that there is no error but rendering should be skipped
*/
return true;
}
}
METAL_ReleaseFence(
(SDL_GPURenderer *)metalCommandBuffer->renderer,
windowData->inFlightFences[windowData->frameCounter]);
windowData->inFlightFences[windowData->frameCounter] = NULL;
}
// Get the drawable and its underlying texture
windowData->drawable = [windowData->layer nextDrawable];
windowData->texture.handle = [windowData->drawable texture];
// Set up presentation
if (metalCommandBuffer->windowDataCount == metalCommandBuffer->windowDataCapacity) {
metalCommandBuffer->windowDataCapacity += 1;
@@ -3725,14 +3792,19 @@ static bool METAL_SetSwapchainParameters(
METAL_Wait(driverData);
windowData->presentMode = SDL_GPU_PRESENTMODE_VSYNC;
#ifdef SDL_PLATFORM_MACOS
if (@available(macOS 10.13, *)) {
windowData->layer.displaySyncEnabled = (presentMode != SDL_GPU_PRESENTMODE_IMMEDIATE);
windowData->presentMode = presentMode;
}
#endif
windowData->layer.pixelFormat = SDLToMetal_SurfaceFormat[SwapchainCompositionToFormat[swapchainComposition]];
windowData->layer.pixelFormat = SDLToMetal_TextureFormat(SwapchainCompositionToFormat[swapchainComposition]);
#ifndef SDL_PLATFORM_TVOS
windowData->layer.wantsExtendedDynamicRangeContent = (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR);
if (@available(iOS 16.0, *)) {
windowData->layer.wantsExtendedDynamicRangeContent = (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR);
}
#endif
colorspace = CGColorSpaceCreateWithName(SwapchainCompositionToColorSpace[swapchainComposition]);
@@ -3756,10 +3828,22 @@ static bool METAL_Submit(
SDL_LockMutex(renderer->submitLock);
if (!METAL_INTERNAL_AcquireFence(renderer, metalCommandBuffer)) {
SDL_UnlockMutex(renderer->submitLock);
return false;
}
// Enqueue present requests, if applicable
for (Uint32 i = 0; i < metalCommandBuffer->windowDataCount; i += 1) {
[metalCommandBuffer->handle presentDrawable:metalCommandBuffer->windowDatas[i]->drawable];
metalCommandBuffer->windowDatas[i]->drawable = nil;
MetalWindowData *windowData = metalCommandBuffer->windowDatas[i];
[metalCommandBuffer->handle presentDrawable:windowData->drawable];
windowData->drawable = nil;
windowData->inFlightFences[windowData->frameCounter] = (SDL_GPUFence *)metalCommandBuffer->fence;
(void)SDL_AtomicIncRef(&metalCommandBuffer->fence->referenceCount);
windowData->frameCounter = (windowData->frameCounter + 1) % MAX_FRAMES_IN_FLIGHT;
}
// Notify the fence when the command buffer has completed
@@ -3787,7 +3871,8 @@ static bool METAL_Submit(
if (SDL_GetAtomicInt(&renderer->submittedCommandBuffers[i]->fence->complete)) {
METAL_INTERNAL_CleanCommandBuffer(
renderer,
renderer->submittedCommandBuffers[i]);
renderer->submittedCommandBuffers[i],
false);
}
}
@@ -3803,12 +3888,25 @@ static SDL_GPUFence *METAL_SubmitAndAcquireFence(
SDL_GPUCommandBuffer *commandBuffer)
{
MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
MetalFence *fence = metalCommandBuffer->fence;
metalCommandBuffer->autoReleaseFence = false;
if (!METAL_Submit(commandBuffer)) {
return NULL;
}
return (SDL_GPUFence *)metalCommandBuffer->fence;
}
metalCommandBuffer->autoReleaseFence = 0;
METAL_Submit(commandBuffer);
static bool METAL_Cancel(
SDL_GPUCommandBuffer *commandBuffer)
{
MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
MetalRenderer *renderer = metalCommandBuffer->renderer;
return (SDL_GPUFence *)fence;
metalCommandBuffer->autoReleaseFence = false;
SDL_LockMutex(renderer->submitLock);
METAL_INTERNAL_CleanCommandBuffer(renderer, metalCommandBuffer, true);
SDL_UnlockMutex(renderer->submitLock);
return true;
}
static bool METAL_Wait(
@@ -3832,7 +3930,7 @@ static bool METAL_Wait(
for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
commandBuffer = renderer->submittedCommandBuffers[i];
METAL_INTERNAL_CleanCommandBuffer(renderer, commandBuffer);
METAL_INTERNAL_CleanCommandBuffer(renderer, commandBuffer, false);
}
METAL_INTERNAL_PerformPendingDestroys(renderer);
@@ -3864,7 +3962,10 @@ static bool METAL_SupportsTextureFormat(
// Cube arrays are not supported on older iOS devices
if (type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
if (@available(macOS 10.15, *)) {
#ifdef SDL_PLATFORM_MACOS
return true;
#else
if (@available(iOS 13.0, tvOS 13.0, *)) {
if (!([renderer->device supportsFamily:MTLGPUFamilyCommon2] ||
[renderer->device supportsFamily:MTLGPUFamilyApple4])) {
return false;
@@ -3872,6 +3973,7 @@ static bool METAL_SupportsTextureFormat(
} else {
return false;
}
#endif
}
switch (format) {
@@ -3879,11 +3981,11 @@ static bool METAL_SupportsTextureFormat(
case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM:
case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM:
case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM:
if (@available(macOS 10.15, *)) {
return [renderer->device supportsFamily:MTLGPUFamilyApple1];
} else {
return false;
}
if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) {
return [renderer->device supportsFamily:MTLGPUFamilyApple1];
} else {
return false;
}
// Requires BC compression support
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM:
@@ -3898,18 +4000,18 @@ static bool METAL_SupportsTextureFormat(
case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB:
#ifdef SDL_PLATFORM_MACOS
if (@available(macOS 11.0, *)) {
return (
[renderer->device supportsBCTextureCompression] &&
!(usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET));
if (@available(iOS 16.4, tvOS 16.4, *)) {
if (usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) {
return false;
}
if (@available(macOS 11.0, *)) {
return [renderer->device supportsBCTextureCompression];
} else {
return true;
}
} else {
return false;
}
#else
// FIXME: iOS 16.4+ allows these formats!
return false;
#endif
// Requires D24S8 support
case SDL_GPU_TEXTUREFORMAT_D24_UNORM:
@@ -3919,6 +4021,14 @@ static bool METAL_SupportsTextureFormat(
#else
return false;
#endif
case SDL_GPU_TEXTUREFORMAT_D16_UNORM:
if (@available(macOS 10.12, iOS 13.0, tvOS 13.0, *)) {
return true;
} else {
return false;
}
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM:
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM:
@@ -3948,7 +4058,11 @@ static bool METAL_SupportsTextureFormat(
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB:
#ifdef SDL_PLATFORM_MACOS
return [renderer->device supportsFamily:MTLGPUFamilyApple7];
if (@available(macOS 11.0, *)) {
return [renderer->device supportsFamily:MTLGPUFamilyApple7];
} else {
return false;
}
#else
return true;
#endif
@@ -3967,9 +4081,17 @@ static bool METAL_SupportsTextureFormat(
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT:
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT:
#ifdef SDL_PLATFORM_MACOS
return [renderer->device supportsFamily:MTLGPUFamilyApple7];
if (@available(macOS 11.0, *)) {
return [renderer->device supportsFamily:MTLGPUFamilyApple7];
} else {
return false;
}
#else
return [renderer->device supportsFamily:MTLGPUFamilyApple6];
if (@available(iOS 13.0, tvOS 13.0, *)) {
return [renderer->device supportsFamily:MTLGPUFamilyApple6];
} else {
return false;
}
#endif
default:
return true;
@@ -3981,8 +4103,10 @@ static bool METAL_SupportsTextureFormat(
static bool METAL_PrepareDriver(SDL_VideoDevice *this)
{
// FIXME: Add a macOS / iOS version check! Maybe support >= 10.14?
return (this->Metal_CreateView != NULL);
if (@available(macOS 10.13, iOS 13.0, tvOS 13.0, *)) {
return (this->Metal_CreateView != NULL);
}
return false;
}
static void METAL_INTERNAL_InitBlitResources(
@@ -4140,33 +4264,40 @@ static SDL_GPUDevice *METAL_CreateDevice(bool debugMode, bool preferLowPower, SD
{
@autoreleasepool {
MetalRenderer *renderer;
// Allocate and zero out the renderer
renderer = (MetalRenderer *)SDL_calloc(1, sizeof(MetalRenderer));
id<MTLDevice> device = NULL;
// Create the Metal device and command queue
#ifdef SDL_PLATFORM_MACOS
if (preferLowPower) {
NSArray<id<MTLDevice>> *devices = MTLCopyAllDevices();
for (id<MTLDevice> device in devices) {
if (device.isLowPower) {
renderer->device = device;
for (id<MTLDevice> candidate in devices) {
if (candidate.isLowPower) {
device = candidate;
break;
}
}
}
#endif
if (renderer->device == NULL) {
renderer->device = MTLCreateSystemDefaultDevice();
if (device == NULL) {
device = MTLCreateSystemDefaultDevice();
if (device == NULL) {
SDL_SetError("Failed to create Metal device");
return NULL;
}
}
renderer->queue = [renderer->device newCommandQueue];
// Allocate and zero out the renderer
renderer = (MetalRenderer *)SDL_calloc(1, sizeof(MetalRenderer));
renderer->device = device;
renderer->queue = [device newCommandQueue];
// Print driver info
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_GPU Driver: Metal");
SDL_LogInfo(
SDL_LOG_CATEGORY_GPU,
"Metal Device: %s",
[renderer->device.name UTF8String]);
[device.name UTF8String]);
// Remember debug mode
renderer->debugMode = debugMode;
@@ -4175,7 +4306,7 @@ static SDL_GPUDevice *METAL_CreateDevice(bool debugMode, bool preferLowPower, SD
SwapchainCompositionToColorSpace[0] = kCGColorSpaceSRGB;
SwapchainCompositionToColorSpace[1] = kCGColorSpaceSRGB;
SwapchainCompositionToColorSpace[2] = kCGColorSpaceExtendedLinearSRGB;
if (@available(macOS 11.0, *)) {
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
SwapchainCompositionToColorSpace[3] = kCGColorSpaceITUR_2100_PQ;
} else {
SwapchainCompositionToColorSpace[3] = NULL;
+224 -171
View File
@@ -587,6 +587,7 @@ struct VulkanBufferContainer
Uint32 bufferCapacity;
Uint32 bufferCount;
bool dedicated;
char *debugName;
};
@@ -629,8 +630,6 @@ typedef struct VulkanTextureSubresource
VkImageView *renderTargetViews; // One render target view per depth slice
VkImageView computeWriteView;
VkImageView depthStencilView;
bool transitioned; // used for layout tracking
} VulkanTextureSubresource;
struct VulkanTexture
@@ -684,6 +683,7 @@ typedef enum VulkanBufferUsageMode
typedef enum VulkanTextureUsageMode
{
VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
VULKAN_TEXTURE_USAGE_MODE_SAMPLER,
@@ -1092,9 +1092,9 @@ typedef struct VulkanCommandBuffer
Sint32 usedUniformBufferCapacity;
VulkanFenceHandle *inFlightFence;
Uint8 autoReleaseFence;
bool autoReleaseFence;
Uint8 isDefrag; // Whether this CB was created for defragging
bool isDefrag; // Whether this CB was created for defragging
} VulkanCommandBuffer;
struct VulkanCommandPool
@@ -1224,6 +1224,7 @@ static void VULKAN_ReleaseWindow(SDL_GPURenderer *driverData, SDL_Window *window
static bool VULKAN_Wait(SDL_GPURenderer *driverData);
static bool VULKAN_WaitForFences(SDL_GPURenderer *driverData, bool waitAll, SDL_GPUFence *const *fences, Uint32 numFences);
static bool VULKAN_Submit(SDL_GPUCommandBuffer *commandBuffer);
static SDL_GPUCommandBuffer *VULKAN_AcquireCommandBuffer(SDL_GPURenderer *driverData);
// Error Handling
@@ -1269,6 +1270,7 @@ static inline const char *VkErrorMessages(VkResult code)
SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s %s", #fn, VkErrorMessages(res)); \
} \
SDL_SetError("%s %s", #fn, VkErrorMessages(res)); \
return ret; \
}
// Utility
@@ -1915,6 +1917,7 @@ static Uint8 VULKAN_INTERNAL_BindResourceMemory(
Uint32 memoryTypeIndex,
VkMemoryRequirements *memoryRequirements,
VkDeviceSize resourceSize, // may be different from requirements size!
bool dedicated, // the entire memory allocation should be used for this resource
VkBuffer buffer, // may be VK_NULL_HANDLE
VkImage image, // may be VK_NULL_HANDLE
VulkanMemoryUsedRegion **pMemoryUsedRegion)
@@ -1949,105 +1952,111 @@ static Uint8 VULKAN_INTERNAL_BindResourceMemory(
selectedRegion = NULL;
for (i = allocator->sortedFreeRegionCount - 1; i >= 0; i -= 1) {
region = allocator->sortedFreeRegions[i];
if (dedicated) {
// Force an allocation
allocationSize = requiredSize;
} else {
// Search for a suitable existing free region
for (i = allocator->sortedFreeRegionCount - 1; i >= 0; i -= 1) {
region = allocator->sortedFreeRegions[i];
if (smallAllocation && region->allocation->size != SMALL_ALLOCATION_SIZE) {
// region is not in a small allocation
continue;
if (smallAllocation && region->allocation->size != SMALL_ALLOCATION_SIZE) {
// region is not in a small allocation
continue;
}
if (!smallAllocation && region->allocation->size == SMALL_ALLOCATION_SIZE) {
// allocation is not small and current region is in a small allocation
continue;
}
alignedOffset = VULKAN_INTERNAL_NextHighestAlignment(
region->offset,
memoryRequirements->alignment);
if (alignedOffset + requiredSize <= region->offset + region->size) {
selectedRegion = region;
break;
}
}
if (!smallAllocation && region->allocation->size == SMALL_ALLOCATION_SIZE) {
// allocation is not small and current region is in a small allocation
continue;
}
if (selectedRegion != NULL) {
region = selectedRegion;
allocation = region->allocation;
alignedOffset = VULKAN_INTERNAL_NextHighestAlignment(
region->offset,
memoryRequirements->alignment);
if (alignedOffset + requiredSize <= region->offset + region->size) {
selectedRegion = region;
break;
}
}
if (selectedRegion != NULL) {
region = selectedRegion;
allocation = region->allocation;
usedRegion = VULKAN_INTERNAL_NewMemoryUsedRegion(
renderer,
allocation,
region->offset,
requiredSize + (alignedOffset - region->offset),
alignedOffset,
resourceSize,
memoryRequirements->alignment);
usedRegion->isBuffer = buffer != VK_NULL_HANDLE;
newRegionSize = region->size - ((alignedOffset - region->offset) + requiredSize);
newRegionOffset = alignedOffset + requiredSize;
// remove and add modified region to re-sort
VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, region);
// if size is 0, no need to re-insert
if (newRegionSize != 0) {
VULKAN_INTERNAL_NewMemoryFreeRegion(
usedRegion = VULKAN_INTERNAL_NewMemoryUsedRegion(
renderer,
allocation,
newRegionOffset,
newRegionSize);
region->offset,
requiredSize + (alignedOffset - region->offset),
alignedOffset,
resourceSize,
memoryRequirements->alignment);
usedRegion->isBuffer = buffer != VK_NULL_HANDLE;
newRegionSize = region->size - ((alignedOffset - region->offset) + requiredSize);
newRegionOffset = alignedOffset + requiredSize;
// remove and add modified region to re-sort
VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, region);
// if size is 0, no need to re-insert
if (newRegionSize != 0) {
VULKAN_INTERNAL_NewMemoryFreeRegion(
renderer,
allocation,
newRegionOffset,
newRegionSize);
}
SDL_UnlockMutex(renderer->allocatorLock);
if (buffer != VK_NULL_HANDLE) {
if (!VULKAN_INTERNAL_BindBufferMemory(
renderer,
usedRegion,
alignedOffset,
buffer)) {
VULKAN_INTERNAL_RemoveMemoryUsedRegion(
renderer,
usedRegion);
return 0;
}
} else if (image != VK_NULL_HANDLE) {
if (!VULKAN_INTERNAL_BindImageMemory(
renderer,
usedRegion,
alignedOffset,
image)) {
VULKAN_INTERNAL_RemoveMemoryUsedRegion(
renderer,
usedRegion);
return 0;
}
}
*pMemoryUsedRegion = usedRegion;
return 1;
}
SDL_UnlockMutex(renderer->allocatorLock);
if (buffer != VK_NULL_HANDLE) {
if (!VULKAN_INTERNAL_BindBufferMemory(
renderer,
usedRegion,
alignedOffset,
buffer)) {
VULKAN_INTERNAL_RemoveMemoryUsedRegion(
renderer,
usedRegion);
return 0;
}
} else if (image != VK_NULL_HANDLE) {
if (!VULKAN_INTERNAL_BindImageMemory(
renderer,
usedRegion,
alignedOffset,
image)) {
VULKAN_INTERNAL_RemoveMemoryUsedRegion(
renderer,
usedRegion);
return 0;
}
// No suitable free regions exist, allocate a new memory region
if (
renderer->allocationsToDefragCount == 0 &&
!renderer->defragInProgress) {
// Mark currently fragmented allocations for defrag
VULKAN_INTERNAL_MarkAllocationsForDefrag(renderer);
}
*pMemoryUsedRegion = usedRegion;
return 1;
}
// No suitable free regions exist, allocate a new memory region
if (
renderer->allocationsToDefragCount == 0 &&
!renderer->defragInProgress) {
// Mark currently fragmented allocations for defrag
VULKAN_INTERNAL_MarkAllocationsForDefrag(renderer);
}
if (requiredSize > SMALL_ALLOCATION_THRESHOLD) {
// allocate a page of required size aligned to LARGE_ALLOCATION_INCREMENT increments
allocationSize =
VULKAN_INTERNAL_NextHighestAlignment(requiredSize, LARGE_ALLOCATION_INCREMENT);
} else {
allocationSize = SMALL_ALLOCATION_SIZE;
if (requiredSize > SMALL_ALLOCATION_THRESHOLD) {
// allocate a page of required size aligned to LARGE_ALLOCATION_INCREMENT increments
allocationSize =
VULKAN_INTERNAL_NextHighestAlignment(requiredSize, LARGE_ALLOCATION_INCREMENT);
} else {
allocationSize = SMALL_ALLOCATION_SIZE;
}
}
allocationResult = VULKAN_INTERNAL_AllocateMemory(
@@ -2161,6 +2170,7 @@ static Uint8 VULKAN_INTERNAL_BindMemoryForImage(
memoryTypesToTry[i],
&memoryRequirements,
memoryRequirements.size,
false,
VK_NULL_HANDLE,
image,
usedRegion);
@@ -2191,6 +2201,7 @@ static Uint8 VULKAN_INTERNAL_BindMemoryForBuffer(
VkBuffer buffer,
VkDeviceSize size,
VulkanBufferType type,
bool dedicated,
VulkanMemoryUsedRegion **usedRegion)
{
Uint8 bindResult = 0;
@@ -2304,6 +2315,7 @@ static Uint8 VULKAN_INTERNAL_BindMemoryForBuffer(
memoryTypesToTry[i],
&memoryRequirements,
size,
dedicated,
buffer,
VK_NULL_HANDLE,
usedRegion);
@@ -2638,7 +2650,11 @@ static void VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
memoryBarrier.subresourceRange.baseMipLevel = textureSubresource->level;
memoryBarrier.subresourceRange.levelCount = 1;
if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE) {
if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED) {
srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
memoryBarrier.srcAccessMask = 0;
memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
} else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE) {
srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
@@ -2675,10 +2691,6 @@ static void VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
return;
}
if (!textureSubresource->transitioned) {
memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
}
if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE) {
dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
@@ -2731,8 +2743,6 @@ static void VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
NULL,
1,
&memoryBarrier);
textureSubresource->transitioned = true;
}
static VulkanBufferUsageMode VULKAN_INTERNAL_DefaultBufferUsageMode(
@@ -4054,7 +4064,8 @@ static VulkanBuffer *VULKAN_INTERNAL_CreateBuffer(
VulkanRenderer *renderer,
VkDeviceSize size,
SDL_GPUBufferUsageFlags usageFlags,
VulkanBufferType type)
VulkanBufferType type,
bool dedicated)
{
VulkanBuffer *buffer;
VkResult vulkanResult;
@@ -4115,7 +4126,7 @@ static VulkanBuffer *VULKAN_INTERNAL_CreateBuffer(
if (vulkanResult != VK_SUCCESS) {
SDL_free(buffer);
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateBuffer, 0)
CHECK_VULKAN_ERROR_AND_RETURN(vulkanResult, vkCreateBuffer, NULL)
}
bindResult = VULKAN_INTERNAL_BindMemoryForBuffer(
@@ -4123,6 +4134,7 @@ static VulkanBuffer *VULKAN_INTERNAL_CreateBuffer(
buffer->buffer,
buffer->size,
buffer->type,
dedicated,
&buffer->usedRegion);
if (bindResult != 1) {
@@ -4146,7 +4158,8 @@ static VulkanBufferContainer *VULKAN_INTERNAL_CreateBufferContainer(
VulkanRenderer *renderer,
VkDeviceSize size,
SDL_GPUBufferUsageFlags usageFlags,
VulkanBufferType type)
VulkanBufferType type,
bool dedicated)
{
VulkanBufferContainer *bufferContainer;
VulkanBuffer *buffer;
@@ -4155,7 +4168,8 @@ static VulkanBufferContainer *VULKAN_INTERNAL_CreateBufferContainer(
renderer,
size,
usageFlags,
type);
type,
dedicated);
if (buffer == NULL) {
return NULL;
@@ -4172,6 +4186,7 @@ static VulkanBufferContainer *VULKAN_INTERNAL_CreateBufferContainer(
bufferContainer->buffers = SDL_malloc(
bufferContainer->bufferCapacity * sizeof(VulkanBuffer *));
bufferContainer->buffers[0] = bufferContainer->activeBuffer;
bufferContainer->dedicated = dedicated;
bufferContainer->debugName = NULL;
return bufferContainer;
@@ -4685,7 +4700,6 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
windowData->textureContainers[i].activeTexture->subresources[0].parent = windowData->textureContainers[i].activeTexture;
windowData->textureContainers[i].activeTexture->subresources[0].layer = 0;
windowData->textureContainers[i].activeTexture->subresources[0].level = 0;
windowData->textureContainers[i].activeTexture->subresources[0].transitioned = true;
windowData->textureContainers[i].activeTexture->subresources[0].renderTargetViews = SDL_malloc(sizeof(VkImageView));
if (!VULKAN_INTERNAL_CreateRenderTargetView(
renderer,
@@ -5746,10 +5760,19 @@ static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
texture->subresources[subresourceIndex].parent = texture;
texture->subresources[subresourceIndex].layer = i;
texture->subresources[subresourceIndex].level = j;
texture->subresources[subresourceIndex].transitioned = false;
}
}
// Let's transition to the default barrier state, because for some reason Vulkan doesn't let us do that with initialLayout.
VulkanCommandBuffer *barrierCommandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GPURenderer *)renderer);
VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
renderer,
barrierCommandBuffer,
VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
texture);
VULKAN_INTERNAL_TrackTexture(barrierCommandBuffer, texture);
VULKAN_Submit((SDL_GPUCommandBuffer *)barrierCommandBuffer);
return texture;
}
@@ -5773,7 +5796,8 @@ static void VULKAN_INTERNAL_CycleActiveBuffer(
renderer,
container->activeBuffer->size,
container->activeBuffer->usage,
container->activeBuffer->type);
container->activeBuffer->type,
container->dedicated);
if (!buffer) {
return;
@@ -6675,7 +6699,8 @@ static SDL_GPUBuffer *VULKAN_CreateBuffer(
(VulkanRenderer *)driverData,
(VkDeviceSize)size,
usageFlags,
VULKAN_BUFFER_TYPE_GPU);
VULKAN_BUFFER_TYPE_GPU,
false);
}
static VulkanUniformBuffer *VULKAN_INTERNAL_CreateUniformBuffer(
@@ -6688,7 +6713,8 @@ static VulkanUniformBuffer *VULKAN_INTERNAL_CreateUniformBuffer(
renderer,
(VkDeviceSize)size,
0,
VULKAN_BUFFER_TYPE_UNIFORM);
VULKAN_BUFFER_TYPE_UNIFORM,
false);
uniformBuffer->drawOffset = 0;
uniformBuffer->writeOffset = 0;
@@ -6699,14 +6725,18 @@ static VulkanUniformBuffer *VULKAN_INTERNAL_CreateUniformBuffer(
static SDL_GPUTransferBuffer *VULKAN_CreateTransferBuffer(
SDL_GPURenderer *driverData,
SDL_GPUTransferBufferUsage usage, // ignored on Vulkan
SDL_GPUTransferBufferUsage usage,
Uint32 size)
{
// We use dedicated allocations for download buffers to avoid an issue
// where a defrag is triggered after submitting a download but before
// waiting on the fence.
return (SDL_GPUTransferBuffer *)VULKAN_INTERNAL_CreateBufferContainer(
(VulkanRenderer *)driverData,
(VkDeviceSize)size,
0,
VULKAN_BUFFER_TYPE_TRANSFER);
VULKAN_BUFFER_TYPE_TRANSFER,
usage == SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD);
}
static void VULKAN_INTERNAL_ReleaseTexture(
@@ -9336,7 +9366,7 @@ static SDL_GPUCommandBuffer *VULKAN_AcquireCommandBuffer(
SDL_zeroa(commandBuffer->readOnlyComputeStorageTextures);
SDL_zeroa(commandBuffer->readOnlyComputeStorageBuffers);
commandBuffer->autoReleaseFence = 1;
commandBuffer->autoReleaseFence = true;
commandBuffer->isDefrag = 0;
@@ -10002,7 +10032,8 @@ static void VULKAN_INTERNAL_PerformPendingDestroys(
static void VULKAN_INTERNAL_CleanCommandBuffer(
VulkanRenderer *renderer,
VulkanCommandBuffer *commandBuffer)
VulkanCommandBuffer *commandBuffer,
bool cancel)
{
if (commandBuffer->autoReleaseFence) {
VULKAN_ReleaseFence(
@@ -10094,10 +10125,12 @@ static void VULKAN_INTERNAL_CleanCommandBuffer(
SDL_UnlockMutex(renderer->acquireCommandBufferLock);
// Remove this command buffer from the submitted list
for (Uint32 i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
if (renderer->submittedCommandBuffers[i] == commandBuffer) {
renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
renderer->submittedCommandBufferCount -= 1;
if (!cancel) {
for (Uint32 i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
if (renderer->submittedCommandBuffers[i] == commandBuffer) {
renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
renderer->submittedCommandBufferCount -= 1;
}
}
}
}
@@ -10137,7 +10170,8 @@ static bool VULKAN_WaitForFences(
if (result == VK_SUCCESS) {
VULKAN_INTERNAL_CleanCommandBuffer(
renderer,
renderer->submittedCommandBuffers[i]);
renderer->submittedCommandBuffers[i],
false);
}
}
@@ -10164,7 +10198,7 @@ static bool VULKAN_Wait(
for (i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
commandBuffer = renderer->submittedCommandBuffers[i];
VULKAN_INTERNAL_CleanCommandBuffer(renderer, commandBuffer);
VULKAN_INTERNAL_CleanCommandBuffer(renderer, commandBuffer, false);
}
VULKAN_INTERNAL_PerformPendingDestroys(renderer);
@@ -10177,15 +10211,11 @@ static bool VULKAN_Wait(
static SDL_GPUFence *VULKAN_SubmitAndAcquireFence(
SDL_GPUCommandBuffer *commandBuffer)
{
VulkanCommandBuffer *vulkanCommandBuffer;
vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
vulkanCommandBuffer->autoReleaseFence = 0;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
vulkanCommandBuffer->autoReleaseFence = false;
if (!VULKAN_Submit(commandBuffer)) {
return NULL;
}
return (SDL_GPUFence *)vulkanCommandBuffer->inFlightFence;
}
@@ -10324,7 +10354,8 @@ static bool VULKAN_Submit(
if (vulkanResult == VK_SUCCESS) {
VULKAN_INTERNAL_CleanCommandBuffer(
renderer,
renderer->submittedCommandBuffers[i]);
renderer->submittedCommandBuffers[i],
false);
commandBufferCleaned = 1;
}
@@ -10365,6 +10396,29 @@ static bool VULKAN_Submit(
return result;
}
static bool VULKAN_Cancel(
SDL_GPUCommandBuffer *commandBuffer)
{
VulkanRenderer *renderer;
VulkanCommandBuffer *vulkanCommandBuffer;
VkResult result;
vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
renderer = vulkanCommandBuffer->renderer;
result = renderer->vkResetCommandBuffer(
vulkanCommandBuffer->commandBuffer,
VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
CHECK_VULKAN_ERROR_AND_RETURN(result, vkResetCommandBuffer, false)
vulkanCommandBuffer->autoReleaseFence = false;
SDL_LockMutex(renderer->submitLock);
VULKAN_INTERNAL_CleanCommandBuffer(renderer, vulkanCommandBuffer, true);
SDL_UnlockMutex(renderer->submitLock);
return true;
}
static bool VULKAN_INTERNAL_DefragmentMemory(
VulkanRenderer *renderer)
{
@@ -10406,7 +10460,8 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
renderer,
currentRegion->vulkanBuffer->size,
currentRegion->vulkanBuffer->usage,
currentRegion->vulkanBuffer->type);
currentRegion->vulkanBuffer->type,
false);
if (newBuffer == NULL) {
SDL_UnlockMutex(renderer->allocatorLock);
@@ -10501,55 +10556,53 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
srcSubresource->parent->container->debugName);
}
if (srcSubresource->transitioned) {
VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
renderer,
commandBuffer,
VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
srcSubresource);
VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
renderer,
commandBuffer,
VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
srcSubresource);
VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
renderer,
commandBuffer,
VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
dstSubresource);
VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
renderer,
commandBuffer,
VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
dstSubresource);
imageCopy.srcOffset.x = 0;
imageCopy.srcOffset.y = 0;
imageCopy.srcOffset.z = 0;
imageCopy.srcSubresource.aspectMask = srcSubresource->parent->aspectFlags;
imageCopy.srcSubresource.baseArrayLayer = srcSubresource->layer;
imageCopy.srcSubresource.layerCount = 1;
imageCopy.srcSubresource.mipLevel = srcSubresource->level;
imageCopy.extent.width = SDL_max(1, info.width >> srcSubresource->level);
imageCopy.extent.height = SDL_max(1, info.height >> srcSubresource->level);
imageCopy.extent.depth = info.type == SDL_GPU_TEXTURETYPE_3D ? info.layer_count_or_depth : 1;
imageCopy.dstOffset.x = 0;
imageCopy.dstOffset.y = 0;
imageCopy.dstOffset.z = 0;
imageCopy.dstSubresource.aspectMask = dstSubresource->parent->aspectFlags;
imageCopy.dstSubresource.baseArrayLayer = dstSubresource->layer;
imageCopy.dstSubresource.layerCount = 1;
imageCopy.dstSubresource.mipLevel = dstSubresource->level;
imageCopy.srcOffset.x = 0;
imageCopy.srcOffset.y = 0;
imageCopy.srcOffset.z = 0;
imageCopy.srcSubresource.aspectMask = srcSubresource->parent->aspectFlags;
imageCopy.srcSubresource.baseArrayLayer = srcSubresource->layer;
imageCopy.srcSubresource.layerCount = 1;
imageCopy.srcSubresource.mipLevel = srcSubresource->level;
imageCopy.extent.width = SDL_max(1, info.width >> srcSubresource->level);
imageCopy.extent.height = SDL_max(1, info.height >> srcSubresource->level);
imageCopy.extent.depth = info.type == SDL_GPU_TEXTURETYPE_3D ? info.layer_count_or_depth : 1;
imageCopy.dstOffset.x = 0;
imageCopy.dstOffset.y = 0;
imageCopy.dstOffset.z = 0;
imageCopy.dstSubresource.aspectMask = dstSubresource->parent->aspectFlags;
imageCopy.dstSubresource.baseArrayLayer = dstSubresource->layer;
imageCopy.dstSubresource.layerCount = 1;
imageCopy.dstSubresource.mipLevel = dstSubresource->level;
renderer->vkCmdCopyImage(
commandBuffer->commandBuffer,
currentRegion->vulkanTexture->image,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
newTexture->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&imageCopy);
renderer->vkCmdCopyImage(
commandBuffer->commandBuffer,
currentRegion->vulkanTexture->image,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
newTexture->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&imageCopy);
VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
renderer,
commandBuffer,
VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
dstSubresource);
VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
renderer,
commandBuffer,
VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
dstSubresource);
VULKAN_INTERNAL_TrackTexture(commandBuffer, srcSubresource->parent);
VULKAN_INTERNAL_TrackTexture(commandBuffer, dstSubresource->parent);
}
VULKAN_INTERNAL_TrackTexture(commandBuffer, srcSubresource->parent);
VULKAN_INTERNAL_TrackTexture(commandBuffer, dstSubresource->parent);
}
// re-point original container to new texture
+6 -6
View File
@@ -492,7 +492,7 @@ public:
bool BOpen()
{
JNIEnv *env = SDL_GetAndroidJNIEnv();
JNIEnv *env = (JNIEnv *)SDL_GetAndroidJNIEnv();
if ( !g_HIDDeviceManagerCallbackHandler )
{
@@ -624,7 +624,7 @@ public:
int WriteReport( const unsigned char *pData, size_t nDataLen, bool bFeature )
{
JNIEnv *env = SDL_GetAndroidJNIEnv();
JNIEnv *env = (JNIEnv *)SDL_GetAndroidJNIEnv();
if ( !g_HIDDeviceManagerCallbackHandler )
{
@@ -654,7 +654,7 @@ public:
int ReadReport( unsigned char *pData, size_t nDataLen, bool bFeature )
{
JNIEnv *env = SDL_GetAndroidJNIEnv();
JNIEnv *env = (JNIEnv *)SDL_GetAndroidJNIEnv();
if ( !g_HIDDeviceManagerCallbackHandler )
{
@@ -727,7 +727,7 @@ public:
void Close( bool bDeleteDevice )
{
JNIEnv *env = SDL_GetAndroidJNIEnv();
JNIEnv *env = (JNIEnv *)SDL_GetAndroidJNIEnv();
if ( g_HIDDeviceManagerCallbackHandler )
{
@@ -1022,7 +1022,7 @@ static void SDLCALL RequestBluetoothPermissionCallback( void *userdata, const ch
if ( granted && g_HIDDeviceManagerCallbackHandler )
{
JNIEnv *env = SDL_GetAndroidJNIEnv();
JNIEnv *env = (JNIEnv *)SDL_GetAndroidJNIEnv();
env->CallBooleanMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerInitialize, false, true );
}
@@ -1035,7 +1035,7 @@ int hid_init(void)
// HIDAPI doesn't work well with Android < 4.3
if ( SDL_GetAndroidSDKVersion() >= 18 )
{
JNIEnv *env = SDL_GetAndroidJNIEnv();
JNIEnv *env = (JNIEnv *)SDL_GetAndroidJNIEnv();
env->CallBooleanMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerInitialize, true, false );
+2 -2
View File
@@ -686,8 +686,8 @@ static const char *s_GamepadMappings[] = {
"03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,",
"03000000222c00000225000011010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"03000000222c00000025000011010000,Qanba Dragon Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000222c00001020000011010000,Qanba Drone 2 Arcade Joystick (PS5),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000222c00001220000011010000,Qanba Drone 2 Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000222c00001020000011010000,Qanba Drone 2 Arcade Joystick (PS5),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000222c00000020000011010000,Qanba Drone Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,",
"03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
@@ -818,7 +818,7 @@ static const char *s_GamepadMappings[] = {
"050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
"050000004c050000cc090000fffe3f80,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,",
"050000004c050000cc090000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
"050000004c050000e60c0000fffe3f80,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,",
"050000004c050000e60c0000fffe3f80,PS5 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a3,rightx:a4,righty:a5,start:b16,x:b2,y:b17,",
"050000004c050000e60c0000ffff3f00,PS5 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
"05000000f8270000bf0b0000ffff3f00,Razer Kishi,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
"050000003215000005070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
@@ -115,7 +115,7 @@ static bool HIDAPI_DriverCombined_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_
for (i = 0; i < device->num_children; ++i) {
SDL_HIDAPI_Device *child = device->children[i];
if (child->driver->RumbleJoystick(child, joystick, low_frequency_rumble, high_frequency_rumble) == 0) {
if (child->driver->RumbleJoystick(child, joystick, low_frequency_rumble, high_frequency_rumble)) {
result = true;
}
}
@@ -129,7 +129,7 @@ static bool HIDAPI_DriverCombined_RumbleJoystickTriggers(SDL_HIDAPI_Device *devi
for (i = 0; i < device->num_children; ++i) {
SDL_HIDAPI_Device *child = device->children[i];
if (child->driver->RumbleJoystickTriggers(child, joystick, left_rumble, right_rumble) == 0) {
if (child->driver->RumbleJoystickTriggers(child, joystick, left_rumble, right_rumble)) {
result = true;
}
}
@@ -155,7 +155,7 @@ static bool HIDAPI_DriverCombined_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_
for (i = 0; i < device->num_children; ++i) {
SDL_HIDAPI_Device *child = device->children[i];
if (child->driver->SetJoystickLED(child, joystick, red, green, blue) == 0) {
if (child->driver->SetJoystickLED(child, joystick, red, green, blue)) {
result = true;
}
}
@@ -174,7 +174,7 @@ static bool HIDAPI_DriverCombined_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *d
for (i = 0; i < device->num_children; ++i) {
SDL_HIDAPI_Device *child = device->children[i];
if (child->driver->SetJoystickSensorsEnabled(child, joystick, enabled) == 0) {
if (child->driver->SetJoystickSensorsEnabled(child, joystick, enabled)) {
result = true;
}
}
@@ -175,8 +175,9 @@ static bool HIDAPI_DriverXbox360W_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Jo
SDL_PlayerLEDHintChanged, ctx);
// Initialize the joystick capabilities
joystick->nbuttons = 15;
joystick->nbuttons = 11;
joystick->naxes = SDL_GAMEPAD_AXIS_COUNT;
joystick->nhats = 1;
return true;
}
@@ -146,6 +146,9 @@ for line in input:
elif (line.startswith("#if")):
print(f"Parsing {line.strip()}")
output.write(line)
elif ("SDL_PRIVATE_GAMEPAD_DEFINITIONS" in line):
write_controllers()
output.write(line)
elif (line.startswith("#endif")):
write_controllers()
output.write(line)
+7 -6
View File
@@ -1812,13 +1812,13 @@ bool SDL_GetTextureColorMod(SDL_Texture *texture, Uint8 *r, Uint8 *g, Uint8 *b)
}
if (r) {
*r = (Uint8)(fR * 255.0f);
*r = (Uint8)SDL_roundf(SDL_clamp(fR, 0.0f, 1.0f) * 255.0f);
}
if (g) {
*g = (Uint8)(fG * 255.0f);
*g = (Uint8)SDL_roundf(SDL_clamp(fG, 0.0f, 1.0f) * 255.0f);
}
if (b) {
*b = (Uint8)(fB * 255.0f);
*b = (Uint8)SDL_roundf(SDL_clamp(fB, 0.0f, 1.0f) * 255.0f);
}
return true;
}
@@ -1883,7 +1883,7 @@ bool SDL_GetTextureAlphaMod(SDL_Texture *texture, Uint8 *alpha)
}
if (alpha) {
*alpha = (Uint8)(fA * 255.0f);
*alpha = (Uint8)SDL_roundf(SDL_clamp(fA, 0.0f, 1.0f) * 255.0f);
}
return true;
}
@@ -3006,8 +3006,8 @@ bool SDL_RenderViewportSet(SDL_Renderer *renderer)
static void GetRenderViewportSize(SDL_Renderer *renderer, SDL_FRect *rect)
{
const SDL_RenderViewState *view = renderer->view;
const float scale_x = view->current_scale.x;
const float scale_y = view->current_scale.y;
const float scale_x = view->logical_scale.x;
const float scale_y = view->logical_scale.y;
rect->x = 0.0f;
rect->y = 0.0f;
@@ -5072,6 +5072,7 @@ static void SDL_DiscardAllCommands(SDL_Renderer *renderer)
renderer->render_commands_pool = NULL;
renderer->render_commands_tail = NULL;
renderer->render_commands = NULL;
renderer->vertex_data_used = 0;
while (cmd) {
SDL_RenderCommand *next = cmd->next;
@@ -307,10 +307,9 @@ static void D3D11_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
static void D3D11_ReleaseAll(SDL_Renderer *renderer)
{
D3D11_RenderData *data = (D3D11_RenderData *)renderer->internal;
SDL_Texture *texture = NULL;
// Release all textures
for (texture = renderer->textures; texture; texture = texture->next) {
for (SDL_Texture *texture = renderer->textures; texture; texture = texture->next) {
D3D11_DestroyTexture(renderer, texture);
}
@@ -336,7 +335,7 @@ static void D3D11_ReleaseAll(SDL_Renderer *renderer)
SAFE_RELEASE(data->blendModes[i].blendState);
}
SDL_free(data->blendModes);
data->blendModes = NULL;
data->blendModesCount = 0;
}
for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) {
@@ -982,37 +981,6 @@ static void D3D11_ReleaseMainRenderTargetView(SDL_Renderer *renderer)
SAFE_RELEASE(data->mainRenderTargetView);
}
static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer *renderer);
static HRESULT D3D11_HandleDeviceLost(SDL_Renderer *renderer)
{
HRESULT result = S_OK;
D3D11_ReleaseAll(renderer);
result = D3D11_CreateDeviceResources(renderer);
if (FAILED(result)) {
// D3D11_CreateDeviceResources will set the SDL error
return result;
}
result = D3D11_UpdateForWindowSizeChange(renderer);
if (FAILED(result)) {
// D3D11_UpdateForWindowSizeChange will set the SDL error
return result;
}
// Let the application know that the device has been reset
{
SDL_Event event;
event.type = SDL_EVENT_RENDER_DEVICE_RESET;
event.common.timestamp = 0;
SDL_PushEvent(&event);
}
return S_OK;
}
// Initialize all resources that change when the window's size changes.
static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
{
@@ -1043,15 +1011,7 @@ static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
w, h,
DXGI_FORMAT_UNKNOWN,
0);
if (result == DXGI_ERROR_DEVICE_REMOVED) {
// If the device was removed for any reason, a new device and swap chain will need to be created.
D3D11_HandleDeviceLost(renderer);
/* Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method
* and correctly set up the new device.
*/
goto done;
} else if (FAILED(result)) {
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::ResizeBuffers"), result);
goto done;
}
@@ -1108,6 +1068,29 @@ done:
return result;
}
static bool D3D11_HandleDeviceLost(SDL_Renderer *renderer)
{
bool recovered = false;
D3D11_ReleaseAll(renderer);
if (SUCCEEDED(D3D11_CreateDeviceResources(renderer)) &&
SUCCEEDED(D3D11_CreateWindowSizeDependentResources(renderer))) {
recovered = true;
} else {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Renderer couldn't recover from device lost: %s\n", SDL_GetError());
D3D11_ReleaseAll(renderer);
}
// Let the application know that the device has been reset or lost
SDL_Event event;
event.type = recovered ? SDL_EVENT_RENDER_DEVICE_RESET : SDL_EVENT_RENDER_DEVICE_LOST;
event.common.timestamp = 0;
SDL_PushEvent(&event);
return recovered;
}
// This method is called when the window's size changes.
static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer *renderer)
{
@@ -1162,6 +1145,10 @@ static bool D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
D3D11_TEXTURE2D_DESC textureDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
if (!rendererData->d3dDevice) {
return SDL_SetError("Device lost and couldn't be recovered");
}
if (textureFormat == DXGI_FORMAT_UNKNOWN) {
return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified",
__FUNCTION__, texture->format);
@@ -2395,6 +2382,10 @@ static bool D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->internal;
const int viewportRotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
if (!rendererData->d3dDevice) {
return SDL_SetError("Device lost and couldn't be recovered");
}
if (rendererData->pixelSizeChanged) {
D3D11_UpdateForWindowSizeChange(renderer);
rendererData->pixelSizeChanged = false;
@@ -2613,6 +2604,10 @@ static bool D3D11_RenderPresent(SDL_Renderer *renderer)
HRESULT result;
DXGI_PRESENT_PARAMETERS parameters;
if (!data->d3dDevice) {
return SDL_SetError("Device lost and couldn't be recovered");
}
SDL_zero(parameters);
/* The application may optionally specify "dirty" or "scroll"
@@ -2634,10 +2629,15 @@ static bool D3D11_RenderPresent(SDL_Renderer *renderer)
* must recreate all device resources.
*/
if (result == DXGI_ERROR_DEVICE_REMOVED) {
D3D11_HandleDeviceLost(renderer);
if (D3D11_HandleDeviceLost(renderer)) {
SDL_SetError("Present failed, device lost");
} else {
// Recovering from device lost failed, error is already set
}
} else if (result == DXGI_ERROR_INVALID_CALL) {
// We probably went through a fullscreen <-> windowed transition
D3D11_CreateWindowSizeDependentResources(renderer);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::Present"), result);
} else {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::Present"), result);
}
@@ -374,14 +374,13 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
static void D3D12_ReleaseAll(SDL_Renderer *renderer)
{
D3D12_RenderData *data = (D3D12_RenderData *)renderer->internal;
SDL_Texture *texture = NULL;
SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
SDL_SetPointerProperty(props, SDL_PROP_RENDERER_D3D12_DEVICE_POINTER, NULL);
SDL_SetPointerProperty(props, SDL_PROP_RENDERER_D3D12_COMMAND_QUEUE_POINTER, NULL);
// Release all textures
for (texture = renderer->textures; texture; texture = texture->next) {
for (SDL_Texture *texture = renderer->textures; texture; texture = texture->next) {
D3D12_DestroyTexture(renderer, texture);
}
@@ -414,6 +413,7 @@ static void D3D12_ReleaseAll(SDL_Renderer *renderer)
D3D_SAFE_RELEASE(data->pipelineStates[i].pipelineState);
}
SDL_free(data->pipelineStates);
data->pipelineStates = NULL;
data->pipelineStateCount = 0;
}
@@ -1325,38 +1325,6 @@ done:
}
#endif
static HRESULT D3D12_UpdateForWindowSizeChange(SDL_Renderer *renderer);
HRESULT
D3D12_HandleDeviceLost(SDL_Renderer *renderer)
{
HRESULT result = S_OK;
D3D12_ReleaseAll(renderer);
result = D3D12_CreateDeviceResources(renderer);
if (FAILED(result)) {
// D3D12_CreateDeviceResources will set the SDL error
return result;
}
result = D3D12_UpdateForWindowSizeChange(renderer);
if (FAILED(result)) {
// D3D12_UpdateForWindowSizeChange will set the SDL error
return result;
}
// Let the application know that the device has been reset
{
SDL_Event event;
event.type = SDL_EVENT_RENDER_DEVICE_RESET;
event.common.timestamp = 0;
SDL_PushEvent(&event);
}
return S_OK;
}
// Initialize all resources that change when the window's size changes.
static HRESULT D3D12_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
{
@@ -1395,15 +1363,7 @@ static HRESULT D3D12_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
w, h,
DXGI_FORMAT_UNKNOWN,
data->swapFlags);
if (result == DXGI_ERROR_DEVICE_REMOVED) {
// If the device was removed for any reason, a new device and swap chain will need to be created.
D3D12_HandleDeviceLost(renderer);
/* Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method
* and correctly set up the new device.
*/
goto done;
} else if (FAILED(result)) {
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::ResizeBuffers"), result);
goto done;
}
@@ -1483,6 +1443,29 @@ done:
return result;
}
static bool D3D12_HandleDeviceLost(SDL_Renderer *renderer)
{
bool recovered = false;
D3D12_ReleaseAll(renderer);
if (SUCCEEDED(D3D12_CreateDeviceResources(renderer)) &&
SUCCEEDED(D3D12_CreateWindowSizeDependentResources(renderer))) {
recovered = true;
} else {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Renderer couldn't recover from device lost: %s\n", SDL_GetError());
D3D12_ReleaseAll(renderer);
}
// Let the application know that the device has been reset or lost
SDL_Event event;
event.type = recovered ? SDL_EVENT_RENDER_DEVICE_RESET : SDL_EVENT_RENDER_DEVICE_LOST;
event.common.timestamp = 0;
SDL_PushEvent(&event);
return recovered;
}
// This method is called when the window's size changes.
static HRESULT D3D12_UpdateForWindowSizeChange(SDL_Renderer *renderer)
{
@@ -1565,6 +1548,10 @@ static bool D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
D3D12_HEAP_PROPERTIES heapProps;
D3D12_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
if (!rendererData->d3dDevice) {
return SDL_SetError("Device lost and couldn't be recovered");
}
if (textureFormat == DXGI_FORMAT_UNKNOWN) {
return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified", __FUNCTION__, texture->format);
}
@@ -2738,6 +2725,10 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
D3D12_CPU_DESCRIPTOR_HANDLE *textureSampler;
D3D12_PixelShaderConstants constants;
if (!textureData) {
return SDL_SetError("Texture is not currently available");
}
D3D12_SetupShaderConstants(renderer, cmd, texture, &constants);
switch (textureData->scaleMode) {
@@ -2825,6 +2816,10 @@ static bool D3D12_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->internal;
const int viewportRotation = D3D12_GetRotationForCurrentRenderTarget(renderer);
if (!rendererData->d3dDevice) {
return SDL_SetError("Device lost and couldn't be recovered");
}
if (rendererData->pixelSizeChanged) {
D3D12_UpdateForWindowSizeChange(renderer);
rendererData->pixelSizeChanged = false;
@@ -3108,6 +3103,10 @@ static bool D3D12_RenderPresent(SDL_Renderer *renderer)
D3D12_RenderData *data = (D3D12_RenderData *)renderer->internal;
HRESULT result;
if (!data->d3dDevice) {
return SDL_SetError("Device lost and couldn't be recovered");
}
// Transition the render target to present state
D3D12_TransitionResource(data,
data->renderTargets[data->currentBackBufferIndex],
@@ -3132,10 +3131,15 @@ static bool D3D12_RenderPresent(SDL_Renderer *renderer)
* must recreate all device resources.
*/
if (result == DXGI_ERROR_DEVICE_REMOVED) {
D3D12_HandleDeviceLost(renderer);
if (D3D12_HandleDeviceLost(renderer)) {
SDL_SetError("Present failed, device lost");
} else {
// Recovering from device lost failed, error is already set
}
} else if (result == DXGI_ERROR_INVALID_CALL) {
// We probably went through a fullscreen <-> windowed transition
D3D12_CreateWindowSizeDependentResources(renderer);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::Present"), result);
} else {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::Present"), result);
}
@@ -432,6 +432,7 @@ static bool GPU_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SD
}
// FIXME: The Vulkan backend doesn't multiply by color_scale. GL does. I'm not sure which one is wrong.
// ANSWER: The color scale should be applied in linear space when using the scRGB colorspace. This is done in shaders in the Vulkan backend.
*(verts++) = col_.r * color_scale;
*(verts++) = col_.g * color_scale;
*(verts++) = col_.b * color_scale;
@@ -31,6 +31,8 @@ void *vita_mem_alloc(unsigned int type, unsigned int size, unsigned int alignmen
if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW) {
size = ALIGN(size, 256 * 1024);
} else if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_MAIN_PHYCONT_NC_RW) {
size = ALIGN(size, 1024 * 1024);
} else {
size = ALIGN(size, 4 * 1024);
}
@@ -1160,7 +1160,7 @@ void gxm_init_for_common_dialog(void)
for (int i = 0; i < VITA_GXM_BUFFERS; i += 1) {
buffer_for_common_dialog[i].displayData.wait_vblank = true;
buffer_for_common_dialog[i].displayData.address = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
SCE_KERNEL_MEMBLOCK_TYPE_USER_MAIN_PHYCONT_NC_RW,
4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
File diff suppressed because it is too large Load Diff
+99 -5
View File
@@ -1743,6 +1743,10 @@ void SDLTest_PrintEvent(const SDL_Event *event)
SDL_Log("SDL EVENT: Keyboard: text editing \"%s\" in window %" SDL_PRIu32,
event->edit.text, event->edit.windowID);
break;
case SDL_EVENT_TEXT_EDITING_CANDIDATES:
SDL_Log("SDL EVENT: Keyboard: text editing candidates in window %" SDL_PRIu32,
event->edit.windowID);
break;
case SDL_EVENT_TEXT_INPUT:
SDL_Log("SDL EVENT: Keyboard: text input \"%s\" in window %" SDL_PRIu32,
event->text.text, event->text.windowID);
@@ -1786,6 +1790,12 @@ void SDLTest_PrintEvent(const SDL_Event *event)
SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 " removed",
event->jdevice.which);
break;
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 " axis %d value: %d",
event->jaxis.which,
event->jaxis.axis,
event->jaxis.value);
break;
case SDL_EVENT_JOYSTICK_BALL_MOTION:
SDL_Log("SDL EVENT: Joystick %" SDL_PRIs32 ": ball %d moved by %d,%d",
event->jball.which, event->jball.ball, event->jball.xrel,
@@ -1834,6 +1844,10 @@ void SDLTest_PrintEvent(const SDL_Event *event)
SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 ": button %d released",
event->jbutton.which, event->jbutton.button);
break;
case SDL_EVENT_JOYSTICK_BATTERY_UPDATED:
SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 ": battery at %d percent",
event->jbattery.which, event->jbattery.percent);
break;
case SDL_EVENT_GAMEPAD_ADDED:
SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " attached",
event->gdevice.which);
@@ -1842,6 +1856,10 @@ void SDLTest_PrintEvent(const SDL_Event *event)
SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " removed",
event->gdevice.which);
break;
case SDL_EVENT_GAMEPAD_REMAPPED:
SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " mapping changed",
event->gdevice.which);
break;
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " axis %d ('%s') value: %d",
event->gaxis.which,
@@ -1880,11 +1898,14 @@ void SDLTest_PrintEvent(const SDL_Event *event)
event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
break;
case SDL_EVENT_RENDER_TARGETS_RESET:
SDL_Log("SDL EVENT: render targets reset");
break;
case SDL_EVENT_RENDER_DEVICE_RESET:
SDL_Log("SDL EVENT: render device reset");
break;
case SDL_EVENT_RENDER_TARGETS_RESET:
SDL_Log("SDL EVENT: render targets reset");
case SDL_EVENT_RENDER_DEVICE_LOST:
SDL_Log("SDL EVENT: render device lost");
break;
case SDL_EVENT_TERMINATING:
@@ -1920,6 +1941,76 @@ void SDLTest_PrintEvent(const SDL_Event *event)
case SDL_EVENT_DROP_COMPLETE:
SDL_Log("SDL EVENT: Drag and drop ending");
break;
case SDL_EVENT_AUDIO_DEVICE_ADDED:
SDL_Log("SDL EVENT: Audio %s device %" SDL_PRIu32 " available",
event->adevice.recording ? "recording" : "playback",
event->adevice.which);
break;
case SDL_EVENT_AUDIO_DEVICE_REMOVED:
SDL_Log("SDL EVENT: Audio %s device %" SDL_PRIu32 " removed",
event->adevice.recording ? "recording" : "playback",
event->adevice.which);
break;
case SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED:
SDL_Log("SDL EVENT: Audio %s device %" SDL_PRIu32 " format changed",
event->adevice.recording ? "recording" : "playback",
event->adevice.which);
break;
case SDL_EVENT_CAMERA_DEVICE_ADDED:
SDL_Log("SDL EVENT: Camera device %" SDL_PRIu32 " available",
event->cdevice.which);
break;
case SDL_EVENT_CAMERA_DEVICE_REMOVED:
SDL_Log("SDL EVENT: Camera device %" SDL_PRIu32 " removed",
event->cdevice.which);
break;
case SDL_EVENT_CAMERA_DEVICE_APPROVED:
SDL_Log("SDL EVENT: Camera device %" SDL_PRIu32 " permission granted",
event->cdevice.which);
break;
case SDL_EVENT_CAMERA_DEVICE_DENIED:
SDL_Log("SDL EVENT: Camera device %" SDL_PRIu32 " permission denied",
event->cdevice.which);
break;
case SDL_EVENT_SENSOR_UPDATE:
SDL_Log("SDL EVENT: Sensor update for %" SDL_PRIu32,
event->sensor.which);
break;
case SDL_EVENT_PEN_PROXIMITY_IN:
SDL_Log("SDL EVENT: Pen %" SDL_PRIu32 " entered proximity",
event->pproximity.which);
break;
case SDL_EVENT_PEN_PROXIMITY_OUT:
SDL_Log("SDL EVENT: Pen %" SDL_PRIu32 " left proximity",
event->ptouch.which);
break;
case SDL_EVENT_PEN_DOWN:
SDL_Log("SDL EVENT: Pen %" SDL_PRIu32 " touched down at %g,%g",
event->ptouch.which, event->ptouch.x, event->ptouch.y);
break;
case SDL_EVENT_PEN_UP:
SDL_Log("SDL EVENT: Pen %" SDL_PRIu32 " lifted off at %g,%g",
event->ptouch.which, event->ptouch.x, event->ptouch.y);
break;
case SDL_EVENT_PEN_BUTTON_DOWN:
SDL_Log("SDL EVENT: Pen %" SDL_PRIu32 " button %d pressed at %g,%g",
event->pbutton.which, event->pbutton.button, event->pbutton.x, event->pbutton.y);
break;
case SDL_EVENT_PEN_BUTTON_UP:
SDL_Log("SDL EVENT: Pen %" SDL_PRIu32 " button %d released at %g,%g",
event->pbutton.which, event->pbutton.button, event->pbutton.x, event->pbutton.y);
break;
case SDL_EVENT_PEN_MOTION:
SDL_Log("SDL EVENT: Pen %" SDL_PRIu32 " moved to %g,%g",
event->pmotion.which, event->pmotion.x, event->pmotion.y);
break;
case SDL_EVENT_PEN_AXIS:
SDL_Log("SDL EVENT: Pen %" SDL_PRIu32 " axis %d changed to %.2f",
event->paxis.which, event->paxis.axis, event->paxis.value);
break;
case SDL_EVENT_LOCALE_CHANGED:
SDL_Log("SDL EVENT: Locale changed");
break;
case SDL_EVENT_QUIT:
SDL_Log("SDL EVENT: Quit requested");
break;
@@ -1927,7 +2018,7 @@ void SDLTest_PrintEvent(const SDL_Event *event)
SDL_Log("SDL EVENT: User event %" SDL_PRIs32, event->user.code);
break;
default:
SDL_Log("Unknown event 0x%4.4" SDL_PRIu32, event->type);
SDL_Log("Unknown event 0x%4.4" SDL_PRIx32, event->type);
break;
}
}
@@ -2113,8 +2204,11 @@ SDL_AppResult SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const
int i;
if (state->verbose & VERBOSE_EVENT) {
if (((event->type != SDL_EVENT_MOUSE_MOTION) &&
(event->type != SDL_EVENT_FINGER_MOTION)) ||
if ((event->type != SDL_EVENT_MOUSE_MOTION &&
event->type != SDL_EVENT_FINGER_MOTION &&
event->type != SDL_EVENT_PEN_MOTION &&
event->type != SDL_EVENT_PEN_AXIS &&
event->type != SDL_EVENT_JOYSTICK_AXIS_MOTION) ||
(state->verbose & VERBOSE_MOTION)) {
SDLTest_PrintEvent(event);
}
+48 -94
View File
@@ -1785,8 +1785,8 @@ static void Blit_RGB565_BGRA8888(SDL_BlitInfo * info)
#endif // SDL_HAVE_BLIT_N_RGB565
// RGB555->ARGB1555, and BGR555->ABGR1555, SET_ALPHA
static void Blit_RGB555_ARGB1555(SDL_BlitInfo *info)
// blits 16 bit RGB<->RGBA with both surfaces having the same R,G,B fields
static void Blit2to2MaskAlpha(SDL_BlitInfo *info)
{
int width = info->dst_w;
int height = info->dst_h;
@@ -1794,22 +1794,43 @@ static void Blit_RGB555_ARGB1555(SDL_BlitInfo *info)
int srcskip = info->src_skip;
Uint16 *dst = (Uint16 *)info->dst;
int dstskip = info->dst_skip;
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
Uint16 mask = ((Uint32)info->a >> (8 - dstfmt->Abits)) << dstfmt->Ashift;
if (dstfmt->Amask) {
// RGB->RGBA, SET_ALPHA
Uint16 mask = ((Uint32)info->a >> (8 - dstfmt->Abits)) << dstfmt->Ashift;
while (height--) {
/* *INDENT-OFF* */ // clang-format off
DUFFS_LOOP_TRIVIAL(
{
*dst = *src | mask;
++dst;
++src;
},
width);
/* *INDENT-ON* */ // clang-format on
src = (Uint16 *)((Uint8 *)src + srcskip);
dst = (Uint16 *)((Uint8 *)dst + dstskip);
while (height--) {
/* *INDENT-OFF* */ // clang-format off
DUFFS_LOOP_TRIVIAL(
{
*dst = *src | mask;
++dst;
++src;
},
width);
/* *INDENT-ON* */ // clang-format on
src = (Uint16 *)((Uint8 *)src + srcskip);
dst = (Uint16 *)((Uint8 *)dst + dstskip);
}
} else {
// RGBA->RGB, NO_ALPHA
Uint16 mask = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask;
while (height--) {
/* *INDENT-OFF* */ // clang-format off
DUFFS_LOOP_TRIVIAL(
{
*dst = *src & mask;
++dst;
++src;
},
width);
/* *INDENT-ON* */ // clang-format on
src = (Uint16 *)((Uint8 *)src + srcskip);
dst = (Uint16 *)((Uint8 *)dst + dstskip);
}
}
}
@@ -2530,68 +2551,6 @@ static void BlitNtoNKeyCopyAlpha(SDL_BlitInfo *info)
}
}
// Special optimized blit for ARGB 2-10-10-10 --> RGBA
static void Blit2101010toN(SDL_BlitInfo *info)
{
int width = info->dst_w;
int height = info->dst_h;
Uint8 *src = info->src;
int srcskip = info->src_skip;
Uint8 *dst = info->dst;
int dstskip = info->dst_skip;
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
int dstbpp = dstfmt->bytes_per_pixel;
Uint32 Pixel;
unsigned sR, sG, sB, sA;
while (height--) {
/* *INDENT-OFF* */ // clang-format off
DUFFS_LOOP(
{
Pixel = *(Uint32 *)src;
RGBA_FROM_ARGB2101010(Pixel, sR, sG, sB, sA);
ASSEMBLE_RGBA(dst, dstbpp, dstfmt, sR, sG, sB, sA);
dst += dstbpp;
src += 4;
},
width);
/* *INDENT-ON* */ // clang-format on
src += srcskip;
dst += dstskip;
}
}
// Special optimized blit for RGBA --> ARGB 2-10-10-10
static void BlitNto2101010(SDL_BlitInfo *info)
{
int width = info->dst_w;
int height = info->dst_h;
Uint8 *src = info->src;
int srcskip = info->src_skip;
Uint8 *dst = info->dst;
int dstskip = info->dst_skip;
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
int srcbpp = srcfmt->bytes_per_pixel;
Uint32 Pixel;
unsigned sR, sG, sB, sA;
while (height--) {
/* *INDENT-OFF* */ // clang-format off
DUFFS_LOOP(
{
DISEMBLE_RGBA(src, srcbpp, srcfmt, Pixel, sR, sG, sB, sA);
ARGB2101010_FROM_RGBA(Pixel, sR, sG, sB, sA);
*(Uint32 *)dst = Pixel;
dst += 4;
src += srcbpp;
},
width);
/* *INDENT-ON* */ // clang-format on
src += srcskip;
dst += dstskip;
}
}
// Blit_3or4_to_3or4__same_rgb: 3 or 4 bpp, same RGB triplet
static void Blit_3or4_to_3or4__same_rgb(SDL_BlitInfo *info)
{
@@ -2804,11 +2763,6 @@ static const struct blit_table normal_blit_2[] = {
{ 0x0000F800, 0x000007E0, 0x0000001F, 4, 0x0000FF00, 0x00FF0000, 0xFF000000,
0, Blit_RGB565_BGRA8888, NO_ALPHA | COPY_ALPHA | SET_ALPHA },
#endif
{ 0x00007C00, 0x000003E0, 0x0000001F, 2, 0x00007C00, 0x000003E0, 0x0000001F,
0, Blit_RGB555_ARGB1555, SET_ALPHA },
{ 0x0000001F, 0x000003E0, 0x00007C00, 2, 0x0000001F, 0x000003E0, 0x00007C00,
0, Blit_RGB555_ARGB1555, SET_ALPHA },
// Default for 16-bit RGB source, used if no other blitter matches
{ 0, 0, 0, 0, 0, 0, 0, 0, BlitNtoN, 0 }
};
@@ -2946,25 +2900,25 @@ SDL_BlitFunc SDL_CalculateBlitN(SDL_Surface *surface)
}
if (blitfun == BlitNtoN) { // default C fallback catch-all. Slow!
if (srcfmt->format == SDL_PIXELFORMAT_ARGB2101010) {
blitfun = Blit2101010toN;
} else if (dstfmt->format == SDL_PIXELFORMAT_ARGB2101010) {
blitfun = BlitNto2101010;
} else if (srcfmt->bytes_per_pixel == 4 &&
dstfmt->bytes_per_pixel == 4 &&
srcfmt->Rmask == dstfmt->Rmask &&
srcfmt->Gmask == dstfmt->Gmask &&
srcfmt->Bmask == dstfmt->Bmask) {
if (srcfmt->bytes_per_pixel == dstfmt->bytes_per_pixel &&
srcfmt->Rmask == dstfmt->Rmask &&
srcfmt->Gmask == dstfmt->Gmask &&
srcfmt->Bmask == dstfmt->Bmask) {
if (a_need == COPY_ALPHA) {
if (srcfmt->Amask == dstfmt->Amask) {
// Fastpath C fallback: 32bit RGBA<->RGBA blit with matching RGBA
// Fastpath C fallback: RGBA<->RGBA blit with matching RGBA
blitfun = SDL_BlitCopy;
} else {
blitfun = BlitNtoNCopyAlpha;
}
} else {
// Fastpath C fallback: 32bit RGB<->RGBA blit with matching RGB
blitfun = Blit4to4MaskAlpha;
if (srcfmt->bytes_per_pixel == 4) {
// Fastpath C fallback: 32bit RGB<->RGBA blit with matching RGB
blitfun = Blit4to4MaskAlpha;
} else if (srcfmt->bytes_per_pixel == 2) {
// Fastpath C fallback: 16bit RGB<->RGBA blit with matching RGB
blitfun = Blit2to2MaskAlpha;
}
}
} else if (a_need == COPY_ALPHA) {
blitfun = BlitNtoNCopyAlpha;
+1 -1
View File
@@ -117,7 +117,7 @@ typedef enum SDL_EGL_ExtensionType
extern bool SDL_EGL_HasExtension(SDL_VideoDevice *_this, SDL_EGL_ExtensionType type, const char *ext);
extern bool SDL_EGL_GetAttribute(SDL_VideoDevice *_this, SDL_GLattr attrib, int *value);
extern bool SDL_EGL_GetAttribute(SDL_VideoDevice *_this, SDL_GLAttr attrib, int *value);
/* SDL_EGL_LoadLibrary can get a display for a specific platform (EGL_PLATFORM_*)
* or, if 0 is passed, let the implementation decide.
*/
+2
View File
@@ -264,6 +264,7 @@ struct SDL_VideoDevice
void (*SetWindowMaximumSize)(SDL_VideoDevice *_this, SDL_Window *window);
void (*SetWindowAspectRatio)(SDL_VideoDevice *_this, SDL_Window *window);
bool (*GetWindowBordersSize)(SDL_VideoDevice *_this, SDL_Window *window, int *top, int *left, int *bottom, int *right);
float (*GetWindowContentScale)(SDL_VideoDevice *_this, SDL_Window *window);
void (*GetWindowSizeInPixels)(SDL_VideoDevice *_this, SDL_Window *window, int *w, int *h);
bool (*SetWindowOpacity)(SDL_VideoDevice *_this, SDL_Window *window, float opacity);
bool (*SetWindowParent)(SDL_VideoDevice *_this, SDL_Window *window, SDL_Window *parent);
@@ -521,6 +522,7 @@ extern VideoBootStrap Emscripten_bootstrap;
extern VideoBootStrap OFFSCREEN_bootstrap;
extern VideoBootStrap NGAGE_bootstrap;
extern VideoBootStrap QNX_bootstrap;
extern VideoBootStrap OPENVR_bootstrap;
// Use SDL_OnVideoThread() sparingly, to avoid regressions in use cases that currently happen to work
extern bool SDL_OnVideoThread(void);
+19 -5
View File
@@ -139,6 +139,9 @@ static VideoBootStrap *bootstrap[] = {
#ifdef SDL_INPUT_LINUXEV
&DUMMY_evdev_bootstrap,
#endif
#endif
#ifdef SDL_VIDEO_DRIVER_OPENVR
&OPENVR_bootstrap,
#endif
NULL
};
@@ -274,6 +277,11 @@ static Uint32 SDL_DefaultGraphicsBackends(SDL_VideoDevice *_this)
if (_this->Metal_CreateView) {
return SDL_WINDOW_METAL;
}
#endif
#if defined(SDL_VIDEO_OPENGL) && defined(SDL_VIDEO_DRIVER_OPENVR)
if (SDL_strcmp(_this->name, "openvr") == 0) {
return SDL_WINDOW_OPENGL;
}
#endif
return 0;
}
@@ -1743,11 +1751,17 @@ float SDL_GetWindowDisplayScale(SDL_Window *window)
static void SDL_CheckWindowDisplayScaleChanged(SDL_Window *window)
{
float pixel_density = SDL_GetWindowPixelDensity(window);
float content_scale = SDL_GetDisplayContentScale(SDL_GetDisplayForWindowPosition(window));
float display_scale;
display_scale = (pixel_density * content_scale);
if (_this->GetWindowContentScale) {
display_scale = _this->GetWindowContentScale(_this, window);
} else {
const float pixel_density = SDL_GetWindowPixelDensity(window);
const float content_scale = SDL_GetDisplayContentScale(SDL_GetDisplayForWindowPosition(window));
display_scale = pixel_density * content_scale;
}
if (display_scale != window->display_scale) {
window->display_scale = display_scale;
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED, 0, 0);
@@ -4529,7 +4543,7 @@ void SDL_GL_ResetAttributes(void)
_this->gl_config.egl_platform = 0;
}
bool SDL_GL_SetAttribute(SDL_GLattr attr, int value)
bool SDL_GL_SetAttribute(SDL_GLAttr attr, int value)
{
#if defined(SDL_VIDEO_OPENGL) || defined(SDL_VIDEO_OPENGL_ES) || defined(SDL_VIDEO_OPENGL_ES2)
bool result;
@@ -4647,7 +4661,7 @@ bool SDL_GL_SetAttribute(SDL_GLattr attr, int value)
#endif // SDL_VIDEO_OPENGL
}
bool SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
bool SDL_GL_GetAttribute(SDL_GLAttr attr, int *value)
{
#if defined(SDL_VIDEO_OPENGL) || defined(SDL_VIDEO_OPENGL_ES) || defined(SDL_VIDEO_OPENGL_ES2)
PFNGLGETERRORPROC glGetErrorFunc;
+19 -1
View File
@@ -523,13 +523,31 @@ bool Cocoa_GL_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
}
bool Cocoa_GL_DestroyContext(SDL_VideoDevice *_this, SDL_GLContext context)
static void DispatchedDestroyContext(SDL_GLContext context)
{
@autoreleasepool {
SDL3OpenGLContext *nscontext = (__bridge SDL3OpenGLContext *)context;
[nscontext cleanup];
CFRelease(context);
}
}
bool Cocoa_GL_DestroyContext(SDL_VideoDevice *_this, SDL_GLContext context)
{
if ([NSThread isMainThread]) {
DispatchedDestroyContext(context);
} else {
if (SDL_opengl_async_dispatch) {
dispatch_async(dispatch_get_main_queue(), ^{
DispatchedDestroyContext(context);
});
} else {
dispatch_sync(dispatch_get_main_queue(), ^{
DispatchedDestroyContext(context);
});
}
}
return true;
}
@@ -88,6 +88,7 @@
// Handle drag-and-drop of files onto the SDL window.
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender;
- (void)draggingExited:(id<NSDraggingInfo>)sender;
- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender;
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender;
- (BOOL)wantsPeriodicDraggingUpdates;
@@ -174,6 +175,12 @@
return NSDragOperationNone; // no idea what to do with this, reject it.
}
- (void)draggingExited:(id<NSDraggingInfo>)sender
{
SDL_Window *sdlwindow = [self findSDLWindow];
SDL_SendDropComplete(sdlwindow);
}
- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender
{
if (([sender draggingSourceOperationMask] & NSDragOperationGeneric) == NSDragOperationGeneric) {
@@ -360,20 +360,24 @@ static EM_BOOL Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent
SDL_WindowData *window_data = userData;
float deltaY = wheelEvent->deltaY;
float deltaX = wheelEvent->deltaX;
switch (wheelEvent->deltaMode) {
case DOM_DELTA_PIXEL:
deltaX /= 100; // 100 pixels make up a step
deltaY /= 100; // 100 pixels make up a step
break;
case DOM_DELTA_LINE:
deltaX /= 3; // 3 lines make up a step
deltaY /= 3; // 3 lines make up a step
break;
case DOM_DELTA_PAGE:
deltaX *= 80; // A page makes up 80 steps
deltaY *= 80; // A page makes up 80 steps
break;
}
SDL_SendMouseWheel(0, window_data->window, SDL_DEFAULT_MOUSE_ID, (float)wheelEvent->deltaX, -deltaY, SDL_MOUSEWHEEL_NORMAL);
SDL_SendMouseWheel(0, window_data->window, SDL_DEFAULT_MOUSE_ID, deltaX, -deltaY, SDL_MOUSEWHEEL_NORMAL);
return SDL_EventEnabled(SDL_EVENT_MOUSE_WHEEL);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,27 @@
#ifndef __gl3platform_h_
#define __gl3platform_h_
/*
** Copyright 2017-2020 The Khronos Group Inc.
** SPDX-License-Identifier: Apache-2.0
*/
/* Platform-specific types and definitions for OpenGL ES 3.X gl3.h
*
* Adopters may modify khrplatform.h and this file to suit their platform.
* Please contribute modifications back to Khronos as pull requests on the
* public github repository:
* https://github.com/KhronosGroup/OpenGL-Registry
*/
#include <KHR/khrplatform.h>
#ifndef GL_APICALL
#define GL_APICALL KHRONOS_APICALL
#endif
#ifndef GL_APIENTRY
#define GL_APIENTRY KHRONOS_APIENTRY
#endif
#endif /* __gl3platform_h_ */
@@ -88,8 +88,11 @@ typedef void* MTLTexture_id;
typedef struct __IOSurface* IOSurfaceRef;
#ifdef __OBJC__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
@protocol MTLSharedEvent;
typedef __unsafe_unretained id<MTLSharedEvent> MTLSharedEvent_id;
#pragma clang diagnostic pop
#else
typedef void* MTLSharedEvent_id;
#endif
@@ -63,6 +63,8 @@ SDL_KMSDRM_SYM_OPT(int,drmModeAddFB2WithModifiers,(int fd, uint32_t width,
const uint32_t pitches[4], const uint32_t offsets[4],
const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags))
SDL_KMSDRM_SYM_OPT(const char *,drmModeGetConnectorTypeName,(uint32_t connector_type))
SDL_KMSDRM_SYM(int,drmModeRmFB,(int fd, uint32_t bufferId))
SDL_KMSDRM_SYM(drmModeFBPtr,drmModeGetFB,(int fd, uint32_t buf))
SDL_KMSDRM_SYM(drmModeCrtcPtr,drmModeGetCrtc,(int fd, uint32_t crtcId))
@@ -799,8 +799,10 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto
SDL_DisplayModeData *modedata = NULL;
drmModeEncoder *encoder = NULL;
drmModeCrtc *crtc = NULL;
const char *connector_type = NULL;
SDL_DisplayID display_id;
SDL_PropertiesID display_properties;
char name_fmt[64];
int orientation;
int mode_index;
int i, j;
@@ -963,6 +965,15 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto
KMSDRM_CrtcSetVrr(viddata->drm_fd, crtc->crtc_id, true);
}
// Set the name by the connector type, if possible
if (KMSDRM_drmModeGetConnectorTypeName) {
connector_type = KMSDRM_drmModeGetConnectorTypeName(connector->connector_type);
if (connector_type == NULL) {
connector_type = "Unknown";
}
SDL_snprintf(name_fmt, sizeof(name_fmt), "%s-%u", connector_type, connector->connector_type_id);
}
/*****************************************/
// Part 2: setup the SDL_Display itself.
/*****************************************/
@@ -984,6 +995,9 @@ static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connecto
CalculateRefreshRate(&dispdata->mode, &display.desktop_mode.refresh_rate_numerator, &display.desktop_mode.refresh_rate_denominator);
display.desktop_mode.format = SDL_PIXELFORMAT_ARGB8888;
display.desktop_mode.internal = modedata;
if (connector_type) {
display.name = name_fmt;
}
// Add the display to the list of SDL displays.
display_id = SDL_AddVideoDisplay(&display, false);
@@ -1016,6 +1030,49 @@ cleanup:
}
} // NOLINT(clang-analyzer-unix.Malloc): If no error `dispdata` is saved in the display
static void KMSDRM_SortDisplays(SDL_VideoDevice *_this)
{
const char *name_hint = SDL_GetHint(SDL_HINT_VIDEO_DISPLAY_PRIORITY);
if (name_hint) {
char *saveptr;
char *str = SDL_strdup(name_hint);
SDL_VideoDisplay **sorted_list = SDL_malloc(sizeof(SDL_VideoDisplay *) * _this->num_displays);
if (str && sorted_list) {
int sorted_index = 0;
// Sort the requested displays to the front of the list.
const char *token = SDL_strtok_r(str, ",", &saveptr);
while (token) {
for (int i = 0; i < _this->num_displays; ++i) {
SDL_VideoDisplay *d = _this->displays[i];
if (d && SDL_strcmp(token, d->name) == 0) {
sorted_list[sorted_index++] = d;
_this->displays[i] = NULL;
break;
}
}
token = SDL_strtok_r(NULL, ",", &saveptr);
}
// Append the remaining displays to the end of the list.
for (int i = 0; i < _this->num_displays; ++i) {
if (_this->displays[i]) {
sorted_list[sorted_index++] = _this->displays[i];
}
}
// Copy the sorted list back to the display list.
SDL_memcpy(_this->displays, sorted_list, sizeof(SDL_VideoDisplay *) * _this->num_displays);
}
SDL_free(str);
SDL_free(sorted_list);
}
}
/* Initializes the list of SDL displays: we build a new display for each
connecter connector we find.
This is to be called early, in VideoInit(), because it gets us
@@ -1078,6 +1135,9 @@ static bool KMSDRM_InitDisplays(SDL_VideoDevice *_this)
goto cleanup;
}
// Sort the displays, if necessary
KMSDRM_SortDisplays(_this);
// Determine if video hardware supports async pageflips.
if (KMSDRM_drmGetCap(viddata->drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &async_pageflip) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not determine async page flip capability.");
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,106 @@
#ifndef _SDL_OPENVRVIDEO_H
#define _SDL_OPENVRVIDEO_H
#ifdef SDL_VIDEO_DRIVER_WINDOWS
#ifdef EXTERN_C
#undef EXTERN_C
#endif
#endif
// OpenVR has a LOT of unused variables that GCC will freak out on.
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#endif
#define USE_SDL
#include "openvr_capi.h"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include <stdint.h>
#ifndef SDL_VIDEO_DRIVER_WINDOWS
#include <GLES3/gl3.h>
#include <GLES3/gl32.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES2/gl2ext.h>
#endif
struct SDL_WindowData
{
#ifdef SDL_VIDEO_DRIVER_WINDOWS
SDL_Window *window;
HWND hwnd;
HWND parent;
HDC hdc;
HDC mdc;
#else
int dummy;
#endif
};
struct SDL_VideoData {
void * openVRLIB;
intptr_t vrtoken;
intptr_t (*FN_VR_InitInternal)( EVRInitError *peError, EVRApplicationType eType );
const char *(*FN_VR_GetVRInitErrorAsEnglishDescription)( EVRInitError error );
intptr_t (*FN_VR_GetGenericInterface)( const char *pchInterfaceVersion, EVRInitError *peError );
int is_buffer_rendering;
unsigned int overlaytexture;
unsigned int fbo, rbo;
int saved_texture_state;
struct VR_IVRSystem_FnTable *oSystem;
struct VR_IVROverlay_FnTable *oOverlay;
struct VR_IVRInput_FnTable * oInput;
VROverlayHandle_t overlayID, thumbID, cursorID;
char * sOverlayName;
VRActionSetHandle_t input_action_set;
VRActionHandle_t * input_action_handles_buttons;
int input_action_handles_buttons_count;
VRActionHandle_t * input_action_handles_axes;
int input_action_handles_axes_count;
VRActionHandle_t input_action_handles_haptics[2];
bool bKeyboardShown;
bool bHasShownOverlay;
int targw, targh;
int last_targw, last_targh;
int swap_interval;
bool bDidCreateOverlay;
bool renderdoc_debugmarker_frame_end;
bool bIconOverridden;
SDL_Window * window;
SDL_Joystick *virtual_joystick;
#ifdef SDL_VIDEO_DRIVER_WINDOWS
HDC hdc;
HGLRC hglrc;
#else
EGLDisplay eglDpy;
EGLContext eglCtx;
#endif
};
struct SDL_DisplayData
{
int dummy;
};
#endif
File diff suppressed because it is too large Load Diff
@@ -609,7 +609,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
CGRect frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen);
#endif
if (self.keyboardHeight) {
if (self.keyboardHeight && self.textInputRect.h) {
int rectbottom = (int)(self.textInputRect.y + self.textInputRect.h);
int keybottom = (int)(self.view.bounds.size.height - self.keyboardHeight);
if (keybottom < rectbottom) {
@@ -165,6 +165,7 @@ extern void SDL_WAYLAND_UnloadSymbols(void);
#define libdecor_frame_is_floating (*WAYLAND_libdecor_frame_is_floating)
#define libdecor_frame_set_parent (*WAYLAND_libdecor_frame_set_parent)
#define libdecor_frame_show_window_menu (*WAYLAND_libdecor_frame_show_window_menu)
#define libdecor_frame_get_wm_capabilities (*WAYLAND_libdecor_frame_get_wm_capabilities)
#define libdecor_frame_get_xdg_surface (*WAYLAND_libdecor_frame_get_xdg_surface)
#define libdecor_frame_get_xdg_toplevel (*WAYLAND_libdecor_frame_get_xdg_toplevel)
#define libdecor_frame_translate_coordinate (*WAYLAND_libdecor_frame_translate_coordinate)
@@ -638,7 +638,7 @@ static bool ProcessHitTest(SDL_WindowData *window_data,
switch (window_data->hit_test_result) {
case SDL_HITTEST_DRAGGABLE:
#ifdef HAVE_LIBDECOR_H
if (window_data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (window_data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (window_data->shell_surface.libdecor.frame) {
libdecor_frame_move(window_data->shell_surface.libdecor.frame,
seat,
@@ -646,9 +646,9 @@ static bool ProcessHitTest(SDL_WindowData *window_data,
}
} else
#endif
if (window_data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) {
if (window_data->shell_surface.xdg.roleobj.toplevel) {
xdg_toplevel_move(window_data->shell_surface.xdg.roleobj.toplevel,
if (window_data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
if (window_data->shell_surface.xdg.toplevel.xdg_toplevel) {
xdg_toplevel_move(window_data->shell_surface.xdg.toplevel.xdg_toplevel,
seat,
serial);
}
@@ -664,7 +664,7 @@ static bool ProcessHitTest(SDL_WindowData *window_data,
case SDL_HITTEST_RESIZE_BOTTOMLEFT:
case SDL_HITTEST_RESIZE_LEFT:
#ifdef HAVE_LIBDECOR_H
if (window_data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (window_data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (window_data->shell_surface.libdecor.frame) {
libdecor_frame_resize(window_data->shell_surface.libdecor.frame,
seat,
@@ -673,9 +673,9 @@ static bool ProcessHitTest(SDL_WindowData *window_data,
}
} else
#endif
if (window_data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) {
if (window_data->shell_surface.xdg.roleobj.toplevel) {
xdg_toplevel_resize(window_data->shell_surface.xdg.roleobj.toplevel,
if (window_data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
if (window_data->shell_surface.xdg.toplevel.xdg_toplevel) {
xdg_toplevel_resize(window_data->shell_surface.xdg.toplevel.xdg_toplevel,
seat,
serial,
directions[window_data->hit_test_result - SDL_HITTEST_RESIZE_TOPLEFT]);
@@ -2134,6 +2134,7 @@ static void data_device_handle_leave(void *data, struct wl_data_device *wl_data_
if (data_device->drag_offer) {
if (data_device->dnd_window) {
SDL_SendDropComplete(data_device->dnd_window);
SDL_LogTrace(SDL_LOG_CATEGORY_INPUT,
". In wl_data_device_listener . data_device_handle_leave on data_offer 0x%08x from window %d for serial %d\n",
WAYLAND_wl_proxy_get_id((struct wl_proxy *)data_device->drag_offer->offer),
@@ -115,8 +115,8 @@ bool Wayland_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
* FIXME: Request EGL_WAYLAND_swap_buffers_with_timeout.
* -flibit
*/
if (data->surface_status != WAYLAND_SURFACE_STATUS_SHOWN &&
data->surface_status != WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME) {
if (data->shell_surface_status != WAYLAND_SHELL_SURFACE_STATUS_SHOWN &&
data->shell_surface_status != WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME) {
return true;
}
@@ -134,7 +134,7 @@ bool Wayland_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
// Control swap interval ourselves. See comments on Wayland_GLES_SetSwapInterval
if (swap_interval != 0 && data->surface_status == WAYLAND_SURFACE_STATUS_SHOWN) {
if (swap_interval != 0 && data->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_SHOWN) {
SDL_VideoData *videodata = _this->internal;
struct wl_display *display = videodata->display;
// 20hz, so we'll progress even if throttled to zero.
@@ -228,6 +228,10 @@ SDL_WAYLAND_SYM_OPT(void, libdecor_frame_get_max_content_size, (const struct lib
int *))
#endif
#if defined(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR) || SDL_LIBDECOR_CHECK_VERSION(0, 3, 0)
SDL_WAYLAND_SYM_OPT(enum libdecor_wm_capabilities, libdecor_frame_get_wm_capabilities, (struct libdecor_frame *))
#endif
#endif
#undef SDL_WAYLAND_MODULE
+14 -107
View File
@@ -49,7 +49,6 @@
#include "frog-color-management-v1-client-protocol.h"
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include "input-timestamps-unstable-v1-client-protocol.h"
#include "kde-output-order-v1-client-protocol.h"
#include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h"
#include "pointer-constraints-unstable-v1-client-protocol.h"
#include "primary-selection-unstable-v1-client-protocol.h"
@@ -203,47 +202,6 @@ error:
return false;
}
static void Wayland_FlushOutputOrder(SDL_VideoData *vid)
{
SDL_WaylandConnectorName *c, *tmp;
wl_list_for_each_safe (c, tmp, &vid->output_order, link) {
WAYLAND_wl_list_remove(&c->link);
SDL_free(c);
}
vid->output_order_finalized = false;
}
/* The order of wl_output displays exposed by KDE doesn't correspond to any priority, but KDE does provide a protocol
* that tells clients the preferred order or all connected displays via an ordered list of connector name strings.
*/
static void handle_kde_output_order_output(void *data, struct kde_output_order_v1 *kde_output_order_v1, const char *output_name)
{
SDL_VideoData *vid = (SDL_VideoData *)data;
// Starting a new list, flush the old.
if (vid->output_order_finalized) {
Wayland_FlushOutputOrder(vid);
}
const int len = SDL_strlen(output_name) + 1;
SDL_WaylandConnectorName *node = SDL_malloc(sizeof(SDL_WaylandConnectorName) + len);
SDL_strlcpy(node->wl_output_name, output_name, len);
WAYLAND_wl_list_insert(vid->output_order.prev, &node->link);
}
static void handle_kde_output_order_done(void *data, struct kde_output_order_v1 *kde_output_order_v1)
{
SDL_VideoData *vid = (SDL_VideoData *)data;
vid->output_order_finalized = true;
}
static const struct kde_output_order_v1_listener kde_output_order_listener = {
handle_kde_output_order_output,
handle_kde_output_order_done
};
// Sort the list of displays into a deterministic order
static int SDLCALL Wayland_DisplayPositionCompare(const void *a, const void *b)
{
@@ -350,7 +308,7 @@ static int Wayland_GetPrimaryDisplay(SDL_VideoData *vid)
return best_index;
}
static bool Wayland_SortOutputsByPriorityHint(SDL_VideoData *vid)
static void Wayland_SortOutputsByPriorityHint(SDL_VideoData *vid)
{
const char *name_hint = SDL_GetHint(SDL_HINT_VIDEO_DISPLAY_PRIORITY);
@@ -358,9 +316,10 @@ static bool Wayland_SortOutputsByPriorityHint(SDL_VideoData *vid)
char *saveptr;
char *str = SDL_strdup(name_hint);
SDL_DisplayData **sorted_list = SDL_malloc(sizeof(SDL_DisplayData *) * vid->output_count);
int sorted_index = 0;
if (str && sorted_list) {
int sorted_index = 0;
// Sort the requested displays to the front of the list.
const char *token = SDL_strtok_r(str, ",", &saveptr);
while (token) {
@@ -389,67 +348,24 @@ static bool Wayland_SortOutputsByPriorityHint(SDL_VideoData *vid)
SDL_free(str);
SDL_free(sorted_list);
return true;
}
return false;
}
static void Wayland_SortOutputs(SDL_VideoData *vid)
{
bool have_primary = false;
// Sort by position or connector name, so the order of outputs is deterministic.
SDL_qsort(vid->output_list, vid->output_count, sizeof(SDL_DisplayData *), Wayland_DisplayPositionCompare);
/* KDE provides the kde-output-order-v1 protocol, which gives us the full preferred display
* ordering in the form of a list of wl_output.name strings.
*/
if (!WAYLAND_wl_list_empty(&vid->output_order)) {
SDL_WaylandConnectorName *c;
SDL_DisplayData **sorted_list = SDL_malloc(sizeof(SDL_DisplayData *) * vid->output_count);
int sorted_index = 0;
if (sorted_list) {
// Sort the outputs by connector name.
wl_list_for_each (c, &vid->output_order, link) {
for (int i = 0; i < vid->output_count; ++i) {
SDL_DisplayData *d = vid->output_list[i];
if (d && d->wl_output_name && SDL_strcmp(c->wl_output_name, d->wl_output_name) == 0) {
sorted_list[sorted_index++] = d;
vid->output_list[i] = NULL;
break;
}
}
}
/* If any displays were omitted during the sort, append them to the new list.
* This shouldn't happen, but better safe than sorry.
*/
for (int i = 0; i < vid->output_count; ++i) {
if (vid->output_list[i]) {
sorted_list[sorted_index++] = vid->output_list[i];
}
}
// Copy the sorted list to the output list.
SDL_memcpy(vid->output_list, sorted_list, sizeof(SDL_DisplayData *) * vid->output_count);
SDL_free(sorted_list);
have_primary = true;
}
} else {
// Sort by position or connector name, so the order of outputs is deterministic.
SDL_qsort(vid->output_list, vid->output_count, sizeof(SDL_DisplayData *), Wayland_DisplayPositionCompare);
// Find a suitable primary display and move it to the front of the list.
const int primary_index = Wayland_GetPrimaryDisplay(vid);
if (primary_index) {
SDL_DisplayData *primary = vid->output_list[primary_index];
SDL_memmove(&vid->output_list[1], &vid->output_list[0], sizeof(SDL_DisplayData *) * primary_index);
vid->output_list[0] = primary;
}
// Apply the ordering hint if specified, otherwise, try to find the primary display, if no preferred order is known.
if (!Wayland_SortOutputsByPriorityHint(vid) && !have_primary) {
const int primary_index = Wayland_GetPrimaryDisplay(vid);
if (primary_index) {
SDL_DisplayData *primary = vid->output_list[primary_index];
SDL_memmove(&vid->output_list[1], &vid->output_list[0], sizeof(SDL_DisplayData *) * primary_index);
vid->output_list[0] = primary;
}
}
// Apply the ordering hint, if specified.
Wayland_SortOutputsByPriorityHint(vid);
}
static void display_handle_done(void *data, struct wl_output *output);
@@ -643,7 +559,6 @@ static SDL_VideoDevice *Wayland_CreateDevice(bool require_preferred_protocols)
data->input = input;
data->display_externally_owned = display_is_external;
data->scale_to_display_enabled = SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY, false);
WAYLAND_wl_list_init(&data->output_order);
WAYLAND_wl_list_init(&external_window_list);
// Initialize all variables that we clean on shutdown
@@ -710,6 +625,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(bool require_preferred_protocols)
device->SetWindowTitle = Wayland_SetWindowTitle;
device->SetWindowIcon = Wayland_SetWindowIcon;
device->GetWindowSizeInPixels = Wayland_GetWindowSizeInPixels;
device->GetWindowContentScale = Wayland_GetWindowContentScale;
device->GetDisplayForWindow = Wayland_GetDisplayForWindow;
device->DestroyWindow = Wayland_DestroyWindow;
device->SetWindowHitTest = Wayland_SetWindowHitTest;
@@ -1353,9 +1269,6 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
d->wp_alpha_modifier_v1 = wl_registry_bind(d->registry, id, &wp_alpha_modifier_v1_interface, 1);
} else if (SDL_strcmp(interface, "xdg_toplevel_icon_manager_v1") == 0) {
d->xdg_toplevel_icon_manager_v1 = wl_registry_bind(d->registry, id, &xdg_toplevel_icon_manager_v1_interface, 1);
} else if (SDL_strcmp(interface, "kde_output_order_v1") == 0) {
d->kde_output_order = wl_registry_bind(d->registry, id, &kde_output_order_v1_interface, 1);
kde_output_order_v1_add_listener(d->kde_output_order, &kde_output_order_listener, d);
} else if (SDL_strcmp(interface, "frog_color_management_factory_v1") == 0) {
d->frog_color_management_factory_v1 = wl_registry_bind(d->registry, id, &frog_color_management_factory_v1_interface, 1);
}
@@ -1634,12 +1547,6 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)
data->xdg_toplevel_icon_manager_v1 = NULL;
}
if (data->kde_output_order) {
Wayland_FlushOutputOrder(data);
kde_output_order_v1_destroy(data->kde_output_order);
data->kde_output_order = NULL;
}
if (data->frog_color_management_factory_v1) {
frog_color_management_factory_v1_destroy(data->frog_color_management_factory_v1);
data->frog_color_management_factory_v1 = NULL;
@@ -82,7 +82,6 @@ struct SDL_VideoData
struct xdg_wm_dialog_v1 *xdg_wm_dialog_v1;
struct wp_alpha_modifier_v1 *wp_alpha_modifier_v1;
struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager_v1;
struct kde_output_order_v1 *kde_output_order;
struct frog_color_management_factory_v1 *frog_color_management_factory_v1;
struct zwp_tablet_manager_v2 *tablet_manager;
@@ -91,9 +90,6 @@ struct SDL_VideoData
SDL_DisplayData **output_list;
int output_count;
int output_max;
struct wl_list output_order;
bool output_order_finalized;
int relative_mouse_mode;
bool display_externally_owned;
+219 -138
View File
@@ -176,7 +176,7 @@ static void SetMinMaxDimensions(SDL_Window *window)
}
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (!wind->shell_surface.libdecor.initial_configure_seen || !wind->shell_surface.libdecor.frame) {
return; // Can't do anything yet, wait for ShowWindow
}
@@ -193,14 +193,14 @@ static void SetMinMaxDimensions(SDL_Window *window)
}
} else
#endif
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.toplevel.xdg_toplevel == NULL) {
return; // Can't do anything yet, wait for ShowWindow
}
xdg_toplevel_set_min_size(wind->shell_surface.xdg.roleobj.toplevel,
xdg_toplevel_set_min_size(wind->shell_surface.xdg.toplevel.xdg_toplevel,
min_width,
min_height);
xdg_toplevel_set_max_size(wind->shell_surface.xdg.roleobj.toplevel,
xdg_toplevel_set_max_size(wind->shell_surface.xdg.toplevel.xdg_toplevel,
max_width,
max_height);
}
@@ -247,7 +247,7 @@ static void AdjustPopupOffset(SDL_Window *popup, int *x, int *y)
{
// Adjust the popup positioning, if necessary
#ifdef HAVE_LIBDECOR_H
if (popup->parent->internal->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (popup->parent->internal->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
int adj_x, adj_y;
libdecor_frame_translate_coordinate(popup->parent->internal->shell_surface.libdecor.frame,
*x, *y, &adj_x, &adj_y);
@@ -261,9 +261,9 @@ static void RepositionPopup(SDL_Window *window, bool use_current_position)
{
SDL_WindowData *wind = window->internal;
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP &&
wind->shell_surface.xdg.roleobj.popup.positioner &&
xdg_popup_get_version(wind->shell_surface.xdg.roleobj.popup.popup) >= XDG_POPUP_REPOSITION_SINCE_VERSION) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP &&
wind->shell_surface.xdg.popup.xdg_positioner &&
xdg_popup_get_version(wind->shell_surface.xdg.popup.xdg_popup) >= XDG_POPUP_REPOSITION_SINCE_VERSION) {
int x = use_current_position ? window->x : window->floating.x;
int y = use_current_position ? window->y : window->floating.y;
@@ -273,11 +273,11 @@ static void RepositionPopup(SDL_Window *window, bool use_current_position)
y = PixelToPoint(window->parent, y);
}
AdjustPopupOffset(window, &x, &y);
xdg_positioner_set_anchor_rect(wind->shell_surface.xdg.roleobj.popup.positioner, 0, 0, window->parent->internal->current.logical_width, window->parent->internal->current.logical_height);
xdg_positioner_set_size(wind->shell_surface.xdg.roleobj.popup.positioner, wind->current.logical_width, wind->current.logical_height);
xdg_positioner_set_offset(wind->shell_surface.xdg.roleobj.popup.positioner, x, y);
xdg_popup_reposition(wind->shell_surface.xdg.roleobj.popup.popup,
wind->shell_surface.xdg.roleobj.popup.positioner,
xdg_positioner_set_anchor_rect(wind->shell_surface.xdg.popup.xdg_positioner, 0, 0, window->parent->internal->current.logical_width, window->parent->internal->current.logical_height);
xdg_positioner_set_size(wind->shell_surface.xdg.popup.xdg_positioner, wind->current.logical_width, wind->current.logical_height);
xdg_positioner_set_offset(wind->shell_surface.xdg.popup.xdg_positioner, x, y);
xdg_popup_reposition(wind->shell_surface.xdg.popup.xdg_popup,
wind->shell_surface.xdg.popup.xdg_positioner,
0);
}
}
@@ -297,7 +297,7 @@ static void SetSurfaceOpaqueRegion(SDL_WindowData *wind, bool is_opaque)
}
}
static void ConfigureWindowGeometry(SDL_Window *window)
static bool ConfigureWindowGeometry(SDL_Window *window)
{
SDL_WindowData *data = window->internal;
const double scale_factor = GetWindowScale(window);
@@ -306,6 +306,17 @@ static void ConfigureWindowGeometry(SDL_Window *window)
int window_width, window_height;
bool window_size_changed;
// Throttle interactive resize events to once per refresh cycle to prevent lag.
if (data->resizing) {
data->resizing = false;
if (data->drop_interactive_resizes) {
return false;
} else {
data->drop_interactive_resizes = true;
}
}
// Set the drawable backbuffer size.
GetBufferSize(window, &data->current.pixel_width, &data->current.pixel_height);
const bool buffer_size_changed = data->current.pixel_width != old_pixel_width ||
@@ -413,7 +424,7 @@ static void ConfigureWindowGeometry(SDL_Window *window)
* aren't supported to avoid a potential protocol violation if a buffer
* with an old size is committed.
*/
if (!data->viewport && data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL && data->shell_surface.xdg.surface) {
if (!data->viewport && data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL && data->shell_surface.xdg.surface) {
xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, data->current.logical_width, data->current.logical_height);
}
@@ -444,7 +455,7 @@ static void ConfigureWindowGeometry(SDL_Window *window)
*
* The occlusion state is immediately set again afterward, if necessary.
*/
if (data->surface_status == WAYLAND_SURFACE_STATUS_SHOWN) {
if (data->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_SHOWN) {
if ((buffer_size_changed || window_size_changed) ||
(!data->suspended && (window->flags & SDL_WINDOW_OCCLUDED))) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
@@ -454,6 +465,8 @@ static void ConfigureWindowGeometry(SDL_Window *window)
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_OCCLUDED, 0, 0);
}
}
return true;
}
static void CommitLibdecorFrame(SDL_Window *window)
@@ -461,7 +474,7 @@ static void CommitLibdecorFrame(SDL_Window *window)
#ifdef HAVE_LIBDECOR_H
SDL_WindowData *wind = window->internal;
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR && wind->shell_surface.libdecor.frame) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR && wind->shell_surface.libdecor.frame) {
struct libdecor_state *state = libdecor_state_new(wind->current.logical_width, wind->current.logical_height);
libdecor_frame_commit(wind->shell_surface.libdecor.frame, state, NULL);
libdecor_state_free(state);
@@ -553,7 +566,7 @@ static void Wayland_move_window(SDL_Window *window)
if (wind->last_displayID != displays[i]) {
wind->last_displayID = displays[i];
if (wind->shell_surface_type != WAYLAND_SURFACE_XDG_POPUP) {
if (wind->shell_surface_type != WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, display->x, display->y);
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_DISPLAY_CHANGED, wind->last_displayID, 0);
}
@@ -571,7 +584,7 @@ static void SetFullscreen(SDL_Window *window, struct wl_output *output)
SDL_VideoData *viddata = wind->waylandData;
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (!wind->shell_surface.libdecor.frame) {
return; // Can't do anything yet, wait for ShowWindow
}
@@ -588,8 +601,8 @@ static void SetFullscreen(SDL_Window *window, struct wl_output *output)
}
} else
#endif
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.toplevel.xdg_toplevel == NULL) {
return; // Can't do anything yet, wait for ShowWindow
}
@@ -599,9 +612,9 @@ static void SetFullscreen(SDL_Window *window, struct wl_output *output)
Wayland_SetWindowResizable(SDL_GetVideoDevice(), window, true);
wl_surface_commit(wind->surface);
xdg_toplevel_set_fullscreen(wind->shell_surface.xdg.roleobj.toplevel, output);
xdg_toplevel_set_fullscreen(wind->shell_surface.xdg.toplevel.xdg_toplevel, output);
} else {
xdg_toplevel_unset_fullscreen(wind->shell_surface.xdg.roleobj.toplevel);
xdg_toplevel_unset_fullscreen(wind->shell_surface.xdg.toplevel.xdg_toplevel);
}
}
@@ -666,12 +679,14 @@ static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time
wl_surface_damage(wind->surface, 0, 0, SDL_MAX_SINT32, SDL_MAX_SINT32);
}
if (wind->surface_status == WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME) {
wind->surface_status = WAYLAND_SURFACE_STATUS_SHOWN;
wind->drop_interactive_resizes = false;
if (wind->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME) {
wind->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_SHOWN;
// If any child windows are waiting on this window to be shown, show them now
for (SDL_Window *w = wind->sdlwindow->first_child; w; w = w->next_sibling) {
if (w->internal->surface_status == WAYLAND_SURFACE_STATUS_SHOW_PENDING) {
if (w->internal->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_SHOW_PENDING) {
Wayland_ShowWindow(SDL_GetVideoDevice(), w);
} else if (w->internal->reparenting_required) {
Wayland_SetWindowParent(SDL_GetVideoDevice(), w, w->parent);
@@ -720,8 +735,9 @@ static void handle_configure_xdg_shell_surface(void *data, struct xdg_surface *x
SDL_WindowData *wind = (SDL_WindowData *)data;
SDL_Window *window = wind->sdlwindow;
ConfigureWindowGeometry(window);
xdg_surface_ack_configure(xdg, serial);
if (ConfigureWindowGeometry(window)) {
xdg_surface_ack_configure(xdg, serial);
}
wind->shell_surface.xdg.initial_configure_seen = true;
}
@@ -745,6 +761,7 @@ static void handle_configure_xdg_toplevel(void *data,
bool floating = true;
bool tiled = false;
bool active = false;
bool resizing = false;
bool suspended = false;
wl_array_for_each (state, states) {
switch (*state) {
@@ -756,6 +773,9 @@ static void handle_configure_xdg_toplevel(void *data,
maximized = true;
floating = false;
break;
case XDG_TOPLEVEL_STATE_RESIZING:
resizing = true;
break;
case XDG_TOPLEVEL_STATE_ACTIVATED:
active = true;
break;
@@ -931,9 +951,10 @@ static void handle_configure_xdg_toplevel(void *data,
wind->suspended = suspended;
wind->active = active;
window->tiled = tiled;
wind->resizing = resizing;
if (wind->surface_status == WAYLAND_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
wind->surface_status = WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME;
if (wind->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
wind->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME;
}
}
@@ -950,11 +971,33 @@ static void handle_xdg_configure_toplevel_bounds(void *data,
// NOP
}
void handle_xdg_toplevel_wm_capabilities(void *data,
struct xdg_toplevel *xdg_toplevel,
struct wl_array *capabilities)
static void handle_xdg_toplevel_wm_capabilities(void *data,
struct xdg_toplevel *xdg_toplevel,
struct wl_array *capabilities)
{
// NOP
SDL_WindowData *wind = (SDL_WindowData *)data;
enum xdg_toplevel_wm_capabilities *wm_cap;
wind->wm_caps = 0;
wl_array_for_each (wm_cap, capabilities) {
switch (*wm_cap) {
case XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU:
wind->wm_caps |= WAYLAND_WM_CAPS_WINDOW_MENU;
break;
case XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE:
wind->wm_caps |= WAYLAND_WM_CAPS_MAXIMIZE;
break;
case XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN:
wind->wm_caps |= WAYLAND_WM_CAPS_FULLSCREEN;
break;
case XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE:
wind->wm_caps |= WAYLAND_WM_CAPS_MINIMIZE;
break;
default:
break;
}
}
}
static const struct xdg_toplevel_listener toplevel_listener_xdg = {
@@ -991,8 +1034,8 @@ static void handle_configure_xdg_popup(void *data,
SDL_SendWindowEvent(wind->sdlwindow, SDL_EVENT_WINDOW_MOVED, x, y);
if (wind->surface_status == WAYLAND_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
wind->surface_status = WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME;
if (wind->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
wind->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME;
}
}
@@ -1041,7 +1084,7 @@ static void handle_configure_zxdg_decoration(void *data,
Wayland_HideWindow(device, window);
SDL_zero(internal->shell_surface);
internal->shell_surface_type = WAYLAND_SURFACE_LIBDECOR;
internal->shell_surface_type = WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR;
Wayland_ShowWindow(device, window);
}
@@ -1099,7 +1142,6 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
{
SDL_WindowData *wind = (SDL_WindowData *)user_data;
SDL_Window *window = wind->sdlwindow;
struct libdecor_state *state;
enum libdecor_window_state window_state;
int width, height;
@@ -1110,7 +1152,7 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
bool maximized = false;
bool tiled = false;
bool suspended = false;
bool floating;
bool resizing = false;
static const enum libdecor_window_state tiled_states = (LIBDECOR_WINDOW_STATE_TILED_LEFT | LIBDECOR_WINDOW_STATE_TILED_RIGHT |
LIBDECOR_WINDOW_STATE_TILED_TOP | LIBDECOR_WINDOW_STATE_TILED_BOTTOM);
@@ -1123,9 +1165,12 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
tiled = (window_state & tiled_states) != 0;
#if SDL_LIBDECOR_CHECK_VERSION(0, 2, 0)
suspended = (window_state & LIBDECOR_WINDOW_STATE_SUSPENDED) != 0;
#endif
#if SDL_LIBDECOR_CHECK_VERSION(0, 3, 0)
resizing = (window_state & LIBDECOR_WINDOW_STATE_RESIZING) != 0;
#endif
}
floating = !(fullscreen || maximized || tiled);
const bool floating = !(fullscreen || maximized || tiled);
UpdateWindowFullscreen(window, fullscreen);
@@ -1295,21 +1340,40 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
wind->suspended = suspended;
wind->active = active;
window->tiled = tiled;
wind->resizing = resizing;
// Update the window manager capabilities.
#if SDL_LIBDECOR_CHECK_VERSION(0, 3, 0)
enum libdecor_wm_capabilities caps;
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR
if (libdecor_frame_get_wm_capabilities) {
caps = libdecor_frame_get_wm_capabilities(wind->shell_surface.libdecor.frame);
#else
caps = libdecor_frame_get_wm_capabilities(wind->shell_surface.libdecor.frame);
{
#endif
wind->wm_caps = 0;
wind->wm_caps |= caps & LIBDECOR_WM_CAPABILITIES_WINDOW_MENU ? WAYLAND_WM_CAPS_WINDOW_MENU : 0;
wind->wm_caps |= caps & LIBDECOR_WM_CAPABILITIES_MAXIMIZE ? WAYLAND_WM_CAPS_MAXIMIZE : 0;
wind->wm_caps |= caps & LIBDECOR_WM_CAPABILITIES_FULLSCREEN ? WAYLAND_WM_CAPS_FULLSCREEN : 0;
wind->wm_caps |= caps & LIBDECOR_WM_CAPABILITIES_MINIMIZE ? WAYLAND_WM_CAPS_MINIMIZE : 0;
}
#endif
// Calculate the new window geometry
ConfigureWindowGeometry(window);
// ... then commit the changes on the libdecor side.
state = libdecor_state_new(wind->current.logical_width, wind->current.logical_height);
libdecor_frame_commit(frame, state, configuration);
libdecor_state_free(state);
if (ConfigureWindowGeometry(window)) {
// ... then commit the changes on the libdecor side.
struct libdecor_state *state = libdecor_state_new(wind->current.logical_width, wind->current.logical_height);
libdecor_frame_commit(frame, state, configuration);
libdecor_state_free(state);
}
if (!wind->shell_surface.libdecor.initial_configure_seen) {
LibdecorGetMinContentSize(frame, &wind->system_limits.min_width, &wind->system_limits.min_height);
wind->shell_surface.libdecor.initial_configure_seen = true;
}
if (wind->surface_status == WAYLAND_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
wind->surface_status = WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME;
if (wind->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
wind->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME;
}
/* Update the resize capability if this config event was the result of the
@@ -1335,7 +1399,7 @@ static void decoration_frame_commit(struct libdecor_frame *frame, void *user_dat
* commit a frame to trigger an update of the decoration surfaces.
*/
SDL_WindowData *wind = (SDL_WindowData *)user_data;
if (!wind->suspended && wind->surface_status == WAYLAND_SURFACE_STATUS_SHOWN) {
if (!wind->suspended && wind->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_SHOWN) {
SDL_SendWindowEvent(wind->sdlwindow, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
}
}
@@ -1573,12 +1637,12 @@ static struct xdg_toplevel *GetToplevelForWindow(SDL_WindowData *wind)
* internally anyways).
*/
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR && wind->shell_surface.libdecor.frame) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR && wind->shell_surface.libdecor.frame) {
return libdecor_frame_get_xdg_toplevel(wind->shell_surface.libdecor.frame);
} else
#endif
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL && wind->shell_surface.xdg.roleobj.toplevel) {
return wind->shell_surface.xdg.roleobj.toplevel;
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL && wind->shell_surface.xdg.toplevel.xdg_toplevel) {
return wind->shell_surface.xdg.toplevel.xdg_toplevel;
}
}
@@ -1592,7 +1656,7 @@ bool Wayland_SetWindowParent(SDL_VideoDevice *_this, SDL_Window *window, SDL_Win
child_data->reparenting_required = false;
if (parent_data && parent_data->surface_status != WAYLAND_SURFACE_STATUS_SHOWN) {
if (parent_data && parent_data->shell_surface_status != WAYLAND_SHELL_SURFACE_STATUS_SHOWN) {
// Need to wait for the parent to become mapped, or it's the same as setting a null parent.
child_data->reparenting_required = true;
return true;
@@ -1614,7 +1678,7 @@ bool Wayland_SetWindowModal(SDL_VideoDevice *_this, SDL_Window *window, bool mod
SDL_WindowData *data = window->internal;
SDL_WindowData *parent_data = window->parent->internal;
if (parent_data->surface_status != WAYLAND_SURFACE_STATUS_SHOWN) {
if (parent_data->shell_surface_status != WAYLAND_SHELL_SURFACE_STATUS_SHOWN) {
// Need to wait for the parent to become mapped before changing modal status.
data->reparenting_required = true;
return true;
@@ -1678,7 +1742,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
SDL_PropertiesID props = SDL_GetWindowProperties(window);
// Custom surfaces don't get toplevels and are always considered 'shown'; nothing to do here.
if (data->shell_surface_type == WAYLAND_SURFACE_CUSTOM) {
if (data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_CUSTOM) {
return;
}
@@ -1691,8 +1755,8 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
* be shown when the parent is in the shown state.
*/
if (window->parent) {
if (window->parent->internal->surface_status != WAYLAND_SURFACE_STATUS_SHOWN) {
data->surface_status = WAYLAND_SURFACE_STATUS_SHOW_PENDING;
if (window->parent->internal->shell_surface_status != WAYLAND_SHELL_SURFACE_STATUS_SHOWN) {
data->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_SHOW_PENDING;
return;
}
}
@@ -1704,7 +1768,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
WAYLAND_wl_display_roundtrip(c->display);
}
data->surface_status = WAYLAND_SURFACE_STATUS_WAITING_FOR_CONFIGURE;
data->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE;
/* Detach any previous buffers before resetting everything, otherwise when
* calling this a second time you'll get an annoying protocol error!
@@ -1725,7 +1789,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
// Create the shell surface and map the toplevel/popup
#ifdef HAVE_LIBDECOR_H
if (data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
data->shell_surface.libdecor.frame = libdecor_decorate(c->shell.libdecor,
data->surface,
&libdecor_frame_interface,
@@ -1752,13 +1816,13 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
} else
#endif
if (data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL || data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
if (data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL || data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP) {
data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(c->shell.xdg, data->surface);
xdg_surface_set_user_data(data->shell_surface.xdg.surface, data);
xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data);
SDL_SetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER, data->shell_surface.xdg.surface);
if (data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
if (data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP) {
SDL_Window *parent = window->parent;
SDL_WindowData *parent_data = parent->internal;
struct xdg_surface *parent_xdg_surface = NULL;
@@ -1766,23 +1830,23 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
// Configure the popup parameters
#ifdef HAVE_LIBDECOR_H
if (parent_data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (parent_data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
parent_xdg_surface = libdecor_frame_get_xdg_surface(parent_data->shell_surface.libdecor.frame);
} else
#endif
if (parent_data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL ||
parent_data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
if (parent_data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL ||
parent_data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP) {
parent_xdg_surface = parent_data->shell_surface.xdg.surface;
}
// Set up the positioner for the popup and configure the constraints
data->shell_surface.xdg.roleobj.popup.positioner = xdg_wm_base_create_positioner(c->shell.xdg);
xdg_positioner_set_anchor(data->shell_surface.xdg.roleobj.popup.positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT);
xdg_positioner_set_anchor_rect(data->shell_surface.xdg.roleobj.popup.positioner, 0, 0, parent->internal->current.logical_width, parent->internal->current.logical_width);
xdg_positioner_set_constraint_adjustment(data->shell_surface.xdg.roleobj.popup.positioner,
data->shell_surface.xdg.popup.xdg_positioner = xdg_wm_base_create_positioner(c->shell.xdg);
xdg_positioner_set_anchor(data->shell_surface.xdg.popup.xdg_positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT);
xdg_positioner_set_anchor_rect(data->shell_surface.xdg.popup.xdg_positioner, 0, 0, parent->internal->current.logical_width, parent->internal->current.logical_width);
xdg_positioner_set_constraint_adjustment(data->shell_surface.xdg.popup.xdg_positioner,
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y);
xdg_positioner_set_gravity(data->shell_surface.xdg.roleobj.popup.positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
xdg_positioner_set_size(data->shell_surface.xdg.roleobj.popup.positioner, data->current.logical_width, data->current.logical_height);
xdg_positioner_set_gravity(data->shell_surface.xdg.popup.xdg_positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
xdg_positioner_set_size(data->shell_surface.xdg.popup.xdg_positioner, data->current.logical_width, data->current.logical_height);
// Set the popup initial position
position_x = window->x;
@@ -1793,13 +1857,13 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
position_y = PixelToPoint(window->parent, position_y);
}
AdjustPopupOffset(window, &position_x, &position_y);
xdg_positioner_set_offset(data->shell_surface.xdg.roleobj.popup.positioner, position_x, position_y);
xdg_positioner_set_offset(data->shell_surface.xdg.popup.xdg_positioner, position_x, position_y);
// Assign the popup role
data->shell_surface.xdg.roleobj.popup.popup = xdg_surface_get_popup(data->shell_surface.xdg.surface,
data->shell_surface.xdg.popup.xdg_popup = xdg_surface_get_popup(data->shell_surface.xdg.surface,
parent_xdg_surface,
data->shell_surface.xdg.roleobj.popup.positioner);
xdg_popup_add_listener(data->shell_surface.xdg.roleobj.popup.popup, &popup_listener_xdg, data);
data->shell_surface.xdg.popup.xdg_positioner);
xdg_popup_add_listener(data->shell_surface.xdg.popup.xdg_popup, &popup_listener_xdg, data);
if (window->flags & SDL_WINDOW_TOOLTIP) {
struct wl_region *region;
@@ -1815,12 +1879,12 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
}
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER, data->shell_surface.xdg.roleobj.popup.popup);
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_POSITIONER_POINTER, data->shell_surface.xdg.roleobj.popup.positioner);
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER, data->shell_surface.xdg.popup.xdg_popup);
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_POSITIONER_POINTER, data->shell_surface.xdg.popup.xdg_positioner);
} else {
data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, data->app_id);
xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
data->shell_surface.xdg.toplevel.xdg_toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
xdg_toplevel_set_app_id(data->shell_surface.xdg.toplevel.xdg_toplevel, data->app_id);
xdg_toplevel_add_listener(data->shell_surface.xdg.toplevel.xdg_toplevel, &toplevel_listener_xdg, data);
if (c->zxdg_exporter_v2) {
data->exported = zxdg_exporter_v2_export_toplevel(c->zxdg_exporter_v2, data->surface);
@@ -1829,11 +1893,11 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
if (c->xdg_toplevel_icon_manager_v1 && data->xdg_toplevel_icon_v1) {
xdg_toplevel_icon_manager_v1_set_icon(_this->internal->xdg_toplevel_icon_manager_v1,
data->shell_surface.xdg.roleobj.toplevel,
data->shell_surface.xdg.toplevel.xdg_toplevel,
data->xdg_toplevel_icon_v1);
}
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, data->shell_surface.xdg.roleobj.toplevel);
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, data->shell_surface.xdg.toplevel.xdg_toplevel);
}
}
@@ -1850,7 +1914,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
* this surface will fail. This is a new rule for xdg_shell.
*/
#ifdef HAVE_LIBDECOR_H
if (data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (data->shell_surface.libdecor.frame) {
while (!data->shell_surface.libdecor.initial_configure_seen) {
WAYLAND_wl_display_flush(c->display);
@@ -1859,7 +1923,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
} else
#endif
if (data->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP || data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) {
if (data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP || data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
/* Unlike libdecor we need to call this explicitly to prevent a deadlock.
* libdecor will call this as part of their configure event!
* -flibit
@@ -1873,8 +1937,8 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
// Create the window decorations
if (data->shell_surface_type != WAYLAND_SURFACE_XDG_POPUP && data->shell_surface.xdg.roleobj.toplevel && c->decoration_manager) {
data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.roleobj.toplevel);
if (data->shell_surface_type != WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP && data->shell_surface.xdg.toplevel.xdg_toplevel && c->decoration_manager) {
data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.toplevel.xdg_toplevel);
zxdg_toplevel_decoration_v1_add_listener(data->server_decoration,
&decoration_listener,
window);
@@ -1893,7 +1957,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
* them immediately afterward.
*/
#ifdef HAVE_LIBDECOR_H
if (data->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
// Libdecor plugins can enforce minimum window sizes, so adjust if the initial window size is too small.
if (window->windowed.w < data->system_limits.min_width ||
window->windowed.h < data->system_limits.min_height) {
@@ -1933,7 +1997,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
wl_callback_add_listener(cb, &show_hide_sync_listener, (void*)((uintptr_t)window->id));
// Send an exposure event to signal that the client should draw.
if (data->surface_status == WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME) {
if (data->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
}
}
@@ -1952,7 +2016,7 @@ static void Wayland_ReleasePopup(SDL_VideoDevice *_this, SDL_Window *popup)
}
// This may already be freed by a parent popup!
if (popupdata->shell_surface.xdg.roleobj.popup.popup == NULL) {
if (popupdata->shell_surface.xdg.popup.xdg_popup == NULL) {
return;
}
@@ -1969,10 +2033,10 @@ static void Wayland_ReleasePopup(SDL_VideoDevice *_this, SDL_Window *popup)
}
}
xdg_popup_destroy(popupdata->shell_surface.xdg.roleobj.popup.popup);
xdg_positioner_destroy(popupdata->shell_surface.xdg.roleobj.popup.positioner);
popupdata->shell_surface.xdg.roleobj.popup.popup = NULL;
popupdata->shell_surface.xdg.roleobj.popup.positioner = NULL;
xdg_popup_destroy(popupdata->shell_surface.xdg.popup.xdg_popup);
xdg_positioner_destroy(popupdata->shell_surface.xdg.popup.xdg_positioner);
popupdata->shell_surface.xdg.popup.xdg_popup = NULL;
popupdata->shell_surface.xdg.popup.xdg_positioner = NULL;
SDL_PropertiesID props = SDL_GetWindowProperties(popup);
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER, NULL);
@@ -1986,7 +2050,7 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
SDL_PropertiesID props = SDL_GetWindowProperties(window);
// Custom surfaces have nothing to destroy and are always considered to be 'shown'; nothing to do here.
if (wind->shell_surface_type == WAYLAND_SURFACE_CUSTOM) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_CUSTOM) {
return;
}
@@ -1997,7 +2061,7 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
WAYLAND_wl_display_roundtrip(data->display);
}
wind->surface_status = WAYLAND_SURFACE_STATUS_HIDDEN;
wind->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_HIDDEN;
if (wind->server_decoration) {
zxdg_toplevel_decoration_v1_destroy(wind->server_decoration);
@@ -2005,7 +2069,7 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
// Be sure to detach after this is done, otherwise ShowWindow crashes!
if (wind->shell_surface_type != WAYLAND_SURFACE_XDG_POPUP) {
if (wind->shell_surface_type != WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP) {
wl_surface_attach(wind->surface, NULL, 0, 0);
wl_surface_commit(wind->surface);
}
@@ -2024,7 +2088,7 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (wind->shell_surface.libdecor.frame) {
libdecor_frame_unref(wind->shell_surface.libdecor.frame);
wind->shell_surface.libdecor.frame = NULL;
@@ -2034,11 +2098,11 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
} else
#endif
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP) {
Wayland_ReleasePopup(_this, window);
} else if (wind->shell_surface.xdg.roleobj.toplevel) {
xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel);
wind->shell_surface.xdg.roleobj.toplevel = NULL;
} else if (wind->shell_surface.xdg.toplevel.xdg_toplevel) {
xdg_toplevel_destroy(wind->shell_surface.xdg.toplevel.xdg_toplevel);
wind->shell_surface.xdg.toplevel.xdg_toplevel = NULL;
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, NULL);
}
if (wind->shell_surface.xdg.surface) {
@@ -2146,7 +2210,7 @@ SDL_FullscreenResult Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Win
struct wl_output *output = display->internal->output;
// Custom surfaces have no toplevel to make fullscreen.
if (wind->shell_surface_type == WAYLAND_SURFACE_CUSTOM) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_CUSTOM) {
return SDL_FULLSCREEN_FAILED;
}
@@ -2205,7 +2269,7 @@ void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window)
SDL_WindowData *wind = window->internal;
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (!wind->shell_surface.libdecor.frame) {
return; // Can't do anything yet, wait for ShowWindow
}
@@ -2213,11 +2277,11 @@ void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window)
} else
#endif
// Note that xdg-shell does NOT provide a way to unset minimize!
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.toplevel.xdg_toplevel == NULL) {
return; // Can't do anything yet, wait for ShowWindow
}
xdg_toplevel_unset_maximized(wind->shell_surface.xdg.roleobj.toplevel);
xdg_toplevel_unset_maximized(wind->shell_surface.xdg.toplevel.xdg_toplevel);
}
}
@@ -2227,13 +2291,13 @@ void Wayland_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, bool
const SDL_VideoData *viddata = (const SDL_VideoData *)_this->internal;
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (wind->shell_surface.libdecor.frame) {
libdecor_frame_set_visibility(wind->shell_surface.libdecor.frame, bordered);
}
} else
#endif
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
if ((viddata->decoration_manager) && (wind->server_decoration)) {
const enum zxdg_toplevel_decoration_v1_mode mode = bordered ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
zxdg_toplevel_decoration_v1_set_mode(wind->server_decoration, mode);
@@ -2246,7 +2310,7 @@ void Wayland_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, bool
#ifdef HAVE_LIBDECOR_H
const SDL_WindowData *wind = window->internal;
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (!wind->shell_surface.libdecor.frame) {
return; // Can't do anything yet, wait for ShowWindow
}
@@ -2277,7 +2341,7 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (!wind->shell_surface.libdecor.frame) {
return; // Can't do anything yet, wait for ShowWindow
}
@@ -2287,14 +2351,14 @@ void Wayland_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
libdecor_frame_set_maximized(wind->shell_surface.libdecor.frame);
} else
#endif
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.toplevel.xdg_toplevel == NULL) {
return; // Can't do anything yet, wait for ShowWindow
}
// Commit to preserve any pending size data.
wl_surface_commit(wind->surface);
xdg_toplevel_set_maximized(wind->shell_surface.xdg.roleobj.toplevel);
xdg_toplevel_set_maximized(wind->shell_surface.xdg.toplevel.xdg_toplevel);
}
++wind->maximized_deadline_count;
@@ -2306,9 +2370,12 @@ void Wayland_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_WindowData *wind = window->internal;
// TODO: Check compositor capabilities to see if minimizing is supported
if (!(wind->wm_caps & WAYLAND_WM_CAPS_MINIMIZE)) {
return;
}
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (!wind->shell_surface.libdecor.frame) {
return; // Can't do anything yet, wait for ShowWindow
}
@@ -2316,11 +2383,11 @@ void Wayland_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
} else
#endif
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.toplevel.xdg_toplevel == NULL) {
return; // Can't do anything yet, wait for ShowWindow
}
xdg_toplevel_set_minimized(wind->shell_surface.xdg.roleobj.toplevel);
xdg_toplevel_set_minimized(wind->shell_surface.xdg.toplevel.xdg_toplevel);
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
}
}
@@ -2395,6 +2462,9 @@ bool Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Proper
data->waylandData = c;
data->sdlwindow = window;
// Default to all capabilities
data->wm_caps = WAYLAND_WM_CAPS_ALL;
data->scale_factor = 1.0;
if (SDL_WINDOW_IS_POPUP(window)) {
@@ -2524,20 +2594,20 @@ bool Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Proper
if (!custom_surface_role) {
#ifdef HAVE_LIBDECOR_H
if (c->shell.libdecor && !SDL_WINDOW_IS_POPUP(window)) {
data->shell_surface_type = WAYLAND_SURFACE_LIBDECOR;
data->shell_surface_type = WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR;
} else
#endif
if (c->shell.xdg) {
if (SDL_WINDOW_IS_POPUP(window)) {
data->shell_surface_type = WAYLAND_SURFACE_XDG_POPUP;
data->shell_surface_type = WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP;
} else {
data->shell_surface_type = WAYLAND_SURFACE_XDG_TOPLEVEL;
data->shell_surface_type = WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL;
}
} // All other cases will be WAYLAND_SURFACE_UNKNOWN
} else {
// Roleless and external surfaces are always considered to be in the shown state by the backend.
data->shell_surface_type = WAYLAND_SURFACE_CUSTOM;
data->surface_status = WAYLAND_SURFACE_STATUS_SHOWN;
data->shell_surface_type = WAYLAND_SHELL_SURFACE_TYPE_CUSTOM;
data->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_SHOWN;
}
if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, false)) {
@@ -2571,15 +2641,15 @@ bool Wayland_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window)
SDL_WindowData *wind = window->internal;
// Only popup windows can be positioned relative to the parent.
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_POPUP) {
if (wind->shell_surface.xdg.roleobj.popup.popup &&
xdg_popup_get_version(wind->shell_surface.xdg.roleobj.popup.popup) < XDG_POPUP_REPOSITION_SINCE_VERSION) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP) {
if (wind->shell_surface.xdg.popup.xdg_popup &&
xdg_popup_get_version(wind->shell_surface.xdg.popup.xdg_popup) < XDG_POPUP_REPOSITION_SINCE_VERSION) {
return SDL_Unsupported();
}
RepositionPopup(window, false);
return true;
} else if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR || wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) {
} else if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR || wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
const int x = window->floating.x;
const int y = window->floating.y;
@@ -2630,7 +2700,7 @@ void Wayland_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window)
FlushPendingEvents(window);
if (!(window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MAXIMIZED)) ||
wind->shell_surface_type == WAYLAND_SURFACE_CUSTOM) {
wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_CUSTOM) {
if (!wind->scale_to_display) {
wind->requested.logical_width = window->floating.w;
wind->requested.logical_height = window->floating.h;
@@ -2658,6 +2728,17 @@ void Wayland_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, i
*h = data->current.pixel_height;
}
float Wayland_GetWindowContentScale(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_WindowData *wind = window->internal;
if (window->flags & SDL_WINDOW_HIGH_PIXEL_DENSITY || wind->scale_to_display || wind->fullscreen_exclusive) {
return (float)wind->scale_factor;
}
return 1.0f;
}
SDL_DisplayID Wayland_GetDisplayForWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_WindowData *wind = window->internal;
@@ -2689,12 +2770,12 @@ void Wayland_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window)
const char *title = window->title ? window->title : "";
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR && wind->shell_surface.libdecor.frame) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR && wind->shell_surface.libdecor.frame) {
libdecor_frame_set_title(wind->shell_surface.libdecor.frame, title);
} else
#endif
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL && wind->shell_surface.xdg.roleobj.toplevel) {
xdg_toplevel_set_title(wind->shell_surface.xdg.roleobj.toplevel, title);
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL && wind->shell_surface.xdg.toplevel.xdg_toplevel) {
xdg_toplevel_set_title(wind->shell_surface.xdg.toplevel.xdg_toplevel, title);
}
}
@@ -2728,12 +2809,12 @@ bool Wayland_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surfa
xdg_toplevel_icon_v1_add_buffer(wind->xdg_toplevel_icon_v1, wind->icon.wl_buffer, 1);
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR && wind->shell_surface.libdecor.frame) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR && wind->shell_surface.libdecor.frame) {
toplevel = libdecor_frame_get_xdg_toplevel(wind->shell_surface.libdecor.frame);
} else
#endif
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL && wind->shell_surface.xdg.roleobj.toplevel) {
toplevel = wind->shell_surface.xdg.roleobj.toplevel;
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL && wind->shell_surface.xdg.toplevel.xdg_toplevel) {
toplevel = wind->shell_surface.xdg.toplevel.xdg_toplevel;
}
if (toplevel) {
@@ -2764,15 +2845,15 @@ void Wayland_ShowWindowSystemMenu(SDL_Window *window, int x, int y)
}
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SURFACE_LIBDECOR) {
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (wind->shell_surface.libdecor.frame) {
libdecor_frame_show_window_menu(wind->shell_surface.libdecor.frame, wind->waylandData->input->seat, wind->waylandData->input->last_implicit_grab_serial, x, y);
}
} else
#endif
if (wind->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.roleobj.toplevel) {
xdg_toplevel_show_window_menu(wind->shell_surface.xdg.roleobj.toplevel, wind->waylandData->input->seat, wind->waylandData->input->last_implicit_grab_serial, x, y);
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.toplevel.xdg_toplevel) {
xdg_toplevel_show_window_menu(wind->shell_surface.xdg.toplevel.xdg_toplevel, wind->waylandData->input->seat, wind->waylandData->input->last_implicit_grab_serial, x, y);
}
}
}
+33 -15
View File
@@ -56,32 +56,47 @@ struct SDL_WindowData
struct xdg_surface *surface;
union
{
struct xdg_toplevel *toplevel;
struct
{
struct xdg_popup *popup;
struct xdg_positioner *positioner;
struct xdg_toplevel *xdg_toplevel;
} toplevel;
struct
{
struct xdg_popup *xdg_popup;
struct xdg_positioner *xdg_positioner;
} popup;
} roleobj;
};
bool initial_configure_seen;
} xdg;
} shell_surface;
enum
{
WAYLAND_SURFACE_UNKNOWN = 0,
WAYLAND_SURFACE_XDG_TOPLEVEL,
WAYLAND_SURFACE_XDG_POPUP,
WAYLAND_SURFACE_LIBDECOR,
WAYLAND_SURFACE_CUSTOM
WAYLAND_SHELL_SURFACE_TYPE_UNKNOWN = 0,
WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL,
WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP,
WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR,
WAYLAND_SHELL_SURFACE_TYPE_CUSTOM
} shell_surface_type;
enum
{
WAYLAND_SURFACE_STATUS_HIDDEN = 0,
WAYLAND_SURFACE_STATUS_WAITING_FOR_CONFIGURE,
WAYLAND_SURFACE_STATUS_WAITING_FOR_FRAME,
WAYLAND_SURFACE_STATUS_SHOW_PENDING,
WAYLAND_SURFACE_STATUS_SHOWN
} surface_status;
WAYLAND_SHELL_SURFACE_STATUS_HIDDEN = 0,
WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE,
WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME,
WAYLAND_SHELL_SURFACE_STATUS_SHOW_PENDING,
WAYLAND_SHELL_SURFACE_STATUS_SHOWN
} shell_surface_status;
enum
{
WAYLAND_WM_CAPS_WINDOW_MENU = 0x01,
WAYLAND_WM_CAPS_MAXIMIZE = 0x02,
WAYLAND_WM_CAPS_FULLSCREEN = 0x04,
WAYLAND_WM_CAPS_MINIMIZE = 0x08,
WAYLAND_WM_CAPS_ALL = WAYLAND_WM_CAPS_WINDOW_MENU |
WAYLAND_WM_CAPS_MAXIMIZE |
WAYLAND_WM_CAPS_FULLSCREEN |
WAYLAND_WM_CAPS_MINIMIZE
} wm_caps;
struct wl_egl_window *egl_window;
struct SDL_WaylandInput *keyboard_device;
@@ -165,7 +180,9 @@ struct SDL_WindowData
Uint64 last_focus_event_time_ns;
bool floating;
bool suspended;
bool resizing;
bool active;
bool drop_interactive_resizes;
bool is_fullscreen;
bool fullscreen_exclusive;
bool drop_fullscreen_requests;
@@ -208,6 +225,7 @@ extern void Wayland_ShowWindowSystemMenu(SDL_Window *window, int x, int y);
extern void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern bool Wayland_SuspendScreenSaver(SDL_VideoDevice *_this);
extern bool Wayland_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon);
extern float Wayland_GetWindowContentScale(SDL_VideoDevice *_this, SDL_Window *window);
extern bool Wayland_SetWindowHitTest(SDL_Window *window, bool enabled);
extern bool Wayland_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);
+18 -16
View File
@@ -308,21 +308,23 @@ static void WIN_UpdateFocus(SDL_Window *window, bool expect_focus)
if (has_focus) {
POINT cursorPos;
bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0;
if (GetAsyncKeyState(VK_LBUTTON)) {
data->focus_click_pending |= !swapButtons ? SDL_BUTTON_LMASK : SDL_BUTTON_RMASK;
}
if (GetAsyncKeyState(VK_RBUTTON)) {
data->focus_click_pending |= !swapButtons ? SDL_BUTTON_RMASK : SDL_BUTTON_LMASK;
}
if (GetAsyncKeyState(VK_MBUTTON)) {
data->focus_click_pending |= SDL_BUTTON_MMASK;
}
if (GetAsyncKeyState(VK_XBUTTON1)) {
data->focus_click_pending |= SDL_BUTTON_X1MASK;
}
if (GetAsyncKeyState(VK_XBUTTON2)) {
data->focus_click_pending |= SDL_BUTTON_X2MASK;
if (!(window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0;
if (GetAsyncKeyState(VK_LBUTTON)) {
data->focus_click_pending |= !swapButtons ? SDL_BUTTON_LMASK : SDL_BUTTON_RMASK;
}
if (GetAsyncKeyState(VK_RBUTTON)) {
data->focus_click_pending |= !swapButtons ? SDL_BUTTON_RMASK : SDL_BUTTON_LMASK;
}
if (GetAsyncKeyState(VK_MBUTTON)) {
data->focus_click_pending |= SDL_BUTTON_MMASK;
}
if (GetAsyncKeyState(VK_XBUTTON1)) {
data->focus_click_pending |= SDL_BUTTON_X1MASK;
}
if (GetAsyncKeyState(VK_XBUTTON2)) {
data->focus_click_pending |= SDL_BUTTON_X2MASK;
}
}
SDL_SetKeyboardFocus(data->keyboard_focus ? data->keyboard_focus : window);
@@ -706,7 +708,7 @@ static void WIN_HandleRawKeyboardInput(Uint64 timestamp, SDL_VideoData *data, HA
return;
}
bool down = ((rawkeyboard->Flags & RI_KEY_BREAK) != 0);
bool down = !(rawkeyboard->Flags & RI_KEY_BREAK);
SDL_Scancode code;
USHORT rawcode = rawkeyboard->MakeCode;
if (data->pending_E1_key_sequence) {
@@ -135,6 +135,7 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
data = NULL;
}
if (!data) {
SDL_UnregisterApp();
SDL_free(device);
return NULL;
}
+5 -1
View File
@@ -1384,7 +1384,6 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
// Have we been requested to quit (or another client message?)
case ClientMessage:
{
static int xdnd_version = 0;
if (xevent->xclient.message_type == videodata->atoms.XdndEnter) {
@@ -1409,6 +1408,11 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
// pick from list of three
data->xdnd_req = X11_PickTargetFromAtoms(display, xevent->xclient.data.l[2], xevent->xclient.data.l[3], xevent->xclient.data.l[4]);
}
} else if (xevent->xclient.message_type == videodata->atoms.XdndLeave) {
#ifdef DEBUG_XEVENTS
SDL_Log("XID of source window : 0x%lx\n", xevent->xclient.data.l[0]);
#endif
SDL_SendDropComplete(data->window);
} else if (xevent->xclient.message_type == videodata->atoms.XdndPosition) {
#ifdef DEBUG_XEVENTS
+49 -144
View File
@@ -46,126 +46,6 @@
*/
// #define XRANDR_DISABLED_BY_DEFAULT
#ifdef SDL_USE_LIBDBUS
#define SCALE_FACTOR_NODE "org.freedesktop.portal.Desktop"
#define SCALE_FACTOR_PATH "/org/freedesktop/portal/desktop"
#define SCALE_FACTOR_INTERFACE "org.freedesktop.portal.Settings"
#define SCALE_FACTOR_NAMESPACE "org.gnome.desktop.interface"
#define SCALE_FACTOR_SIGNAL_NAME "SettingChanged"
#define SCALE_FACTOR_KEY "text-scaling-factor"
static DBusMessage *ReadDBusSetting(SDL_DBusContext *dbus, const char *key)
{
static const char *iface = SCALE_FACTOR_NAMESPACE;
DBusMessage *reply = NULL;
DBusMessage *msg = dbus->message_new_method_call(SCALE_FACTOR_NODE,
SCALE_FACTOR_PATH,
SCALE_FACTOR_INTERFACE,
"Read"); // Method
if (msg) {
if (dbus->message_append_args(msg, DBUS_TYPE_STRING, &iface, DBUS_TYPE_STRING, &key, DBUS_TYPE_INVALID)) {
reply = dbus->connection_send_with_reply_and_block(dbus->session_conn, msg, DBUS_TIMEOUT_USE_DEFAULT, NULL);
}
dbus->message_unref(msg);
}
return reply;
}
static bool ParseDBusReply(SDL_DBusContext *dbus, DBusMessage *reply, int type, void *value)
{
DBusMessageIter iter[3];
dbus->message_iter_init(reply, &iter[0]);
if (dbus->message_iter_get_arg_type(&iter[0]) != DBUS_TYPE_VARIANT) {
return false;
}
dbus->message_iter_recurse(&iter[0], &iter[1]);
if (dbus->message_iter_get_arg_type(&iter[1]) != DBUS_TYPE_VARIANT) {
return false;
}
dbus->message_iter_recurse(&iter[1], &iter[2]);
if (dbus->message_iter_get_arg_type(&iter[2]) != type) {
return false;
}
dbus->message_iter_get_basic(&iter[2], value);
return true;
}
static void UpdateDisplayContentScale(float scale)
{
SDL_VideoDevice *viddevice = SDL_GetVideoDevice();
int i;
if (viddevice) {
for (i = 0; i < viddevice->num_displays; ++i) {
SDL_SetDisplayContentScale(viddevice->displays[i], scale);
}
}
}
static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
{
SDL_DBusContext *dbus = SDL_DBus_GetContext();
double *scale_factor = (double *)data;
double new_scale = 0.0;
if (dbus->message_is_signal(msg, SCALE_FACTOR_INTERFACE, SCALE_FACTOR_SIGNAL_NAME)) {
DBusMessageIter signal_iter, variant_iter;
const char *namespace, *key;
dbus->message_iter_init(msg, &signal_iter);
// Check if the parameters are what we expect
if (dbus->message_iter_get_arg_type(&signal_iter) != DBUS_TYPE_STRING) {
goto not_our_signal;
}
dbus->message_iter_get_basic(&signal_iter, &namespace);
if (SDL_strcmp(SCALE_FACTOR_NAMESPACE, namespace) != 0) {
goto not_our_signal;
}
if (!dbus->message_iter_next(&signal_iter)) {
goto not_our_signal;
}
if (dbus->message_iter_get_arg_type(&signal_iter) != DBUS_TYPE_STRING) {
goto not_our_signal;
}
dbus->message_iter_get_basic(&signal_iter, &key);
if (SDL_strcmp(SCALE_FACTOR_KEY, key) != 0) {
goto not_our_signal;
}
if (!dbus->message_iter_next(&signal_iter)) {
goto not_our_signal;
}
if (dbus->message_iter_get_arg_type(&signal_iter) != DBUS_TYPE_VARIANT) {
goto not_our_signal;
}
dbus->message_iter_recurse(&signal_iter, &variant_iter);
if (dbus->message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_DOUBLE) {
goto not_our_signal;
}
dbus->message_iter_get_basic(&variant_iter, &new_scale);
if (new_scale > 0.0) {
*scale_factor = new_scale;
UpdateDisplayContentScale((float)new_scale);
}
return DBUS_HANDLER_RESULT_HANDLED;
}
not_our_signal:
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
#endif
static float GetGlobalContentScale(SDL_VideoDevice *_this)
{
static double scale_factor = 0.0;
@@ -181,30 +61,6 @@ static float GetGlobalContentScale(SDL_VideoDevice *_this)
}
}
// Next try the settings portal via D-Bus for the text scaling factor (aka 'Global Scale' on KDE)
#ifdef SDL_USE_LIBDBUS
if (scale_factor <= 0.0)
{
DBusMessage *reply;
SDL_DBusContext *dbus = SDL_DBus_GetContext();
if (dbus) {
if ((reply = ReadDBusSetting(dbus, SCALE_FACTOR_KEY))) {
if (ParseDBusReply(dbus, reply, DBUS_TYPE_DOUBLE, &scale_factor)) {
// If the setting exists, register a listener for scale changes.
dbus->bus_add_match(dbus->session_conn,
"type='signal', interface='"SCALE_FACTOR_INTERFACE"',"
"member='"SCALE_FACTOR_SIGNAL_NAME"', arg0='"SCALE_FACTOR_NAMESPACE"',"
"arg1='"SCALE_FACTOR_KEY"'", NULL);
dbus->connection_add_filter(dbus->session_conn, &DBus_MessageFilter, &scale_factor, NULL);
dbus->connection_flush(dbus->session_conn);
}
dbus->message_unref(reply);
}
}
}
#endif
// If that failed, try "Xft.dpi" from the XResourcesDatabase...
if (scale_factor <= 0.0)
{
@@ -623,6 +479,7 @@ static bool X11_FillXRandRDisplayInfo(SDL_VideoDevice *_this, Display *dpy, int
displaydata->y = display_y;
displaydata->use_xrandr = true;
displaydata->xrandr_output = outputid;
SDL_strlcpy(displaydata->connector_name, display_name, sizeof(displaydata->connector_name));
SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode);
SetXRandRDisplayName(dpy, EDID, display_name, display_name_size, outputid, display_mm_width, display_mm_height);
@@ -751,6 +608,52 @@ void X11_HandleXRandREvent(SDL_VideoDevice *_this, const XEvent *xevent)
}
}
static void X11_SortOutputsByPriorityHint(SDL_VideoDevice *_this)
{
const char *name_hint = SDL_GetHint(SDL_HINT_VIDEO_DISPLAY_PRIORITY);
if (name_hint) {
char *saveptr;
char *str = SDL_strdup(name_hint);
SDL_VideoDisplay **sorted_list = SDL_malloc(sizeof(SDL_VideoDisplay *) * _this->num_displays);
if (str && sorted_list) {
int sorted_index = 0;
// Sort the requested displays to the front of the list.
const char *token = SDL_strtok_r(str, ",", &saveptr);
while (token) {
for (int i = 0; i < _this->num_displays; ++i) {
SDL_VideoDisplay *d = _this->displays[i];
if (d) {
SDL_DisplayData *data = d->internal;
if (SDL_strcmp(token, data->connector_name) == 0) {
sorted_list[sorted_index++] = d;
_this->displays[i] = NULL;
break;
}
}
}
token = SDL_strtok_r(NULL, ",", &saveptr);
}
// Append the remaining displays to the end of the list.
for (int i = 0; i < _this->num_displays; ++i) {
if (_this->displays[i]) {
sorted_list[sorted_index++] = _this->displays[i];
}
}
// Copy the sorted list back to the display list.
SDL_memcpy(_this->displays, sorted_list, sizeof(SDL_VideoDisplay *) * _this->num_displays);
}
SDL_free(str);
SDL_free(sorted_list);
}
}
static bool X11_InitModes_XRandR(SDL_VideoDevice *_this)
{
SDL_VideoData *data = _this->internal;
@@ -810,6 +713,8 @@ static bool X11_InitModes_XRandR(SDL_VideoDevice *_this)
return SDL_SetError("No available displays");
}
X11_SortOutputsByPriorityHint(_this);
return true;
}
#endif // SDL_VIDEO_DRIVER_X11_XRANDR
+1
View File
@@ -38,6 +38,7 @@ struct SDL_DisplayData
#ifdef SDL_VIDEO_DRIVER_X11_XRANDR
RROutput xrandr_output;
char connector_name[16];
#endif
};
+58
View File
@@ -608,6 +608,32 @@ static int X11_GL_GetAttributes(SDL_VideoDevice *_this, Display *display, int sc
return i;
}
//get the first transparent Visual
static XVisualInfo* X11_GL_GetTransparentVisualInfo(Display *display, int screen)
{
XVisualInfo* visualinfo = NULL;
XVisualInfo vi_in;
int out_count = 0;
vi_in.screen = screen;
visualinfo = X11_XGetVisualInfo(display, VisualScreenMask, &vi_in, &out_count);
if (visualinfo != NULL) {
int i = 0;
for (i = 0; i < out_count; i++) {
XVisualInfo* v = &visualinfo[i];
Uint32 format = X11_GetPixelFormatFromVisualInfo(display, v);
if (SDL_ISPIXELFORMAT_ALPHA(format)) {
vi_in.screen = screen;
vi_in.visualid = v->visualid;
X11_XFree(visualinfo);
visualinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &vi_in, &out_count);
break;
}
}
}
return visualinfo;
}
XVisualInfo *X11_GL_GetVisual(SDL_VideoDevice *_this, Display *display, int screen, bool transparent)
{
// 64 seems nice.
@@ -666,6 +692,18 @@ XVisualInfo *X11_GL_GetVisual(SDL_VideoDevice *_this, Display *display, int scre
}
}
if (transparent && vinfo) {
Uint32 format = X11_GetPixelFormatFromVisualInfo(display, vinfo);
if (!SDL_ISPIXELFORMAT_ALPHA(format)) {
// not transparent!
XVisualInfo* visualinfo = X11_GL_GetTransparentVisualInfo(display, screen);
if (visualinfo != NULL) {
X11_XFree(vinfo);
vinfo = visualinfo;
}
}
}
if (!vinfo) {
SDL_SetError("Couldn't find matching GLX visual");
}
@@ -814,6 +852,26 @@ SDL_GLContext X11_GL_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
&fbcount);
}
if (transparent && (framebuffer_config != NULL)) {
int i;
for (i = 0; i < fbcount; i++) {
XVisualInfo* vinfo_temp = _this->gl_data->glXGetVisualFromFBConfig(display, framebuffer_config[i]);
if ( vinfo_temp != NULL) {
Uint32 format = X11_GetPixelFormatFromVisualInfo(display, vinfo_temp);
if (SDL_ISPIXELFORMAT_ALPHA(format)) {
// found!
context = (SDL_GLContext)_this->gl_data->glXCreateContextAttribsARB(display,
framebuffer_config[i],
share_context, True, attribs);
X11_XFree(framebuffer_config);
framebuffer_config = NULL;
X11_XFree(vinfo_temp);
break;
}
X11_XFree(vinfo_temp);
}
}
}
if (framebuffer_config) {
context = (SDL_GLContext)_this->gl_data->glXCreateContextAttribsARB(display,
framebuffer_config[0],
+1 -34
View File
@@ -49,8 +49,6 @@ static void X11_VideoQuit(SDL_VideoDevice *_this);
// X11 driver bootstrap functions
static int (*orig_x11_errhandler)(Display *, XErrorEvent *) = NULL;
static void X11_DeleteDevice(SDL_VideoDevice *device)
{
SDL_VideoData *data = device->internal;
@@ -58,7 +56,6 @@ static void X11_DeleteDevice(SDL_VideoDevice *device)
device->Vulkan_UnloadLibrary(device);
}
if (data->display) {
X11_XSetErrorHandler(orig_x11_errhandler);
X11_XCloseDisplay(data->display);
}
if (data->request_display) {
@@ -74,33 +71,6 @@ static void X11_DeleteDevice(SDL_VideoDevice *device)
SDL_X11_UnloadSymbols();
}
// An error handler to reset the vidmode and then call the default handler.
static bool safety_net_triggered = false;
static int X11_SafetyNetErrHandler(Display *d, XErrorEvent *e)
{
SDL_VideoDevice *device = NULL;
// if we trigger an error in our error handler, don't try again.
if (!safety_net_triggered) {
safety_net_triggered = true;
device = SDL_GetVideoDevice();
if (device) {
int i;
for (i = 0; i < device->num_displays; i++) {
SDL_VideoDisplay *display = device->displays[i];
if (SDL_GetCurrentDisplayMode(display->id) != SDL_GetDesktopDisplayMode(display->id)) {
X11_SetDisplayMode(device, display, &display->desktop_mode);
}
}
}
}
if (orig_x11_errhandler) {
return orig_x11_errhandler(d, e); // probably terminate.
}
return 0;
}
static bool X11_IsXWayland(Display *d)
{
int opcode, event, error;
@@ -164,10 +134,6 @@ static SDL_VideoDevice *X11_CreateDevice(void)
X11_XSynchronize(data->display, True);
#endif
// Hook up an X11 error handler to recover the desktop resolution.
safety_net_triggered = false;
orig_x11_errhandler = X11_XSetErrorHandler(X11_SafetyNetErrHandler);
/* Steam Deck will have an on-screen keyboard, so check their environment
* variable so we can make use of SDL_StartTextInput.
*/
@@ -425,6 +391,7 @@ static bool X11_VideoInit(SDL_VideoDevice *_this)
GET_ATOM(SDL_FORMATS);
GET_ATOM(XdndAware);
GET_ATOM(XdndEnter);
GET_ATOM(XdndLeave);
GET_ATOM(XdndPosition);
GET_ATOM(XdndStatus);
GET_ATOM(XdndTypeList);
+1
View File
@@ -103,6 +103,7 @@ struct SDL_VideoData
Atom SDL_FORMATS;
Atom XdndAware;
Atom XdndEnter;
Atom XdndLeave;
Atom XdndPosition;
Atom XdndStatus;
Atom XdndTypeList;