mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-03-20 15:51:07 +01:00
gdk: Update Suspend/Resume best practices.
Updated testgdk to demonstrate correct handling of suspend/resume and the new Render APIs, and updated the docs to explain the correct usage of these GDK functions.
This commit is contained in:
@@ -30,7 +30,9 @@ extern "C" {
|
|||||||
#include <XGameRuntime.h>
|
#include <XGameRuntime.h>
|
||||||
|
|
||||||
#define NUM_SPRITES 100
|
#define NUM_SPRITES 100
|
||||||
#define MAX_SPEED 1
|
#define MAX_SPEED 1
|
||||||
|
#define SUSPEND_CODE 0
|
||||||
|
#define RESUME_CODE 1
|
||||||
|
|
||||||
static SDLTest_CommonState *state;
|
static SDLTest_CommonState *state;
|
||||||
static int num_sprites;
|
static int num_sprites;
|
||||||
@@ -291,7 +293,7 @@ static void DrawSprites(SDL_Renderer * renderer, SDL_Texture * sprite)
|
|||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update()
|
static void update(bool *suppressdraw)
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
|
||||||
@@ -305,6 +307,25 @@ static void update()
|
|||||||
if (event.type != SDL_EVENT_KEY_DOWN) {
|
if (event.type != SDL_EVENT_KEY_DOWN) {
|
||||||
SDLTest_CommonEvent(state, &event, &done);
|
SDLTest_CommonEvent(state, &event, &done);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.type == SDL_EVENT_USER) {
|
||||||
|
if (event.user.code == SUSPEND_CODE) {
|
||||||
|
for (int i = 0; i < state->num_windows; ++i) {
|
||||||
|
if (state->windows[i] != NULL) {
|
||||||
|
SDL_GDKSuspendRenderer(state->renderers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*suppressdraw = true;
|
||||||
|
SDL_GDKSuspendComplete();
|
||||||
|
} else if (event.user.code == RESUME_CODE) {
|
||||||
|
for (int i = 0; i < state->num_windows; ++i) {
|
||||||
|
if (state->windows[i] != NULL) {
|
||||||
|
SDL_GDKResumeRenderer(state->renderers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*suppressdraw = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
SDLTest_CommonEvent(state, &event, &done);
|
SDLTest_CommonEvent(state, &event, &done);
|
||||||
#endif
|
#endif
|
||||||
@@ -316,24 +337,33 @@ static void draw()
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < state->num_windows; ++i) {
|
for (i = 0; i < state->num_windows; ++i) {
|
||||||
if (state->windows[i] == NULL) {
|
if (state->windows[i] != NULL) {
|
||||||
continue;
|
DrawSprites(state->renderers[i], sprites[i]);
|
||||||
}
|
}
|
||||||
DrawSprites(state->renderers[i], sprites[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SDLCALL GDKEventWatch(void* userdata, SDL_Event* event)
|
static bool SDLCALL GDKEventWatch(void* userdata, SDL_Event* event)
|
||||||
{
|
{
|
||||||
bool *suppressdraw = (bool *)userdata;
|
/* This callback may be on a different thread, so we'll
|
||||||
SDL_assert(suppressdraw != NULL);
|
* push these events as USER events so they appear
|
||||||
|
* in the main thread's event loop.
|
||||||
|
*
|
||||||
|
* That allows us to cancel drawing before/after we finish
|
||||||
|
* drawing a frame, rather than mid-draw (which can crash).
|
||||||
|
*/
|
||||||
if (event->type == SDL_EVENT_DID_ENTER_BACKGROUND) {
|
if (event->type == SDL_EVENT_DID_ENTER_BACKGROUND) {
|
||||||
*suppressdraw = true;
|
SDL_Event evt;
|
||||||
SDL_GDKSuspendComplete();
|
evt.type = SDL_EVENT_USER;
|
||||||
|
evt.user.code = 0;
|
||||||
|
SDL_PushEvent(&evt);
|
||||||
} else if (event->type == SDL_EVENT_WILL_ENTER_FOREGROUND) {
|
} else if (event->type == SDL_EVENT_WILL_ENTER_FOREGROUND) {
|
||||||
*suppressdraw = false;
|
SDL_Event evt;
|
||||||
|
evt.type = SDL_EVENT_USER;
|
||||||
|
evt.user.code = 1;
|
||||||
|
SDL_PushEvent(&evt);
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@@ -408,8 +438,8 @@ int main(int argc, char *argv[])
|
|||||||
quit(2);
|
quit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* By this point the renderers are made, so we can now add this watcher */
|
/* Set up the lifecycle event watcher */
|
||||||
SDL_AddEventWatch(GDKEventWatch, &suppressdraw);
|
SDL_AddEventWatch(GDKEventWatch, NULL);
|
||||||
|
|
||||||
/* Create the windows, initialize the renderers, and load the textures */
|
/* Create the windows, initialize the renderers, and load the textures */
|
||||||
sprites =
|
sprites =
|
||||||
@@ -462,7 +492,7 @@ int main(int argc, char *argv[])
|
|||||||
AddUserSilent();
|
AddUserSilent();
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
update();
|
update(&suppressdraw);
|
||||||
if (!suppressdraw) {
|
if (!suppressdraw) {
|
||||||
draw();
|
draw();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4581,12 +4581,14 @@ extern SDL_DECLSPEC SDL_GPUTextureFormat SDLCALL SDL_GetGPUTextureFormatFromPixe
|
|||||||
#ifdef SDL_PLATFORM_GDK
|
#ifdef SDL_PLATFORM_GDK
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this to suspend GPU operation on Xbox when you receive the
|
* Call this to suspend GPU operation on Xbox after receiving the
|
||||||
* SDL_EVENT_DID_ENTER_BACKGROUND event.
|
* SDL_EVENT_DID_ENTER_BACKGROUND event.
|
||||||
*
|
*
|
||||||
* Do NOT call any SDL_GPU functions after calling this function! This must
|
* Do NOT call any SDL_GPU functions after calling this function! This must
|
||||||
* also be called before calling SDL_GDKSuspendComplete.
|
* also be called before calling SDL_GDKSuspendComplete.
|
||||||
*
|
*
|
||||||
|
* This function MUST be called from the application's render thread.
|
||||||
|
*
|
||||||
* \param device a GPU context.
|
* \param device a GPU context.
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
@@ -4596,12 +4598,14 @@ extern SDL_DECLSPEC SDL_GPUTextureFormat SDLCALL SDL_GetGPUTextureFormatFromPixe
|
|||||||
extern SDL_DECLSPEC void SDLCALL SDL_GDKSuspendGPU(SDL_GPUDevice *device);
|
extern SDL_DECLSPEC void SDLCALL SDL_GDKSuspendGPU(SDL_GPUDevice *device);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this to resume GPU operation on Xbox when you receive the
|
* Call this to resume GPU operation on Xbox after receiving the
|
||||||
* SDL_EVENT_WILL_ENTER_FOREGROUND event.
|
* SDL_EVENT_WILL_ENTER_FOREGROUND event.
|
||||||
*
|
*
|
||||||
* When resuming, this function MUST be called before calling any other
|
* When resuming, this function MUST be called before calling any other
|
||||||
* SDL_GPU functions.
|
* SDL_GPU functions.
|
||||||
*
|
*
|
||||||
|
* This function MUST be called from the application's render thread.
|
||||||
|
*
|
||||||
* \param device a GPU context.
|
* \param device a GPU context.
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.2.0.
|
* \since This function is available since SDL 3.2.0.
|
||||||
|
|||||||
@@ -664,8 +664,11 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnregisterApp(void);
|
|||||||
/**
|
/**
|
||||||
* Callback from the application to let the suspend continue.
|
* Callback from the application to let the suspend continue.
|
||||||
*
|
*
|
||||||
* This should be called from an event watch in response to an
|
* This should be called in response to an `SDL_EVENT_DID_ENTER_BACKGROUND` event,
|
||||||
* `SDL_EVENT_DID_ENTER_BACKGROUND` event.
|
* which can be detected via event watch. However, do NOT call this function
|
||||||
|
* directly from within an event watch callback. Instead, wait until the app has
|
||||||
|
* suppressed all rendering operations, then call this from the application
|
||||||
|
* render thread.
|
||||||
*
|
*
|
||||||
* When using SDL_Render, this should be called after calling SDL_GDKSuspendRenderer.
|
* When using SDL_Render, this should be called after calling SDL_GDKSuspendRenderer.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -3085,12 +3085,14 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroyGPURenderState(SDL_GPURenderState *s
|
|||||||
#ifdef SDL_PLATFORM_GDK
|
#ifdef SDL_PLATFORM_GDK
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this to suspend Render operations on Xbox when you receive the
|
* Call this to suspend Render operations on Xbox after receiving the
|
||||||
* SDL_EVENT_DID_ENTER_BACKGROUND event.
|
* SDL_EVENT_DID_ENTER_BACKGROUND event.
|
||||||
*
|
*
|
||||||
* Do NOT call any SDL_Render functions after calling this function! This must
|
* Do NOT call any SDL_Render functions after calling this function! This must
|
||||||
* also be called before calling SDL_GDKSuspendComplete.
|
* also be called before calling SDL_GDKSuspendComplete.
|
||||||
*
|
*
|
||||||
|
* This function MUST be called on the application's render thread.
|
||||||
|
*
|
||||||
* \param renderer the renderer which should suspend operation
|
* \param renderer the renderer which should suspend operation
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.6.0.
|
* \since This function is available since SDL 3.6.0.
|
||||||
@@ -3100,12 +3102,14 @@ extern SDL_DECLSPEC void SDLCALL SDL_DestroyGPURenderState(SDL_GPURenderState *s
|
|||||||
extern SDL_DECLSPEC void SDLCALL SDL_GDKSuspendRenderer(SDL_Renderer *renderer);
|
extern SDL_DECLSPEC void SDLCALL SDL_GDKSuspendRenderer(SDL_Renderer *renderer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this to resume Render operations on Xbox when you receive the
|
* Call this to resume Render operations on Xbox after receiving the
|
||||||
* SDL_EVENT_WILL_ENTER_FOREGROUND event.
|
* SDL_EVENT_WILL_ENTER_FOREGROUND event.
|
||||||
*
|
*
|
||||||
* When resuming, this function MUST be called before calling any other
|
* When resuming, this function MUST be called before calling any other
|
||||||
* SDL_Render functions.
|
* SDL_Render functions.
|
||||||
*
|
*
|
||||||
|
* This function MUST be called on the application's render thread.
|
||||||
|
*
|
||||||
* \param renderer the renderer which should resume operation
|
* \param renderer the renderer which should resume operation
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.6.0.
|
* \since This function is available since SDL 3.6.0.
|
||||||
|
|||||||
Reference in New Issue
Block a user