Merge commit '852f2a6343518919e5ca8d3c1bbcab9f493e3cd8'

This commit is contained in:
2024-01-17 17:02:59 +01:00
1244 changed files with 50102 additions and 28146 deletions

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -43,16 +43,16 @@ this should probably be removed at some point in the future. --ryan. */
#define DONT_DRAW_WHILE_HIDDEN 0
#endif
#define SDL_WINDOWRENDERDATA "_SDL_WindowRenderData"
#define SDL_PROPERTY_WINDOW_RENDERER "SDL.internal.window.renderer"
#define CHECK_RENDERER_MAGIC(renderer, retval) \
if (!(renderer) || (renderer)->magic != &renderer_magic) { \
if (!(renderer) || (renderer)->magic != &SDL_renderer_magic) { \
SDL_InvalidParamError("renderer"); \
return retval; \
}
#define CHECK_TEXTURE_MAGIC(texture, retval) \
if (!(texture) || (texture)->magic != &texture_magic) { \
if (!(texture) || (texture)->magic != &SDL_texture_magic) { \
SDL_InvalidParamError("texture"); \
return retval; \
}
@ -122,8 +122,8 @@ static const SDL_RenderDriver *render_drivers[] = {
};
#endif /* !SDL_RENDER_DISABLED */
static char renderer_magic;
static char texture_magic;
char SDL_renderer_magic;
char SDL_texture_magic;
static SDL_INLINE void DebugLogRenderCommands(const SDL_RenderCommand *cmd)
{
@ -231,7 +231,7 @@ static int FlushRenderCommands(SDL_Renderer *renderer)
SDL_assert((renderer->render_commands == NULL) == (renderer->render_commands_tail == NULL));
if (renderer->render_commands == NULL) { /* nothing to do! */
if (!renderer->render_commands) { /* nothing to do! */
SDL_assert(renderer->vertex_data_used == 0);
return 0;
}
@ -241,7 +241,7 @@ static int FlushRenderCommands(SDL_Renderer *renderer)
retval = renderer->RunCommandQueue(renderer, renderer->render_commands, renderer->vertex_data, renderer->vertex_data_used);
/* Move the whole render command queue to the unused pool so we can reuse them next time. */
if (renderer->render_commands_tail != NULL) {
if (renderer->render_commands_tail) {
renderer->render_commands_tail->next = renderer->render_commands_pool;
renderer->render_commands_pool = renderer->render_commands;
renderer->render_commands_tail = NULL;
@ -265,14 +265,13 @@ static int FlushRenderCommandsIfTextureNeeded(SDL_Texture *texture)
return 0;
}
static SDL_INLINE int FlushRenderCommandsIfNotBatching(SDL_Renderer *renderer)
int SDL_FlushRenderer(SDL_Renderer *renderer)
{
return renderer->batching ? 0 : FlushRenderCommands(renderer);
}
int SDL_RenderFlush(SDL_Renderer *renderer)
{
return FlushRenderCommands(renderer);
if (FlushRenderCommands(renderer) == -1) {
return -1;
}
renderer->InvalidateCachedState(renderer);
return 0;
}
void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset)
@ -293,8 +292,7 @@ void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes,
ptr = SDL_realloc(renderer->vertex_data, newsize);
if (ptr == NULL) {
SDL_OutOfMemory();
if (!ptr) {
return NULL;
}
renderer->vertex_data = ptr;
@ -316,19 +314,18 @@ static SDL_RenderCommand *AllocateRenderCommand(SDL_Renderer *renderer)
/* !!! FIXME: are there threading limitations in SDL's render API? If not, we need to mutex this. */
retval = renderer->render_commands_pool;
if (retval != NULL) {
if (retval) {
renderer->render_commands_pool = retval->next;
retval->next = NULL;
} else {
retval = SDL_calloc(1, sizeof(*retval));
if (retval == NULL) {
SDL_OutOfMemory();
if (!retval) {
return NULL;
}
}
SDL_assert((renderer->render_commands == NULL) == (renderer->render_commands_tail == NULL));
if (renderer->render_commands_tail != NULL) {
if (renderer->render_commands_tail) {
renderer->render_commands_tail->next = retval;
} else {
renderer->render_commands = retval;
@ -364,7 +361,7 @@ static int QueueCmdSetViewport(SDL_Renderer *renderer)
if (!renderer->viewport_queued ||
SDL_memcmp(&viewport, &renderer->last_queued_viewport, sizeof(viewport)) != 0) {
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
if (cmd != NULL) {
if (cmd) {
cmd->command = SDL_RENDERCMD_SETVIEWPORT;
cmd->data.viewport.first = 0; /* render backend will fill this in. */
SDL_copyp(&cmd->data.viewport.rect, &viewport);
@ -396,7 +393,7 @@ static int QueueCmdSetClipRect(SDL_Renderer *renderer)
renderer->view->clipping_enabled != renderer->last_queued_cliprect_enabled ||
SDL_memcmp(&clip_rect, &renderer->last_queued_cliprect, sizeof(clip_rect)) != 0) {
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
if (cmd != NULL) {
if (cmd) {
cmd->command = SDL_RENDERCMD_SETCLIPRECT;
cmd->data.cliprect.enabled = renderer->view->clipping_enabled;
SDL_copyp(&cmd->data.cliprect.rect, &clip_rect);
@ -419,7 +416,7 @@ static int QueueCmdSetDrawColor(SDL_Renderer *renderer, SDL_Color *col)
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
retval = -1;
if (cmd != NULL) {
if (cmd) {
cmd->command = SDL_RENDERCMD_SETDRAWCOLOR;
cmd->data.color.first = 0; /* render backend will fill this in. */
cmd->data.color.r = col->r;
@ -441,7 +438,7 @@ static int QueueCmdSetDrawColor(SDL_Renderer *renderer, SDL_Color *col)
static int QueueCmdClear(SDL_Renderer *renderer)
{
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
if (cmd == NULL) {
if (!cmd) {
return -1;
}
@ -484,7 +481,7 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren
if (retval == 0) {
cmd = AllocateRenderCommand(renderer);
if (cmd != NULL) {
if (cmd) {
cmd->command = cmdtype;
cmd->data.draw.first = 0; /* render backend will fill this in. */
cmd->data.draw.count = 0; /* render backend will fill this in. */
@ -503,7 +500,7 @@ static int QueueCmdDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points,
{
SDL_RenderCommand *cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_DRAW_POINTS, NULL);
int retval = -1;
if (cmd != NULL) {
if (cmd) {
retval = renderer->QueueDrawPoints(renderer, cmd, points, count);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
@ -516,7 +513,7 @@ static int QueueCmdDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, c
{
SDL_RenderCommand *cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_DRAW_LINES, NULL);
int retval = -1;
if (cmd != NULL) {
if (cmd) {
retval = renderer->QueueDrawLines(renderer, cmd, points, count);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
@ -529,11 +526,11 @@ static int QueueCmdFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, con
{
SDL_RenderCommand *cmd;
int retval = -1;
const int use_rendergeometry = (renderer->QueueFillRects == NULL);
const int use_rendergeometry = (!renderer->QueueFillRects);
cmd = PrepQueueCmdDraw(renderer, (use_rendergeometry ? SDL_RENDERCMD_GEOMETRY : SDL_RENDERCMD_FILL_RECTS), NULL);
if (cmd != NULL) {
if (cmd) {
if (use_rendergeometry) {
SDL_bool isstack1;
SDL_bool isstack2;
@ -603,7 +600,7 @@ static int QueueCmdCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_
{
SDL_RenderCommand *cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_COPY, texture);
int retval = -1;
if (cmd != NULL) {
if (cmd) {
retval = renderer->QueueCopy(renderer, cmd, texture, srcrect, dstrect);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
@ -618,7 +615,7 @@ static int QueueCmdCopyEx(SDL_Renderer *renderer, SDL_Texture *texture,
{
SDL_RenderCommand *cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_COPY_EX, texture);
int retval = -1;
if (cmd != NULL) {
if (cmd) {
retval = renderer->QueueCopyEx(renderer, cmd, texture, srcquad, dstrect, angle, center, flip, scale_x, scale_y);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
@ -638,7 +635,7 @@ static int QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture,
SDL_RenderCommand *cmd;
int retval = -1;
cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_GEOMETRY, texture);
if (cmd != NULL) {
if (cmd) {
retval = renderer->QueueGeometry(renderer, cmd, texture,
xy, xy_stride,
color, color_stride, uv, uv_stride,
@ -804,20 +801,27 @@ static void SDL_CalculateSimulatedVSyncInterval(SDL_Renderer *renderer, SDL_Wind
#endif /* !SDL_RENDER_DISABLED */
SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags)
SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
{
#ifndef SDL_RENDER_DISABLED
SDL_Window *window = SDL_GetProperty(props, SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER, NULL);
SDL_Surface *surface = SDL_GetProperty(props, SDL_PROPERTY_RENDERER_CREATE_SURFACE_POINTER, NULL);
const char *name = SDL_GetStringProperty(props, SDL_PROPERTY_RENDERER_CREATE_NAME_STRING, NULL);
SDL_Renderer *renderer = NULL;
const int n = SDL_GetNumRenderDrivers();
SDL_bool batching = SDL_TRUE;
const char *hint;
int i;
if (!window && surface) {
return SDL_CreateSoftwareRenderer(surface);
}
#ifdef __ANDROID__
Android_ActivityMutex_Lock_Running();
#endif
if (window == NULL) {
if (!window) {
SDL_InvalidParamError("window");
goto error;
}
@ -834,11 +838,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl
hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC);
if (hint && *hint) {
if (SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE)) {
flags |= SDL_RENDERER_PRESENTVSYNC;
} else {
flags &= ~SDL_RENDERER_PRESENTVSYNC;
}
SDL_SetBooleanProperty(props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE));
}
if (!name) {
@ -850,33 +850,28 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl
const SDL_RenderDriver *driver = render_drivers[i];
if (SDL_strcasecmp(name, driver->info.name) == 0) {
/* Create a new renderer instance */
renderer = driver->CreateRenderer(window, flags);
if (renderer) {
batching = SDL_FALSE;
}
renderer = driver->CreateRenderer(window, props);
break;
}
}
} else {
for (i = 0; i < n; i++) {
const SDL_RenderDriver *driver = render_drivers[i];
if ((driver->info.flags & flags) == flags) {
/* Create a new renderer instance */
renderer = driver->CreateRenderer(window, flags);
if (renderer) {
/* Yay, we got one! */
break;
}
/* Create a new renderer instance */
renderer = driver->CreateRenderer(window, props);
if (renderer) {
/* Yay, we got one! */
break;
}
}
}
if (renderer == NULL) {
if (!renderer) {
SDL_SetError("Couldn't find matching render driver");
goto error;
}
if (flags & SDL_RENDERER_PRESENTVSYNC) {
if (SDL_GetBooleanProperty(props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
renderer->wanted_vsync = SDL_TRUE;
if (!(renderer->info.flags & SDL_RENDERER_PRESENTVSYNC)) {
@ -888,15 +883,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl
VerifyDrawQueueFunctions(renderer);
/* let app/user override batching decisions. */
if (renderer->always_batch) {
batching = SDL_TRUE;
} else if (SDL_GetHint(SDL_HINT_RENDER_BATCHING)) {
batching = SDL_GetHintBoolean(SDL_HINT_RENDER_BATCHING, SDL_TRUE);
}
renderer->batching = batching;
renderer->magic = &renderer_magic;
renderer->magic = &SDL_renderer_magic;
renderer->window = window;
renderer->target_mutex = SDL_CreateMutex();
renderer->main_view.viewport.w = -1;
@ -929,7 +916,7 @@ SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 fl
renderer->hidden = SDL_FALSE;
}
SDL_SetWindowData(window, SDL_WINDOWRENDERDATA, renderer);
SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_RENDERER, renderer);
SDL_SetRenderViewport(renderer, NULL);
@ -956,6 +943,24 @@ error:
#endif
}
SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags)
{
SDL_Renderer *renderer;
SDL_PropertiesID props = SDL_CreateProperties();
SDL_SetProperty(props, SDL_PROPERTY_RENDERER_CREATE_WINDOW_POINTER, window);
if (flags & SDL_RENDERER_SOFTWARE) {
SDL_SetStringProperty(props, SDL_PROPERTY_RENDERER_CREATE_NAME_STRING, "software");
} else {
SDL_SetStringProperty(props, SDL_PROPERTY_RENDERER_CREATE_NAME_STRING, name);
}
if (flags & SDL_RENDERER_PRESENTVSYNC) {
SDL_SetBooleanProperty(props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_TRUE);
}
renderer = SDL_CreateRendererWithProperties(props);
SDL_DestroyProperties(props);
return renderer;
}
SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface)
{
#if !defined(SDL_RENDER_DISABLED) && SDL_VIDEO_RENDER_SW
@ -965,7 +970,7 @@ SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface)
if (renderer) {
VerifyDrawQueueFunctions(renderer);
renderer->magic = &renderer_magic;
renderer->magic = &SDL_renderer_magic;
renderer->target_mutex = SDL_CreateMutex();
renderer->main_view.pixel_w = surface->w;
renderer->main_view.pixel_h = surface->h;
@ -994,7 +999,7 @@ SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface)
SDL_Renderer *SDL_GetRenderer(SDL_Window *window)
{
return (SDL_Renderer *)SDL_GetWindowData(window, SDL_WINDOWRENDERDATA);
return (SDL_Renderer *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_RENDERER, NULL);
}
SDL_Window *SDL_GetRenderWindow(SDL_Renderer *renderer)
@ -1007,10 +1012,20 @@ int SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_RendererInfo *info)
{
CHECK_RENDERER_MAGIC(renderer, -1);
*info = renderer->info;
SDL_copyp(info, &renderer->info);
return 0;
}
SDL_PropertiesID SDL_GetRendererProperties(SDL_Renderer *renderer)
{
CHECK_RENDERER_MAGIC(renderer, 0);
if (renderer->props == 0) {
renderer->props = SDL_CreateProperties();
}
return renderer->props;
}
int SDL_GetRenderOutputSize(SDL_Renderer *renderer, int *w, int *h)
{
CHECK_RENDERER_MAGIC(renderer, -1);
@ -1095,7 +1110,7 @@ static SDL_ScaleMode SDL_GetScaleMode(void)
{
const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
if (hint == NULL || SDL_strcasecmp(hint, "nearest") == 0) {
if (!hint || SDL_strcasecmp(hint, "nearest") == 0) {
return SDL_SCALEMODE_NEAREST;
} else if (SDL_strcasecmp(hint, "linear") == 0) {
return SDL_SCALEMODE_LINEAR;
@ -1106,9 +1121,13 @@ static SDL_ScaleMode SDL_GetScaleMode(void)
}
}
SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h)
SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props)
{
SDL_Texture *texture;
Uint32 format = (Uint32)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER, SDL_PIXELFORMAT_UNKNOWN);
int access = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC);
int w = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER, 0);
int h = (int)SDL_GetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER, 0);
SDL_bool texture_is_fourcc_and_target;
CHECK_RENDERER_MAGIC(renderer, NULL);
@ -1136,11 +1155,10 @@ SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access
return NULL;
}
texture = (SDL_Texture *)SDL_calloc(1, sizeof(*texture));
if (texture == NULL) {
SDL_OutOfMemory();
if (!texture) {
return NULL;
}
texture->magic = &texture_magic;
texture->magic = &SDL_texture_magic;
texture->format = format;
texture->access = access;
texture->w = w;
@ -1167,7 +1185,7 @@ SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access
texture_is_fourcc_and_target = (access == SDL_TEXTUREACCESS_TARGET && SDL_ISPIXELFORMAT_FOURCC(texture->format));
if (texture_is_fourcc_and_target == SDL_FALSE && IsSupportedFormat(renderer, format)) {
if (renderer->CreateTexture(renderer, texture) < 0) {
if (renderer->CreateTexture(renderer, texture, props) < 0) {
SDL_DestroyTexture(texture);
return NULL;
}
@ -1222,6 +1240,19 @@ SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access
return texture;
}
SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h)
{
SDL_Texture *texture;
SDL_PropertiesID props = SDL_CreateProperties();
SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_FORMAT_NUMBER, format);
SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_ACCESS_NUMBER, access);
SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_WIDTH_NUMBER, w);
SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_CREATE_HEIGHT_NUMBER, h);
texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props);
return texture;
}
SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface)
{
const SDL_PixelFormat *fmt;
@ -1233,7 +1264,7 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
CHECK_RENDERER_MAGIC(renderer, NULL);
if (surface == NULL) {
if (!surface) {
SDL_InvalidParamError("SDL_CreateTextureFromSurface(): surface");
return NULL;
}
@ -1297,7 +1328,7 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
surface->w, surface->h);
if (texture == NULL) {
if (!texture) {
return NULL;
}
@ -1329,7 +1360,7 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
/* Set up a destination surface for the texture update */
dst_fmt = SDL_CreatePixelFormat(format);
if (dst_fmt == NULL) {
if (!dst_fmt) {
SDL_DestroyTexture(texture);
return NULL;
}
@ -1365,6 +1396,22 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
return texture;
}
SDL_Renderer *SDL_GetRendererFromTexture(SDL_Texture *texture)
{
CHECK_TEXTURE_MAGIC(texture, NULL);
return texture->renderer;
}
SDL_PropertiesID SDL_GetTextureProperties(SDL_Texture *texture)
{
CHECK_TEXTURE_MAGIC(texture, 0);
if (texture->props == 0) {
texture->props = SDL_CreateProperties();
}
return texture->props;
}
int SDL_QueryTexture(SDL_Texture *texture, Uint32 *format, int *access, int *w, int *h)
{
CHECK_TEXTURE_MAGIC(texture, -1);
@ -1388,11 +1435,6 @@ int SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r, Uint8 g, Uint8 b)
{
CHECK_TEXTURE_MAGIC(texture, -1);
if (r < 255 || g < 255 || b < 255) {
texture->modMode |= SDL_TEXTUREMODULATE_COLOR;
} else {
texture->modMode &= ~SDL_TEXTUREMODULATE_COLOR;
}
texture->color.r = r;
texture->color.g = g;
texture->color.b = b;
@ -1422,11 +1464,6 @@ int SDL_SetTextureAlphaMod(SDL_Texture *texture, Uint8 alpha)
{
CHECK_TEXTURE_MAGIC(texture, -1);
if (alpha < 255) {
texture->modMode |= SDL_TEXTUREMODULATE_ALPHA;
} else {
texture->modMode &= ~SDL_TEXTUREMODULATE_ALPHA;
}
texture->color.a = alpha;
if (texture->native) {
return SDL_SetTextureAlphaMod(texture->native, alpha);
@ -1497,21 +1534,6 @@ int SDL_GetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode *scaleMode)
return 0;
}
int SDL_SetTextureUserData(SDL_Texture *texture, void *userdata)
{
CHECK_TEXTURE_MAGIC(texture, -1);
texture->userdata = userdata;
return 0;
}
void *SDL_GetTextureUserData(SDL_Texture *texture)
{
CHECK_TEXTURE_MAGIC(texture, NULL);
return texture->userdata;
}
#if SDL_HAVE_YUV
static int SDL_UpdateTextureYUV(SDL_Texture *texture, const SDL_Rect *rect,
const void *pixels, int pitch)
@ -1546,8 +1568,8 @@ static int SDL_UpdateTextureYUV(SDL_Texture *texture, const SDL_Rect *rect,
const size_t alloclen = (size_t)rect->h * temp_pitch;
if (alloclen > 0) {
void *temp_pixels = SDL_malloc(alloclen);
if (temp_pixels == NULL) {
return SDL_OutOfMemory();
if (!temp_pixels) {
return -1;
}
SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
rect->w, rect->h, temp_pixels, temp_pitch);
@ -1586,8 +1608,8 @@ static int SDL_UpdateTextureNative(SDL_Texture *texture, const SDL_Rect *rect,
const size_t alloclen = (size_t)rect->h * temp_pitch;
if (alloclen > 0) {
void *temp_pixels = SDL_malloc(alloclen);
if (temp_pixels == NULL) {
return SDL_OutOfMemory();
if (!temp_pixels) {
return -1;
}
SDL_ConvertPixels(rect->w, rect->h,
texture->format, pixels, pitch,
@ -1605,7 +1627,7 @@ int SDL_UpdateTexture(SDL_Texture *texture, const SDL_Rect *rect, const void *pi
CHECK_TEXTURE_MAGIC(texture, -1);
if (pixels == NULL) {
if (!pixels) {
return SDL_InvalidParamError("pixels");
}
if (!pitch) {
@ -1679,8 +1701,8 @@ static int SDL_UpdateTextureYUVPlanar(SDL_Texture *texture, const SDL_Rect *rect
const size_t alloclen = (size_t)rect->h * temp_pitch;
if (alloclen > 0) {
void *temp_pixels = SDL_malloc(alloclen);
if (temp_pixels == NULL) {
return SDL_OutOfMemory();
if (!temp_pixels) {
return -1;
}
SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
rect->w, rect->h, temp_pixels, temp_pitch);
@ -1729,8 +1751,8 @@ static int SDL_UpdateTextureNVPlanar(SDL_Texture *texture, const SDL_Rect *rect,
const size_t alloclen = (size_t)rect->h * temp_pitch;
if (alloclen > 0) {
void *temp_pixels = SDL_malloc(alloclen);
if (temp_pixels == NULL) {
return SDL_OutOfMemory();
if (!temp_pixels) {
return -1;
}
SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
rect->w, rect->h, temp_pixels, temp_pitch);
@ -1754,19 +1776,19 @@ int SDL_UpdateYUVTexture(SDL_Texture *texture, const SDL_Rect *rect,
CHECK_TEXTURE_MAGIC(texture, -1);
if (Yplane == NULL) {
if (!Yplane) {
return SDL_InvalidParamError("Yplane");
}
if (!Ypitch) {
return SDL_InvalidParamError("Ypitch");
}
if (Uplane == NULL) {
if (!Uplane) {
return SDL_InvalidParamError("Uplane");
}
if (!Upitch) {
return SDL_InvalidParamError("Upitch");
}
if (Vplane == NULL) {
if (!Vplane) {
return SDL_InvalidParamError("Vplane");
}
if (!Vpitch) {
@ -1820,13 +1842,13 @@ int SDL_UpdateNVTexture(SDL_Texture *texture, const SDL_Rect *rect,
CHECK_TEXTURE_MAGIC(texture, -1);
if (Yplane == NULL) {
if (!Yplane) {
return SDL_InvalidParamError("Yplane");
}
if (!Ypitch) {
return SDL_InvalidParamError("Ypitch");
}
if (UVplane == NULL) {
if (!UVplane) {
return SDL_InvalidParamError("UVplane");
}
if (!UVpitch) {
@ -1899,7 +1921,7 @@ int SDL_LockTexture(SDL_Texture *texture, const SDL_Rect *rect, void **pixels, i
return SDL_SetError("SDL_LockTexture(): texture must be streaming");
}
if (rect == NULL) {
if (!rect) {
full_rect.x = 0;
full_rect.y = 0;
full_rect.w = texture->w;
@ -1934,7 +1956,7 @@ int SDL_LockTextureToSurface(SDL_Texture *texture, const SDL_Rect *rect, SDL_Sur
int pitch = 0; /* fix static analysis */
int ret;
if (texture == NULL || surface == NULL) {
if (!texture || !surface) {
return -1;
}
@ -1952,7 +1974,7 @@ int SDL_LockTextureToSurface(SDL_Texture *texture, const SDL_Rect *rect, SDL_Sur
}
texture->locked_surface = SDL_CreateSurfaceFrom(pixels, real_rect.w, real_rect.h, pitch, texture->format);
if (texture->locked_surface == NULL) {
if (!texture->locked_surface) {
SDL_UnlockTexture(texture);
return -1;
}
@ -2074,12 +2096,12 @@ static int SDL_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *text
}
/* All set! */
return FlushRenderCommandsIfNotBatching(renderer);
return 0;
}
int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
if (texture == NULL && renderer->logical_target) {
if (!texture && renderer->logical_target) {
return SDL_SetRenderTargetInternal(renderer, renderer->logical_target);
} else {
return SDL_SetRenderTargetInternal(renderer, texture);
@ -2468,13 +2490,20 @@ int SDL_ConvertEventToRenderCoordinates(SDL_Renderer *renderer, SDL_Event *event
}
SDL_RenderCoordinatesFromWindow(renderer, event->tfinger.x * w, event->tfinger.y * h, &event->tfinger.x, &event->tfinger.y);
}
} else if (event->type == SDL_EVENT_DROP_POSITION ||
event->type == SDL_EVENT_DROP_FILE ||
event->type == SDL_EVENT_DROP_TEXT ||
event->type == SDL_EVENT_DROP_COMPLETE) {
SDL_Window *window = SDL_GetWindowFromID(event->drop.windowID);
if (window == renderer->window) {
SDL_RenderCoordinatesFromWindow(renderer, event->drop.x, event->drop.y, &event->drop.x, &event->drop.y);
}
}
return 0;
}
int SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect)
{
int retval;
CHECK_RENDERER_MAGIC(renderer, -1);
if (rect) {
@ -2488,8 +2517,7 @@ int SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect)
renderer->view->viewport.w = -1;
renderer->view->viewport.h = -1;
}
retval = QueueCmdSetViewport(renderer);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
return QueueCmdSetViewport(renderer);
}
int SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect)
@ -2531,7 +2559,6 @@ static void GetRenderViewportSize(SDL_Renderer *renderer, SDL_FRect *rect)
int SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect)
{
int retval;
CHECK_RENDERER_MAGIC(renderer, -1)
if (rect && rect->w >= 0 && rect->h >= 0) {
@ -2545,8 +2572,7 @@ int SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect)
SDL_zero(renderer->view->clip_rect);
}
retval = QueueCmdSetClipRect(renderer);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
return QueueCmdSetClipRect(renderer);
}
int SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect)
@ -2585,7 +2611,7 @@ int SDL_SetRenderScale(SDL_Renderer *renderer, float scaleX, float scaleY)
/* The scale affects the existing viewport and clip rectangle */
retval += QueueCmdSetViewport(renderer);
retval += QueueCmdSetClipRect(renderer);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
return retval;
}
int SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY)
@ -2655,7 +2681,7 @@ int SDL_RenderClear(SDL_Renderer *renderer)
int retval;
CHECK_RENDERER_MAGIC(renderer, -1);
retval = QueueCmdClear(renderer);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
return retval;
}
int SDL_RenderPoint(SDL_Renderer *renderer, float x, float y)
@ -2678,8 +2704,8 @@ static int RenderPointsWithRects(SDL_Renderer *renderer, const SDL_FPoint *fpoin
}
frects = SDL_small_alloc(SDL_FRect, count, &isstack);
if (frects == NULL) {
return SDL_OutOfMemory();
if (!frects) {
return -1;
}
for (i = 0; i < count; ++i) {
@ -2702,7 +2728,7 @@ int SDL_RenderPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count
CHECK_RENDERER_MAGIC(renderer, -1);
if (points == NULL) {
if (!points) {
return SDL_InvalidParamError("SDL_RenderPoints(): points");
}
if (count < 1) {
@ -2721,7 +2747,7 @@ int SDL_RenderPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count
} else {
retval = QueueCmdDrawPoints(renderer, points, count);
}
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
return retval;
}
int SDL_RenderLine(SDL_Renderer *renderer, float x1, float y1, float x2, float y2)
@ -2744,6 +2770,15 @@ static int RenderLineBresenham(SDL_Renderer *renderer, int x1, int y1, int x2, i
int retval;
SDL_bool isstack;
SDL_FPoint *points;
SDL_Rect viewport;
/* the backend might clip this further to the clipping rect, but we
just want a basic safety against generating millions of points for
massive lines. */
GetRenderViewportInPixels(renderer, &viewport);
if (!SDL_GetRectAndLineIntersection(&viewport, &x1, &y1, &x2, &y2)) {
return 0;
}
deltax = SDL_abs(x2 - x1);
deltay = SDL_abs(y2 - y1);
@ -2789,8 +2824,8 @@ static int RenderLineBresenham(SDL_Renderer *renderer, int x1, int y1, int x2, i
}
points = SDL_small_alloc(SDL_FPoint, numpixels, &isstack);
if (points == NULL) {
return SDL_OutOfMemory();
if (!points) {
return -1;
}
for (i = 0; i < numpixels; ++i) {
points[i].x = (float)x;
@ -2832,8 +2867,8 @@ static int RenderLinesWithRectsF(SDL_Renderer *renderer,
SDL_bool draw_last = SDL_FALSE;
frects = SDL_small_alloc(SDL_FRect, count - 1, &isstack);
if (frects == NULL) {
return SDL_OutOfMemory();
if (!frects) {
return -1;
}
for (i = 0; i < count - 1; ++i) {
@ -2898,7 +2933,7 @@ int SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
CHECK_RENDERER_MAGIC(renderer, -1);
if (points == NULL) {
if (!points) {
return SDL_InvalidParamError("SDL_RenderLines(): points");
}
if (count < 2) {
@ -3040,7 +3075,7 @@ int SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
retval = QueueCmdDrawLines(renderer, points, count);
}
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
return retval;
}
int SDL_RenderRect(SDL_Renderer *renderer, const SDL_FRect *rect)
@ -3051,7 +3086,7 @@ int SDL_RenderRect(SDL_Renderer *renderer, const SDL_FRect *rect)
CHECK_RENDERER_MAGIC(renderer, -1);
/* If 'rect' == NULL, then outline the whole surface */
if (rect == NULL) {
if (!rect) {
GetRenderViewportSize(renderer, &frect);
rect = &frect;
}
@ -3075,7 +3110,7 @@ int SDL_RenderRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
CHECK_RENDERER_MAGIC(renderer, -1);
if (rects == NULL) {
if (!rects) {
return SDL_InvalidParamError("SDL_RenderRects(): rects");
}
if (count < 1) {
@ -3104,7 +3139,7 @@ int SDL_RenderFillRect(SDL_Renderer *renderer, const SDL_FRect *rect)
CHECK_RENDERER_MAGIC(renderer, -1);
/* If 'rect' == NULL, then fill the whole surface */
if (rect == NULL) {
if (!rect) {
GetRenderViewportSize(renderer, &frect);
rect = &frect;
}
@ -3120,7 +3155,7 @@ int SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int coun
CHECK_RENDERER_MAGIC(renderer, -1);
if (rects == NULL) {
if (!rects) {
return SDL_InvalidParamError("SDL_RenderFillRects(): rects");
}
if (count < 1) {
@ -3135,8 +3170,8 @@ int SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int coun
#endif
frects = SDL_small_alloc(SDL_FRect, count, &isstack);
if (frects == NULL) {
return SDL_OutOfMemory();
if (!frects) {
return -1;
}
for (i = 0; i < count; ++i) {
frects[i].x = rects[i].x * renderer->view->scale.x;
@ -3149,7 +3184,7 @@ int SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int coun
SDL_small_free(frects, isstack);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
return retval;
}
int SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, const SDL_FRect *dstrect)
@ -3173,7 +3208,7 @@ int SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FR
}
#endif
use_rendergeometry = (renderer->QueueCopy == NULL);
use_rendergeometry = (!renderer->QueueCopy);
real_srcrect.x = 0.0f;
real_srcrect.y = 0.0f;
@ -3254,7 +3289,7 @@ int SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FR
retval = QueueCmdCopy(renderer, texture, &real_srcrect, &real_dstrect);
}
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
return retval;
}
int SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture,
@ -3288,7 +3323,7 @@ int SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture,
}
#endif
use_rendergeometry = (renderer->QueueCopyEx == NULL);
use_rendergeometry = (!renderer->QueueCopyEx);
real_srcrect.x = 0.0f;
real_srcrect.y = 0.0f;
@ -3409,7 +3444,7 @@ int SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture,
renderer->view->scale.x,
renderer->view->scale.y);
}
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
return retval;
}
int SDL_RenderGeometry(SDL_Renderer *renderer,
@ -3766,8 +3801,6 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer,
renderer->view->scale.y);
if (retval < 0) {
goto end;
} else {
FlushRenderCommandsIfNotBatching(renderer);
}
}
@ -3789,8 +3822,6 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer,
renderer->view->scale.y);
if (retval < 0) {
goto end;
} else {
FlushRenderCommandsIfNotBatching(renderer);
}
}
@ -3828,15 +3859,15 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer,
}
}
if (xy == NULL) {
if (!xy) {
return SDL_InvalidParamError("xy");
}
if (color == NULL) {
if (!color) {
return SDL_InvalidParamError("color");
}
if (texture && uv == NULL) {
if (texture && !uv) {
return SDL_InvalidParamError("uv");
}
@ -3912,7 +3943,7 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer,
renderer->view->scale.x,
renderer->view->scale.y);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
return retval;
}
int SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
@ -3928,7 +3959,7 @@ int SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 fo
FlushRenderCommands(renderer); /* we need to render before we read the results. */
if (!format) {
if (renderer->target == NULL) {
if (!renderer->target) {
format = SDL_GetWindowPixelFormat(renderer->window);
} else {
format = renderer->target->format;
@ -4021,6 +4052,8 @@ static int SDL_DestroyTextureInternal(SDL_Texture *texture, SDL_bool is_destroyi
CHECK_TEXTURE_MAGIC(texture, -1);
SDL_DestroyProperties(texture->props);
renderer = texture->renderer;
if (is_destroying) {
/* Renderer get destroyed, avoid to queue more commands */
@ -4081,7 +4114,7 @@ static void SDL_DiscardAllCommands(SDL_Renderer *renderer)
{
SDL_RenderCommand *cmd;
if (renderer->render_commands_tail != NULL) {
if (renderer->render_commands_tail) {
renderer->render_commands_tail->next = renderer->render_commands_pool;
cmd = renderer->render_commands;
} else {
@ -4092,7 +4125,7 @@ static void SDL_DiscardAllCommands(SDL_Renderer *renderer)
renderer->render_commands_tail = NULL;
renderer->render_commands = NULL;
while (cmd != NULL) {
while (cmd) {
SDL_RenderCommand *next = cmd->next;
SDL_free(cmd);
cmd = next;
@ -4103,6 +4136,8 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer)
{
CHECK_RENDERER_MAGIC(renderer,);
SDL_DestroyProperties(renderer->props);
SDL_DelEventWatch(SDL_RendererEventWatch, renderer);
SDL_DiscardAllCommands(renderer);
@ -4118,7 +4153,7 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer)
SDL_free(renderer->vertex_data);
if (renderer->window) {
SDL_SetWindowData(renderer->window, SDL_WINDOWRENDERDATA, NULL);
SDL_ClearProperty(SDL_GetWindowProperties(renderer->window), SDL_PROPERTY_WINDOW_RENDERER);
}
/* It's no longer magical... */
@ -4132,38 +4167,6 @@ void SDL_DestroyRenderer(SDL_Renderer *renderer)
renderer->DestroyRenderer(renderer);
}
int SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh)
{
SDL_Renderer *renderer;
CHECK_TEXTURE_MAGIC(texture, -1);
renderer = texture->renderer;
if (texture->native) {
return SDL_GL_BindTexture(texture->native, texw, texh);
} else if (renderer && renderer->GL_BindTexture) {
FlushRenderCommandsIfTextureNeeded(texture); /* in case the app is going to mess with it. */
return renderer->GL_BindTexture(renderer, texture, texw, texh);
} else {
return SDL_Unsupported();
}
}
int SDL_GL_UnbindTexture(SDL_Texture *texture)
{
SDL_Renderer *renderer;
CHECK_TEXTURE_MAGIC(texture, -1);
renderer = texture->renderer;
if (texture->native) {
return SDL_GL_UnbindTexture(texture->native);
} else if (renderer && renderer->GL_UnbindTexture) {
FlushRenderCommandsIfTextureNeeded(texture); /* in case the app messed with it. */
return renderer->GL_UnbindTexture(renderer, texture);
}
return SDL_Unsupported();
}
void *SDL_GetRenderMetalLayer(SDL_Renderer *renderer)
{
CHECK_RENDERER_MAGIC(renderer, NULL);
@ -4307,7 +4310,7 @@ int SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync)
int SDL_GetRenderVSync(SDL_Renderer *renderer, int *vsync)
{
CHECK_RENDERER_MAGIC(renderer, -1);
if (vsync == NULL) {
if (!vsync) {
return SDL_InvalidParamError("vsync");
}
*vsync = renderer->wanted_vsync;

View File

@ -0,0 +1,22 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 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"

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -44,6 +44,8 @@ typedef struct SDL_DRect
/* The SDL 2D rendering system */
typedef struct SDL_RenderDriver SDL_RenderDriver;
extern char SDL_renderer_magic;
extern char SDL_texture_magic;
/* Rendering view state */
typedef struct SDL_RenderViewState
@ -65,7 +67,6 @@ struct SDL_Texture
int access; /**< SDL_TextureAccess */
int w; /**< The width of the texture */
int h; /**< The height of the texture */
int modMode; /**< The texture modulation mode */
SDL_BlendMode blendMode; /**< The texture blend mode */
SDL_ScaleMode scaleMode; /**< The texture scale mode */
SDL_Color color; /**< Texture modulation values */
@ -83,8 +84,9 @@ struct SDL_Texture
Uint32 last_command_generation; /* last command queue generation this texture was in. */
SDL_PropertiesID props;
void *driverdata; /**< Driver specific texture representation */
void *userdata;
SDL_Texture *prev;
SDL_Texture *next;
@ -158,7 +160,7 @@ struct SDL_Renderer
void (*WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event);
int (*GetOutputSize)(SDL_Renderer *renderer, int *w, int *h);
SDL_bool (*SupportsBlendMode)(SDL_Renderer *renderer, SDL_BlendMode blendMode);
int (*CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture);
int (*CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props);
int (*QueueSetViewport)(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
int (*QueueSetDrawColor)(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
int (*QueueDrawPoints)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points,
@ -177,6 +179,7 @@ struct SDL_Renderer
int num_vertices, const void *indices, int num_indices, int size_indices,
float scale_x, float scale_y);
void (*InvalidateCachedState)(SDL_Renderer *renderer);
int (*RunCommandQueue)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
int (*UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, const void *pixels,
@ -206,9 +209,6 @@ struct SDL_Renderer
int (*SetVSync)(SDL_Renderer *renderer, int vsync);
int (*GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh);
int (*GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture);
void *(*GetMetalLayer)(SDL_Renderer *renderer);
void *(*GetMetalCommandEncoder)(SDL_Renderer *renderer);
@ -252,8 +252,6 @@ struct SDL_Renderer
SDL_Color color; /**< Color for drawing operations values */
SDL_BlendMode blendMode; /**< The drawing blend mode */
SDL_bool always_batch;
SDL_bool batching;
SDL_RenderCommand *render_commands;
SDL_RenderCommand *render_commands_tail;
SDL_RenderCommand *render_commands_pool;
@ -270,13 +268,15 @@ struct SDL_Renderer
size_t vertex_data_used;
size_t vertex_data_allocation;
SDL_PropertiesID props;
void *driverdata;
};
/* Define the SDL render driver structure */
struct SDL_RenderDriver
{
SDL_Renderer *(*CreateRenderer)(SDL_Window *window, Uint32 flags);
SDL_Renderer *(*CreateRenderer)(SDL_Window *window, SDL_PropertiesID props);
/* Info about the renderer capabilities */
SDL_RendererInfo info;
@ -307,9 +307,6 @@ extern SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode
the next call, because it might be in an array that gets realloc()'d. */
extern void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset);
extern int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode);
extern int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect, SDL_ScaleMode scaleMode);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -46,8 +46,7 @@ SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
}
swdata = (SDL_SW_YUVTexture *)SDL_calloc(1, sizeof(*swdata));
if (swdata == NULL) {
SDL_OutOfMemory();
if (!swdata) {
return NULL;
}
@ -59,13 +58,11 @@ SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
size_t dst_size;
if (SDL_CalculateYUVSize(format, w, h, &dst_size, NULL) < 0) {
SDL_SW_DestroyYUVTexture(swdata);
SDL_OutOfMemory();
return NULL;
}
swdata->pixels = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), dst_size);
if (!swdata->pixels) {
SDL_SW_DestroyYUVTexture(swdata);
SDL_OutOfMemory();
return NULL;
}
}
@ -385,7 +382,7 @@ int SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture *swdata, const SDL_Rect *srcrect,
}
if (stretch) {
SDL_Rect rect = *srcrect;
SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL);
SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL, SDL_SCALEMODE_NEAREST);
}
return 0;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -28,8 +28,6 @@
#include "../SDL_d3dmath.h"
#include "../../video/windows/SDL_windowsvideo.h"
#include <SDL3/SDL_syswm.h>
#ifdef SDL_VIDEO_RENDER_D3D
#define D3D_DEBUG_INFO
#include <d3d9.h>
@ -434,7 +432,7 @@ static int D3D_CreateStagingTexture(IDirect3DDevice9 *device, D3D_TextureRep *te
{
HRESULT result;
if (texture->staging == NULL) {
if (!texture->staging) {
result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, 0,
texture->d3dfmt, D3DPOOL_SYSTEMMEM, &texture->staging, NULL);
if (FAILED(result)) {
@ -519,15 +517,15 @@ static void D3D_DestroyTextureRep(D3D_TextureRep *texture)
}
}
static int D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
D3D_TextureData *texturedata;
DWORD usage;
texturedata = (D3D_TextureData *)SDL_calloc(1, sizeof(*texturedata));
if (texturedata == NULL) {
return SDL_OutOfMemory();
if (!texturedata) {
return -1;
}
texturedata->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3DTEXF_POINT : D3DTEXF_LINEAR;
@ -564,7 +562,7 @@ static int D3D_RecreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
if (texturedata == NULL) {
if (!texturedata) {
return 0;
}
@ -591,7 +589,7 @@ static int D3D_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
if (texturedata == NULL) {
if (!texturedata) {
return SDL_SetError("Texture is not currently available");
}
@ -627,7 +625,7 @@ static int D3D_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
if (texturedata == NULL) {
if (!texturedata) {
return SDL_SetError("Texture is not currently available");
}
@ -651,7 +649,7 @@ static int D3D_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
IDirect3DDevice9 *device = data->device;
if (texturedata == NULL) {
if (!texturedata) {
return SDL_SetError("Texture is not currently available");
}
#if SDL_HAVE_YUV
@ -663,7 +661,7 @@ static int D3D_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
texturedata->pitch = texture->w;
texturedata->pixels = (Uint8 *)SDL_malloc((texture->h * texturedata->pitch * 3) / 2);
if (!texturedata->pixels) {
return SDL_OutOfMemory();
return -1;
}
}
*pixels =
@ -701,7 +699,7 @@ static void D3D_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
if (texturedata == NULL) {
if (!texturedata) {
return;
}
#if SDL_HAVE_YUV
@ -729,7 +727,7 @@ static void D3D_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture
{
D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
if (texturedata == NULL) {
if (!texturedata) {
return;
}
@ -745,18 +743,18 @@ static int D3D_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *text
IDirect3DDevice9 *device = data->device;
/* Release the previous render target if it wasn't the default one */
if (data->currentRenderTarget != NULL) {
if (data->currentRenderTarget) {
IDirect3DSurface9_Release(data->currentRenderTarget);
data->currentRenderTarget = NULL;
}
if (texture == NULL) {
if (!texture) {
IDirect3DDevice9_SetRenderTarget(data->device, 0, data->defaultRenderTarget);
return 0;
}
texturedata = (D3D_TextureData *)texture->driverdata;
if (texturedata == NULL) {
if (!texturedata) {
return SDL_SetError("Texture is not currently available");
}
@ -811,7 +809,7 @@ static int D3D_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, c
Vertex *verts = (Vertex *)SDL_AllocateRenderVertices(renderer, vertslen, 0, &cmd->data.draw.first);
int i;
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -836,7 +834,7 @@ static int D3D_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL
int count = indices ? num_indices : num_vertices;
Vertex *verts = (Vertex *)SDL_AllocateRenderVertices(renderer, count * sizeof(Vertex), 0, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -932,7 +930,7 @@ static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, LPDIREC
SDL_assert(*shader == NULL);
if (texturedata == NULL) {
if (!texturedata) {
return SDL_SetError("Texture is not currently available");
}
@ -984,11 +982,11 @@ static int SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
LPDIRECT3DPIXELSHADER9 shader = NULL;
/* disable any enabled textures we aren't going to use, let SetupTextureState() do the rest. */
if (texture == NULL) {
if (!texture) {
IDirect3DDevice9_SetTexture(data->device, 0, NULL);
}
#if SDL_HAVE_YUV
if ((newtexturedata == NULL || !newtexturedata->yuv) && (oldtexturedata && oldtexturedata->yuv)) {
if ((!newtexturedata || !newtexturedata->yuv) && (oldtexturedata && oldtexturedata->yuv)) {
IDirect3DDevice9_SetTexture(data->device, 1, NULL);
IDirect3DDevice9_SetTexture(data->device, 2, NULL);
}
@ -1088,6 +1086,17 @@ static int SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
return 0;
}
static void D3D_InvalidateCachedState(SDL_Renderer *renderer)
{
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
data->drawstate.viewport_dirty = SDL_TRUE;
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.blend = SDL_BLENDMODE_INVALID;
data->drawstate.texture = NULL;
data->drawstate.shader = NULL;
}
static int D3D_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
@ -1186,7 +1195,7 @@ static int D3D_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
const SDL_Rect *viewport = &data->drawstate.viewport;
const int backw = istarget ? renderer->target->w : data->pparams.BackBufferWidth;
const int backh = istarget ? renderer->target->h : data->pparams.BackBufferHeight;
const SDL_bool viewport_equal = ((viewport->x == 0) && (viewport->y == 0) && (viewport->w == backw) && (viewport->h == backh)) ? SDL_TRUE : SDL_FALSE;
const SDL_bool viewport_equal = ((viewport->x == 0) && (viewport->y == 0) && (viewport->w == backw) && (viewport->h == backh));
if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) {
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
@ -1382,7 +1391,7 @@ static void D3D_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
#endif
}
if (data == NULL) {
if (!data) {
return;
}
@ -1408,7 +1417,7 @@ static void D3D_DestroyRenderer(SDL_Renderer *renderer)
IDirect3DSurface9_Release(data->defaultRenderTarget);
data->defaultRenderTarget = NULL;
}
if (data->currentRenderTarget != NULL) {
if (data->currentRenderTarget) {
IDirect3DSurface9_Release(data->currentRenderTarget);
data->currentRenderTarget = NULL;
}
@ -1459,7 +1468,7 @@ static int D3D_Reset(SDL_Renderer *renderer)
IDirect3DSurface9_Release(data->defaultRenderTarget);
data->defaultRenderTarget = NULL;
}
if (data->currentRenderTarget != NULL) {
if (data->currentRenderTarget) {
IDirect3DSurface9_Release(data->currentRenderTarget);
data->currentRenderTarget = NULL;
}
@ -1495,19 +1504,16 @@ static int D3D_Reset(SDL_Renderer *renderer)
/* Allocate application render targets */
for (texture = renderer->textures; texture; texture = texture->next) {
if (texture->access == SDL_TEXTUREACCESS_TARGET) {
D3D_CreateTexture(renderer, texture);
D3D_CreateTexture(renderer, texture, 0);
}
}
IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget);
D3D_InitRenderState(data);
D3D_SetRenderTargetInternal(renderer, renderer->target);
data->drawstate.viewport_dirty = SDL_TRUE;
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
data->drawstate.texture = NULL;
data->drawstate.shader = NULL;
data->drawstate.blend = SDL_BLENDMODE_INVALID;
D3D_InvalidateCachedState(renderer);
IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX *)&d3dmatrix);
/* Let the application know that render targets were reset */
@ -1538,11 +1544,10 @@ static int D3D_SetVSync(SDL_Renderer *renderer, const int vsync)
return 0;
}
SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props)
{
SDL_Renderer *renderer;
D3D_RenderData *data;
SDL_SysWMinfo windowinfo;
HRESULT result;
D3DPRESENT_PARAMETERS pparams;
IDirect3DSwapChain9 *chain;
@ -1552,22 +1557,15 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_DisplayID displayID;
const SDL_DisplayMode *fullscreen_mode = NULL;
if (SDL_GetWindowWMInfo(window, &windowinfo, SDL_SYSWM_CURRENT_VERSION) < 0 ||
windowinfo.subsystem != SDL_SYSWM_WINDOWS) {
SDL_SetError("Couldn't get window handle");
return NULL;
}
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (renderer == NULL) {
SDL_OutOfMemory();
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
data = (D3D_RenderData *)SDL_calloc(1, sizeof(*data));
if (data == NULL) {
if (!data) {
SDL_free(renderer);
SDL_OutOfMemory();
return NULL;
}
@ -1594,6 +1592,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->QueueDrawPoints = D3D_QueueDrawPoints;
renderer->QueueDrawLines = D3D_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueGeometry = D3D_QueueGeometry;
renderer->InvalidateCachedState = D3D_InvalidateCachedState;
renderer->RunCommandQueue = D3D_RunCommandQueue;
renderer->RenderReadPixels = D3D_RenderReadPixels;
renderer->RenderPresent = D3D_RenderPresent;
@ -1603,6 +1602,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->info = D3D_RenderDriver.info;
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
D3D_InvalidateCachedState(renderer);
SDL_GetWindowSizeInPixels(window, &w, &h);
if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
@ -1610,7 +1610,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags)
}
SDL_zero(pparams);
pparams.hDeviceWindow = windowinfo.info.win.window;
pparams.hDeviceWindow = (HWND)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER, NULL);
pparams.BackBufferWidth = w;
pparams.BackBufferHeight = h;
pparams.BackBufferCount = 1;
@ -1625,7 +1625,7 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags)
pparams.BackBufferFormat = D3DFMT_UNKNOWN;
pparams.FullScreen_RefreshRateInHz = 0;
}
if (flags & SDL_RENDERER_PRESENTVSYNC) {
if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
} else {
pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
@ -1708,10 +1708,8 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, Uint32 flags)
}
}
#endif
data->drawstate.viewport_dirty = SDL_TRUE;
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
data->drawstate.blend = SDL_BLENDMODE_INVALID;
SDL_SetProperty(SDL_GetRendererProperties(renderer), SDL_PROPERTY_RENDERER_D3D9_DEVICE_POINTER, data->device);
return renderer;
}
@ -1726,28 +1724,3 @@ SDL_RenderDriver D3D_RenderDriver = {
0 }
};
#endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
#if defined(__WIN32__) || defined(__WINGDK__)
/* This function needs to always exist on Windows, for the Dynamic API. */
IDirect3DDevice9 *SDL_GetRenderD3D9Device(SDL_Renderer *renderer)
{
IDirect3DDevice9 *device = NULL;
#if defined(SDL_VIDEO_RENDER_D3D) && !defined(SDL_RENDER_DISABLED)
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
/* Make sure that this is a D3D renderer */
if (renderer->DestroyRenderer != D3D_DestroyRenderer) {
SDL_SetError("Renderer is not a D3D renderer");
return NULL;
}
device = data->device;
if (device) {
IDirect3DDevice9_AddRef(device);
}
#endif /* SDL_VIDEO_RENDER_D3D && !SDL_RENDER_DISABLED */
return device;
}
#endif /* defined(__WIN32__) || defined(__WINGDK__) */

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -30,8 +30,6 @@
#include "../SDL_sysrender.h"
#include "../SDL_d3dmath.h"
#include <SDL3/SDL_syswm.h>
#include <d3d11_1.h>
#include "SDL_shaders_d3d11.h"
@ -102,7 +100,6 @@ typedef struct
/* NV12 texture support */
SDL_bool nv12;
ID3D11Texture2D *mainTextureNV;
ID3D11ShaderResourceView *mainTextureResourceViewNV;
Uint8 *pixels;
@ -141,6 +138,7 @@ typedef struct
ID3D11SamplerState *nearestPixelSampler;
ID3D11SamplerState *linearSampler;
D3D_FEATURE_LEVEL featureLevel;
SDL_bool pixelSizeChanged;
/* Rasterizers */
ID3D11RasterizerState *mainRasterizer;
@ -177,7 +175,7 @@ typedef struct
* linker errors in WinRT/UWP builds.)
*/
#ifdef __GNUC__
#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-const-variable"
#endif
@ -192,7 +190,7 @@ static const GUID SDL_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4,
static const GUID SDL_IID_ID3D11DeviceContext1 = { 0xbb2c6faa, 0xb5fb, 0x4082, { 0x8e, 0x6b, 0x38, 0x8b, 0x8c, 0xfa, 0x90, 0xe1 } };
/*static const GUID SDL_IID_ID3D11Debug = { 0x79cf2233, 0x7536, 0x4948, { 0x9d, 0x36, 0x1e, 0x46, 0x92, 0xdc, 0x57, 0x60 } };*/
#ifdef __GNUC__
#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
#pragma GCC diagnostic pop
#endif
@ -208,7 +206,7 @@ Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat)
}
}
static DXGI_FORMAT SDLPixelFormatToDXGIFormat(Uint32 sdlFormat)
static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 sdlFormat)
{
switch (sdlFormat) {
case SDL_PIXELFORMAT_ARGB8888:
@ -217,8 +215,26 @@ static DXGI_FORMAT SDLPixelFormatToDXGIFormat(Uint32 sdlFormat)
return DXGI_FORMAT_B8G8R8X8_UNORM;
case SDL_PIXELFORMAT_YV12:
case SDL_PIXELFORMAT_IYUV:
case SDL_PIXELFORMAT_NV12: /* For the Y texture */
case SDL_PIXELFORMAT_NV21: /* For the Y texture */
return DXGI_FORMAT_R8_UNORM;
case SDL_PIXELFORMAT_NV12:
case SDL_PIXELFORMAT_NV21:
return DXGI_FORMAT_NV12;
default:
return DXGI_FORMAT_UNKNOWN;
}
}
static DXGI_FORMAT SDLPixelFormatToDXGIMainResourceViewFormat(Uint32 sdlFormat)
{
switch (sdlFormat) {
case SDL_PIXELFORMAT_ARGB8888:
return DXGI_FORMAT_B8G8R8A8_UNORM;
case SDL_PIXELFORMAT_XRGB8888:
return DXGI_FORMAT_B8G8R8X8_UNORM;
case SDL_PIXELFORMAT_YV12:
case SDL_PIXELFORMAT_IYUV:
case SDL_PIXELFORMAT_NV12: /* For the Y texture */
case SDL_PIXELFORMAT_NV21: /* For the Y texture */
return DXGI_FORMAT_R8_UNORM;
default:
return DXGI_FORMAT_UNKNOWN;
@ -381,9 +397,8 @@ static ID3D11BlendState *D3D11_CreateBlendState(SDL_Renderer *renderer, SDL_Blen
}
blendModes = (D3D11_BlendMode *)SDL_realloc(data->blendModes, (data->blendModesCount + 1) * sizeof(*blendModes));
if (blendModes == NULL) {
if (!blendModes) {
SAFE_RELEASE(blendState);
SDL_OutOfMemory();
return NULL;
}
blendModes[data->blendModesCount].blendMode = blendMode;
@ -438,7 +453,7 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer)
}
CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY)SDL_LoadFunction(data->hDXGIMod, "CreateDXGIFactory");
if (CreateDXGIFactoryFunc == NULL) {
if (!CreateDXGIFactoryFunc) {
result = E_FAIL;
goto done;
}
@ -650,6 +665,8 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer)
ID3D11DeviceContext_VSSetShader(data->d3dContext, data->vertexShader, NULL, 0);
ID3D11DeviceContext_VSSetConstantBuffers(data->d3dContext, 0, 1, &data->vertexShaderConstants);
SDL_SetProperty(SDL_GetRendererProperties(renderer), SDL_PROPERTY_RENDERER_D3D11_DEVICE_POINTER, data->d3dDevice);
done:
SAFE_RELEASE(d3dDevice);
SAFE_RELEASE(d3dContext);
@ -736,7 +753,7 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
#ifdef __WINRT__
IUnknown *coreWindow = D3D11_GetCoreWindowFromSDLRenderer(renderer);
const BOOL usingXAML = (coreWindow == NULL);
const BOOL usingXAML = (!coreWindow);
#else
IUnknown *coreWindow = NULL;
const BOOL usingXAML = FALSE;
@ -768,7 +785,12 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
}
}
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; /* All Windows Store apps must use this SwapEffect. */
if (SDL_GetWindowFlags(renderer->window) & SDL_WINDOW_TRANSPARENT) {
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
} else {
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; /* All Windows Store apps must use this SwapEffect. */
}
#endif
swapChainDesc.Flags = 0;
@ -807,18 +829,11 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
#endif
} else {
#if defined(__WIN32__) || defined(__WINGDK__)
SDL_SysWMinfo windowinfo;
if (SDL_GetWindowWMInfo(renderer->window, &windowinfo, SDL_SYSWM_CURRENT_VERSION) < 0 ||
windowinfo.subsystem != SDL_SYSWM_WINDOWS) {
SDL_SetError("Couldn't get window handle");
result = E_FAIL;
goto done;
}
HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER, NULL);
result = IDXGIFactory2_CreateSwapChainForHwnd(data->dxgiFactory,
(IUnknown *)data->d3dDevice,
windowinfo.info.win.window,
hwnd,
&swapChainDesc,
NULL,
NULL, /* Allow on all displays. */
@ -828,7 +843,7 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
goto done;
}
IDXGIFactory_MakeWindowAssociation(data->dxgiFactory, windowinfo.info.win.window, DXGI_MWA_NO_WINDOW_CHANGES);
IDXGIFactory_MakeWindowAssociation(data->dxgiFactory, hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
#else
SDL_SetError(__FUNCTION__ ", Unable to find something to attach a swap chain to");
goto done;
@ -850,8 +865,7 @@ static void D3D11_ReleaseMainRenderTargetView(SDL_Renderer *renderer)
static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer *renderer);
HRESULT
D3D11_HandleDeviceLost(SDL_Renderer *renderer)
static HRESULT D3D11_HandleDeviceLost(SDL_Renderer *renderer)
{
HRESULT result = S_OK;
@ -931,7 +945,7 @@ static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
#endif
} else {
result = D3D11_CreateSwapChain(renderer, w, h);
if (FAILED(result) || data->swapChain == NULL) {
if (FAILED(result) || !data->swapChain) {
goto done;
}
}
@ -1027,8 +1041,10 @@ void D3D11_Trim(SDL_Renderer *renderer)
static void D3D11_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event)
{
D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
if (event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) {
D3D11_UpdateForWindowSizeChange(renderer);
data->pixelSizeChanged = SDL_TRUE;
}
}
@ -1050,12 +1066,24 @@ static SDL_bool D3D11_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode bl
return SDL_TRUE;
}
static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int GetTextureProperty(SDL_PropertiesID props, const char *name, ID3D11Texture2D **texture)
{
IUnknown *unknown = SDL_GetProperty(props, name, NULL);
if (unknown) {
HRESULT result = IUnknown_QueryInterface(unknown, &SDL_IID_ID3D11Texture2D, (void **)texture);
if (FAILED(result)) {
return WIN_SetErrorFromHRESULT(name, result);
}
}
return 0;
}
static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
D3D11_TextureData *textureData;
HRESULT result;
DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format);
DXGI_FORMAT textureFormat = SDLPixelFormatToDXGITextureFormat(texture->format);
D3D11_TEXTURE2D_DESC textureDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
@ -1065,8 +1093,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
}
textureData = (D3D11_TextureData *)SDL_calloc(1, sizeof(*textureData));
if (textureData == NULL) {
SDL_OutOfMemory();
if (!textureData) {
return -1;
}
textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
@ -1097,14 +1124,20 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
}
result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
&textureDesc,
NULL,
&textureData->mainTexture);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
if (GetTextureProperty(create_props, "d3d11.texture", &textureData->mainTexture) < 0) {
return -1;
}
if (!textureData->mainTexture) {
result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
&textureDesc,
NULL,
&textureData->mainTexture);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
}
}
SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_POINTER, textureData->mainTexture);
#if SDL_HAVE_YUV
if (texture->format == SDL_PIXELFORMAT_YV12 ||
texture->format == SDL_PIXELFORMAT_IYUV) {
@ -1113,47 +1146,43 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
textureDesc.Width = (textureDesc.Width + 1) / 2;
textureDesc.Height = (textureDesc.Height + 1) / 2;
result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
&textureDesc,
NULL,
&textureData->mainTextureU);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
if (GetTextureProperty(create_props, "d3d11.texture_u", &textureData->mainTextureU) < 0) {
return -1;
}
if (!textureData->mainTextureU) {
result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
&textureDesc,
NULL,
&textureData->mainTextureU);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
}
}
SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_U_POINTER, textureData->mainTextureU);
result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
&textureDesc,
NULL,
&textureData->mainTextureV);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
if (GetTextureProperty(create_props, "d3d11.texture_v", &textureData->mainTextureV) < 0) {
return -1;
}
if (!textureData->mainTextureV) {
result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
&textureDesc,
NULL,
&textureData->mainTextureV);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
}
}
SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D11_TEXTURE_V_POINTER, textureData->mainTextureV);
}
if (texture->format == SDL_PIXELFORMAT_NV12 ||
texture->format == SDL_PIXELFORMAT_NV21) {
D3D11_TEXTURE2D_DESC nvTextureDesc = textureDesc;
textureData->nv12 = SDL_TRUE;
nvTextureDesc.Format = DXGI_FORMAT_R8G8_UNORM;
nvTextureDesc.Width = (textureDesc.Width + 1) / 2;
nvTextureDesc.Height = (textureDesc.Height + 1) / 2;
result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
&nvTextureDesc,
NULL,
&textureData->mainTextureNV);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
}
}
#endif /* SDL_HAVE_YUV */
SDL_zero(resourceViewDesc);
resourceViewDesc.Format = textureDesc.Format;
resourceViewDesc.Format = SDLPixelFormatToDXGIMainResourceViewFormat(texture->format);
resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
resourceViewDesc.Texture2D.MostDetailedMip = 0;
resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
@ -1191,7 +1220,7 @@ static int D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM;
result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
(ID3D11Resource *)textureData->mainTextureNV,
(ID3D11Resource *)textureData->mainTexture,
&nvResourceViewDesc,
&textureData->mainTextureResourceViewNV);
if (FAILED(result)) {
@ -1226,7 +1255,7 @@ static void D3D11_DestroyTexture(SDL_Renderer *renderer,
{
D3D11_TextureData *data = (D3D11_TextureData *)texture->driverdata;
if (data == NULL) {
if (!data) {
return;
}
@ -1239,7 +1268,6 @@ static void D3D11_DestroyTexture(SDL_Renderer *renderer,
SAFE_RELEASE(data->mainTextureResourceViewU);
SAFE_RELEASE(data->mainTextureV);
SAFE_RELEASE(data->mainTextureResourceViewV);
SAFE_RELEASE(data->mainTextureNV);
SAFE_RELEASE(data->mainTextureResourceViewNV);
SDL_free(data->pixels);
#endif
@ -1286,6 +1314,11 @@ static int D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Tex
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
}
if (stagingTextureDesc.Format == DXGI_FORMAT_NV12) {
/* Copy the UV plane as well */
h += (h + 1) / 2;
}
src = (const Uint8 *)pixels;
dst = textureMemory.pData;
length = w * bpp;
@ -1333,7 +1366,7 @@ static int D3D11_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
if (textureData == NULL) {
if (!textureData) {
return SDL_SetError("Texture is not currently available");
}
@ -1355,15 +1388,6 @@ static int D3D11_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
return -1;
}
}
if (textureData->nv12) {
/* Skip to the correct offset into the next texture */
srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch);
if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, srcPixels, 2 * ((srcPitch + 1) / 2)) < 0) {
return -1;
}
}
#endif /* SDL_HAVE_YUV */
return 0;
}
@ -1378,7 +1402,7 @@ static int D3D11_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
if (textureData == NULL) {
if (!textureData) {
return SDL_SetError("Texture is not currently available");
}
@ -1401,18 +1425,110 @@ static int D3D11_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture,
{
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
ID3D11Texture2D *stagingTexture;
const Uint8 *src;
Uint8 *dst;
int w, h, row;
UINT length;
HRESULT result;
D3D11_TEXTURE2D_DESC stagingTextureDesc;
D3D11_MAPPED_SUBRESOURCE textureMemory;
if (textureData == NULL) {
if (!textureData) {
return SDL_SetError("Texture is not currently available");
}
if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
return -1;
w = rect->w;
h = rect->h;
/* Create a 'staging' texture, which will be used to write to a portion of the main texture. */
ID3D11Texture2D_GetDesc(textureData->mainTexture, &stagingTextureDesc);
stagingTextureDesc.Width = w;
stagingTextureDesc.Height = h;
stagingTextureDesc.BindFlags = 0;
stagingTextureDesc.MiscFlags = 0;
stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
&stagingTextureDesc,
NULL,
&stagingTexture);
if (FAILED(result)) {
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
}
if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, UVplane, UVpitch) < 0) {
return -1;
/* Get a write-only pointer to data in the staging texture: */
result = ID3D11DeviceContext_Map(rendererData->d3dContext,
(ID3D11Resource *)stagingTexture,
0,
D3D11_MAP_WRITE,
0,
&textureMemory);
if (FAILED(result)) {
SAFE_RELEASE(stagingTexture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
}
src = Yplane;
dst = textureMemory.pData;
length = w;
if (length == (UINT)Ypitch && length == textureMemory.RowPitch) {
SDL_memcpy(dst, src, (size_t)length * rect->h);
dst += length * rect->h;
} else {
if (length > (UINT)Ypitch) {
length = Ypitch;
}
if (length > textureMemory.RowPitch) {
length = textureMemory.RowPitch;
}
for (row = 0; row < h; ++row) {
SDL_memcpy(dst, src, length);
src += Ypitch;
dst += textureMemory.RowPitch;
}
}
/* Adjust dimensions for the UV plane */
w = ((w + 1) / 2) * 2;
h = ((h + 1) / 2);
src = UVplane;
length = w;
if (length == (UINT)UVpitch && length == textureMemory.RowPitch) {
SDL_memcpy(dst, src, (size_t)length * h);
} else {
if (length > (UINT)UVpitch) {
length = UVpitch;
}
if (length > textureMemory.RowPitch) {
length = textureMemory.RowPitch;
}
for (row = 0; row < h; ++row) {
SDL_memcpy(dst, src, length);
src += UVpitch;
dst += textureMemory.RowPitch;
}
}
/* Commit the pixel buffer's changes back to the staging texture: */
ID3D11DeviceContext_Unmap(rendererData->d3dContext,
(ID3D11Resource *)stagingTexture,
0);
/* Copy the staging texture's contents back to the texture: */
ID3D11DeviceContext_CopySubresourceRegion(rendererData->d3dContext,
(ID3D11Resource *)textureData->mainTexture,
0,
rect->x,
rect->y,
0,
(ID3D11Resource *)stagingTexture,
0,
NULL);
SAFE_RELEASE(stagingTexture);
return 0;
}
#endif
@ -1426,7 +1542,7 @@ static int D3D11_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
D3D11_TEXTURE2D_DESC stagingTextureDesc;
D3D11_MAPPED_SUBRESOURCE textureMemory;
if (textureData == NULL) {
if (!textureData) {
return SDL_SetError("Texture is not currently available");
}
#if SDL_HAVE_YUV
@ -1436,7 +1552,7 @@ static int D3D11_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
textureData->pitch = texture->w;
textureData->pixels = (Uint8 *)SDL_malloc((texture->h * textureData->pitch * 3) / 2);
if (!textureData->pixels) {
return SDL_OutOfMemory();
return -1;
}
}
textureData->locked_rect = *rect;
@ -1505,7 +1621,7 @@ static void D3D11_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
if (textureData == NULL) {
if (!textureData) {
return;
}
#if SDL_HAVE_YUV
@ -1541,7 +1657,7 @@ static void D3D11_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *textu
{
D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
if (textureData == NULL) {
if (!textureData) {
return;
}
@ -1553,7 +1669,7 @@ static int D3D11_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
D3D11_TextureData *textureData = NULL;
if (texture == NULL) {
if (!texture) {
rendererData->currentOffscreenRenderTargetView = NULL;
return 0;
}
@ -1584,7 +1700,7 @@ static int D3D11_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
color.b = cmd->data.draw.b;
color.a = cmd->data.draw.a;
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -1611,7 +1727,7 @@ static int D3D11_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S
int count = indices ? num_indices : num_vertices;
VertexPositionColor *verts = (VertexPositionColor *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertexPositionColor), 0, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -1883,9 +1999,9 @@ static int D3D11_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *c
break;
}
}
if (blendState == NULL) {
if (!blendState) {
blendState = D3D11_CreateBlendState(renderer, blendMode);
if (blendState == NULL) {
if (!blendState) {
return -1;
}
}
@ -2006,11 +2122,29 @@ static void D3D11_DrawPrimitives(SDL_Renderer *renderer, D3D11_PRIMITIVE_TOPOLOG
ID3D11DeviceContext_Draw(rendererData->d3dContext, (UINT)vertexCount, (UINT)vertexStart);
}
static void D3D11_InvalidateCachedState(SDL_Renderer *renderer)
{
D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
data->currentRenderTargetView = NULL;
data->currentRasterizerState = NULL;
data->currentBlendState = NULL;
data->currentShader = NULL;
data->currentShaderResource = NULL;
data->currentSampler = NULL;
data->cliprectDirty = SDL_TRUE;
data->viewportDirty = SDL_TRUE;
}
static int D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->driverdata;
const int viewportRotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
if (rendererData->pixelSizeChanged) {
D3D11_UpdateForWindowSizeChange(renderer);
rendererData->pixelSizeChanged = SDL_FALSE;
}
if (rendererData->currentViewportRotation != viewportRotation) {
rendererData->currentViewportRotation = viewportRotation;
rendererData->viewportDirty = SDL_TRUE;
@ -2138,13 +2272,13 @@ static int D3D11_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
D3D11_MAPPED_SUBRESOURCE textureMemory;
renderTargetView = D3D11_GetCurrentRenderTargetView(renderer);
if (renderTargetView == NULL) {
if (!renderTargetView) {
SDL_SetError("%s, ID3D11DeviceContext::OMGetRenderTargets failed", __FUNCTION__);
goto done;
}
ID3D11View_GetResource(renderTargetView, (ID3D11Resource **)&backBuffer);
if (backBuffer == NULL) {
if (!backBuffer) {
SDL_SetError("%s, ID3D11View::GetResource failed", __FUNCTION__);
goto done;
}
@ -2293,21 +2427,20 @@ static int D3D11_SetVSync(SDL_Renderer *renderer, const int vsync)
}
#endif
SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props)
{
SDL_Renderer *renderer;
D3D11_RenderData *data;
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (renderer == NULL) {
SDL_OutOfMemory();
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
data = (D3D11_RenderData *)SDL_calloc(1, sizeof(*data));
if (data == NULL) {
if (!data) {
SDL_free(renderer);
SDL_OutOfMemory();
return NULL;
}
@ -2330,6 +2463,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->QueueDrawPoints = D3D11_QueueDrawPoints;
renderer->QueueDrawLines = D3D11_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueGeometry = D3D11_QueueGeometry;
renderer->InvalidateCachedState = D3D11_InvalidateCachedState;
renderer->RunCommandQueue = D3D11_RunCommandQueue;
renderer->RenderReadPixels = D3D11_RenderReadPixels;
renderer->RenderPresent = D3D11_RenderPresent;
@ -2338,6 +2472,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->info = D3D11_RenderDriver.info;
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
D3D11_InvalidateCachedState(renderer);
#if SDL_WINAPI_FAMILY_PHONE
/* VSync is required in Windows Phone, at least for Win Phone 8.0 and 8.1.
@ -2353,7 +2488,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, Uint32 flags)
*/
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
#else
if (flags & SDL_RENDERER_PRESENTVSYNC) {
if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
renderer->SetVSync = D3D11_SetVSync;
@ -2397,28 +2532,3 @@ SDL_RenderDriver D3D11_RenderDriver = {
};
#endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */
#if defined(__WIN32__) || defined(__WINGDK__)
/* This function needs to always exist on Windows, for the Dynamic API. */
ID3D11Device *SDL_GetRenderD3D11Device(SDL_Renderer *renderer)
{
ID3D11Device *device = NULL;
#if defined(SDL_VIDEO_RENDER_D3D11) && !defined(SDL_RENDER_DISABLED)
D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
/* Make sure that this is a D3D renderer */
if (renderer->DestroyRenderer != D3D11_DestroyRenderer) {
SDL_SetError("Renderer is not a D3D11 renderer");
return NULL;
}
device = (ID3D11Device *)data->d3dDevice;
if (device) {
ID3D11Device_AddRef(device);
}
#endif /* SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED */
return device;
}
#endif /* defined(__WIN32__) || defined(__WINGDK__) */

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -39,35 +39,14 @@ using namespace Windows::Graphics::Display;
#include <DXGI.h>
#include <SDL3/SDL_syswm.h>
#include "SDL_render_winrt.h"
extern "C" void *
D3D11_GetCoreWindowFromSDLRenderer(SDL_Renderer *renderer)
{
SDL_Window *sdlWindow = renderer->window;
if (renderer->window == NULL) {
return NULL;
}
SDL_SysWMinfo sdlWindowInfo;
if (SDL_GetWindowWMInfo(sdlWindow, &sdlWindowInfo, SDL_SYSWM_CURRENT_VERSION) < 0 ||
sdlWindowInfo.subsystem != SDL_SYSWM_WINRT) {
SDL_SetError("Couldn't get window handle");
return NULL;
}
if (sdlWindowInfo.subsystem != SDL_SYSWM_WINRT) {
return NULL;
}
if (!sdlWindowInfo.info.winrt.window) {
return NULL;
}
IInspectable *window = (IInspectable *)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), SDL_PROPERTY_WINDOW_WINRT_WINDOW_POINTER, NULL);
ABI::Windows::UI::Core::ICoreWindow *coreWindow = NULL;
if (FAILED(sdlWindowInfo.info.winrt.window->QueryInterface(&coreWindow))) {
if (!window || FAILED(window->QueryInterface(&coreWindow))) {
return NULL;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -32,8 +32,6 @@
#include "../SDL_sysrender.h"
#include "../SDL_d3dmath.h"
#include <SDL3/SDL_syswm.h>
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
#include "SDL_render_d3d12_xbox.h"
#ifndef D3D12_TEXTURE_DATA_PITCH_ALIGNMENT
@ -123,9 +121,7 @@ typedef struct
/* NV12 texture support */
SDL_bool nv12;
ID3D12Resource *mainTextureNV;
D3D12_CPU_DESCRIPTOR_HANDLE mainTextureResourceViewNV;
D3D12_RESOURCE_STATES mainResourceStateNV;
SIZE_T mainSRVIndexNV;
Uint8 *pixels;
@ -178,6 +174,7 @@ typedef struct
ID3D12GraphicsCommandList2 *commandList;
DXGI_SWAP_EFFECT swapEffect;
UINT swapFlags;
SDL_bool pixelSizeChanged;
/* Descriptor heaps */
ID3D12DescriptorHeap *rtvDescriptorHeap;
@ -238,7 +235,7 @@ typedef struct
/* Define D3D GUIDs here so we don't have to include uuid.lib. */
#if defined(__GNUC__) || defined(__clang__)
#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-const-variable"
#endif
@ -263,7 +260,7 @@ static const GUID SDL_IID_ID3D12PipelineState = { 0x765a30f3, 0xf624, 0x4c6f, {
static const GUID SDL_IID_ID3D12Heap = { 0x6b3b2502, 0x6e51, 0x45b3, { 0x90, 0xee, 0x98, 0x84, 0x26, 0x5e, 0x8d, 0xf3 } };
static const GUID SDL_IID_ID3D12InfoQueue = { 0x0742a90b, 0xc387, 0x483f, { 0xb9, 0x46, 0x30, 0xa7, 0xe4, 0xe6, 0x14, 0x58 } };
#if defined(__GNUC__) || defined(__clang__)
#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
#pragma GCC diagnostic pop
#endif
@ -284,7 +281,25 @@ Uint32 D3D12_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat)
}
}
static DXGI_FORMAT SDLPixelFormatToDXGIFormat(Uint32 sdlFormat)
static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 sdlFormat)
{
switch (sdlFormat) {
case SDL_PIXELFORMAT_ARGB8888:
return DXGI_FORMAT_B8G8R8A8_UNORM;
case SDL_PIXELFORMAT_XRGB8888:
return DXGI_FORMAT_B8G8R8X8_UNORM;
case SDL_PIXELFORMAT_YV12:
case SDL_PIXELFORMAT_IYUV:
return DXGI_FORMAT_R8_UNORM;
case SDL_PIXELFORMAT_NV12:
case SDL_PIXELFORMAT_NV21:
return DXGI_FORMAT_NV12;
default:
return DXGI_FORMAT_UNKNOWN;
}
}
static DXGI_FORMAT SDLPixelFormatToDXGIMainResourceViewFormat(Uint32 sdlFormat)
{
switch (sdlFormat) {
case SDL_PIXELFORMAT_ARGB8888:
@ -308,6 +323,10 @@ static void D3D12_ReleaseAll(SDL_Renderer *renderer)
D3D12_RenderData *data = (D3D12_RenderData *)renderer->driverdata;
SDL_Texture *texture = NULL;
SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
SDL_SetProperty(props, SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER, NULL);
SDL_SetProperty(props, SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER, NULL);
/* Release all textures */
for (texture = renderer->textures; texture; texture = texture->next) {
D3D12_DestroyTexture(renderer, texture);
@ -461,6 +480,7 @@ static void D3D12_ResetCommandList(D3D12_RenderData *data)
data->cliprectDirty = SDL_TRUE;
data->viewportDirty = SDL_TRUE;
data->currentRenderTargetView.ptr = 0;
/* FIXME should we also clear currentSampler.ptr and currentRenderTargetView.ptr ? (and use D3D12_InvalidateCachedState() instead) */
/* Release any upload buffers that were inflight */
for (i = 0; i < data->currentUploadBuffer; ++i) {
@ -623,9 +643,8 @@ static D3D12_PipelineState *D3D12_CreatePipelineState(SDL_Renderer *renderer,
}
pipelineStates = (D3D12_PipelineState *)SDL_realloc(data->pipelineStates, (data->pipelineStateCount + 1) * sizeof(*pipelineStates));
if (pipelineStates == NULL) {
if (!pipelineStates) {
SAFE_RELEASE(pipelineState);
SDL_OutOfMemory();
return NULL;
}
@ -703,7 +722,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
HRESULT result = S_OK;
UINT creationFlags = 0;
int i, j, k, l;
SDL_bool createDebug = SDL_FALSE;
SDL_bool createDebug;
D3D12_COMMAND_QUEUE_DESC queueDesc;
D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc;
@ -738,7 +757,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
}
}
#endif
if (CreateEventExFunc == NULL) {
if (!CreateEventExFunc) {
result = E_FAIL;
goto done;
}
@ -751,7 +770,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
}
CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY)SDL_LoadFunction(data->hDXGIMod, "CreateDXGIFactory2");
if (CreateDXGIFactoryFunc == NULL) {
if (!CreateDXGIFactoryFunc) {
result = E_FAIL;
goto done;
}
@ -776,8 +795,9 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
result = E_FAIL;
goto done;
}
D3D12GetDebugInterfaceFunc(D3D_GUID(SDL_IID_ID3D12Debug), (void **)&data->debugInterface);
D3D_CALL(data->debugInterface, EnableDebugLayer);
if (SUCCEEDED(D3D12GetDebugInterfaceFunc(D3D_GUID(SDL_IID_ID3D12Debug), (void **)&data->debugInterface))) {
D3D_CALL(data->debugInterface, EnableDebugLayer);
}
}
#endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/
@ -795,7 +815,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
/* If the debug hint is set, also create the DXGI factory in debug mode */
DXGIGetDebugInterfaceFunc = (PFN_CREATE_DXGI_FACTORY)SDL_LoadFunction(data->hDXGIMod, "DXGIGetDebugInterface1");
if (DXGIGetDebugInterfaceFunc == NULL) {
if (!DXGIGetDebugInterfaceFunc) {
result = E_FAIL;
goto done;
}
@ -1052,6 +1072,11 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
}
}
data->srvPoolHead = &data->srvPoolNodes[0];
SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
SDL_SetProperty(props, SDL_PROPERTY_RENDERER_D3D12_DEVICE_POINTER, data->d3dDevice);
SDL_SetProperty(props, SDL_PROPERTY_RENDERER_D3D12_COMMAND_QUEUE_POINTER, data->commandQueue);
done:
SAFE_RELEASE(d3dDevice);
return result;
@ -1133,7 +1158,6 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
D3D12_RenderData *data = (D3D12_RenderData *)renderer->driverdata;
IDXGISwapChain1 *swapChain = NULL;
HRESULT result = S_OK;
SDL_SysWMinfo windowinfo;
/* Create a swap chain using the same adapter as the existing Direct3D device. */
DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
@ -1155,16 +1179,11 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT | /* To support SetMaximumFrameLatency */
DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; /* To support presenting with allow tearing on */
if (SDL_GetWindowWMInfo(renderer->window, &windowinfo, SDL_SYSWM_CURRENT_VERSION) < 0 ||
windowinfo.subsystem != SDL_SYSWM_WINDOWS) {
SDL_SetError("Couldn't get window handle");
result = E_FAIL;
goto done;
}
HWND hwnd = (HWND)SDL_GetProperty(SDL_GetWindowProperties(renderer->window), SDL_PROPERTY_WINDOW_WIN32_HWND_POINTER, NULL);
result = D3D_CALL(data->dxgiFactory, CreateSwapChainForHwnd,
(IUnknown *)data->commandQueue,
windowinfo.info.win.window,
hwnd,
&swapChainDesc,
NULL,
NULL, /* Allow on all displays. */
@ -1174,7 +1193,7 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
goto done;
}
D3D_CALL(data->dxgiFactory, MakeWindowAssociation, windowinfo.info.win.window, DXGI_MWA_NO_WINDOW_CHANGES);
D3D_CALL(data->dxgiFactory, MakeWindowAssociation, hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
result = D3D_CALL(swapChain, QueryInterface, D3D_GUID(SDL_IID_IDXGISwapChain4), (void **)&data->swapChain);
if (FAILED(result)) {
@ -1284,7 +1303,7 @@ static HRESULT D3D12_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
}
} else {
result = D3D12_CreateSwapChain(renderer, w, h);
if (FAILED(result)) {
if (FAILED(result) || !data->swapChain) {
goto done;
}
}
@ -1369,8 +1388,10 @@ static HRESULT D3D12_UpdateForWindowSizeChange(SDL_Renderer *renderer)
static void D3D12_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event)
{
D3D12_RenderData *data = (D3D12_RenderData *)renderer->driverdata;
if (event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) {
D3D12_UpdateForWindowSizeChange(renderer);
data->pixelSizeChanged = SDL_TRUE;
}
}
@ -1412,12 +1433,24 @@ static void D3D12_FreeSRVIndex(SDL_Renderer *renderer, SIZE_T index)
rendererData->srvPoolHead = &rendererData->srvPoolNodes[index];
}
static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int GetTextureProperty(SDL_PropertiesID props, const char *name, ID3D12Resource **texture)
{
IUnknown *unknown = (IUnknown*)SDL_GetProperty(props, name, NULL);
if (unknown) {
HRESULT result = D3D_CALL(unknown, QueryInterface, D3D_GUID(SDL_IID_ID3D12Resource), (void **)texture);
if (FAILED(result)) {
return WIN_SetErrorFromHRESULT(name, result);
}
}
return 0;
}
static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata;
D3D12_TextureData *textureData;
HRESULT result;
DXGI_FORMAT textureFormat = SDLPixelFormatToDXGIFormat(texture->format);
DXGI_FORMAT textureFormat = SDLPixelFormatToDXGITextureFormat(texture->format);
D3D12_RESOURCE_DESC textureDesc;
D3D12_HEAP_PROPERTIES heapProps;
D3D12_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
@ -1427,8 +1460,7 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
}
textureData = (D3D12_TextureData *)SDL_calloc(1, sizeof(*textureData));
if (textureData == NULL) {
SDL_OutOfMemory();
if (!textureData) {
return -1;
}
textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3D12_FILTER_MIN_MAG_MIP_POINT : D3D12_FILTER_MIN_MAG_MIP_LINEAR;
@ -1456,19 +1488,25 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
heapProps.CreationNodeMask = 1;
heapProps.VisibleNodeMask = 1;
result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource,
&heapProps,
D3D12_HEAP_FLAG_NONE,
&textureDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
NULL,
D3D_GUID(SDL_IID_ID3D12Resource),
(void **)&textureData->mainTexture);
textureData->mainResourceState = D3D12_RESOURCE_STATE_COPY_DEST;
if (FAILED(result)) {
D3D12_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result);
if (GetTextureProperty(create_props, "d3d12.texture", &textureData->mainTexture) < 0) {
return -1;
}
if (!textureData->mainTexture) {
result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource,
&heapProps,
D3D12_HEAP_FLAG_NONE,
&textureDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
NULL,
D3D_GUID(SDL_IID_ID3D12Resource),
(void **)&textureData->mainTexture);
if (FAILED(result)) {
D3D12_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result);
}
}
textureData->mainResourceState = D3D12_RESOURCE_STATE_COPY_DEST;
SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_POINTER, textureData->mainTexture);
#if SDL_HAVE_YUV
if (texture->format == SDL_PIXELFORMAT_YV12 ||
texture->format == SDL_PIXELFORMAT_IYUV) {
@ -1477,65 +1515,56 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
textureDesc.Width = (textureDesc.Width + 1) / 2;
textureDesc.Height = (textureDesc.Height + 1) / 2;
result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource,
&heapProps,
D3D12_HEAP_FLAG_NONE,
&textureDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
NULL,
D3D_GUID(SDL_IID_ID3D12Resource),
(void **)&textureData->mainTextureU);
if (GetTextureProperty(create_props, "d3d12.texture_u", &textureData->mainTextureU) < 0) {
return -1;
}
if (!textureData->mainTextureU) {
result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource,
&heapProps,
D3D12_HEAP_FLAG_NONE,
&textureDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
NULL,
D3D_GUID(SDL_IID_ID3D12Resource),
(void **)&textureData->mainTextureU);
if (FAILED(result)) {
D3D12_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result);
}
}
textureData->mainResourceStateU = D3D12_RESOURCE_STATE_COPY_DEST;
if (FAILED(result)) {
D3D12_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result);
}
SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_U_POINTER, textureData->mainTextureU);
result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource,
&heapProps,
D3D12_HEAP_FLAG_NONE,
&textureDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
NULL,
D3D_GUID(SDL_IID_ID3D12Resource),
(void **)&textureData->mainTextureV);
textureData->mainResourceStateV = D3D12_RESOURCE_STATE_COPY_DEST;
if (FAILED(result)) {
D3D12_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result);
if (GetTextureProperty(create_props, "d3d12.texture_v", &textureData->mainTextureV) < 0) {
return -1;
}
if (!textureData->mainTextureV) {
result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource,
&heapProps,
D3D12_HEAP_FLAG_NONE,
&textureDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
NULL,
D3D_GUID(SDL_IID_ID3D12Resource),
(void **)&textureData->mainTextureV);
if (FAILED(result)) {
D3D12_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateCommittedResource [texture]"), result);
}
}
textureData->mainResourceStateV = D3D12_RESOURCE_STATE_COPY_DEST;
SDL_SetProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_D3D12_TEXTURE_V_POINTER, textureData->mainTextureV);
}
if (texture->format == SDL_PIXELFORMAT_NV12 ||
texture->format == SDL_PIXELFORMAT_NV21) {
D3D12_RESOURCE_DESC nvTextureDesc = textureDesc;
textureData->nv12 = SDL_TRUE;
nvTextureDesc.Format = DXGI_FORMAT_R8G8_UNORM;
nvTextureDesc.Width = (textureDesc.Width + 1) / 2;
nvTextureDesc.Height = (textureDesc.Height + 1) / 2;
result = D3D_CALL(rendererData->d3dDevice, CreateCommittedResource,
&heapProps,
D3D12_HEAP_FLAG_NONE,
&nvTextureDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
NULL,
D3D_GUID(SDL_IID_ID3D12Resource),
(void **)&textureData->mainTextureNV);
textureData->mainResourceStateNV = D3D12_RESOURCE_STATE_COPY_DEST;
if (FAILED(result)) {
D3D12_DestroyTexture(renderer, texture);
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateTexture2D"), result);
}
}
#endif /* SDL_HAVE_YUV */
SDL_zero(resourceViewDesc);
resourceViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
resourceViewDesc.Format = textureDesc.Format;
resourceViewDesc.Format = SDLPixelFormatToDXGIMainResourceViewFormat(texture->format);
resourceViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
resourceViewDesc.Texture2D.MostDetailedMip = 0;
resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
textureData->mainSRVIndex = D3D12_GetAvailableSRVIndex(renderer);
@ -1569,12 +1598,13 @@ static int D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
D3D12_SHADER_RESOURCE_VIEW_DESC nvResourceViewDesc = resourceViewDesc;
nvResourceViewDesc.Format = DXGI_FORMAT_R8G8_UNORM;
nvResourceViewDesc.Texture2D.PlaneSlice = 1;
D3D_CALL_RET(rendererData->srvDescriptorHeap, GetCPUDescriptorHandleForHeapStart, &textureData->mainTextureResourceViewNV);
textureData->mainSRVIndexNV = D3D12_GetAvailableSRVIndex(renderer);
textureData->mainTextureResourceViewNV.ptr += textureData->mainSRVIndexNV * rendererData->srvDescriptorSize;
D3D_CALL(rendererData->d3dDevice, CreateShaderResourceView,
textureData->mainTextureNV,
textureData->mainTexture,
&nvResourceViewDesc,
textureData->mainTextureResourceViewNV);
}
@ -1605,7 +1635,7 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer,
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata;
D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata;
if (textureData == NULL) {
if (!textureData) {
return;
}
@ -1623,8 +1653,7 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer,
D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexU);
D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexV);
}
SAFE_RELEASE(textureData->mainTextureNV);
if (textureData->yuv) {
if (textureData->nv12) {
D3D12_FreeSRVIndex(renderer, textureData->mainSRVIndexNV);
}
SDL_free(textureData->pixels);
@ -1633,22 +1662,22 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer,
texture->driverdata = NULL;
}
static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Resource *texture, int bpp, int x, int y, int w, int h, const void *pixels, int pitch, D3D12_RESOURCE_STATES *resourceState)
static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Resource *texture, int plane, int x, int y, int w, int h, const void *pixels, int pitch, D3D12_RESOURCE_STATES *resourceState)
{
const Uint8 *src;
Uint8 *dst;
int row;
UINT length;
HRESULT result;
D3D12_RESOURCE_DESC textureDesc;
D3D12_RESOURCE_DESC uploadDesc;
D3D12_HEAP_PROPERTIES heapProps;
D3D12_SUBRESOURCE_FOOTPRINT pitchedDesc;
D3D12_PLACED_SUBRESOURCE_FOOTPRINT placedTextureDesc;
D3D12_TEXTURE_COPY_LOCATION srcLocation;
D3D12_TEXTURE_COPY_LOCATION dstLocation;
BYTE *textureMemory;
ID3D12Resource *uploadBuffer;
UINT row, NumRows, RowPitch;
UINT64 RowLength;
/* Create an upload buffer, which will be used to write to the main texture. */
SDL_zero(textureDesc);
@ -1671,13 +1700,14 @@ static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Res
/* Figure out how much we need to allocate for the upload buffer */
D3D_CALL(rendererData->d3dDevice, GetCopyableFootprints,
&textureDesc,
0,
plane,
1,
0,
NULL,
NULL,
NULL,
&placedTextureDesc,
&NumRows,
&RowLength,
&uploadDesc.Width);
RowPitch = placedTextureDesc.Footprint.RowPitch;
SDL_zero(heapProps);
heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
@ -1708,33 +1738,22 @@ static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Res
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Resource::Map [map staging texture]"), result);
}
SDL_zero(pitchedDesc);
pitchedDesc.Format = textureDesc.Format;
pitchedDesc.Width = w;
pitchedDesc.Height = h;
pitchedDesc.Depth = 1;
pitchedDesc.RowPitch = D3D12_Align(w * bpp, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
SDL_zero(placedTextureDesc);
placedTextureDesc.Offset = 0;
placedTextureDesc.Footprint = pitchedDesc;
src = (const Uint8 *)pixels;
dst = textureMemory;
length = w * bpp;
if (length == (UINT)pitch && length == pitchedDesc.RowPitch) {
SDL_memcpy(dst, src, (size_t)length * h);
length = (UINT)RowLength;
if (length == (UINT)pitch && length == RowPitch) {
SDL_memcpy(dst, src, (size_t)length * NumRows);
} else {
if (length > (UINT)pitch) {
length = pitch;
}
if (length > pitchedDesc.RowPitch) {
length = pitchedDesc.RowPitch;
if (length > RowPitch) {
length = RowPitch;
}
for (row = 0; row < h; ++row) {
for (row = NumRows; row--; ) {
SDL_memcpy(dst, src, length);
src += pitch;
dst += pitchedDesc.RowPitch;
dst += RowPitch;
}
}
@ -1748,7 +1767,7 @@ static int D3D12_UpdateTextureInternal(D3D12_RenderData *rendererData, ID3D12Res
SDL_zero(dstLocation);
dstLocation.pResource = texture;
dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
dstLocation.SubresourceIndex = 0;
dstLocation.SubresourceIndex = plane;
SDL_zero(srcLocation);
srcLocation.pResource = rendererData->uploadBuffers[rendererData->currentUploadBuffer];
@ -1783,11 +1802,11 @@ static int D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata;
D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata;
if (textureData == NULL) {
if (!textureData) {
return SDL_SetError("Texture is not currently available");
}
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch, &textureData->mainResourceState) < 0) {
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch, &textureData->mainResourceState) < 0) {
return -1;
}
#if SDL_HAVE_YUV
@ -1795,13 +1814,13 @@ static int D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
/* Skip to the correct offset into the next texture */
srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch);
if (D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureV : textureData->mainTextureU, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateV : &textureData->mainResourceStateU) < 0) {
if (D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureV : textureData->mainTextureU, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateV : &textureData->mainResourceStateU) < 0) {
return -1;
}
/* Skip to the correct offset into the next texture */
srcPixels = (const void *)((const Uint8 *)srcPixels + ((rect->h + 1) / 2) * ((srcPitch + 1) / 2));
if (D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureU : textureData->mainTextureV, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateU : &textureData->mainResourceStateV) < 0) {
if (D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureU : textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateU : &textureData->mainResourceStateV) < 0) {
return -1;
}
}
@ -1810,7 +1829,7 @@ static int D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
/* Skip to the correct offset into the next texture */
srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch);
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, srcPixels, 2 * ((srcPitch + 1) / 2), &textureData->mainResourceStateNV) < 0) {
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 1, rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch, &textureData->mainResourceState) < 0) {
return -1;
}
}
@ -1828,17 +1847,17 @@ static int D3D12_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata;
D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata;
if (textureData == NULL) {
if (!textureData) {
return SDL_SetError("Texture is not currently available");
}
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState) < 0) {
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState) < 0) {
return -1;
}
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureU, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch, &textureData->mainResourceStateU) < 0) {
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureU, 0, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch, &textureData->mainResourceStateU) < 0) {
return -1;
}
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch, &textureData->mainResourceStateV) < 0) {
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch, &textureData->mainResourceStateV) < 0) {
return -1;
}
return 0;
@ -1852,15 +1871,15 @@ static int D3D12_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture,
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata;
D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata;
if (textureData == NULL) {
if (!textureData) {
return SDL_SetError("Texture is not currently available");
}
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState) < 0) {
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState) < 0) {
return -1;
}
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureNV, 2, rect->x / 2, rect->y / 2, ((rect->w + 1) / 2), (rect->h + 1) / 2, UVplane, UVpitch, &textureData->mainResourceStateNV) < 0) {
if (D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 1, rect->x, rect->y, rect->w, rect->h, UVplane, UVpitch, &textureData->mainResourceState) < 0) {
return -1;
}
return 0;
@ -1881,7 +1900,7 @@ static int D3D12_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
BYTE *textureMemory;
int bpp;
if (textureData == NULL) {
if (!textureData) {
return SDL_SetError("Texture is not currently available");
}
#if SDL_HAVE_YUV
@ -1891,7 +1910,7 @@ static int D3D12_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
textureData->pitch = texture->w;
textureData->pixels = (Uint8 *)SDL_malloc((texture->h * textureData->pitch * 3) / 2);
if (!textureData->pixels) {
return SDL_OutOfMemory();
return -1;
}
}
textureData->lockedRect = *rect;
@ -2000,7 +2019,7 @@ static void D3D12_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
D3D12_TEXTURE_COPY_LOCATION dstLocation;
int bpp;
if (textureData == NULL) {
if (!textureData) {
return;
}
#if SDL_HAVE_YUV
@ -2071,7 +2090,7 @@ static void D3D12_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *textu
{
D3D12_TextureData *textureData = (D3D12_TextureData *)texture->driverdata;
if (textureData == NULL) {
if (!textureData) {
return;
}
@ -2083,7 +2102,7 @@ static int D3D12_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata;
D3D12_TextureData *textureData = NULL;
if (texture == NULL) {
if (!texture) {
if (rendererData->textureRenderTarget) {
D3D12_TransitionResource(rendererData,
rendererData->textureRenderTarget->mainTexture,
@ -2126,7 +2145,7 @@ static int D3D12_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
color.b = cmd->data.draw.b;
color.a = cmd->data.draw.a;
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -2153,7 +2172,7 @@ static int D3D12_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S
int count = indices ? num_indices : num_vertices;
VertexPositionColor *verts = (VertexPositionColor *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertexPositionColor), 0, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -2550,8 +2569,6 @@ static int D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c
/* Make sure each texture is in the correct state to be accessed by the pixel shader. */
D3D12_TransitionResource(rendererData, textureData->mainTexture, textureData->mainResourceState, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
textureData->mainResourceState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
D3D12_TransitionResource(rendererData, textureData->mainTextureNV, textureData->mainResourceStateNV, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
textureData->mainResourceStateNV = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
return D3D12_SetDrawState(renderer, cmd, shader, D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, SDL_arraysize(shaderResources), shaderResources,
textureSampler, matrix);
@ -2570,11 +2587,26 @@ static void D3D12_DrawPrimitives(SDL_Renderer *renderer, D3D12_PRIMITIVE_TOPOLOG
D3D_CALL(rendererData->commandList, DrawInstanced, (UINT)vertexCount, 1, (UINT)vertexStart, 0);
}
static void D3D12_InvalidateCachedState(SDL_Renderer *renderer)
{
D3D12_RenderData *data = (D3D12_RenderData *)renderer->driverdata;
data->currentRenderTargetView.ptr = 0;
data->currentShaderResource.ptr = 0;
data->currentSampler.ptr = 0;
data->cliprectDirty = SDL_TRUE;
data->viewportDirty = SDL_TRUE;
}
static int D3D12_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->driverdata;
const int viewportRotation = D3D12_GetRotationForCurrentRenderTarget(renderer);
if (rendererData->pixelSizeChanged) {
D3D12_UpdateForWindowSizeChange(renderer);
rendererData->pixelSizeChanged = SDL_FALSE;
}
if (rendererData->currentViewportRotation != viewportRotation) {
rendererData->currentViewportRotation = viewportRotation;
rendererData->viewportDirty = SDL_TRUE;
@ -2948,21 +2980,20 @@ static int D3D12_SetVSync(SDL_Renderer *renderer, const int vsync)
return 0;
}
SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props)
{
SDL_Renderer *renderer;
D3D12_RenderData *data;
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (renderer == NULL) {
SDL_OutOfMemory();
if (!renderer) {
return NULL;
}
renderer->magic = &SDL_renderer_magic;
data = (D3D12_RenderData *)SDL_calloc(1, sizeof(*data));
if (data == NULL) {
if (!data) {
SDL_free(renderer);
SDL_OutOfMemory();
return NULL;
}
@ -2985,6 +3016,7 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->QueueDrawPoints = D3D12_QueueDrawPoints;
renderer->QueueDrawLines = D3D12_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueGeometry = D3D12_QueueGeometry;
renderer->InvalidateCachedState = D3D12_InvalidateCachedState;
renderer->RunCommandQueue = D3D12_RunCommandQueue;
renderer->RenderReadPixels = D3D12_RenderReadPixels;
renderer->RenderPresent = D3D12_RenderPresent;
@ -2993,8 +3025,9 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->info = D3D12_RenderDriver.info;
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
D3D12_InvalidateCachedState(renderer);
if (flags & SDL_RENDERER_PRESENTVSYNC) {
if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
renderer->SetVSync = D3D12_SetVSync;
@ -3042,32 +3075,3 @@ SDL_RenderDriver D3D12_RenderDriver = {
#endif
#endif /* SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED */
#if defined(__WIN32__) || defined(__GDK__)
#ifdef __cplusplus
extern "C"
#endif
/* This function needs to always exist on Windows, for the Dynamic API. */
ID3D12Device *
SDL_RenderGetD3D12Device(SDL_Renderer *renderer)
{
ID3D12Device *device = NULL;
#if defined(SDL_VIDEO_RENDER_D3D12) && !defined(SDL_RENDER_DISABLED)
D3D12_RenderData *data = (D3D12_RenderData *)renderer->driverdata;
/* Make sure that this is a D3D renderer */
if (renderer->DestroyRenderer != D3D12_DestroyRenderer) {
SDL_SetError("Renderer is not a D3D12 renderer");
return NULL;
}
device = (ID3D12Device *)data->d3dDevice;
if (device) {
D3D_CALL(device, AddRef);
}
#endif /* SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED */
return device;
}
#endif /* defined(__WIN32__) || defined(__GDK__) */

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -19,9 +19,156 @@
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#if defined(SDL_VIDEO_RENDER_D3D12) && !defined(SDL_RENDER_DISABLED) && (defined(__XBOXONE__) || defined(__XBOXSERIES__))
#include "../../SDL_internal.h"
#if SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED && (defined(__XBOXONE__) || defined(__XBOXSERIES__))
#include "SDL_render_d3d12_xbox.h"
#include "../../core/windows/SDL_windows.h"
#include <XGameRuntime.h>
#if defined(_MSC_VER) && !defined(__clang__)
#define SDL_COMPOSE_ERROR(str) __FUNCTION__ ", " str
#else
#define SDL_COMPOSE_ERROR(str) SDL_STRINGIFY_ARG(__FUNCTION__) ", " str
#endif
static const GUID SDL_IID_ID3D12Device1 = { 0x77acce80, 0x638e, 0x4e65, { 0x88, 0x95, 0xc1, 0xf2, 0x33, 0x86, 0x86, 0x3e } };
static const GUID SDL_IID_ID3D12Resource = { 0x696442be, 0xa72e, 0x4059, { 0xbc, 0x79, 0x5b, 0x5c, 0x98, 0x04, 0x0f, 0xad } };
static const GUID SDL_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
extern "C" HRESULT
D3D12_XBOX_CreateDevice(ID3D12Device **device, SDL_bool createDebug)
{
HRESULT result;
D3D12XBOX_CREATE_DEVICE_PARAMETERS params;
IDXGIDevice1 *dxgiDevice;
IDXGIAdapter *dxgiAdapter;
IDXGIOutput *dxgiOutput;
SDL_zero(params);
params.Version = D3D12_SDK_VERSION;
params.ProcessDebugFlags = createDebug ? D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED : D3D12XBOX_PROCESS_DEBUG_FLAG_NONE;
params.GraphicsCommandQueueRingSizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES;
params.GraphicsScratchMemorySizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES;
params.ComputeScratchMemorySizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES;
result = D3D12XboxCreateDevice(NULL, &params, SDL_IID_ID3D12Device1, (void **) device);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("[xbox] D3D12XboxCreateDevice"), result);
goto done;
}
result = (*device)->QueryInterface(SDL_IID_IDXGIDevice1, (void **) &dxgiDevice);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("[xbox] ID3D12Device to IDXGIDevice1"), result);
goto done;
}
result = dxgiDevice->GetAdapter(&dxgiAdapter);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("[xbox] dxgiDevice->GetAdapter"), result);
goto done;
}
result = dxgiAdapter->EnumOutputs(0, &dxgiOutput);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("[xbox] dxgiAdapter->EnumOutputs"), result);
goto done;
}
/* Set frame interval */
result = (*device)->SetFrameIntervalX(dxgiOutput, D3D12XBOX_FRAME_INTERVAL_60_HZ, 1, D3D12XBOX_FRAME_INTERVAL_FLAG_NONE);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("[xbox] SetFrameIntervalX"), result);
goto done;
}
result = (*device)->ScheduleFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, 0, NULL, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("[xbox] ScheduleFrameEventX"), result);
goto done;
}
done:
return result;
}
extern "C" HRESULT
D3D12_XBOX_CreateBackBufferTarget(ID3D12Device1 *device, int width, int height, void **resource)
{
D3D12_HEAP_PROPERTIES heapProps;
D3D12_RESOURCE_DESC resourceDesc;
SDL_zero(heapProps);
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapProps.CreationNodeMask = 1;
heapProps.VisibleNodeMask = 1;
SDL_zero(resourceDesc);
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
resourceDesc.Alignment = 0;
resourceDesc.Width = width;
resourceDesc.Height = height;
resourceDesc.DepthOrArraySize = 1;
resourceDesc.MipLevels = 1;
resourceDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
resourceDesc.SampleDesc.Count = 1;
resourceDesc.SampleDesc.Quality = 0;
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
return device->CreateCommittedResource(&heapProps,
D3D12_HEAP_FLAG_ALLOW_DISPLAY,
&resourceDesc,
D3D12_RESOURCE_STATE_PRESENT,
NULL,
SDL_IID_ID3D12Resource,
resource
);
}
extern "C" HRESULT
D3D12_XBOX_StartFrame(ID3D12Device1 *device, UINT64 *outToken)
{
*outToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL;
return device->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, NULL, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, outToken);
}
extern "C" HRESULT
D3D12_XBOX_PresentFrame(ID3D12CommandQueue *commandQueue, UINT64 token, ID3D12Resource *renderTarget)
{
D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters;
SDL_zero(planeParameters);
planeParameters.Token = token;
planeParameters.ResourceCount = 1;
planeParameters.ppResources = &renderTarget;
return commandQueue->PresentX(1, &planeParameters, NULL);
}
extern "C" void
D3D12_XBOX_GetResolution(Uint32 *width, Uint32 *height)
{
switch (XSystemGetDeviceType()) {
case XSystemDeviceType::XboxScarlettLockhart:
*width = 2560;
*height = 1440;
break;
case XSystemDeviceType::XboxOneX:
case XSystemDeviceType::XboxScarlettAnaconda:
case XSystemDeviceType::XboxOneXDevkit:
case XSystemDeviceType::XboxScarlettDevkit:
*width = 3840;
*height = 2160;
break;
default:
*width = 1920;
*height = 1080;
break;
}
}
#error "This is a placeholder Xbox file, as the real one is under NDA. See README-gdk.md for more info."
#endif

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -19,4 +19,31 @@
3. This notice may not be removed or altered from any source distribution.
*/
#error "This is a placeholder Xbox file, as the real one is under NDA. See README-gdk.md for more info."
#ifndef SDL_render_d3d12_xbox_h_
#define SDL_render_d3d12_xbox_h_
#include "../../SDL_internal.h"
#if defined(__XBOXONE__)
#include <d3d12_x.h>
#else /* __XBOXSERIES__ */
#include <d3d12_xs.h>
#endif
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
extern HRESULT D3D12_XBOX_CreateDevice(ID3D12Device **device, SDL_bool createDebug);
extern HRESULT D3D12_XBOX_CreateBackBufferTarget(ID3D12Device1 *device, int width, int height, void **resource);
extern HRESULT D3D12_XBOX_StartFrame(ID3D12Device1 *device, UINT64 *outToken);
extern HRESULT D3D12_XBOX_PresentFrame(ID3D12CommandQueue *commandQueue, UINT64 token, ID3D12Resource *renderTarget);
extern void D3D12_XBOX_GetResolution(Uint32 *width, Uint32 *height);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -18,10 +18,127 @@
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_internal.h"
#if defined(SDL_VIDEO_RENDER_D3D12) && !defined(SDL_RENDER_DISABLED) && defined(__XBOXONE__)
#if SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED && defined(__XBOXONE__)
#error "This is a placeholder Xbox file, as the real one is under NDA. See README-gdk.md for more info."
#include <SDL3/SDL_stdinc.h>
#include "../../core/windows/SDL_windows.h"
#include <d3d12_x.h>
#include "SDL_shaders_d3d12.h"
#define SDL_COMPOSE_ERROR(str) SDL_STRINGIFY_ARG(__FUNCTION__) ", " str
/* Shader blob headers are generated with a pre-build step using buildshaders.bat */
#include "../VisualC-GDK/shaders/D3D12_PixelShader_Colors_One.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601_One.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709_One.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG_One.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601_One.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709_One.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG_One.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_Textures_One.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601_One.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709_One.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG_One.h"
#include "../VisualC-GDK/shaders/D3D12_VertexShader_Color_One.h"
#include "../VisualC-GDK/shaders/D3D12_VertexShader_NV_One.h"
#include "../VisualC-GDK/shaders/D3D12_VertexShader_Texture_One.h"
#include "../VisualC-GDK/shaders/D3D12_VertexShader_YUV_One.h"
#include "../VisualC-GDK/shaders/D3D12_RootSig_Color_One.h"
#include "../VisualC-GDK/shaders/D3D12_RootSig_NV_One.h"
#include "../VisualC-GDK/shaders/D3D12_RootSig_Texture_One.h"
#include "../VisualC-GDK/shaders/D3D12_RootSig_YUV_One.h"
static struct
{
const void *ps_shader_data;
SIZE_T ps_shader_size;
const void *vs_shader_data;
SIZE_T vs_shader_size;
D3D12_RootSignature root_sig;
} D3D12_shaders[NUM_SHADERS] = {
{ D3D12_PixelShader_Colors, sizeof(D3D12_PixelShader_Colors),
D3D12_VertexShader_Color, sizeof(D3D12_VertexShader_Color),
ROOTSIG_COLOR },
{ D3D12_PixelShader_Textures, sizeof(D3D12_PixelShader_Textures),
D3D12_VertexShader_Texture, sizeof(D3D12_VertexShader_Texture),
ROOTSIG_TEXTURE },
#if SDL_HAVE_YUV
{ D3D12_PixelShader_YUV_JPEG, sizeof(D3D12_PixelShader_YUV_JPEG),
D3D12_VertexShader_YUV, sizeof(D3D12_VertexShader_YUV),
ROOTSIG_YUV },
{ D3D12_PixelShader_YUV_BT601, sizeof(D3D12_PixelShader_YUV_BT601),
D3D12_VertexShader_YUV, sizeof(D3D12_VertexShader_YUV),
ROOTSIG_YUV },
{ D3D12_PixelShader_YUV_BT709, sizeof(D3D12_PixelShader_YUV_BT709),
D3D12_VertexShader_YUV, sizeof(D3D12_VertexShader_YUV),
ROOTSIG_YUV },
{ D3D12_PixelShader_NV12_JPEG, sizeof(D3D12_PixelShader_NV12_JPEG),
D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV),
ROOTSIG_NV },
{ D3D12_PixelShader_NV12_BT601, sizeof(D3D12_PixelShader_NV12_BT601),
D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV),
ROOTSIG_NV },
{ D3D12_PixelShader_NV12_BT709, sizeof(D3D12_PixelShader_NV12_BT709),
D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV),
ROOTSIG_NV },
{ D3D12_PixelShader_NV21_JPEG, sizeof(D3D12_PixelShader_NV21_JPEG),
D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV),
ROOTSIG_NV },
{ D3D12_PixelShader_NV21_BT601, sizeof(D3D12_PixelShader_NV21_BT601),
D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV),
ROOTSIG_NV },
{ D3D12_PixelShader_NV21_BT709, sizeof(D3D12_PixelShader_NV21_BT709),
D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV),
ROOTSIG_NV },
#endif
};
static struct
{
const void *rs_shader_data;
SIZE_T rs_shader_size;
} D3D12_rootsigs[NUM_ROOTSIGS] = {
{ D3D12_RootSig_Color, sizeof(D3D12_RootSig_Color) },
{ D3D12_RootSig_Texture, sizeof(D3D12_RootSig_Texture) },
#if SDL_HAVE_YUV
{ D3D12_RootSig_YUV, sizeof(D3D12_RootSig_YUV) },
{ D3D12_RootSig_NV, sizeof(D3D12_RootSig_NV) },
#endif
};
extern "C" void
D3D12_GetVertexShader(D3D12_Shader shader, D3D12_SHADER_BYTECODE *outBytecode)
{
outBytecode->pShaderBytecode = D3D12_shaders[shader].vs_shader_data;
outBytecode->BytecodeLength = D3D12_shaders[shader].vs_shader_size;
}
extern "C" void
D3D12_GetPixelShader(D3D12_Shader shader, D3D12_SHADER_BYTECODE *outBytecode)
{
outBytecode->pShaderBytecode = D3D12_shaders[shader].ps_shader_data;
outBytecode->BytecodeLength = D3D12_shaders[shader].ps_shader_size;
}
extern "C" D3D12_RootSignature
D3D12_GetRootSignatureType(D3D12_Shader shader)
{
return D3D12_shaders[shader].root_sig;
}
extern "C" void
D3D12_GetRootSignatureData(D3D12_RootSignature rootSig, D3D12_SHADER_BYTECODE *outBytecode)
{
outBytecode->pShaderBytecode = D3D12_rootsigs[rootSig].rs_shader_data;
outBytecode->BytecodeLength = D3D12_rootsigs[rootSig].rs_shader_size;
}
#endif /* SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED && defined(__XBOXONE__) */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -18,10 +18,127 @@
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_internal.h"
#if defined(SDL_VIDEO_RENDER_D3D12) && !defined(SDL_RENDER_DISABLED) && defined(__XBOXSERIES__)
#if SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED && defined(__XBOXSERIES__)
#error "This is a placeholder Xbox file, as the real one is under NDA. See README-gdk.md for more info."
#include <SDL3/SDL_stdinc.h>
#include "../../core/windows/SDL_windows.h"
#include <d3d12_xs.h>
#include "SDL_shaders_d3d12.h"
#define SDL_COMPOSE_ERROR(str) SDL_STRINGIFY_ARG(__FUNCTION__) ", " str
/* Shader blob headers are generated with a pre-build step using buildshaders.bat */
#include "../VisualC-GDK/shaders/D3D12_PixelShader_Colors_Series.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_Textures_Series.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT601_Series.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV12_BT709_Series.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV12_JPEG_Series.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT601_Series.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV21_BT709_Series.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_NV21_JPEG_Series.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT601_Series.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_YUV_BT709_Series.h"
#include "../VisualC-GDK/shaders/D3D12_PixelShader_YUV_JPEG_Series.h"
#include "../VisualC-GDK/shaders/D3D12_VertexShader_Color_Series.h"
#include "../VisualC-GDK/shaders/D3D12_VertexShader_Texture_Series.h"
#include "../VisualC-GDK/shaders/D3D12_VertexShader_NV_Series.h"
#include "../VisualC-GDK/shaders/D3D12_VertexShader_YUV_Series.h"
#include "../VisualC-GDK/shaders/D3D12_RootSig_Color_Series.h"
#include "../VisualC-GDK/shaders/D3D12_RootSig_Texture_Series.h"
#include "../VisualC-GDK/shaders/D3D12_RootSig_YUV_Series.h"
#include "../VisualC-GDK/shaders/D3D12_RootSig_NV_Series.h"
static struct
{
const void *ps_shader_data;
SIZE_T ps_shader_size;
const void *vs_shader_data;
SIZE_T vs_shader_size;
D3D12_RootSignature root_sig;
} D3D12_shaders[NUM_SHADERS] = {
{ D3D12_PixelShader_Colors, sizeof(D3D12_PixelShader_Colors),
D3D12_VertexShader_Color, sizeof(D3D12_VertexShader_Color),
ROOTSIG_COLOR },
{ D3D12_PixelShader_Textures, sizeof(D3D12_PixelShader_Textures),
D3D12_VertexShader_Texture, sizeof(D3D12_VertexShader_Texture),
ROOTSIG_TEXTURE },
#if SDL_HAVE_YUV
{ D3D12_PixelShader_YUV_JPEG, sizeof(D3D12_PixelShader_YUV_JPEG),
D3D12_VertexShader_YUV, sizeof(D3D12_VertexShader_YUV),
ROOTSIG_YUV },
{ D3D12_PixelShader_YUV_BT601, sizeof(D3D12_PixelShader_YUV_BT601),
D3D12_VertexShader_YUV, sizeof(D3D12_VertexShader_YUV),
ROOTSIG_YUV },
{ D3D12_PixelShader_YUV_BT709, sizeof(D3D12_PixelShader_YUV_BT709),
D3D12_VertexShader_YUV, sizeof(D3D12_VertexShader_YUV),
ROOTSIG_YUV },
{ D3D12_PixelShader_NV12_JPEG, sizeof(D3D12_PixelShader_NV12_JPEG),
D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV),
ROOTSIG_NV },
{ D3D12_PixelShader_NV12_BT601, sizeof(D3D12_PixelShader_NV12_BT601),
D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV),
ROOTSIG_NV },
{ D3D12_PixelShader_NV12_BT709, sizeof(D3D12_PixelShader_NV12_BT709),
D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV),
ROOTSIG_NV },
{ D3D12_PixelShader_NV21_JPEG, sizeof(D3D12_PixelShader_NV21_JPEG),
D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV),
ROOTSIG_NV },
{ D3D12_PixelShader_NV21_BT601, sizeof(D3D12_PixelShader_NV21_BT601),
D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV),
ROOTSIG_NV },
{ D3D12_PixelShader_NV21_BT709, sizeof(D3D12_PixelShader_NV21_BT709),
D3D12_VertexShader_NV, sizeof(D3D12_VertexShader_NV),
ROOTSIG_NV },
#endif
};
static struct
{
const void *rs_shader_data;
SIZE_T rs_shader_size;
} D3D12_rootsigs[NUM_ROOTSIGS] = {
{ D3D12_RootSig_Color, sizeof(D3D12_RootSig_Color) },
{ D3D12_RootSig_Texture, sizeof(D3D12_RootSig_Texture) },
#if SDL_HAVE_YUV
{ D3D12_RootSig_YUV, sizeof(D3D12_RootSig_YUV) },
{ D3D12_RootSig_NV, sizeof(D3D12_RootSig_NV) },
#endif
};
extern "C" void
D3D12_GetVertexShader(D3D12_Shader shader, D3D12_SHADER_BYTECODE *outBytecode)
{
outBytecode->pShaderBytecode = D3D12_shaders[shader].vs_shader_data;
outBytecode->BytecodeLength = D3D12_shaders[shader].vs_shader_size;
}
extern "C" void
D3D12_GetPixelShader(D3D12_Shader shader, D3D12_SHADER_BYTECODE *outBytecode)
{
outBytecode->pShaderBytecode = D3D12_shaders[shader].ps_shader_data;
outBytecode->BytecodeLength = D3D12_shaders[shader].ps_shader_size;
}
extern "C" D3D12_RootSignature
D3D12_GetRootSignatureType(D3D12_Shader shader)
{
return D3D12_shaders[shader].root_sig;
}
extern "C" void
D3D12_GetRootSignatureData(D3D12_RootSignature rootSig, D3D12_SHADER_BYTECODE *outBytecode)
{
outBytecode->pShaderBytecode = D3D12_rootsigs[rootSig].rs_shader_data;
outBytecode->BytecodeLength = D3D12_rootsigs[rootSig].rs_shader_size;
}
#endif /* SDL_VIDEO_RENDER_D3D12 && !SDL_RENDER_DISABLED && defined(__XBOXSERIES__) */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -35,7 +35,6 @@
#ifdef SDL_VIDEO_DRIVER_UIKIT
#import <UIKit/UIKit.h>
#endif
#include <SDL3/SDL_syswm.h>
/* Regenerate these with build-metal-shaders.sh */
#ifdef __MACOS__
@ -160,20 +159,16 @@ typedef struct METAL_ShaderPipelines
@implementation METAL_TextureData
@end
static int IsMetalAvailable(const SDL_SysWMinfo *syswm)
static SDL_bool IsMetalAvailable()
{
if (syswm->subsystem != SDL_SYSWM_COCOA && syswm->subsystem != SDL_SYSWM_UIKIT) {
return SDL_SetError("Metal render target only supports Cocoa and UIKit video targets at the moment.");
}
// this checks a weak symbol.
#if (defined(__MACOS__) && (MAC_OS_X_VERSION_MIN_REQUIRED < 101100))
// this checks a weak symbol.
if (MTLCreateSystemDefaultDevice == NULL) { // probably on 10.10 or lower.
return SDL_SetError("Metal framework not available on this system");
SDL_SetError("Metal framework not available on this system");
return SDL_FALSE;
}
#endif
return 0;
return SDL_TRUE;
}
static const MTLBlendOperation invalidBlendOperation = (MTLBlendOperation)0xFFFFFFFF;
@ -344,7 +339,6 @@ static id<MTLRenderPipelineState> MakePipelineState(METAL_RenderData *data, META
return (__bridge id<MTLRenderPipelineState>)pipeline.pipe;
} else {
CFBridgingRelease(pipeline.pipe);
SDL_OutOfMemory();
return NULL;
}
}
@ -406,7 +400,6 @@ static METAL_ShaderPipelines *ChooseShaderPipelines(METAL_RenderData *data, MTLP
allpipelines = SDL_realloc(allpipelines, (count + 1) * sizeof(METAL_ShaderPipelines));
if (allpipelines == NULL) {
SDL_OutOfMemory();
return NULL;
}
@ -549,7 +542,7 @@ static SDL_bool METAL_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode bl
return SDL_TRUE;
}
static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
@autoreleasepool {
METAL_RenderData *data = (__bridge METAL_RenderData *)renderer->driverdata;
@ -1315,6 +1308,11 @@ static SDL_bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cm
return SDL_TRUE;
}
static void METAL_InvalidateCachedState(SDL_Renderer *renderer)
{
// METAL_DrawStateCache only exists during a run of METAL_RunCommandQueue, so there's nothing to invalidate!
}
static int METAL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
@autoreleasepool {
@ -1507,7 +1505,7 @@ static int METAL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
temp_pitch = rect->w * 4UL;
temp_pixels = SDL_malloc(temp_pitch * rect->h);
if (!temp_pixels) {
return SDL_OutOfMemory();
return -1;
}
[mtltexture getBytes:temp_pixels bytesPerRow:temp_pitch fromRegion:mtlregion mipmapLevel:0];
@ -1527,9 +1525,10 @@ static int METAL_RenderPresent(SDL_Renderer *renderer)
// If we don't have a command buffer, we can't present, so activate to get one.
if (data.mtlcmdencoder == nil) {
// We haven't even gotten a backbuffer yet? Clear it to black. Otherwise, load the existing data.
// We haven't even gotten a backbuffer yet? Load and clear it. Otherwise, load the existing data.
if (data.mtlbackbuffer == nil) {
MTLClearColor color = MTLClearColorMake(0.0f, 0.0f, 0.0f, 1.0f);
float alpha = (SDL_GetWindowFlags(renderer->window) & SDL_WINDOW_TRANSPARENT) ? 0.0f : 1.0f;
MTLClearColor color = MTLClearColorMake(0.0f, 0.0f, 0.0f, alpha);
ready = METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, nil);
} else {
ready = METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
@ -1630,33 +1629,35 @@ static int METAL_SetVSync(SDL_Renderer *renderer, const int vsync)
static SDL_MetalView GetWindowView(SDL_Window *window)
{
SDL_SysWMinfo info;
if (SDL_GetWindowWMInfo(window, &info, SDL_SYSWM_CURRENT_VERSION) == 0) {
#ifdef SDL_ENABLE_SYSWM_COCOA
if (info.subsystem == SDL_SYSWM_COCOA) {
NSView *view = info.info.cocoa.window.contentView;
if (view.subviews.count > 0) {
view = view.subviews[0];
if (view.tag == SDL_METALVIEW_TAG) {
return (SDL_MetalView)CFBridgingRetain(view);
}
}
}
#endif
#ifdef SDL_ENABLE_SYSWM_UIKIT
if (info.subsystem == SDL_SYSWM_UIKIT) {
UIView *view = info.info.uikit.window.rootViewController.view;
if (view.tag == SDL_METALVIEW_TAG) {
#ifdef SDL_VIDEO_DRIVER_COCOA
NSWindow *nswindow = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_COCOA_WINDOW_POINTER, NULL);
NSInteger tag = (NSInteger)SDL_GetNumberProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER, 0);
if (nswindow && tag) {
NSView *view = nswindow.contentView;
if (view.subviews.count > 0) {
view = view.subviews[0];
if (view.tag == tag) {
return (SDL_MetalView)CFBridgingRetain(view);
}
}
#endif
}
#endif
#ifdef SDL_VIDEO_DRIVER_UIKIT
UIWindow *uiwindow = (__bridge UIWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_UIKIT_WINDOW_POINTER, NULL);
NSInteger tag = (NSInteger)SDL_GetNumberProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER, 0);
if (uiwindow && tag) {
UIView *view = uiwindow.rootViewController.view;
if (view.tag == tag) {
return (SDL_MetalView)CFBridgingRetain(view);
}
}
#endif
return nil;
}
static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, Uint32 flags)
static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props)
{
@autoreleasepool {
SDL_Renderer *renderer = NULL;
@ -1664,7 +1665,6 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, Uint32 flags)
id<MTLDevice> mtldevice = nil;
SDL_MetalView view = NULL;
CAMetalLayer *layer = nil;
SDL_SysWMinfo syswm;
NSError *err = nil;
dispatch_data_t mtllibdata;
char *constantdata;
@ -1740,17 +1740,12 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, Uint32 flags)
1.0000, 1.7720, 0.0000, 0.0, /* Bcoeff */
};
if (SDL_GetWindowWMInfo(window, &syswm, SDL_SYSWM_CURRENT_VERSION) < 0) {
return NULL;
}
if (IsMetalAvailable(&syswm) == -1) {
if (!IsMetalAvailable()) {
return NULL;
}
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
SDL_OutOfMemory();
return NULL;
}
@ -1801,6 +1796,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, Uint32 flags)
}
renderer->driverdata = (void *)CFBridgingRetain(data);
METAL_InvalidateCachedState(renderer);
renderer->window = window;
data.mtlview = view;
@ -1913,6 +1909,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->QueueDrawPoints = METAL_QueueDrawPoints;
renderer->QueueDrawLines = METAL_QueueDrawLines;
renderer->QueueGeometry = METAL_QueueGeometry;
renderer->InvalidateCachedState = METAL_InvalidateCachedState;
renderer->RunCommandQueue = METAL_RunCommandQueue;
renderer->RenderReadPixels = METAL_RenderReadPixels;
renderer->RenderPresent = METAL_RenderPresent;
@ -1925,11 +1922,9 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->info = METAL_RenderDriver.info;
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->always_batch = SDL_TRUE;
#if (defined(__MACOS__) && defined(MAC_OS_X_VERSION_10_13)) || TARGET_OS_MACCATALYST
if (@available(macOS 10.13, *)) {
data.mtllayer.displaySyncEnabled = (flags & SDL_RENDERER_PRESENTVSYNC) != 0;
data.mtllayer.displaySyncEnabled = SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE);
if (data.mtllayer.displaySyncEnabled) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -75,10 +75,13 @@ typedef struct
SDL_bool cliprect_dirty;
SDL_Rect cliprect;
SDL_bool texturing;
SDL_bool texturing_dirty;
SDL_bool vertex_array;
SDL_bool color_array;
SDL_bool texture_array;
SDL_bool color_dirty;
Uint32 color;
SDL_bool clear_color_dirty;
Uint32 clear_color;
} GL_DrawStateCache;
@ -125,6 +128,7 @@ typedef struct
typedef struct
{
GLuint texture;
SDL_bool texture_external;
GLfloat texw;
GLfloat texh;
GLenum format;
@ -139,7 +143,9 @@ typedef struct
SDL_bool yuv;
SDL_bool nv12;
GLuint utexture;
SDL_bool utexture_external;
GLuint vtexture;
SDL_bool vtexture_external;
#endif
GL_FBOList *fbo;
@ -183,7 +189,7 @@ static void GL_ClearErrors(SDL_Renderer *renderer)
data->errors = 0;
data->error_messages = NULL;
}
} else if (data->glGetError != NULL) {
} else if (data->glGetError) {
while (data->glGetError() != GL_NO_ERROR) {
/* continue; */
}
@ -302,7 +308,7 @@ static GL_FBOList *GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h)
result = result->next;
}
if (result == NULL) {
if (!result) {
result = SDL_malloc(sizeof(GL_FBOList));
if (result) {
result->w = w;
@ -434,7 +440,7 @@ static SDL_bool convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
return SDL_TRUE;
}
static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
GL_RenderData *renderdata = (GL_RenderData *)renderer->driverdata;
const GLenum textype = renderdata->textype;
@ -447,6 +453,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
GL_ActivateRenderer(renderer);
renderdata->drawstate.texture = NULL; /* we trash this state. */
renderdata->drawstate.texturing_dirty = SDL_TRUE; /* we trash this state. */
if (texture->access == SDL_TEXTUREACCESS_TARGET &&
!renderdata->GL_EXT_framebuffer_object_supported) {
@ -460,8 +467,8 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
}
data = (GL_TextureData *)SDL_calloc(1, sizeof(*data));
if (data == NULL) {
return SDL_OutOfMemory();
if (!data) {
return -1;
}
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
@ -481,7 +488,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
data->pixels = SDL_calloc(1, size);
if (!data->pixels) {
SDL_free(data);
return SDL_OutOfMemory();
return -1;
}
}
@ -491,14 +498,19 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
data->fbo = NULL;
}
GL_CheckError("", renderer);
renderdata->glGenTextures(1, &data->texture);
if (GL_CheckError("glGenTextures()", renderer) < 0) {
if (data->pixels) {
SDL_free(data->pixels);
data->texture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER, 0);
if (data->texture) {
data->texture_external = SDL_TRUE;
} else {
GL_CheckError("", renderer);
renderdata->glGenTextures(1, &data->texture);
if (GL_CheckError("glGenTextures()", renderer) < 0) {
if (data->pixels) {
SDL_free(data->pixels);
}
SDL_free(data);
return -1;
}
SDL_free(data);
return -1;
}
texture->driverdata = data;
@ -518,6 +530,11 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
data->texw = (GLfloat)(texture->w) / texture_w;
data->texh = (GLfloat)texture->h / texture_h;
}
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_NUMBER, data->texture);
SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_TARGET, (Sint64) textype);
SDL_SetFloatProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEX_W_FLOAT, data->texw);
SDL_SetFloatProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEX_H_FLOAT, data->texh);
data->format = format;
data->formattype = type;
@ -576,8 +593,18 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
texture->format == SDL_PIXELFORMAT_IYUV) {
data->yuv = SDL_TRUE;
renderdata->glGenTextures(1, &data->utexture);
renderdata->glGenTextures(1, &data->vtexture);
data->utexture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER, 0);
if (data->utexture) {
data->utexture_external = SDL_TRUE;
} else {
renderdata->glGenTextures(1, &data->utexture);
}
data->vtexture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER, 0);
if (data->vtexture) {
data->vtexture_external = SDL_TRUE;
} else {
renderdata->glGenTextures(1, &data->vtexture);
}
renderdata->glBindTexture(textype, data->utexture);
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
@ -590,6 +617,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
GL_CLAMP_TO_EDGE);
renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
(texture_h + 1) / 2, 0, format, type, NULL);
SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_U_NUMBER, data->utexture);
renderdata->glBindTexture(textype, data->vtexture);
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
@ -602,13 +630,19 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
GL_CLAMP_TO_EDGE);
renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
(texture_h + 1) / 2, 0, format, type, NULL);
SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture);
}
if (texture->format == SDL_PIXELFORMAT_NV12 ||
texture->format == SDL_PIXELFORMAT_NV21) {
data->nv12 = SDL_TRUE;
renderdata->glGenTextures(1, &data->utexture);
data->utexture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER, 0);
if (data->utexture) {
data->utexture_external = SDL_TRUE;
} else {
renderdata->glGenTextures(1, &data->utexture);
}
renderdata->glBindTexture(textype, data->utexture);
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
scaleMode);
@ -620,6 +654,7 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
GL_CLAMP_TO_EDGE);
renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w + 1) / 2,
(texture_h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
SDL_SetNumberProperty(props, SDL_PROPERTY_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, data->utexture);
}
#endif
@ -877,7 +912,7 @@ static int GL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
data->drawstate.viewport_dirty = SDL_TRUE;
if (texture == NULL) {
if (!texture) {
data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
return 0;
}
@ -907,7 +942,7 @@ static int GL_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, co
GLfloat *verts = (GLfloat *)SDL_AllocateRenderVertices(renderer, count * 2 * sizeof(GLfloat), 0, &cmd->data.draw.first);
int i;
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -927,7 +962,7 @@ static int GL_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, con
const size_t vertlen = (sizeof(GLfloat) * 2) * count;
GLfloat *verts = (GLfloat *)SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
@ -972,7 +1007,7 @@ static int GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_
size_t sz = 2 * sizeof(GLfloat) + 4 * sizeof(Uint8) + (texture ? 2 : 0) * sizeof(GLfloat);
verts = (GLfloat *)SDL_AllocateRenderVertices(renderer, count * sz, 0, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -1077,14 +1112,15 @@ static int SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const
data->drawstate.shader = shader;
}
if ((cmd->data.draw.texture != NULL) != data->drawstate.texturing) {
if (cmd->data.draw.texture == NULL) {
if (data->drawstate.texturing_dirty || ((cmd->data.draw.texture != NULL) != data->drawstate.texturing)) {
if (!cmd->data.draw.texture) {
data->glDisable(data->textype);
data->drawstate.texturing = SDL_FALSE;
} else {
data->glEnable(data->textype);
data->drawstate.texturing = SDL_TRUE;
}
data->drawstate.texturing_dirty = SDL_FALSE;
}
vertex_array = cmd->command == SDL_RENDERCMD_DRAW_POINTS || cmd->command == SDL_RENDERCMD_DRAW_LINES || cmd->command == SDL_RENDERCMD_GEOMETRY;
@ -1110,7 +1146,7 @@ static int SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const
}
/* This is a little awkward but should avoid texcoord arrays getting into
a bad state if SDL_GL_BindTexture/UnbindTexture are called. */
a bad state if the application is manually binding textures */
if (texture_array != data->drawstate.texture_array) {
if (texture_array) {
data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@ -1162,6 +1198,25 @@ static int SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
return 0;
}
static void GL_InvalidateCachedState(SDL_Renderer *renderer)
{
GL_DrawStateCache *cache = &((GL_RenderData *)renderer->driverdata)->drawstate;
cache->viewport_dirty = SDL_TRUE;
cache->texture = NULL;
cache->drawablew = 0;
cache->drawableh = 0;
cache->blend = SDL_BLENDMODE_INVALID;
cache->shader = SHADER_INVALID;
cache->cliprect_enabled_dirty = SDL_TRUE;
cache->cliprect_dirty = SDL_TRUE;
cache->texturing_dirty = SDL_TRUE;
cache->vertex_array = SDL_FALSE; /* !!! FIXME: this resets to false at the end of GL_RunCommandQueue, but we could cache this more aggressively. */
cache->color_array = SDL_FALSE; /* !!! FIXME: this resets to false at the end of GL_RunCommandQueue, but we could cache this more aggressively. */
cache->texture_array = SDL_FALSE; /* !!! FIXME: this resets to false at the end of GL_RunCommandQueue, but we could cache this more aggressively. */
cache->color_dirty = SDL_TRUE;
cache->clear_color_dirty = SDL_TRUE;
}
static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
/* !!! FIXME: it'd be nice to use a vertex buffer instead of immediate mode... */
@ -1199,9 +1254,10 @@ static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
const Uint8 b = cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b);
if (color != data->drawstate.color) {
if ((data->drawstate.color_dirty) || (color != data->drawstate.color)) {
data->glColor4ub((GLubyte)r, (GLubyte)g, (GLubyte)b, (GLubyte)a);
data->drawstate.color = color;
data->drawstate.color_dirty = SDL_FALSE;
}
break;
}
@ -1238,13 +1294,14 @@ static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
const Uint8 b = cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b);
if (color != data->drawstate.clear_color) {
if ((data->drawstate.clear_color_dirty) || (color != data->drawstate.clear_color)) {
const GLfloat fr = ((GLfloat)r) * inv255f;
const GLfloat fg = ((GLfloat)g) * inv255f;
const GLfloat fb = ((GLfloat)b) * inv255f;
const GLfloat fa = ((GLfloat)a) * inv255f;
data->glClearColor(fr, fg, fb, fa);
data->drawstate.clear_color = color;
data->drawstate.clear_color_dirty = SDL_FALSE;
}
if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) {
@ -1283,7 +1340,7 @@ static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
SDL_RenderCommand *nextcmd = cmd->next;
SDL_BlendMode thisblend = cmd->data.draw.blend;
while (nextcmd != NULL) {
while (nextcmd) {
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) {
break; /* can't go any further on this draw call, different render command up next. */
@ -1317,7 +1374,7 @@ static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
SDL_RenderCommand *nextcmd = cmd->next;
size_t count = cmd->data.draw.count;
int ret;
while (nextcmd != NULL) {
while (nextcmd) {
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
if (nextcmdtype != thiscmdtype) {
break; /* can't go any further on this draw call, different render command up next. */
@ -1426,8 +1483,8 @@ static int GL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
temp_pixels = SDL_malloc((size_t)rect->h * temp_pitch);
if (temp_pixels == NULL) {
return SDL_OutOfMemory();
if (!temp_pixels) {
return -1;
}
SDL_GetCurrentRenderOutputSize(renderer, &w, &h);
@ -1491,16 +1548,25 @@ static void GL_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
renderdata->drawstate.target = NULL;
}
if (data == NULL) {
if (!data) {
return;
}
if (data->texture) {
if (data->texture && !data->texture_external) {
renderdata->glDeleteTextures(1, &data->texture);
}
#if SDL_HAVE_YUV
if (data->yuv) {
renderdata->glDeleteTextures(1, &data->utexture);
renderdata->glDeleteTextures(1, &data->vtexture);
if (!data->utexture_external) {
renderdata->glDeleteTextures(1, &data->utexture);
}
if (!data->vtexture_external) {
renderdata->glDeleteTextures(1, &data->vtexture);
}
}
if (data->nv12) {
if (!data->utexture_external) {
renderdata->glDeleteTextures(1, &data->utexture);
}
}
#endif
SDL_free(data->pixels);
@ -1513,7 +1579,7 @@ static void GL_DestroyRenderer(SDL_Renderer *renderer)
GL_RenderData *data = (GL_RenderData *)renderer->driverdata;
if (data) {
if (data->context != NULL) {
if (data->context) {
/* make sure we delete the right resources! */
GL_ActivateRenderer(renderer);
}
@ -1545,105 +1611,6 @@ static void GL_DestroyRenderer(SDL_Renderer *renderer)
SDL_free(renderer);
}
static int GL_BindTexture(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
{
GL_RenderData *data = (GL_RenderData *)renderer->driverdata;
GL_TextureData *texturedata = (GL_TextureData *)texture->driverdata;
const GLenum textype = data->textype;
GL_ActivateRenderer(renderer);
data->glEnable(textype);
#if SDL_HAVE_YUV
if (texturedata->yuv) {
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE2_ARB);
}
data->glBindTexture(textype, texturedata->vtexture);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
}
data->glBindTexture(textype, texturedata->utexture);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
}
if (texturedata->nv12) {
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
}
data->glBindTexture(textype, texturedata->utexture);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
}
#endif
data->glBindTexture(textype, texturedata->texture);
data->drawstate.texturing = SDL_TRUE;
data->drawstate.texture = texture;
if (texw) {
*texw = (float)texturedata->texw;
}
if (texh) {
*texh = (float)texturedata->texh;
}
return 0;
}
static int GL_UnbindTexture(SDL_Renderer *renderer, SDL_Texture *texture)
{
GL_RenderData *data = (GL_RenderData *)renderer->driverdata;
const GLenum textype = data->textype;
#if SDL_HAVE_YUV
GL_TextureData *texturedata = (GL_TextureData *)texture->driverdata;
#endif
GL_ActivateRenderer(renderer);
#if SDL_HAVE_YUV
if (texturedata->yuv) {
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE2_ARB);
}
data->glBindTexture(textype, 0);
data->glDisable(textype);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
}
data->glBindTexture(textype, 0);
data->glDisable(textype);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
}
if (texturedata->nv12) {
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
}
data->glBindTexture(textype, 0);
data->glDisable(textype);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
}
#endif
data->glBindTexture(textype, 0);
data->glDisable(textype);
data->drawstate.texturing = SDL_FALSE;
data->drawstate.texture = NULL;
return 0;
}
static int GL_SetVSync(SDL_Renderer *renderer, const int vsync)
{
int retval;
@ -1662,7 +1629,7 @@ static int GL_SetVSync(SDL_Renderer *renderer, const int vsync)
return retval;
}
if (interval > 0) {
if (interval != 0) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
} else {
renderer->info.flags &= ~SDL_RENDERER_PRESENTVSYNC;
@ -1696,7 +1663,7 @@ static SDL_bool GL_IsProbablyAccelerated(const GL_RenderData *data)
return SDL_TRUE;
}
static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags)
static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props)
{
SDL_Renderer *renderer;
GL_RenderData *data;
@ -1712,6 +1679,7 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
#ifndef SDL_VIDEO_VITA_PVR_OGL
SDL_SyncWindow(window);
window_flags = SDL_GetWindowFlags(window);
if (!(window_flags & SDL_WINDOW_OPENGL) ||
profile_mask == SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
@ -1728,15 +1696,13 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags)
#endif
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (renderer == NULL) {
SDL_OutOfMemory();
if (!renderer) {
goto error;
}
data = (GL_RenderData *)SDL_calloc(1, sizeof(*data));
if (data == NULL) {
if (!data) {
SDL_free(renderer);
SDL_OutOfMemory();
goto error;
}
@ -1757,17 +1723,17 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->QueueDrawPoints = GL_QueueDrawPoints;
renderer->QueueDrawLines = GL_QueueDrawLines;
renderer->QueueGeometry = GL_QueueGeometry;
renderer->InvalidateCachedState = GL_InvalidateCachedState;
renderer->RunCommandQueue = GL_RunCommandQueue;
renderer->RenderReadPixels = GL_RenderReadPixels;
renderer->RenderPresent = GL_RenderPresent;
renderer->DestroyTexture = GL_DestroyTexture;
renderer->DestroyRenderer = GL_DestroyRenderer;
renderer->SetVSync = GL_SetVSync;
renderer->GL_BindTexture = GL_BindTexture;
renderer->GL_UnbindTexture = GL_UnbindTexture;
renderer->info = GL_RenderDriver.info;
renderer->info.flags = 0; /* will set some flags below. */
renderer->driverdata = data;
GL_InvalidateCachedState(renderer);
renderer->window = window;
data->context = SDL_GL_CreateContext(window);
@ -1801,7 +1767,7 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags)
*/
#endif
if (flags & SDL_RENDERER_PRESENTVSYNC) {
if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
SDL_GL_SetSwapInterval(1);
} else {
SDL_GL_SetSwapInterval(0);
@ -1811,10 +1777,8 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags)
int interval = 0;
if (SDL_GL_GetSwapInterval(&interval) < 0) {
/* Error */
} else {
if (interval > 0) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
} else if (interval != 0) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
}
@ -1836,7 +1800,7 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags)
}
hint = SDL_getenv("GL_ARB_texture_non_power_of_two");
if (hint == NULL || *hint != '0') {
if (!hint || *hint != '0') {
SDL_bool isGL2 = SDL_FALSE;
const char *verstr = (const char *)data->glGetString(GL_VERSION);
if (verstr) {
@ -1946,8 +1910,6 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags)
/* This ended up causing video discrepancies between OpenGL and Direct3D */
/* data->glEnable(GL_LINE_SMOOTH); */
data->drawstate.blend = SDL_BLENDMODE_INVALID;
data->drawstate.shader = SHADER_INVALID;
data->drawstate.color = 0xFFFFFFFF;
data->drawstate.clear_color = 0xFFFFFFFF;

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -495,7 +495,7 @@ GL_ShaderContext *GL_CreateShaderContext(void)
int i;
ctx = (GL_ShaderContext *)SDL_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
if (!ctx) {
return NULL;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -61,6 +61,7 @@ struct GLES2_FBOList
typedef struct GLES2_TextureData
{
GLuint texture;
SDL_bool texture_external;
GLenum texture_type;
GLenum pixel_format;
GLenum pixel_type;
@ -71,7 +72,9 @@ typedef struct GLES2_TextureData
SDL_bool yuv;
SDL_bool nv12;
GLuint texture_v;
GLuint texture_v_external;
GLuint texture_u;
GLuint texture_u_external;
#endif
GLES2_FBOList *fbo;
} GLES2_TextureData;
@ -135,7 +138,9 @@ typedef struct
SDL_bool cliprect_dirty;
SDL_Rect cliprect;
SDL_bool texturing;
SDL_bool texturing_dirty;
Uint32 clear_color;
SDL_bool clear_color_dirty;
int drawablew;
int drawableh;
GLES2_ProgramCacheEntry *program;
@ -216,7 +221,7 @@ static int GL_CheckAllErrors(const char *prefix, SDL_Renderer *renderer, const c
for (;;) {
GLenum error = data->glGetError();
if (error != GL_NO_ERROR) {
if (prefix == NULL || prefix[0] == '\0') {
if (!prefix || prefix[0] == '\0') {
prefix = "generic";
}
SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error);
@ -269,7 +274,7 @@ static GLES2_FBOList *GLES2_GetFBO(GLES2_RenderData *data, Uint32 w, Uint32 h)
while ((result) && ((result->w != w) || (result->h != h))) {
result = result->next;
}
if (result == NULL) {
if (!result) {
result = SDL_malloc(sizeof(GLES2_FBOList));
result->w = w;
result->h = h;
@ -415,8 +420,7 @@ static GLES2_ProgramCacheEntry *GLES2_CacheProgram(GLES2_RenderData *data, GLuin
/* Create a program cache entry */
entry = (GLES2_ProgramCacheEntry *)SDL_calloc(1, sizeof(GLES2_ProgramCacheEntry));
if (entry == NULL) {
SDL_OutOfMemory();
if (!entry) {
return NULL;
}
entry->vertex_shader = vertex;
@ -476,7 +480,7 @@ static GLES2_ProgramCacheEntry *GLES2_CacheProgram(GLES2_RenderData *data, GLuin
if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) {
data->glDeleteProgram(data->program_cache.tail->id);
data->program_cache.tail = data->program_cache.tail->prev;
if (data->program_cache.tail != NULL) {
if (data->program_cache.tail) {
SDL_free(data->program_cache.tail->next);
data->program_cache.tail->next = NULL;
}
@ -493,7 +497,7 @@ static GLuint GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type, G
const GLchar *shader_src_list[3];
const GLchar *shader_body = GLES2_GetShader(type);
if (shader_body == NULL) {
if (!shader_body) {
SDL_SetError("No shader body src");
return 0;
}
@ -539,20 +543,19 @@ static GLuint GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type, G
}
if (!compileSuccessful) {
SDL_bool isstack = SDL_FALSE;
char *info = NULL;
int length = 0;
data->glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
if (length > 0) {
info = SDL_small_alloc(char, length, &isstack);
info = (char *)SDL_malloc(length);
if (info) {
data->glGetShaderInfoLog(id, length, &length, info);
}
}
if (info) {
SDL_SetError("Failed to load the shader %d: %s", type, info);
SDL_small_free(info, isstack);
SDL_free(info);
} else {
SDL_SetError("Failed to load the shader %d", type);
}
@ -703,7 +706,7 @@ static int GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source,
/* Generate a matching program */
program = GLES2_CacheProgram(data, vertex, fragment);
if (program == NULL) {
if (!program) {
goto fault;
}
@ -727,7 +730,7 @@ static int GLES2_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd
static int GLES2_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
{
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_XRGB8888));
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_BGRA32 || renderer->target->format == SDL_PIXELFORMAT_BGRX32));
SDL_VertexSolid *verts = (SDL_VertexSolid *)SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first);
int i;
SDL_Color color;
@ -736,7 +739,7 @@ static int GLES2_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
color.b = cmd->data.draw.b;
color.a = cmd->data.draw.a;
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -759,7 +762,7 @@ static int GLES2_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
static int GLES2_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
{
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_XRGB8888));
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_BGRA32 || renderer->target->format == SDL_PIXELFORMAT_BGRX32));
int i;
GLfloat prevx, prevy;
SDL_VertexSolid *verts = (SDL_VertexSolid *)SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first);
@ -769,7 +772,7 @@ static int GLES2_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
color.b = cmd->data.draw.b;
color.a = cmd->data.draw.a;
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -819,7 +822,7 @@ static int GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S
float scale_x, float scale_y)
{
int i;
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_XRGB8888));
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_BGRA32 || renderer->target->format == SDL_PIXELFORMAT_BGRX32));
int count = indices ? num_indices : num_vertices;
cmd->data.draw.count = count;
@ -827,7 +830,7 @@ static int GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S
if (texture) {
SDL_Vertex *verts = (SDL_Vertex *)SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -867,7 +870,7 @@ static int GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S
} else {
SDL_VertexSolid *verts = (SDL_VertexSolid *)SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -946,14 +949,15 @@ static int SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, co
data->drawstate.cliprect_dirty = SDL_FALSE;
}
if ((texture != NULL) != data->drawstate.texturing) {
if (texture == NULL) {
if (data->drawstate.texturing_dirty || ((texture != NULL) != data->drawstate.texturing)) {
if (!texture) {
data->glDisableVertexAttribArray((GLenum)GLES2_ATTRIBUTE_TEXCOORD);
data->drawstate.texturing = SDL_FALSE;
} else {
data->glEnableVertexAttribArray((GLenum)GLES2_ATTRIBUTE_TEXCOORD);
data->drawstate.texturing = SDL_TRUE;
}
data->drawstate.texturing_dirty = SDL_FALSE;
}
if (texture) {
@ -1017,50 +1021,50 @@ static int SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, vo
/* Check if we need to do color mapping between the source and render target textures */
if (renderer->target->format != texture->format) {
switch (texture->format) {
case SDL_PIXELFORMAT_ARGB8888:
case SDL_PIXELFORMAT_BGRA32:
switch (renderer->target->format) {
case SDL_PIXELFORMAT_ABGR8888:
case SDL_PIXELFORMAT_XBGR8888:
case SDL_PIXELFORMAT_RGBA32:
case SDL_PIXELFORMAT_RGBX32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
break;
case SDL_PIXELFORMAT_XRGB8888:
case SDL_PIXELFORMAT_BGRX32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
break;
}
break;
case SDL_PIXELFORMAT_ABGR8888:
case SDL_PIXELFORMAT_RGBA32:
switch (renderer->target->format) {
case SDL_PIXELFORMAT_ARGB8888:
case SDL_PIXELFORMAT_XRGB8888:
case SDL_PIXELFORMAT_BGRA32:
case SDL_PIXELFORMAT_BGRX32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
break;
case SDL_PIXELFORMAT_XBGR8888:
case SDL_PIXELFORMAT_RGBX32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
break;
}
break;
case SDL_PIXELFORMAT_XRGB8888:
case SDL_PIXELFORMAT_BGRX32:
switch (renderer->target->format) {
case SDL_PIXELFORMAT_ABGR8888:
case SDL_PIXELFORMAT_RGBA32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
break;
case SDL_PIXELFORMAT_ARGB8888:
case SDL_PIXELFORMAT_BGRA32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
break;
case SDL_PIXELFORMAT_XBGR8888:
case SDL_PIXELFORMAT_RGBX32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
break;
}
break;
case SDL_PIXELFORMAT_XBGR8888:
case SDL_PIXELFORMAT_RGBX32:
switch (renderer->target->format) {
case SDL_PIXELFORMAT_ABGR8888:
case SDL_PIXELFORMAT_RGBA32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
break;
case SDL_PIXELFORMAT_ARGB8888:
case SDL_PIXELFORMAT_BGRA32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
break;
case SDL_PIXELFORMAT_XRGB8888:
case SDL_PIXELFORMAT_BGRX32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
break;
}
@ -1088,16 +1092,16 @@ static int SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, vo
}
} else {
switch (texture->format) {
case SDL_PIXELFORMAT_ARGB8888:
case SDL_PIXELFORMAT_BGRA32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
break;
case SDL_PIXELFORMAT_ABGR8888:
case SDL_PIXELFORMAT_RGBA32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
break;
case SDL_PIXELFORMAT_XRGB8888:
case SDL_PIXELFORMAT_BGRX32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
break;
case SDL_PIXELFORMAT_XBGR8888:
case SDL_PIXELFORMAT_RGBX32:
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
break;
#if SDL_HAVE_YUV
@ -1147,10 +1151,25 @@ static int SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, vo
return ret;
}
static void GLES2_InvalidateCachedState(SDL_Renderer *renderer)
{
GLES2_DrawStateCache *cache = &((GLES2_RenderData *)renderer->driverdata)->drawstate;
cache->viewport_dirty = SDL_TRUE;
cache->texture = NULL;
cache->blend = SDL_BLENDMODE_INVALID;
cache->cliprect_enabled_dirty = SDL_TRUE;
cache->cliprect_dirty = SDL_TRUE;
cache->texturing_dirty = SDL_TRUE;
cache->clear_color_dirty = SDL_TRUE;
cache->drawablew = 0;
cache->drawableh = 0;
cache->program = NULL;
}
static int GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_XRGB8888));
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_BGRA32 || renderer->target->format == SDL_PIXELFORMAT_BGRX32));
#if USE_VERTEX_BUFFER_OBJECTS
const int vboidx = data->current_vertex_buffer;
@ -1230,13 +1249,14 @@ static int GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b);
if (color != data->drawstate.clear_color) {
if (data->drawstate.clear_color_dirty || (color != data->drawstate.clear_color)) {
const GLfloat fr = ((GLfloat)r) * inv255f;
const GLfloat fg = ((GLfloat)g) * inv255f;
const GLfloat fb = ((GLfloat)b) * inv255f;
const GLfloat fa = ((GLfloat)a) * inv255f;
data->glClearColor(fr, fg, fb, fa);
data->drawstate.clear_color = color;
data->drawstate.clear_color_dirty = SDL_FALSE;
}
if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) {
@ -1270,7 +1290,7 @@ static int GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
SDL_RenderCommand *nextcmd = cmd->next;
SDL_BlendMode thisblend = cmd->data.draw.blend;
while (nextcmd != NULL) {
while (nextcmd) {
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) {
break; /* can't go any further on this draw call, different render command up next. */
@ -1304,7 +1324,7 @@ static int GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
SDL_RenderCommand *nextcmd = cmd->next;
size_t count = cmd->data.draw.count;
int ret;
while (nextcmd != NULL) {
while (nextcmd) {
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
if (nextcmdtype != thiscmdtype) {
break; /* can't go any further on this draw call, different render command up next. */
@ -1396,7 +1416,7 @@ static void GLES2_DestroyRenderer(SDL_Renderer *renderer)
SDL_free(renderer);
}
static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->driverdata;
GLES2_TextureData *data;
@ -1410,10 +1430,10 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
/* Determine the corresponding GLES texture format params */
switch (texture->format) {
case SDL_PIXELFORMAT_ARGB8888:
case SDL_PIXELFORMAT_ABGR8888:
case SDL_PIXELFORMAT_XRGB8888:
case SDL_PIXELFORMAT_XBGR8888:
case SDL_PIXELFORMAT_BGRA32:
case SDL_PIXELFORMAT_RGBA32:
case SDL_PIXELFORMAT_BGRX32:
case SDL_PIXELFORMAT_RGBX32:
format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
break;
@ -1443,8 +1463,8 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
/* Allocate a texture struct */
data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData));
if (data == NULL) {
return SDL_OutOfMemory();
if (!data) {
return -1;
}
data->texture = 0;
#ifdef GL_TEXTURE_EXTERNAL_OES
@ -1479,7 +1499,7 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
data->pixel_data = SDL_calloc(1, size);
if (!data->pixel_data) {
SDL_free(data);
return SDL_OutOfMemory();
return -1;
}
}
@ -1488,9 +1508,14 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
#if SDL_HAVE_YUV
if (data->yuv) {
renderdata->glGenTextures(1, &data->texture_v);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
return -1;
data->texture_v = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER, 0);
if (data->texture_v) {
data->texture_v_external = SDL_TRUE;
} else {
renderdata->glGenTextures(1, &data->texture_v);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
return -1;
}
}
renderdata->glActiveTexture(GL_TEXTURE2);
renderdata->glBindTexture(data->texture_type, data->texture_v);
@ -1499,10 +1524,16 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, data->texture_v);
renderdata->glGenTextures(1, &data->texture_u);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
return -1;
data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER, 0);
if (data->texture_u) {
data->texture_u_external = SDL_TRUE;
} else {
renderdata->glGenTextures(1, &data->texture_u);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
return -1;
}
}
renderdata->glActiveTexture(GL_TEXTURE1);
renderdata->glBindTexture(data->texture_type, data->texture_u);
@ -1514,10 +1545,17 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
if (GL_CheckError("glTexImage2D()", renderer) < 0) {
return -1;
}
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER, data->texture_u);
} else if (data->nv12) {
renderdata->glGenTextures(1, &data->texture_u);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
return -1;
data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER, 0);
if (data->texture_u) {
data->texture_u_external = SDL_TRUE;
} else {
renderdata->glGenTextures(1, &data->texture_u);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
return -1;
}
}
renderdata->glActiveTexture(GL_TEXTURE1);
renderdata->glBindTexture(data->texture_type, data->texture_u);
@ -1529,12 +1567,18 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
if (GL_CheckError("glTexImage2D()", renderer) < 0) {
return -1;
}
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, data->texture_u);
}
#endif
renderdata->glGenTextures(1, &data->texture);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
return -1;
data->texture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROPERTY_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER, 0);
if (data->texture) {
data->texture_external = SDL_TRUE;
} else {
renderdata->glGenTextures(1, &data->texture);
if (GL_CheckError("glGenTexures()", renderer) < 0) {
return -1;
}
}
texture->driverdata = data;
renderdata->glActiveTexture(GL_TEXTURE0);
@ -1549,6 +1593,8 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
return -1;
}
}
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_NUMBER, data->texture);
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROPERTY_TEXTURE_OPENGLES2_TEXTURE_TARGET, data->texture_type);
if (texture->access == SDL_TEXTUREACCESS_TARGET) {
data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h);
@ -1562,9 +1608,6 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, GLint pitch, GLint bpp)
{
Uint8 *blob = NULL;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 *blob2 = NULL;
#endif
Uint8 *src;
size_t src_pitch;
int y;
@ -1578,8 +1621,8 @@ static int GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoff
src = (Uint8 *)pixels;
if ((size_t)pitch != src_pitch) {
blob = (Uint8 *)SDL_malloc(src_pitch * height);
if (blob == NULL) {
return SDL_OutOfMemory();
if (!blob) {
return -1;
}
src = blob;
for (y = 0; y < height; ++y) {
@ -1590,33 +1633,10 @@ static int GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoff
src = blob;
}
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
if (format == GL_RGBA) {
int i;
Uint32 *src32 = (Uint32 *)src;
blob2 = (Uint32 *)SDL_malloc(src_pitch * height);
if (blob2 == NULL) {
if (blob) {
SDL_free(blob);
}
return SDL_OutOfMemory();
}
for (i = 0; i < (src_pitch * height) / 4; i++) {
blob2[i] = SDL_Swap32(src32[i]);
}
src = (Uint8 *)blob2;
}
#endif
data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
if (blob) {
SDL_free(blob);
}
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
if (blob2) {
SDL_free(blob2);
}
#endif
return 0;
}
@ -1856,7 +1876,7 @@ static int GLES2_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
data->drawstate.viewport_dirty = SDL_TRUE;
if (texture == NULL) {
if (!texture) {
data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer);
} else {
texturedata = (GLES2_TextureData *)texture->driverdata;
@ -1888,12 +1908,14 @@ static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
/* Destroy the texture */
if (tdata) {
data->glDeleteTextures(1, &tdata->texture);
if (tdata->texture && !tdata->texture_external) {
data->glDeleteTextures(1, &tdata->texture);
}
#if SDL_HAVE_YUV
if (tdata->texture_v) {
if (tdata->texture_v && !tdata->texture_v_external) {
data->glDeleteTextures(1, &tdata->texture_v);
}
if (tdata->texture_u) {
if (tdata->texture_u && !tdata->texture_u_external) {
data->glDeleteTextures(1, &tdata->texture_u);
}
#endif
@ -1907,7 +1929,7 @@ static int GLES2_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
Uint32 pixel_format, void *pixels, int pitch)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_RGBA32;
size_t buflen;
void *temp_pixels;
int temp_pitch;
@ -1922,8 +1944,8 @@ static int GLES2_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
}
temp_pixels = SDL_malloc(buflen);
if (temp_pixels == NULL) {
return SDL_OutOfMemory();
if (!temp_pixels) {
return -1;
}
SDL_GetCurrentRenderOutputSize(renderer, &w, &h);
@ -1984,7 +2006,7 @@ static int GLES2_SetVSync(SDL_Renderer *renderer, const int vsync)
return retval;
}
if (interval > 0) {
if (interval != 0) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
} else {
renderer->info.flags &= ~SDL_RENDERER_PRESENTVSYNC;
@ -1992,65 +2014,11 @@ static int GLES2_SetVSync(SDL_Renderer *renderer, const int vsync)
return retval;
}
/*************************************************************************************************
* Bind/unbinding of textures
*************************************************************************************************/
static int GLES2_BindTexture(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh);
static int GLES2_UnbindTexture(SDL_Renderer *renderer, SDL_Texture *texture);
static int GLES2_BindTexture(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
GLES2_ActivateRenderer(renderer);
#if SDL_HAVE_YUV
if (texturedata->yuv) {
data->glActiveTexture(GL_TEXTURE2);
data->glBindTexture(texturedata->texture_type, texturedata->texture_v);
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(texturedata->texture_type, texturedata->texture_u);
data->glActiveTexture(GL_TEXTURE0);
} else if (texturedata->nv12) {
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(texturedata->texture_type, texturedata->texture_u);
data->glActiveTexture(GL_TEXTURE0);
}
#endif
data->glBindTexture(texturedata->texture_type, texturedata->texture);
data->drawstate.texture = texture;
if (texw) {
*texw = 1.0;
}
if (texh) {
*texh = 1.0;
}
return 0;
}
static int GLES2_UnbindTexture(SDL_Renderer *renderer, SDL_Texture *texture)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
GLES2_ActivateRenderer(renderer);
data->glBindTexture(texturedata->texture_type, 0);
data->drawstate.texture = NULL;
return 0;
}
/*************************************************************************************************
* Renderer instantiation *
*************************************************************************************************/
static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props)
{
SDL_Renderer *renderer;
GLES2_RenderData *data;
@ -2070,6 +2038,7 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
goto error;
}
SDL_SyncWindow(window);
window_flags = SDL_GetWindowFlags(window);
/* OpenGL ES 3.0 is a superset of OpenGL ES 2.0 */
@ -2088,20 +2057,19 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
/* Create the renderer struct */
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer));
if (renderer == NULL) {
SDL_OutOfMemory();
if (!renderer) {
goto error;
}
data = (GLES2_RenderData *)SDL_calloc(1, sizeof(GLES2_RenderData));
if (data == NULL) {
if (!data) {
SDL_free(renderer);
SDL_OutOfMemory();
goto error;
}
renderer->info = GLES2_RenderDriver.info;
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
GLES2_InvalidateCachedState(renderer);
renderer->window = window;
/* Create an OpenGL ES 2.0 context */
@ -2137,10 +2105,10 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
* is turned on. Not doing so will freeze the screen's contents to that
* of the first drawn frame.
*/
flags |= SDL_RENDERER_PRESENTVSYNC;
SDL_SetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_TRUE);
#endif
if (flags & SDL_RENDERER_PRESENTVSYNC) {
if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
SDL_GL_SetSwapInterval(1);
} else {
SDL_GL_SetSwapInterval(0);
@ -2150,10 +2118,8 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
int interval = 0;
if (SDL_GL_GetSwapInterval(&interval) < 0) {
/* Error */
} else {
if (interval > 0) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
} else if (interval != 0) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
}
@ -2197,14 +2163,13 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->QueueDrawPoints = GLES2_QueueDrawPoints;
renderer->QueueDrawLines = GLES2_QueueDrawLines;
renderer->QueueGeometry = GLES2_QueueGeometry;
renderer->InvalidateCachedState = GLES2_InvalidateCachedState;
renderer->RunCommandQueue = GLES2_RunCommandQueue;
renderer->RenderReadPixels = GLES2_RenderReadPixels;
renderer->RenderPresent = GLES2_RenderPresent;
renderer->DestroyTexture = GLES2_DestroyTexture;
renderer->DestroyRenderer = GLES2_DestroyRenderer;
renderer->SetVSync = GLES2_SetVSync;
renderer->GL_BindTexture = GLES2_BindTexture;
renderer->GL_UnbindTexture = GLES2_UnbindTexture;
#if SDL_HAVE_YUV
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
@ -2239,7 +2204,6 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
data->drawstate.blend = SDL_BLENDMODE_INVALID;
data->drawstate.clear_color = 0xFFFFFFFF;
data->drawstate.projection[3][0] = -1.0f;
data->drawstate.projection[3][3] = 1.0f;
@ -2264,10 +2228,10 @@ SDL_RenderDriver GLES2_RenderDriver = {
{ "opengles2",
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
4,
{ SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_ABGR8888,
SDL_PIXELFORMAT_XRGB8888,
SDL_PIXELFORMAT_XBGR8888 },
{ SDL_PIXELFORMAT_RGBA32,
SDL_PIXELFORMAT_BGRA32,
SDL_PIXELFORMAT_BGRX32,
SDL_PIXELFORMAT_RGBX32 },
0,
0 }
};

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -30,10 +30,16 @@
#include <dmaKit.h>
#include <gsToolkit.h>
#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
#endif
#include <gsInline.h>
#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
#pragma GCC diagnostic pop
#endif
/* turn black GS Screen */
#define GS_BLACK GS_SETREG_RGBA(0x00, 0x00, 0x00, 0x80)
@ -100,12 +106,12 @@ static void PS2_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event
{
}
static int PS2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int PS2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
GSTEXTURE *ps2_tex = (GSTEXTURE *)SDL_calloc(1, sizeof(GSTEXTURE));
if (ps2_tex == NULL) {
return SDL_OutOfMemory();
if (!ps2_tex) {
return -1;
}
ps2_tex->Width = texture->w;
@ -115,7 +121,7 @@ static int PS2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
if (!ps2_tex->Mem) {
SDL_free(ps2_tex);
return SDL_OutOfMemory();
return -1;
}
texture->driverdata = ps2_tex;
@ -201,7 +207,7 @@ static int PS2_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, c
gs_rgbaq rgbaq;
int i;
if (vertices == NULL) {
if (!vertices) {
return -1;
}
@ -236,7 +242,7 @@ static int PS2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL
GSPRIMUVPOINT *vertices = (GSPRIMUVPOINT *) SDL_AllocateRenderVertices(renderer, count * sizeof(GSPRIMUVPOINT), 4, &cmd->data.draw.first);
GSTEXTURE *ps2_tex = (GSTEXTURE *) texture->driverdata;
if (vertices == NULL) {
if (!vertices) {
return -1;
}
@ -269,7 +275,7 @@ static int PS2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL
} else {
GSPRIMPOINT *vertices = (GSPRIMPOINT *)SDL_AllocateRenderVertices(renderer, count * sizeof(GSPRIMPOINT), 4, &cmd->data.draw.first);
if (vertices == NULL) {
if (!vertices) {
return -1;
}
@ -440,6 +446,11 @@ int PS2_RenderPoints(SDL_Renderer *renderer, void *vertices, SDL_RenderCommand *
return 0;
}
static void PS2_InvalidateCachedState(SDL_Renderer *renderer)
{
/* currently this doesn't do anything. If this needs to do something (and someone is mixing their own rendering calls in!), update this. */
}
static int PS2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
while (cmd) {
@ -530,11 +541,11 @@ static void PS2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
GSTEXTURE *ps2_texture = (GSTEXTURE *)texture->driverdata;
PS2_RenderData *data = (PS2_RenderData *)renderer->driverdata;
if (data == NULL) {
if (!data) {
return;
}
if (ps2_texture == NULL) {
if (!ps2_texture) {
return;
}
@ -574,7 +585,7 @@ static int PS2_SetVSync(SDL_Renderer *renderer, const int vsync)
return 0;
}
static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, Uint32 flags)
static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props)
{
SDL_Renderer *renderer;
PS2_RenderData *data;
@ -583,15 +594,13 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_bool dynamicVsync;
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (renderer == NULL) {
SDL_OutOfMemory();
if (!renderer) {
return NULL;
}
data = (PS2_RenderData *)SDL_calloc(1, sizeof(*data));
if (data == NULL) {
if (!data) {
PS2_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
}
@ -634,7 +643,9 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, Uint32 flags)
data->gsGlobal = gsGlobal;
dynamicVsync = SDL_GetHintBoolean(SDL_HINT_PS2_DYNAMIC_VSYNC, SDL_FALSE);
data->vsync = flags & SDL_RENDERER_PRESENTVSYNC ? (dynamicVsync ? 2 : 1) : 0;
if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
data->vsync = (dynamicVsync ? 2 : 1);
}
renderer->WindowEvent = PS2_WindowEvent;
renderer->CreateTexture = PS2_CreateTexture;
@ -648,6 +659,7 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->QueueDrawPoints = PS2_QueueDrawPoints;
renderer->QueueDrawLines = PS2_QueueDrawPoints;
renderer->QueueGeometry = PS2_QueueGeometry;
renderer->InvalidateCachedState = PS2_InvalidateCachedState;
renderer->RunCommandQueue = PS2_RunCommandQueue;
renderer->RenderReadPixels = PS2_RenderReadPixels;
renderer->RenderPresent = PS2_RenderPresent;
@ -655,9 +667,14 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->DestroyRenderer = PS2_DestroyRenderer;
renderer->SetVSync = PS2_SetVSync;
renderer->info = PS2_RenderDriver.info;
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
PS2_InvalidateCachedState(renderer);
renderer->window = window;
if (data->vsync) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
return renderer;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -281,12 +281,12 @@ static int TextureSwizzle(PSP_TextureData *psp_texture, void *dst)
src = (unsigned int *)psp_texture->data;
data = dst;
if (data == NULL) {
if (!data) {
data = SDL_malloc(psp_texture->size);
}
if (data == NULL) {
return SDL_OutOfMemory();
if (!data) {
return -1;
}
for (j = 0; j < height; j++, blockaddress += 16) {
@ -343,12 +343,12 @@ static int TextureUnswizzle(PSP_TextureData *psp_texture, void *dst)
data = dst;
if (data == NULL) {
if (!data) {
data = SDL_malloc(psp_texture->size);
}
if (data == NULL) {
return SDL_OutOfMemory();
if (!data) {
return -1;
}
ydst = (unsigned char *)data;
@ -391,8 +391,8 @@ static int TextureSpillToSram(PSP_RenderData *data, PSP_TextureData *psp_texture
if (psp_texture->swizzled) {
// Texture was swizzled in vram, just copy to system memory
void *sdata = SDL_malloc(psp_texture->size);
if (sdata == NULL) {
return SDL_OutOfMemory();
if (!sdata) {
return -1;
}
SDL_memcpy(sdata, psp_texture->data, psp_texture->size);
@ -478,13 +478,13 @@ static void PSP_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event
{
}
static int PSP_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int PSP_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
PSP_RenderData *data = renderer->driverdata;
PSP_TextureData *psp_texture = (PSP_TextureData *)SDL_calloc(1, sizeof(*psp_texture));
if (psp_texture == NULL) {
return SDL_OutOfMemory();
if (!psp_texture) {
return -1;
}
psp_texture->swizzled = SDL_FALSE;
@ -527,7 +527,7 @@ static int PSP_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
if (!psp_texture->data) {
SDL_free(psp_texture);
return SDL_OutOfMemory();
return -1;
}
texture->driverdata = psp_texture;
@ -629,7 +629,7 @@ static int PSP_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, c
VertV *verts = (VertV *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertV), 4, &cmd->data.draw.first);
int i;
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -655,10 +655,10 @@ static int PSP_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL
cmd->data.draw.count = count;
size_indices = indices ? size_indices : 0;
if (texture == NULL) {
if (!texture) {
VertCV *verts;
verts = (VertCV *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertCV), 4, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -691,7 +691,7 @@ static int PSP_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL
PSP_TextureData *psp_texture = (PSP_TextureData *)texture->driverdata;
VertTCV *verts;
verts = (VertTCV *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertTCV), 4, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -736,7 +736,7 @@ static int PSP_QueueFillRects(SDL_Renderer *renderer, SDL_RenderCommand *cmd, co
VertV *verts = (VertV *)SDL_AllocateRenderVertices(renderer, count * 2 * sizeof(VertV), 4, &cmd->data.draw.first);
int i;
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -772,7 +772,7 @@ static int PSP_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Tex
if ((MathAbs(u1) - MathAbs(u0)) < 64.0f) {
verts = (VertTV *)SDL_AllocateRenderVertices(renderer, 2 * sizeof(VertTV), 4, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -808,7 +808,7 @@ static int PSP_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Tex
cmd->data.draw.count = count;
verts = (VertTV *)SDL_AllocateRenderVertices(renderer, count * 2 * sizeof(VertTV), 4, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -859,7 +859,7 @@ static int PSP_QueueCopyEx(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_T
float u1 = srcrect->x + srcrect->w;
float v1 = srcrect->y + srcrect->h;
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -1010,7 +1010,7 @@ static void PSP_SetBlendState(PSP_RenderData *data, PSP_BlendState *state)
}
if (state->texture != current->texture) {
if (state->texture != NULL) {
if (state->texture) {
TextureActivate(state->texture);
sceGuEnable(GU_TEXTURE_2D);
} else {
@ -1021,6 +1021,11 @@ static void PSP_SetBlendState(PSP_RenderData *data, PSP_BlendState *state)
*current = *state;
}
static void PSP_InvalidateCachedState(SDL_Renderer *renderer)
{
/* currently this doesn't do anything. If this needs to do something (and someone is mixing their own rendering calls in!), update this. */
}
static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
PSP_RenderData *data = (PSP_RenderData *)renderer->driverdata;
@ -1034,7 +1039,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
rendering backends report a reasonable maximum, so the higher level can flush
if we appear to be exceeding that. */
gpumem = (Uint8 *)sceGuGetMemory(vertsize);
if (gpumem == NULL) {
if (!gpumem) {
return SDL_SetError("Couldn't obtain a %d-byte vertex buffer!", (int)vertsize);
}
SDL_memcpy(gpumem, vertices, vertsize);
@ -1176,7 +1181,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
case SDL_RENDERCMD_GEOMETRY:
{
const size_t count = cmd->data.draw.count;
if (cmd->data.draw.texture == NULL) {
if (!cmd->data.draw.texture) {
const VertCV *verts = (VertCV *)(gpumem + cmd->data.draw.first);
sceGuDisable(GU_TEXTURE_2D);
/* In GU_SMOOTH mode */
@ -1244,11 +1249,11 @@ static void PSP_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
PSP_RenderData *renderdata = (PSP_RenderData *)renderer->driverdata;
PSP_TextureData *psp_texture = (PSP_TextureData *)texture->driverdata;
if (renderdata == NULL) {
if (!renderdata) {
return;
}
if (psp_texture == NULL) {
if (!psp_texture) {
return;
}
@ -1290,24 +1295,21 @@ static int PSP_SetVSync(SDL_Renderer *renderer, const int vsync)
return 0;
}
SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props)
{
SDL_Renderer *renderer;
PSP_RenderData *data;
int pixelformat;
void *doublebuffer = NULL;
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (renderer == NULL) {
SDL_OutOfMemory();
if (!renderer) {
return NULL;
}
data = (PSP_RenderData *)SDL_calloc(1, sizeof(*data));
if (data == NULL) {
if (!data) {
PSP_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
}
@ -1326,6 +1328,7 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->QueueFillRects = PSP_QueueFillRects;
renderer->QueueCopy = PSP_QueueCopy;
renderer->QueueCopyEx = PSP_QueueCopyEx;
renderer->InvalidateCachedState = PSP_InvalidateCachedState;
renderer->RunCommandQueue = PSP_RunCommandQueue;
renderer->RenderReadPixels = PSP_RenderReadPixels;
renderer->RenderPresent = PSP_RenderPresent;
@ -1335,13 +1338,14 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->info = PSP_RenderDriver.info;
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
PSP_InvalidateCachedState(renderer);
renderer->window = window;
data->initialized = SDL_TRUE;
data->most_recent_target = NULL;
data->least_recent_target = NULL;
if (flags & SDL_RENDERER_PRESENTVSYNC) {
if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
data->vsync = SDL_TRUE;
} else {
data->vsync = SDL_FALSE;
@ -1400,6 +1404,9 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, Uint32 flags)
sceKernelRegisterSubIntrHandler(PSP_VBLANK_INT, 0, psp_on_vblank, data);
sceKernelEnableSubIntr(PSP_VBLANK_INT, 0);
if (data->vsync) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
return renderer;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -211,7 +211,7 @@ int SDL_BlendFillRect(SDL_Surface *dst, const SDL_Rect *rect,
{
SDL_Rect clipped;
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("SDL_BlendFillRect(): dst");
}
@ -281,7 +281,7 @@ int SDL_BlendFillRects(SDL_Surface *dst, const SDL_Rect *rects, int count,
SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
int status = 0;
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("SDL_BlendFillRects(): dst");
}
@ -325,7 +325,7 @@ int SDL_BlendFillRects(SDL_Surface *dst, const SDL_Rect *rects, int count,
break;
}
if (func == NULL) {
if (!func) {
if (!dst->format->Amask) {
func = SDL_BlendFillRect_RGB;
} else {

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -798,12 +798,12 @@ int SDL_BlendLine(SDL_Surface *dst, int x1, int y1, int x2, int y2,
{
BlendLineFunc func;
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("SDL_BlendLine(): dst");
}
func = SDL_CalculateBlendLineFunc(dst->format);
if (func == NULL) {
if (!func) {
return SDL_SetError("SDL_BlendLine(): Unsupported surface format");
}
@ -826,12 +826,12 @@ int SDL_BlendLines(SDL_Surface *dst, const SDL_Point *points, int count,
SDL_bool draw_end;
BlendLineFunc func;
if (dst == NULL) {
if (!dst) {
return SDL_SetError("SDL_BlendLines(): Passed NULL destination surface");
}
func = SDL_CalculateBlendLineFunc(dst->format);
if (func == NULL) {
if (!func) {
return SDL_SetError("SDL_BlendLines(): Unsupported surface format");
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -209,7 +209,7 @@ static int SDL_BlendPoint_RGBA(SDL_Surface *dst, int x, int y, SDL_BlendMode ble
int SDL_BlendPoint(SDL_Surface *dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
Uint8 g, Uint8 b, Uint8 a)
{
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("SDL_BlendPoint(): dst");
}
@ -277,7 +277,7 @@ int SDL_BlendPoints(SDL_Surface *dst, const SDL_Point *points, int count,
SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
int status = 0;
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("SDL_BlendPoints(): dst");
}
@ -323,7 +323,7 @@ int SDL_BlendPoints(SDL_Surface *dst, const SDL_Point *points, int count,
break;
}
if (func == NULL) {
if (!func) {
if (!dst->format->Amask) {
func = SDL_BlendPoint_RGB;
} else {

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -137,12 +137,12 @@ int SDL_DrawLine(SDL_Surface *dst, int x1, int y1, int x2, int y2, Uint32 color)
{
DrawLineFunc func;
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("SDL_DrawLine(): dst");
}
func = SDL_CalculateDrawLineFunc(dst->format);
if (func == NULL) {
if (!func) {
return SDL_SetError("SDL_DrawLine(): Unsupported surface format");
}
@ -165,12 +165,12 @@ int SDL_DrawLines(SDL_Surface *dst, const SDL_Point *points, int count,
SDL_bool draw_end;
DrawLineFunc func;
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("SDL_DrawLines(): dst");
}
func = SDL_CalculateDrawLineFunc(dst->format);
if (func == NULL) {
if (!func) {
return SDL_SetError("SDL_DrawLines(): Unsupported surface format");
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -27,7 +27,7 @@
int SDL_DrawPoint(SDL_Surface *dst, int x, int y, Uint32 color)
{
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("SDL_DrawPoint(): dst");
}
@ -67,7 +67,7 @@ int SDL_DrawPoints(SDL_Surface *dst, const SDL_Point *points, int count,
int i;
int x, y;
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("SDL_DrawPoints(): dst");
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -97,11 +97,11 @@ static int SW_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
return SDL_SetError("Software renderer doesn't have an output surface");
}
static int SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int SW_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
SDL_Surface *surface = SDL_CreateSurface(texture->w, texture->h, texture->format);
if (surface == NULL) {
if (!surface) {
return SDL_SetError("Cannot create surface");
}
texture->driverdata = surface;
@ -191,7 +191,7 @@ static int SW_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, co
SDL_Point *verts = (SDL_Point *)SDL_AllocateRenderVertices(renderer, count * sizeof(SDL_Point), 0, &cmd->data.draw.first);
int i;
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -210,7 +210,7 @@ static int SW_QueueFillRects(SDL_Renderer *renderer, SDL_RenderCommand *cmd, con
SDL_Rect *verts = (SDL_Rect *)SDL_AllocateRenderVertices(renderer, count * sizeof(SDL_Rect), 0, &cmd->data.draw.first);
int i;
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -231,7 +231,7 @@ static int SW_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Text
{
SDL_Rect *verts = (SDL_Rect *)SDL_AllocateRenderVertices(renderer, 2 * sizeof(SDL_Rect), 0, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -268,7 +268,7 @@ static int SW_QueueCopyEx(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Te
{
CopyExData *verts = (CopyExData *)SDL_AllocateRenderVertices(renderer, sizeof(CopyExData), 0, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -302,7 +302,7 @@ static int Blit_to_Screen(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *surf
r.y = (int)((float)dstrect->y * scale_y);
r.w = (int)((float)dstrect->w * scale_x);
r.h = (int)((float)dstrect->h * scale_y);
retval = SDL_PrivateBlitSurfaceScaled(src, srcrect, surface, &r, scaleMode);
retval = SDL_BlitSurfaceScaled(src, srcrect, surface, &r, scaleMode);
} else {
retval = SDL_BlitSurface(src, srcrect, surface, dstrect);
}
@ -324,7 +324,7 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex
int blitRequired = SDL_FALSE;
int isOpaque = SDL_FALSE;
if (surface == NULL) {
if (!surface) {
return -1;
}
@ -344,7 +344,7 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex
* The original source surface must be treated as read-only.
*/
src_clone = SDL_CreateSurfaceFrom(src->pixels, src->w, src->h, src->pitch, src->format->format);
if (src_clone == NULL) {
if (!src_clone) {
if (SDL_MUSTLOCK(src)) {
SDL_UnlockSurface(src);
}
@ -387,7 +387,7 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex
*/
if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) {
mask = SDL_CreateSurface(final_rect->w, final_rect->h, SDL_PIXELFORMAT_ARGB8888);
if (mask == NULL) {
if (!mask) {
retval = -1;
} else {
SDL_SetSurfaceBlendMode(mask, SDL_BLENDMODE_MOD);
@ -400,11 +400,11 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex
if (!retval && (blitRequired || applyModulation)) {
SDL_Rect scale_rect = tmp_rect;
src_scaled = SDL_CreateSurface(final_rect->w, final_rect->h, SDL_PIXELFORMAT_ARGB8888);
if (src_scaled == NULL) {
if (!src_scaled) {
retval = -1;
} else {
SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE);
retval = SDL_PrivateBlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, texture->scaleMode);
retval = SDL_BlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, texture->scaleMode);
SDL_DestroySurface(src_clone);
src_clone = src_scaled;
src_scaled = NULL;
@ -423,15 +423,15 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex
src_rotated = SDLgfx_rotateSurface(src_clone, angle,
(texture->scaleMode == SDL_SCALEMODE_NEAREST) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL,
&rect_dest, cangle, sangle, center);
if (src_rotated == NULL) {
if (!src_rotated) {
retval = -1;
}
if (!retval && mask != NULL) {
if (!retval && mask) {
/* The mask needed for the NONE blend mode gets rotated with the same parameters. */
mask_rotated = SDLgfx_rotateSurface(mask, angle,
SDL_FALSE, 0, 0,
&rect_dest, cangle, sangle, center);
if (mask_rotated == NULL) {
if (!mask_rotated) {
retval = -1;
}
}
@ -487,7 +487,7 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex
src_rotated_rgb = SDL_CreateSurfaceFrom(src_rotated->pixels, src_rotated->w, src_rotated->h,
src_rotated->pitch, f);
if (src_rotated_rgb == NULL) {
if (!src_rotated_rgb) {
retval = -1;
} else {
SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD);
@ -499,7 +499,7 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex
}
SDL_DestroySurface(mask_rotated);
}
if (src_rotated != NULL) {
if (src_rotated) {
SDL_DestroySurface(src_rotated);
}
}
@ -508,10 +508,10 @@ static int SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Tex
if (SDL_MUSTLOCK(src)) {
SDL_UnlockSurface(src);
}
if (mask != NULL) {
if (mask) {
SDL_DestroySurface(mask);
}
if (src_clone != NULL) {
if (src_clone) {
SDL_DestroySurface(src_clone);
}
return retval;
@ -538,10 +538,10 @@ static int SW_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_
int i;
int count = indices ? num_indices : num_vertices;
void *verts;
size_t sz = texture != NULL ? sizeof(GeometryCopyData) : sizeof(GeometryFillData);
size_t sz = texture ? sizeof(GeometryCopyData) : sizeof(GeometryFillData);
verts = SDL_AllocateRenderVertices(renderer, count * sz, 0, &cmd->data.draw.first);
if (verts == NULL) {
if (!verts) {
return -1;
}
@ -643,7 +643,7 @@ static void SetDrawState(SDL_Surface *surface, SW_DrawStateCache *drawstate)
const SDL_Rect *cliprect = drawstate->cliprect;
SDL_assert_release(viewport != NULL); /* the higher level should have forced a SDL_RENDERCMD_SETVIEWPORT */
if (cliprect != NULL) {
if (cliprect && viewport) {
SDL_Rect clip_rect;
clip_rect.x = cliprect->x + viewport->x;
clip_rect.y = cliprect->y + viewport->y;
@ -658,12 +658,18 @@ static void SetDrawState(SDL_Surface *surface, SW_DrawStateCache *drawstate)
}
}
static void SW_InvalidateCachedState(SDL_Renderer *renderer)
{
/* SW_DrawStateCache only lives during SW_RunCommandQueue, so nothing to do here! */
}
static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
SDL_Surface *surface = SW_ActivateRenderer(renderer);
SW_DrawStateCache drawstate;
if (surface == NULL) {
if (!surface) {
return -1;
}
@ -717,7 +723,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
SetDrawState(surface, &drawstate);
/* Apply viewport */
if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) {
if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) {
int i;
for (i = 0; i < count; i++) {
verts[i].x += drawstate.viewport->x;
@ -745,7 +751,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
SetDrawState(surface, &drawstate);
/* Apply viewport */
if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) {
if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) {
int i;
for (i = 0; i < count; i++) {
verts[i].x += drawstate.viewport->x;
@ -773,7 +779,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
SetDrawState(surface, &drawstate);
/* Apply viewport */
if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) {
if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) {
int i;
for (i = 0; i < count; i++) {
verts[i].x += drawstate.viewport->x;
@ -802,7 +808,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
PrepTextureForCopy(cmd);
/* Apply viewport */
if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) {
if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) {
dstrect->x += drawstate.viewport->x;
dstrect->y += drawstate.viewport->y;
}
@ -837,7 +843,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
SDL_SetSurfaceColorMod(src, 255, 255, 255);
SDL_SetSurfaceAlphaMod(src, 255);
SDL_PrivateBlitSurfaceScaled(src, srcrect, tmp, &r, texture->scaleMode);
SDL_BlitSurfaceScaled(src, srcrect, tmp, &r, texture->scaleMode);
SDL_SetSurfaceColorMod(tmp, rMod, gMod, bMod);
SDL_SetSurfaceAlphaMod(tmp, alphaMod);
@ -848,7 +854,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
/* No need to set back r/g/b/a/blendmode to 'src' since it's done in PrepTextureForCopy() */
}
} else {
SDL_PrivateBlitSurfaceScaled(src, srcrect, surface, dstrect, texture->scaleMode);
SDL_BlitSurfaceScaled(src, srcrect, surface, dstrect, texture->scaleMode);
}
}
break;
@ -861,7 +867,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
PrepTextureForCopy(cmd);
/* Apply viewport */
if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) {
if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) {
copydata->dstrect.x += drawstate.viewport->x;
copydata->dstrect.y += drawstate.viewport->y;
}
@ -890,7 +896,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
PrepTextureForCopy(cmd);
/* Apply viewport */
if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) {
if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) {
SDL_Point vp;
vp.x = drawstate.viewport->x;
vp.y = drawstate.viewport->y;
@ -913,7 +919,7 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
GeometryFillData *ptr = (GeometryFillData *)verts;
/* Apply viewport */
if (drawstate.viewport != NULL && (drawstate.viewport->x || drawstate.viewport->y)) {
if (drawstate.viewport && (drawstate.viewport->x || drawstate.viewport->y)) {
SDL_Point vp;
vp.x = drawstate.viewport->x;
vp.y = drawstate.viewport->y;
@ -948,7 +954,7 @@ static int SW_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
Uint32 src_format;
void *src_pixels;
if (surface == NULL) {
if (!surface) {
return -1;
}
@ -975,7 +981,7 @@ static int SW_RenderPresent(SDL_Renderer *renderer)
{
SDL_Window *window = renderer->window;
if (window == NULL) {
if (!window) {
return -1;
}
return SDL_UpdateWindowSurface(window);
@ -990,8 +996,12 @@ static void SW_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static void SW_DestroyRenderer(SDL_Renderer *renderer)
{
SDL_Window *window = renderer->window;
SW_RenderData *data = (SW_RenderData *)renderer->driverdata;
if (window) {
SDL_DestroyWindowSurface(window);
}
SDL_free(data);
SDL_free(renderer);
}
@ -1094,21 +1104,19 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface)
SDL_Renderer *renderer;
SW_RenderData *data;
if (surface == NULL) {
if (!surface) {
SDL_InvalidParamError("surface");
return NULL;
}
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (renderer == NULL) {
SDL_OutOfMemory();
if (!renderer) {
return NULL;
}
data = (SW_RenderData *)SDL_calloc(1, sizeof(*data));
if (data == NULL) {
if (!data) {
SW_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
}
data->surface = surface;
@ -1130,6 +1138,7 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface)
renderer->QueueCopy = SW_QueueCopy;
renderer->QueueCopyEx = SW_QueueCopyEx;
renderer->QueueGeometry = SW_QueueGeometry;
renderer->InvalidateCachedState = SW_InvalidateCachedState;
renderer->RunCommandQueue = SW_RunCommandQueue;
renderer->RenderReadPixels = SW_RenderReadPixels;
renderer->RenderPresent = SW_RenderPresent;
@ -1137,15 +1146,14 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface)
renderer->DestroyRenderer = SW_DestroyRenderer;
renderer->info = SW_RenderDriver.info;
renderer->driverdata = data;
SW_InvalidateCachedState(renderer);
SW_SelectBestFormats(renderer, surface->format->format);
SW_ActivateRenderer(renderer);
return renderer;
}
static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, Uint32 flags)
static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props)
{
const char *hint;
SDL_Surface *surface;
@ -1153,14 +1161,18 @@ static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, Uint32 flags)
/* Set the vsync hint based on our flags, if it's not already set */
hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC);
if (hint == NULL || !*hint) {
if (!hint || !*hint) {
no_hint_set = SDL_TRUE;
} else {
no_hint_set = SDL_FALSE;
}
if (no_hint_set) {
SDL_SetHint(SDL_HINT_RENDER_VSYNC, (flags & SDL_RENDERER_PRESENTVSYNC) ? "1" : "0");
if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1");
} else {
SDL_SetHint(SDL_HINT_RENDER_VSYNC, "0");
}
}
surface = SDL_GetWindowSurface(window);
@ -1170,7 +1182,7 @@ static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_SetHint(SDL_HINT_RENDER_VSYNC, "");
}
if (surface == NULL) {
if (!surface) {
return NULL;
}
return SW_CreateRendererForSurface(surface);

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -44,7 +44,7 @@ Andreas Schiffler -- aschiffler at ferzkopp dot net
/* ---- Internally used structures */
/**
\brief A 32 bit RGBA pixel.
A 32 bit RGBA pixel.
*/
typedef struct tColorRGBA
{
@ -55,7 +55,7 @@ typedef struct tColorRGBA
} tColorRGBA;
/**
\brief A 8bit Y/palette pixel.
A 8bit Y/palette pixel.
*/
typedef struct tColorY
{
@ -63,7 +63,7 @@ typedef struct tColorY
} tColorY;
/**
\brief Number of guard rows added to destination surfaces.
Number of guard rows added to destination surfaces.
This is a simple but effective workaround for observed issues.
These rows allocate extra memory and are then hidden from the surface.
@ -75,7 +75,7 @@ to a situation where the program can segfault.
#define GUARD_ROWS (2)
/**
\brief Returns colorkey info for a surface
Returns colorkey info for a surface
*/
static Uint32 get_colorkey(SDL_Surface *src)
{
@ -100,7 +100,7 @@ static void rotate(double sx, double sy, double sinangle, double cosangle, const
}
/**
\brief Internal target surface sizing function for rotations with trig result return.
Internal target surface sizing function for rotations with trig result return.
\param width The source surface width.
\param height The source surface height.
@ -249,7 +249,7 @@ static void transformSurfaceY90(SDL_Surface *src, SDL_Surface *dst, int angle, i
#undef TRANSFORM_SURFACE_90
/**
\brief Internal 32 bit rotozoomer with optional anti-aliasing.
Internal 32 bit rotozoomer with optional anti-aliasing.
Rotates and zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control
parameters by scanning the destination surface and applying optionally anti-aliasing
@ -296,8 +296,8 @@ static void transformSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int isin, i
int y;
for (y = 0; y < dst->h; y++) {
int x;
double src_x = (rect_dest->x + 0 + 0.5 - center->x);
double src_y = (rect_dest->y + y + 0.5 - center->y);
double src_x = ((double)rect_dest->x + 0 + 0.5 - center->x);
double src_y = ((double)rect_dest->y + y + 0.5 - center->y);
int sdx = (int)((icos * src_x - isin * src_y) + cx - fp_half);
int sdy = (int)((isin * src_x + icos * src_y) + cy - fp_half);
for (x = 0; x < dst->w; x++) {
@ -364,8 +364,8 @@ static void transformSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int isin, i
int y;
for (y = 0; y < dst->h; y++) {
int x;
double src_x = (rect_dest->x + 0 + 0.5 - center->x);
double src_y = (rect_dest->y + y + 0.5 - center->y);
double src_x = ((double)rect_dest->x + 0 + 0.5 - center->x);
double src_y = ((double)rect_dest->y + y + 0.5 - center->y);
int sdx = (int)((icos * src_x - isin * src_y) + cx - fp_half);
int sdy = (int)((isin * src_x + icos * src_y) + cy - fp_half);
for (x = 0; x < dst->w; x++) {
@ -391,7 +391,7 @@ static void transformSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int isin, i
/**
\brief Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing.
Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing.
Rotates and zooms 8 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control
parameters by scanning the destination surface.
@ -437,8 +437,8 @@ static void transformSurfaceY(SDL_Surface *src, SDL_Surface *dst, int isin, int
*/
for (y = 0; y < dst->h; y++) {
int x;
double src_x = (rect_dest->x + 0 + 0.5 - center->x);
double src_y = (rect_dest->y + y + 0.5 - center->y);
double src_x = ((double)rect_dest->x + 0 + 0.5 - center->x);
double src_y = ((double)rect_dest->y + y + 0.5 - center->y);
int sdx = (int)((icos * src_x - isin * src_y) + cx - fp_half);
int sdy = (int)((isin * src_x + icos * src_y) + cy - fp_half);
for (x = 0; x < dst->w; x++) {
@ -462,7 +462,7 @@ static void transformSurfaceY(SDL_Surface *src, SDL_Surface *dst, int isin, int
}
/**
\brief Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-aliasing.
Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-aliasing.
Rotates a 32-bit or 8-bit 'src' surface to newly created 'dst' surface.
'angle' is the rotation in degrees, 'center' the rotation center. If 'smooth' is set
@ -498,7 +498,7 @@ SDL_Surface *SDLgfx_rotateSurface(SDL_Surface *src, double angle, int smooth, in
double sangleinv, cangleinv;
/* Sanity check */
if (src == NULL) {
if (!src) {
return NULL;
}
@ -522,7 +522,7 @@ SDL_Surface *SDLgfx_rotateSurface(SDL_Surface *src, double angle, int smooth, in
if (is8bit) {
/* Target surface is 8 bit */
rz_dst = SDL_CreateSurface(rect_dest->w, rect_dest->h + GUARD_ROWS, src->format->format);
if (rz_dst != NULL) {
if (rz_dst) {
if (src->format->palette) {
for (i = 0; i < src->format->palette->ncolors; i++) {
rz_dst->format->palette->colors[i] = src->format->palette->colors[i];
@ -536,7 +536,7 @@ SDL_Surface *SDLgfx_rotateSurface(SDL_Surface *src, double angle, int smooth, in
}
/* Check target */
if (rz_dst == NULL) {
if (!rz_dst) {
return NULL;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -86,9 +86,9 @@ int SDL_FillTriangle(SDL_Surface *dst, const SDL_Point points[3], Uint32 color)
#endif
/* cross product AB x AC */
static int cross_product(const SDL_Point *a, const SDL_Point *b, int c_x, int c_y)
static Sint64 cross_product(const SDL_Point *a, const SDL_Point *b, int c_x, int c_y)
{
return (b->x - a->x) * (c_y - a->y) - (b->y - a->y) * (c_x - a->x);
return ((Sint64)(b->x - a->x)) * ((Sint64)(c_y - a->y)) - ((Sint64)(b->y - a->y)) * ((Sint64)(c_x - a->x));
}
/* check for top left rules */
@ -112,10 +112,23 @@ static int is_top_left(const SDL_Point *a, const SDL_Point *b, int is_clockwise)
return 0;
}
/* x = (y << FP_BITS) */
/* prevent runtime error: left shift of negative value */
#define PRECOMP(x, y) \
val = y; \
if (val >= 0) { \
x = val << FP_BITS; \
} else { \
val *= -1; \
x = val << FP_BITS; \
x *= -1; \
}
void trianglepoint_2_fixedpoint(SDL_Point *a)
{
a->x <<= FP_BITS;
a->y <<= FP_BITS;
int val;
PRECOMP(a->x, a->x);
PRECOMP(a->y, a->y);
}
/* bounding rect of three points (in fixed point) */
@ -157,9 +170,9 @@ static void bounding_rect(const SDL_Point *a, const SDL_Point *b, const SDL_Poin
int x, y; \
for (y = 0; y < dstrect.h; y++) { \
/* y start */ \
int w0 = w0_row; \
int w1 = w1_row; \
int w2 = w2_row; \
Sint64 w0 = w0_row; \
Sint64 w1 = w1_row; \
Sint64 w2 = w2_row; \
for (x = 0; x < dstrect.w; x++) { \
/* In triangle */ \
if (w0 + bias_w0 >= 0 && w1 + bias_w1 >= 0 && w2 + bias_w2 >= 0) { \
@ -212,14 +225,14 @@ int SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Poin
int area, is_clockwise;
int d2d1_y, d1d2_x, d0d2_y, d2d0_x, d1d0_y, d0d1_x;
int w0_row, w1_row, w2_row;
Sint64 w0_row, w1_row, w2_row;
int bias_w0, bias_w1, bias_w2;
int is_uniform;
SDL_Surface *tmp = NULL;
if (dst == NULL) {
if (!dst) {
return -1;
}
@ -271,7 +284,7 @@ int SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Poin
/* Use an intermediate surface */
tmp = SDL_CreateSurface(dstrect.w, dstrect.h, format);
if (tmp == NULL) {
if (!tmp) {
ret = -1;
goto end;
}
@ -297,12 +310,15 @@ int SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Poin
is_clockwise = area > 0;
area = SDL_abs(area);
d2d1_y = (d1->y - d2->y) << FP_BITS;
d0d2_y = (d2->y - d0->y) << FP_BITS;
d1d0_y = (d0->y - d1->y) << FP_BITS;
d1d2_x = (d2->x - d1->x) << FP_BITS;
d2d0_x = (d0->x - d2->x) << FP_BITS;
d0d1_x = (d1->x - d0->x) << FP_BITS;
{
int val;
PRECOMP(d2d1_y, d1->y - d2->y)
PRECOMP(d0d2_y, d2->y - d0->y)
PRECOMP(d1d0_y, d0->y - d1->y)
PRECOMP(d1d2_x, d2->x - d1->x)
PRECOMP(d2d0_x, d0->x - d2->x)
PRECOMP(d0d1_x, d1->x - d0->x)
}
/* Starting point for rendering, at the middle of a pixel */
{
@ -338,12 +354,7 @@ int SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Poin
if (is_uniform) {
Uint32 color;
if (tmp) {
if (dst->format->Amask) {
color = SDL_MapRGBA(tmp->format, c0.r, c0.g, c0.b, c0.a);
} else {
// color = SDL_MapRGB(tmp->format, c0.r, c0.g, c0.b);
color = SDL_MapRGBA(tmp->format, c0.r, c0.g, c0.b, c0.a);
}
color = SDL_MapRGBA(tmp->format, c0.r, c0.g, c0.b, c0.a);
} else {
color = SDL_MapRGBA(dst->format, c0.r, c0.g, c0.b, c0.a);
}
@ -457,14 +468,14 @@ int SDL_SW_BlitTriangle(
int d2d1_y, d1d2_x, d0d2_y, d2d0_x, d1d0_y, d0d1_x;
int s2s0_x, s2s1_x, s2s0_y, s2s1_y;
int w0_row, w1_row, w2_row;
Sint64 w0_row, w1_row, w2_row;
int bias_w0, bias_w1, bias_w2;
int is_uniform;
int has_modulation;
if (src == NULL || dst == NULL) {
if (!src || !dst) {
return -1;
}
@ -569,13 +580,15 @@ int SDL_SW_BlitTriangle(
is_clockwise = area > 0;
area = SDL_abs(area);
d2d1_y = (d1->y - d2->y) << FP_BITS;
d0d2_y = (d2->y - d0->y) << FP_BITS;
d1d0_y = (d0->y - d1->y) << FP_BITS;
d1d2_x = (d2->x - d1->x) << FP_BITS;
d2d0_x = (d0->x - d2->x) << FP_BITS;
d0d1_x = (d1->x - d0->x) << FP_BITS;
{
int val;
PRECOMP(d2d1_y, d1->y - d2->y)
PRECOMP(d0d2_y, d2->y - d0->y)
PRECOMP(d1d0_y, d0->y - d1->y)
PRECOMP(d1d2_x, d2->x - d1->x)
PRECOMP(d2d0_x, d0->x - d2->x)
PRECOMP(d0d1_x, d1->x - d0->x)
}
s2s0_x = s0->x - s2->x;
s2s1_x = s1->x - s2->x;
@ -788,15 +801,20 @@ static void SDL_BlitTriangle_Slow(SDL_BlitInfo *info,
continue;
}
}
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB, dstA);
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB);
dstA = 0xFF;
if ((flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL))) {
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB, dstA);
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB);
dstA = 0xFF;
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
dstpixel = *((Uint32 *) (dst));
RGBA_FROM_ARGB2101010(dstpixel, dstR, dstG, dstB, dstA);
}
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
dstpixel = *((Uint32 *)(dst));
RGBA_FROM_ARGB2101010(dstpixel, dstR, dstG, dstB, dstA);
/* don't care */
dstR = dstG = dstB = dstA = 0;
}
if (!is_uniform) {

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -42,13 +42,13 @@
#include <psp2/sysmodule.h>
#endif
static SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags);
static SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props);
static void VITA_GXM_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event);
static SDL_bool VITA_GXM_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode);
static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture);
static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props);
static int VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, const void *pixels, int pitch);
@ -89,6 +89,8 @@ static int VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd
static int VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
static void VITA_GXM_InvalidateCachedState(SDL_Renderer *renderer);
static int VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
static int VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
@ -167,7 +169,7 @@ void StartDrawing(SDL_Renderer *renderer)
// data->colorFragmentProgram = in->color;
// data->textureFragmentProgram = in->texture;
if (renderer->target == NULL) {
if (!renderer->target) {
sceGxmBeginScene(
data->gxm_context,
0,
@ -209,21 +211,19 @@ static int VITA_GXM_SetVSync(SDL_Renderer *renderer, const int vsync)
return 0;
}
SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags)
SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_props)
{
SDL_Renderer *renderer;
VITA_GXM_RenderData *data;
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(*renderer));
if (renderer == NULL) {
SDL_OutOfMemory();
if (!renderer) {
return NULL;
}
data = (VITA_GXM_RenderData *)SDL_calloc(1, sizeof(VITA_GXM_RenderData));
if (data == NULL) {
if (!data) {
SDL_free(renderer);
SDL_OutOfMemory();
return NULL;
}
@ -244,6 +244,7 @@ SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->QueueDrawPoints = VITA_GXM_QueueDrawPoints;
renderer->QueueDrawLines = VITA_GXM_QueueDrawLines;
renderer->QueueGeometry = VITA_GXM_QueueGeometry;
renderer->InvalidateCachedState = VITA_GXM_InvalidateCachedState;
renderer->RunCommandQueue = VITA_GXM_RunCommandQueue;
renderer->RenderReadPixels = VITA_GXM_RenderReadPixels;
renderer->RenderPresent = VITA_GXM_RenderPresent;
@ -254,12 +255,14 @@ SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->info = VITA_GXM_RenderDriver.info;
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
VITA_GXM_InvalidateCachedState(renderer);
renderer->window = window;
data->initialized = SDL_TRUE;
if (flags & SDL_RENDERER_PRESENTVSYNC) {
if (SDL_GetBooleanProperty(create_props, SDL_PROPERTY_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN, SDL_FALSE)) {
data->displayData.wait_vblank = SDL_TRUE;
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
} else {
data->displayData.wait_vblank = SDL_FALSE;
}
@ -288,13 +291,13 @@ static SDL_bool VITA_GXM_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode
return SDL_FALSE;
}
static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static int VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata;
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)SDL_calloc(1, sizeof(VITA_GXM_TextureData));
if (vita_texture == NULL) {
return SDL_OutOfMemory();
if (!vita_texture) {
return -1;
}
vita_texture->tex = create_gxm_texture(
@ -581,7 +584,7 @@ static int VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
*pitch = vita_texture->pitch;
// make sure that rendering is finished on render target textures
if (vita_texture->tex->gxm_rendertarget != NULL) {
if (vita_texture->tex->gxm_rendertarget) {
sceGxmFinish(data->gxm_context);
}
@ -731,7 +734,7 @@ static int VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd
data,
count * sizeof(texture_vertex));
if (vertices == NULL) {
if (!vertices) {
return -1;
}
@ -770,7 +773,7 @@ static int VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd
data,
count * sizeof(color_vertex));
if (vertices == NULL) {
if (!vertices) {
return -1;
}
@ -928,6 +931,11 @@ static int SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd)
return 0;
}
static void VITA_GXM_InvalidateCachedState(SDL_Renderer *renderer)
{
/* currently this doesn't do anything. If this needs to do something (and someone is mixing their own rendering calls in!), update this. */
}
static int VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata;
@ -1004,7 +1012,7 @@ static int VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *c
SDL_RenderCommand *nextcmd = cmd->next;
size_t count = cmd->data.draw.count;
int ret;
while (nextcmd != NULL) {
while (nextcmd) {
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
if (nextcmdtype != thiscmdtype) {
break; /* can't go any further on this draw call, different render command up next. */
@ -1101,8 +1109,8 @@ static int VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rec
}
temp_pixels = SDL_malloc(buflen);
if (temp_pixels == NULL) {
return SDL_OutOfMemory();
if (!temp_pixels) {
return -1;
}
SDL_GetCurrentRenderOutputSize(renderer, &w, &h);
@ -1184,15 +1192,15 @@ static void VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->driverdata;
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->driverdata;
if (data == NULL) {
if (!data) {
return;
}
if (vita_texture == NULL) {
if (!vita_texture) {
return;
}
if (vita_texture->tex == NULL) {
if (!vita_texture->tex) {
return;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -66,7 +66,7 @@ void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size)
{
void *mem;
if (data->texturePool == NULL) {
if (!data->texturePool) {
int poolsize;
int ret;
SceKernelFreeMemorySizeInfo info;
@ -88,7 +88,7 @@ void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size)
}
data->texturePool = sceClibMspaceCreate(mem, poolsize);
if (data->texturePool == NULL) {
if (!data->texturePool) {
return NULL;
}
ret = sceGxmMapMemory(mem, poolsize, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE);
@ -101,7 +101,7 @@ void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size)
void vita_gpu_mem_free(VITA_GXM_RenderData *data, void *ptr)
{
if (data->texturePool != NULL) {
if (data->texturePool) {
sceClibMspaceFree(data->texturePool, ptr);
}
}
@ -109,7 +109,7 @@ void vita_gpu_mem_free(VITA_GXM_RenderData *data, void *ptr)
void vita_gpu_mem_destroy(VITA_GXM_RenderData *data)
{
void *mem = NULL;
if (data->texturePool != NULL) {
if (data->texturePool) {
sceClibMspaceDestroy(data->texturePool);
data->texturePool = NULL;
if (sceKernelGetMemBlockBase(data->texturePoolUID, &mem) < 0) {

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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
@ -1001,7 +1001,7 @@ gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsig
tex_size += (((aligned_w + 1) / 2) * ((h + 1) / 2)) * 2;
}
if (texture == NULL) {
if (!texture) {
return NULL;
}
@ -1015,7 +1015,7 @@ gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsig
tex_size);
/* Try SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE in case we're out of VRAM */
if (texture_data == NULL) {
if (!texture_data) {
SDL_LogWarn(SDL_LOG_CATEGORY_RENDER, "CDRAM texture allocation failed\n");
texture_data = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
@ -1028,7 +1028,7 @@ gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsig
texture->cdram = 1;
}
if (texture_data == NULL) {
if (!texture_data) {
SDL_free(texture);
return NULL;
}

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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

View File

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2024 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