mirror of
https://github.com/love2d/megasource.git
synced 2026-08-20 12:40:06 +02:00
update SDL3 to 3.1.6.
This commit is contained in:
+1
-1
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -38,6 +38,7 @@ struct SDL_DisplayData
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XRANDR
|
||||
RROutput xrandr_output;
|
||||
char connector_name[16];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -103,6 +103,7 @@ struct SDL_VideoData
|
||||
Atom SDL_FORMATS;
|
||||
Atom XdndAware;
|
||||
Atom XdndEnter;
|
||||
Atom XdndLeave;
|
||||
Atom XdndPosition;
|
||||
Atom XdndStatus;
|
||||
Atom XdndTypeList;
|
||||
|
||||
Reference in New Issue
Block a user