mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-09-28 16:15:55 +08:00
Cocoa metal layers need their size updated before renderer updates
Build (All) / Create test plan (push) Waiting to run
Build (All) / level1 (push) Blocked by required conditions
Build (All) / level2 (push) Blocked by required conditions
Build (All) / Create test plan (push) Waiting to run
Build (All) / level1 (push) Blocked by required conditions
Build (All) / level2 (push) Blocked by required conditions
Also refactored event watch code so it can be shared between internal window event dispatch and public event watchers. Fixes https://github.com/libsdl-org/SDL/issues/12376
This commit is contained in:
+25
-115
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_eventwatch_c.h"
|
||||
|
||||
|
||||
bool SDL_InitEventWatchList(SDL_EventWatchList *list)
|
||||
{
|
||||
if (list->lock == NULL) {
|
||||
list->lock = SDL_CreateMutex();
|
||||
if (list->lock == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SDL_QuitEventWatchList(SDL_EventWatchList *list)
|
||||
{
|
||||
if (list->lock) {
|
||||
SDL_DestroyMutex(list->lock);
|
||||
list->lock = NULL;
|
||||
}
|
||||
if (list->watchers) {
|
||||
SDL_free(list->watchers);
|
||||
list->watchers = NULL;
|
||||
list->count = 0;
|
||||
}
|
||||
SDL_zero(list->filter);
|
||||
}
|
||||
|
||||
bool SDL_DispatchEventWatchList(SDL_EventWatchList *list, SDL_Event *event)
|
||||
{
|
||||
SDL_EventWatcher *filter = &list->filter;
|
||||
|
||||
if (!filter->callback && list->count == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SDL_LockMutex(list->lock);
|
||||
{
|
||||
// Make sure we only dispatch the current watcher list
|
||||
int i, count = list->count;
|
||||
|
||||
if (filter->callback && !filter->callback(filter->userdata, event)) {
|
||||
SDL_UnlockMutex(list->lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
list->dispatching = true;
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (!list->watchers[i].removed) {
|
||||
list->watchers[i].callback(list->watchers[i].userdata, event);
|
||||
}
|
||||
}
|
||||
list->dispatching = false;
|
||||
|
||||
if (list->removed) {
|
||||
for (i = list->count; i--;) {
|
||||
if (list->watchers[i].removed) {
|
||||
--list->count;
|
||||
if (i < list->count) {
|
||||
SDL_memmove(&list->watchers[i], &list->watchers[i + 1], (list->count - i) * sizeof(list->watchers[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
list->removed = false;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(list->lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDL_AddEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
SDL_LockMutex(list->lock);
|
||||
{
|
||||
SDL_EventWatcher *watchers;
|
||||
|
||||
watchers = (SDL_EventWatcher *)SDL_realloc(list->watchers, (list->count + 1) * sizeof(*watchers));
|
||||
if (watchers) {
|
||||
SDL_EventWatcher *watcher;
|
||||
|
||||
list->watchers = watchers;
|
||||
watcher = &list->watchers[list->count];
|
||||
watcher->callback = filter;
|
||||
watcher->userdata = userdata;
|
||||
watcher->removed = false;
|
||||
++list->count;
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(list->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SDL_RemoveEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata)
|
||||
{
|
||||
SDL_LockMutex(list->lock);
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < list->count; ++i) {
|
||||
if (list->watchers[i].callback == filter && list->watchers[i].userdata == userdata) {
|
||||
if (list->dispatching) {
|
||||
list->watchers[i].removed = true;
|
||||
list->removed = true;
|
||||
} else {
|
||||
--list->count;
|
||||
if (i < list->count) {
|
||||
SDL_memmove(&list->watchers[i], &list->watchers[i + 1], (list->count - i) * sizeof(list->watchers[i]));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(list->lock);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
typedef struct SDL_EventWatcher
|
||||
{
|
||||
SDL_EventFilter callback;
|
||||
void *userdata;
|
||||
bool removed;
|
||||
} SDL_EventWatcher;
|
||||
|
||||
typedef struct SDL_EventWatchList
|
||||
{
|
||||
SDL_Mutex *lock;
|
||||
SDL_EventWatcher filter;
|
||||
SDL_EventWatcher *watchers;
|
||||
int count;
|
||||
bool dispatching;
|
||||
bool removed;
|
||||
} SDL_EventWatchList;
|
||||
|
||||
|
||||
extern bool SDL_InitEventWatchList(SDL_EventWatchList *list);
|
||||
extern void SDL_QuitEventWatchList(SDL_EventWatchList *list);
|
||||
extern bool SDL_DispatchEventWatchList(SDL_EventWatchList *list, SDL_Event *event);
|
||||
extern bool SDL_AddEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata);
|
||||
extern void SDL_RemoveEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata);
|
||||
@@ -23,10 +23,39 @@
|
||||
// Window event handling code for SDL
|
||||
|
||||
#include "SDL_events_c.h"
|
||||
#include "SDL_eventwatch_c.h"
|
||||
#include "SDL_mouse_c.h"
|
||||
#include "../render/SDL_sysrender.h"
|
||||
#include "../tray/SDL_tray_utils.h"
|
||||
|
||||
|
||||
#define NUM_WINDOW_EVENT_WATCH_PRIORITIES (SDL_WINDOW_EVENT_WATCH_NORMAL + 1)
|
||||
|
||||
static SDL_EventWatchList SDL_window_event_watchers[NUM_WINDOW_EVENT_WATCH_PRIORITIES];
|
||||
|
||||
void SDL_InitWindowEventWatch(void)
|
||||
{
|
||||
for (int i = 0; i < SDL_arraysize(SDL_window_event_watchers); ++i) {
|
||||
SDL_InitEventWatchList(&SDL_window_event_watchers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_QuitWindowEventWatch(void)
|
||||
{
|
||||
for (int i = 0; i < SDL_arraysize(SDL_window_event_watchers); ++i) {
|
||||
SDL_QuitEventWatchList(&SDL_window_event_watchers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_AddWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata)
|
||||
{
|
||||
SDL_AddEventWatchList(&SDL_window_event_watchers[priority], filter, userdata);
|
||||
}
|
||||
|
||||
void SDL_RemoveWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata)
|
||||
{
|
||||
SDL_RemoveEventWatchList(&SDL_window_event_watchers[priority], filter, userdata);
|
||||
}
|
||||
|
||||
static bool SDLCALL RemoveSupercededWindowEvents(void *userdata, SDL_Event *event)
|
||||
{
|
||||
SDL_Event *new_event = (SDL_Event *)userdata;
|
||||
@@ -191,10 +220,8 @@ bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data
|
||||
event.window.data2 = data2;
|
||||
event.window.windowID = window->id;
|
||||
|
||||
for (int i = 0; i < window->num_renderers; ++i) {
|
||||
SDL_Renderer *renderer = window->renderers[i];
|
||||
SDL_RendererEventWatch(renderer, &event);
|
||||
}
|
||||
SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_EARLY], &event);
|
||||
SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_NORMAL], &event);
|
||||
|
||||
if (SDL_EventEnabled(windowevent)) {
|
||||
// Fixes queue overflow with move/resize events that aren't processed
|
||||
|
||||
@@ -23,6 +23,17 @@
|
||||
#ifndef SDL_windowevents_c_h_
|
||||
#define SDL_windowevents_c_h_
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SDL_WINDOW_EVENT_WATCH_EARLY,
|
||||
SDL_WINDOW_EVENT_WATCH_NORMAL
|
||||
} SDL_WindowEventWatchPriority;
|
||||
|
||||
extern void SDL_InitWindowEventWatch(void);
|
||||
extern void SDL_QuitWindowEventWatch(void);
|
||||
extern void SDL_AddWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata);
|
||||
extern void SDL_RemoveWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata);
|
||||
|
||||
extern bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data1, int data2);
|
||||
|
||||
#endif // SDL_windowevents_c_h_
|
||||
|
||||
+10
-1
@@ -25,6 +25,7 @@
|
||||
#include "SDL_sysrender.h"
|
||||
#include "SDL_render_debug_font.h"
|
||||
#include "software/SDL_render_sw_c.h"
|
||||
#include "../events/SDL_windowevents_c.h"
|
||||
#include "../video/SDL_pixels_c.h"
|
||||
#include "../video/SDL_video_c.h"
|
||||
|
||||
@@ -820,8 +821,9 @@ const char *SDL_GetRenderDriver(int index)
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDL_RendererEventWatch(SDL_Renderer *renderer, SDL_Event *event)
|
||||
static bool SDL_RendererEventWatch(void *userdata, SDL_Event *event)
|
||||
{
|
||||
SDL_Renderer *renderer = (SDL_Renderer *)userdata;
|
||||
SDL_Window *window = renderer->window;
|
||||
|
||||
if (renderer->WindowEvent) {
|
||||
@@ -849,6 +851,7 @@ void SDL_RendererEventWatch(SDL_Renderer *renderer, SDL_Event *event)
|
||||
event->type == SDL_EVENT_WINDOW_HDR_STATE_CHANGED) {
|
||||
UpdateHDRProperties(renderer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDL_CreateWindowAndRenderer(const char *title, int width, int height, SDL_WindowFlags window_flags, SDL_Window **window, SDL_Renderer **renderer)
|
||||
@@ -1107,6 +1110,10 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
|
||||
|
||||
SDL_SetRenderViewport(renderer, NULL);
|
||||
|
||||
if (window) {
|
||||
SDL_AddWindowEventWatch(SDL_WINDOW_EVENT_WATCH_NORMAL, SDL_RendererEventWatch, renderer);
|
||||
}
|
||||
|
||||
int vsync = (int)SDL_GetNumberProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, 0);
|
||||
if (!SDL_SetRenderVSync(renderer, vsync)) {
|
||||
if (vsync == 0) {
|
||||
@@ -5224,6 +5231,8 @@ void SDL_DestroyRendererWithoutFreeing(SDL_Renderer *renderer)
|
||||
|
||||
renderer->destroyed = true;
|
||||
|
||||
SDL_RemoveWindowEventWatch(SDL_WINDOW_EVENT_WATCH_NORMAL, SDL_RendererEventWatch, renderer);
|
||||
|
||||
if (renderer->window) {
|
||||
SDL_PropertiesID props = SDL_GetWindowProperties(renderer->window);
|
||||
if (SDL_GetPointerProperty(props, SDL_PROP_WINDOW_RENDERER_POINTER, NULL) == renderer) {
|
||||
|
||||
@@ -339,9 +339,6 @@ extern SDL_RenderDriver GPU_RenderDriver;
|
||||
// Clean up any renderers at shutdown
|
||||
extern void SDL_QuitRender(void);
|
||||
|
||||
// Handle window events for a renderer
|
||||
extern void SDL_RendererEventWatch(SDL_Renderer *renderer, SDL_Event *event);
|
||||
|
||||
// Add a supported texture format to a renderer
|
||||
extern bool SDL_AddSupportedTextureFormat(SDL_Renderer *renderer, SDL_PixelFormat format);
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "../../events/SDL_windowevents_c.h"
|
||||
|
||||
#import "SDL_cocoametalview.h"
|
||||
|
||||
#if defined(SDL_VIDEO_DRIVER_COCOA) && (defined(SDL_VIDEO_VULKAN) || defined(SDL_VIDEO_METAL))
|
||||
@@ -88,7 +90,7 @@ static bool SDLCALL SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
|
||||
|
||||
self.layer.opaque = opaque;
|
||||
|
||||
SDL_AddEventWatch(SDL_MetalViewEventWatch, (__bridge void *)(self));
|
||||
SDL_AddWindowEventWatch(SDL_WINDOW_EVENT_WATCH_EARLY, SDL_MetalViewEventWatch, (__bridge void *)(self));
|
||||
|
||||
[self updateDrawableSize];
|
||||
}
|
||||
@@ -98,7 +100,7 @@ static bool SDLCALL SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
SDL_RemoveEventWatch(SDL_MetalViewEventWatch, (__bridge void *)(self));
|
||||
SDL_RemoveWindowEventWatch(SDL_WINDOW_EVENT_WATCH_EARLY, SDL_MetalViewEventWatch, (__bridge void *)(self));
|
||||
}
|
||||
|
||||
- (NSInteger)tag
|
||||
|
||||
Reference in New Issue
Block a user