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
@ -1023,7 +1023,7 @@ static int RLEAlphaSurface(SDL_Surface *surface)
SDL_PixelFormat *, SDL_PixelFormat *);
dest = surface->map->dst;
if (dest == NULL) {
if (!dest) {
return -1;
}
df = dest->format;
@ -1080,8 +1080,8 @@ static int RLEAlphaSurface(SDL_Surface *surface)
maxsize += sizeof(RLEDestFormat);
rlebuf = (Uint8 *)SDL_malloc(maxsize);
if (rlebuf == NULL) {
return SDL_OutOfMemory();
if (!rlebuf) {
return -1;
}
{
/* save the destination format so we can undo the encoding later */
@ -1226,7 +1226,7 @@ static int RLEAlphaSurface(SDL_Surface *surface)
/* reallocate the buffer to release unused memory */
{
Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf);
if (p == NULL) {
if (!p) {
p = rlebuf;
}
surface->map->data = p;
@ -1299,8 +1299,8 @@ static int RLEColorkeySurface(SDL_Surface *surface)
}
rlebuf = (Uint8 *)SDL_malloc(maxsize);
if (rlebuf == NULL) {
return SDL_OutOfMemory();
if (!rlebuf) {
return -1;
}
/* Set up the conversion */
@ -1394,7 +1394,7 @@ static int RLEColorkeySurface(SDL_Surface *surface)
{
/* If SDL_realloc returns NULL, the original block is left intact */
Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf);
if (p == NULL) {
if (!p) {
p = rlebuf;
}
surface->map->data = p;
@ -1496,7 +1496,7 @@ static SDL_bool UnRLEAlpha(SDL_Surface *surface)
}
surface->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), size);
if (surface->pixels == NULL) {
if (!surface->pixels) {
return SDL_FALSE;
}
surface->flags |= SDL_SIMD_ALIGNED;
@ -1568,7 +1568,7 @@ void SDL_UnRLESurface(SDL_Surface *surface, int recode)
return;
}
surface->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), size);
if (surface->pixels == NULL) {
if (!surface->pixels) {
/* Oh crap... */
surface->flags |= SDL_RLEACCEL;
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

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
@ -126,7 +126,7 @@ static SDL_BlitFunc SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int
SDL_BlitFuncEntry *entries)
{
int i, flagcheck = (flags & (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL | SDL_COPY_COLORKEY | SDL_COPY_NEAREST));
static int features = 0x7fffffff;
static unsigned int features = 0x7fffffff;
/* Get the available CPU features */
if (features == 0x7fffffff) {
@ -247,7 +247,7 @@ int SDL_CalculateBlit(SDL_Surface *surface)
}
#endif
#if SDL_HAVE_BLIT_AUTO
if (blit == NULL) {
if (!blit) {
Uint32 src_format = surface->format->format;
Uint32 dst_format = dst->format->format;
@ -258,7 +258,7 @@ int SDL_CalculateBlit(SDL_Surface *surface)
#endif
#ifndef TEST_SLOW_BLIT
if (blit == NULL)
if (!blit)
#endif
{
Uint32 src_format = surface->format->format;
@ -274,7 +274,7 @@ int SDL_CalculateBlit(SDL_Surface *surface)
map->data = blit;
/* Make sure we have a blit function */
if (blit == NULL) {
if (!blit) {
SDL_InvalidateMap(map);
return SDL_SetError("Blit combination not supported");
}

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
@ -79,7 +79,7 @@ typedef struct
Uint32 src_format;
Uint32 dst_format;
int flags;
int cpu;
unsigned int cpu;
SDL_BlitFunc func;
} SDL_BlitFuncEntry;
@ -260,6 +260,14 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface);
a = (a * 3) / 255; \
Pixel = (a << 30) | (r << 20) | (g << 10) | b; \
}
#define ABGR2101010_FROM_RGBA(Pixel, r, g, b, a) \
{ \
r = r ? ((r << 2) | 0x3) : 0; \
g = g ? ((g << 2) | 0x3) : 0; \
b = b ? ((b << 2) | 0x3) : 0; \
a = (a * 3) / 255; \
Pixel = (a << 30) | (b << 20) | (g << 10) | r; \
}
#define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) \
{ \
switch (bpp) { \
@ -352,6 +360,13 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface);
b = ((Pixel >> 2) & 0xFF); \
a = SDL_expand_byte[6][(Pixel >> 30)]; \
}
#define RGBA_FROM_ABGR2101010(Pixel, r, g, b, a) \
{ \
r = ((Pixel >> 2) & 0xFF); \
g = ((Pixel >> 12) & 0xFF); \
b = ((Pixel >> 22) & 0xFF); \
a = SDL_expand_byte[6][(Pixel >> 30)]; \
}
#define DISEMBLE_RGBA(buf, bpp, fmt, Pixel, r, g, b, a) \
do { \
switch (bpp) { \

File diff suppressed because it is too large Load Diff

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
@ -435,7 +435,7 @@ static void Blit1toNAlpha(SDL_BlitInfo *info)
const SDL_Color *srcpal = info->src_fmt->palette->colors;
int dstbpp;
Uint32 pixel;
unsigned sR, sG, sB;
unsigned sR, sG, sB, sA;
unsigned dR, dG, dB, dA;
const unsigned A = info->a;
@ -449,8 +449,9 @@ static void Blit1toNAlpha(SDL_BlitInfo *info)
sR = srcpal[*src].r;
sG = srcpal[*src].g;
sB = srcpal[*src].b;
sA = (srcpal[*src].a * A) / 255;
DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
ALPHA_BLEND_RGBA(sR, sG, sB, sA, dR, dG, dB, dA);
ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
src++;
dst += dstbpp;
@ -475,7 +476,7 @@ static void Blit1toNAlphaKey(SDL_BlitInfo *info)
Uint32 ckey = info->colorkey;
int dstbpp;
Uint32 pixel;
unsigned sR, sG, sB;
unsigned sR, sG, sB, sA;
unsigned dR, dG, dB, dA;
const unsigned A = info->a;
@ -490,8 +491,9 @@ static void Blit1toNAlphaKey(SDL_BlitInfo *info)
sR = srcpal[*src].r;
sG = srcpal[*src].g;
sB = srcpal[*src].b;
sA = (srcpal[*src].a * A) / 255;
DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
ALPHA_BLEND_RGBA(sR, sG, sB, sA, dR, dG, dB, dA);
ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
}
src++;
@ -531,8 +533,10 @@ SDL_BlitFunc SDL_CalculateBlit1(SDL_Surface *surface)
return one_blitkey[which];
case SDL_COPY_COLORKEY | SDL_COPY_BLEND: /* this is not super-robust but handles a specific case we found sdl12-compat. */
return (surface->map->info.a == 255) ? one_blitkey[which] : (SDL_BlitFunc)NULL;
return (surface->map->info.a == 255) ? one_blitkey[which] :
which >= 2 ? Blit1toNAlphaKey : (SDL_BlitFunc)NULL;
case SDL_COPY_BLEND:
case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
/* Supporting 8bpp->8bpp alpha is doable but requires lots of
tables which consume space and takes time to precompute,

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
@ -345,7 +345,7 @@ static void SDL_TARGETING("mmx") BlitRGBtoRGBPixelAlphaMMX(SDL_BlitInfo *info)
}
multmask = 0x00FF;
multmask <<= (ashift * 2);
multmask <<= ((Uint64)ashift * 2);
multmask2 = 0x00FF00FF00FF00FFULL;
while (height--) {
@ -1326,7 +1326,7 @@ SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface)
/* Per-pixel alpha blits */
switch (df->BytesPerPixel) {
case 1:
if (df->palette != NULL) {
if (df->palette) {
return BlitNto1PixelAlpha;
} else {
/* RGB332 has no palette ! */
@ -1397,7 +1397,7 @@ SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface)
/* Per-surface alpha blits */
switch (df->BytesPerPixel) {
case 1:
if (df->palette != NULL) {
if (df->palette) {
return BlitNto1SurfaceAlpha;
} else {
/* RGB332 has no palette ! */
@ -1452,7 +1452,7 @@ SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface)
if (sf->Amask == 0) {
if (df->BytesPerPixel == 1) {
if (df->palette != NULL) {
if (df->palette) {
return BlitNto1SurfaceAlphaKey;
} else {
/* RGB332 has no palette ! */

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
@ -971,7 +971,7 @@ static void Blit_XRGB8888_index8(SDL_BlitInfo *info)
dstskip = info->dst_skip;
map = info->table;
if (map == NULL) {
if (!map) {
while (height--) {
#ifdef USE_DUFFS_LOOP
/* *INDENT-OFF* */ /* clang-format off */
@ -1085,7 +1085,7 @@ static void Blit_RGB101010_index8(SDL_BlitInfo *info)
dstskip = info->dst_skip;
map = info->table;
if (map == NULL) {
if (!map) {
while (height--) {
#ifdef USE_DUFFS_LOOP
/* *INDENT-OFF* */ /* clang-format off */
@ -2109,7 +2109,7 @@ static void BlitNto1(SDL_BlitInfo *info)
srcfmt = info->src_fmt;
srcbpp = srcfmt->BytesPerPixel;
if (map == NULL) {
if (!map) {
while (height--) {
#ifdef USE_DUFFS_LOOP
/* *INDENT-OFF* */ /* clang-format off */
@ -2327,8 +2327,8 @@ static void BlitNtoN(SDL_BlitInfo *info)
#if HAVE_FAST_WRITE_INT8
/* Blit with permutation: 4->4 */
if (srcbpp == 4 && dstbpp == 4 &&
srcfmt->format != SDL_PIXELFORMAT_ARGB2101010 &&
dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) {
!SDL_ISPIXELFORMAT_10BIT(srcfmt->format) &&
!SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) {
/* Find the appropriate permutation */
int alpha_channel, p0, p1, p2, p3;
@ -2356,7 +2356,7 @@ static void BlitNtoN(SDL_BlitInfo *info)
/* Blit with permutation: 4->3 */
if (srcbpp == 4 && dstbpp == 3 &&
srcfmt->format != SDL_PIXELFORMAT_ARGB2101010) {
!SDL_ISPIXELFORMAT_10BIT(srcfmt->format)) {
/* Find the appropriate permutation */
int p0, p1, p2, p3;
@ -2382,7 +2382,7 @@ static void BlitNtoN(SDL_BlitInfo *info)
#if HAVE_FAST_WRITE_INT8
/* Blit with permutation: 3->4 */
if (srcbpp == 3 && dstbpp == 4 &&
dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) {
!SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) {
/* Find the appropriate permutation */
int alpha_channel, p0, p1, p2, p3;
@ -2445,8 +2445,8 @@ static void BlitNtoNCopyAlpha(SDL_BlitInfo *info)
#if HAVE_FAST_WRITE_INT8
/* Blit with permutation: 4->4 */
if (srcbpp == 4 && dstbpp == 4 &&
srcfmt->format != SDL_PIXELFORMAT_ARGB2101010 &&
dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) {
!SDL_ISPIXELFORMAT_10BIT(srcfmt->format) &&
!SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) {
/* Find the appropriate permutation */
int p0, p1, p2, p3;
@ -2505,7 +2505,7 @@ static void BlitNto1Key(SDL_BlitInfo *info)
srcbpp = srcfmt->BytesPerPixel;
ckey &= rgbmask;
if (palmap == NULL) {
if (!palmap) {
while (height--) {
/* *INDENT-OFF* */ /* clang-format off */
DUFFS_LOOP(
@ -2651,8 +2651,8 @@ static void BlitNtoNKey(SDL_BlitInfo *info)
#if HAVE_FAST_WRITE_INT8
/* Blit with permutation: 4->4 */
if (srcbpp == 4 && dstbpp == 4 &&
srcfmt->format != SDL_PIXELFORMAT_ARGB2101010 &&
dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) {
!SDL_ISPIXELFORMAT_10BIT(srcfmt->format) &&
!SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) {
/* Find the appropriate permutation */
int alpha_channel, p0, p1, p2, p3;
@ -2760,7 +2760,7 @@ static void BlitNtoNKey(SDL_BlitInfo *info)
/* Blit with permutation: 4->3 */
if (srcbpp == 4 && dstbpp == 3 &&
srcfmt->format != SDL_PIXELFORMAT_ARGB2101010) {
!SDL_ISPIXELFORMAT_10BIT(srcfmt->format)) {
/* Find the appropriate permutation */
int p0, p1, p2, p3;
@ -2789,7 +2789,7 @@ static void BlitNtoNKey(SDL_BlitInfo *info)
#if HAVE_FAST_WRITE_INT8
/* Blit with permutation: 3->4 */
if (srcbpp == 3 && dstbpp == 4 &&
dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) {
!SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) {
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
Uint8 k0 = ckey & 0xFF;
@ -2909,8 +2909,8 @@ static void BlitNtoNKeyCopyAlpha(SDL_BlitInfo *info)
#if HAVE_FAST_WRITE_INT8
/* Blit with permutation: 4->4 */
if (srcbpp == 4 && dstbpp == 4 &&
srcfmt->format != SDL_PIXELFORMAT_ARGB2101010 &&
dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) {
!SDL_ISPIXELFORMAT_10BIT(srcfmt->format) &&
!SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) {
/* Find the appropriate permutation */
int p0, p1, p2, p3;

View File

@ -1,7 +1,7 @@
/* DO NOT EDIT! This file is generated by sdlgenblit.pl */
/*
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,7 +1,7 @@
/* DO NOT EDIT! This file is generated by sdlgenblit.pl */
/*
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
@ -30,7 +30,7 @@
#define FORMAT_HAS_NO_ALPHA(format) format < 0
static int detect_format(SDL_PixelFormat *pf)
{
if (pf->format == SDL_PIXELFORMAT_ARGB2101010) {
if (SDL_ISPIXELFORMAT_10BIT(pf->format)) {
return FORMAT_2101010;
} else if (pf->Amask) {
return FORMAT_ALPHA;
@ -88,9 +88,27 @@ void SDL_Blit_Slow(SDL_BlitInfo *info)
DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB);
srcA = 0xFF;
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
/* 10-bit pixel format */
srcpixel = *((Uint32 *)(src));
RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA);
switch (src_fmt->format) {
case SDL_PIXELFORMAT_XRGB2101010:
RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA);
srcA = 0xFF;
break;
case SDL_PIXELFORMAT_XBGR2101010:
RGBA_FROM_ABGR2101010(srcpixel, srcR, srcG, srcB, srcA);
srcA = 0xFF;
break;
case SDL_PIXELFORMAT_ARGB2101010:
RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA);
break;
case SDL_PIXELFORMAT_ABGR2101010:
RGBA_FROM_ABGR2101010(srcpixel, srcR, srcG, srcB, srcA);
break;
default:
srcR = srcG = srcB = srcA = 0;
break;
}
}
if (flags & SDL_COPY_COLORKEY) {
@ -105,15 +123,20 @@ void SDL_Blit_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 (flags & SDL_COPY_MODULATE_COLOR) {
@ -184,9 +207,25 @@ void SDL_Blit_Slow(SDL_BlitInfo *info)
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB);
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
/* 10-bit pixel format */
Uint32 pixel;
ARGB2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA);
switch (dst_fmt->format) {
case SDL_PIXELFORMAT_XRGB2101010:
dstA = 0xFF;
SDL_FALLTHROUGH;
case SDL_PIXELFORMAT_ARGB2101010:
ARGB2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA);
break;
case SDL_PIXELFORMAT_XBGR2101010:
dstA = 0xFF;
SDL_FALLTHROUGH;
case SDL_PIXELFORMAT_ABGR2101010:
ABGR2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA);
break;
default:
pixel = 0;
break;
}
*(Uint32 *)dst = pixel;
}
posx += incx;

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
@ -197,7 +197,6 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
{
SDL_bool was_error = SDL_TRUE;
Sint64 fp_offset = 0;
int bmpPitch;
int i, pad;
SDL_Surface *surface;
Uint32 Rmask = 0;
@ -208,7 +207,6 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
Uint8 *bits;
Uint8 *top, *end;
SDL_bool topDown;
int ExpandBMP;
SDL_bool haveRGBMasks = SDL_FALSE;
SDL_bool haveAlphaMask = SDL_FALSE;
SDL_bool correctAlpha = SDL_FALSE;
@ -235,7 +233,7 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
/* Make sure we are passed a valid data source */
surface = NULL;
if (src == NULL) {
if (!src) {
SDL_InvalidParamError("src");
goto done;
}
@ -365,23 +363,16 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
goto done;
}
/* Expand 1, 2 and 4 bit bitmaps to 8 bits per pixel */
/* Reject invalid bit depths */
switch (biBitCount) {
case 1:
case 2:
case 4:
ExpandBMP = biBitCount;
biBitCount = 8;
break;
case 0:
case 3:
case 5:
case 6:
case 7:
SDL_SetError("%d-bpp BMP images are not supported", biBitCount);
SDL_SetError("%u bpp BMP images are not supported", biBitCount);
goto done;
default:
ExpandBMP = 0;
break;
}
@ -442,7 +433,7 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
format = SDL_GetPixelFormatEnumForMasks(biBitCount, Rmask, Gmask, Bmask, Amask);
surface = SDL_CreateSurface(biWidth, biHeight, format);
if (surface == NULL) {
if (!surface) {
goto done;
}
}
@ -514,89 +505,49 @@ SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
}
top = (Uint8 *)surface->pixels;
end = (Uint8 *)surface->pixels + (surface->h * surface->pitch);
switch (ExpandBMP) {
case 1:
bmpPitch = (biWidth + 7) >> 3;
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
break;
case 2:
bmpPitch = (biWidth + 3) >> 2;
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
break;
case 4:
bmpPitch = (biWidth + 1) >> 1;
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
break;
default:
pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0);
break;
}
pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0);
if (topDown) {
bits = top;
} else {
bits = end - surface->pitch;
}
while (bits >= top && bits < end) {
switch (ExpandBMP) {
case 1:
case 2:
case 4:
{
Uint8 pixel = 0;
int shift = (8 - ExpandBMP);
if (SDL_RWread(src, bits, surface->pitch) != (size_t)surface->pitch) {
goto done;
}
if (biBitCount == 8 && palette && biClrUsed < (1u << biBitCount)) {
for (i = 0; i < surface->w; ++i) {
if (i % (8 / ExpandBMP) == 0) {
if (!SDL_ReadU8(src, &pixel)) {
goto done;
}
}
bits[i] = (pixel >> shift);
if (bits[i] >= biClrUsed) {
SDL_SetError("A BMP image contains a pixel with a color out of the palette");
goto done;
}
pixel <<= ExpandBMP;
}
} break;
default:
if (SDL_RWread(src, bits, surface->pitch) != (size_t)surface->pitch) {
goto done;
}
if (biBitCount == 8 && palette && biClrUsed < (1u << biBitCount)) {
for (i = 0; i < surface->w; ++i) {
if (bits[i] >= biClrUsed) {
SDL_SetError("A BMP image contains a pixel with a color out of the palette");
goto done;
}
}
}
}
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
/* Byte-swap the pixels if needed. Note that the 24bpp
case has already been taken care of above. */
switch (biBitCount) {
case 15:
case 16:
{
Uint16 *pix = (Uint16 *)bits;
for (i = 0; i < surface->w; i++) {
pix[i] = SDL_Swap16(pix[i]);
}
break;
/* Byte-swap the pixels if needed. Note that the 24bpp
case has already been taken care of above. */
switch (biBitCount) {
case 15:
case 16:
{
Uint16 *pix = (Uint16 *)bits;
for (i = 0; i < surface->w; i++) {
pix[i] = SDL_Swap16(pix[i]);
}
case 32:
{
Uint32 *pix = (Uint32 *)bits;
for (i = 0; i < surface->w; i++) {
pix[i] = SDL_Swap32(pix[i]);
}
break;
}
}
#endif
break;
}
case 32:
{
Uint32 *pix = (Uint32 *)bits;
for (i = 0; i < surface->w; i++) {
pix[i] = SDL_Swap32(pix[i]);
}
break;
}
}
#endif
/* Skip padding bytes, ugh */
if (pad) {
Uint8 padbyte;
@ -695,11 +646,11 @@ int SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst)
}
#endif /* SAVE_32BIT_BMP */
if (surface->format->palette != NULL && !save32bit) {
if (surface->format->palette && !save32bit) {
if (surface->format->BitsPerPixel == 8) {
intermediate_surface = surface;
} else {
SDL_SetError("%d bpp BMP files not supported",
SDL_SetError("%u bpp BMP files not supported",
surface->format->BitsPerPixel);
goto done;
}
@ -726,7 +677,7 @@ int SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, SDL_bool freedst)
pixel_format = SDL_PIXELFORMAT_BGR24;
}
intermediate_surface = SDL_ConvertSurfaceFormat(surface, pixel_format);
if (intermediate_surface == NULL) {
if (!intermediate_surface) {
SDL_SetError("Couldn't convert image to %d bpp",
(int)SDL_BITSPERPIXEL(pixel_format));
goto done;

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
@ -58,7 +58,7 @@ int SDL_SetClipboardData(SDL_ClipboardDataCallback callback, SDL_ClipboardCleanu
SDL_VideoDevice *_this = SDL_GetVideoDevice();
size_t i;
if (_this == NULL) {
if (!_this) {
return SDL_SetError("Video subsystem must be initialized to set clipboard text");
}
@ -97,7 +97,7 @@ int SDL_SetClipboardData(SDL_ClipboardDataCallback callback, SDL_ClipboardCleanu
}
if (num_allocated < num_mime_types) {
SDL_ClearClipboardData();
return SDL_OutOfMemory();
return -1;
}
_this->num_clipboard_mime_types = num_mime_types;
}
@ -156,8 +156,6 @@ void *SDL_GetInternalClipboardData(SDL_VideoDevice *_this, const char *mime_type
if (data) {
SDL_memcpy(data, provided_data, *size);
SDL_memset((Uint8 *)data + *size, 0, sizeof(Uint32));
} else {
SDL_OutOfMemory();
}
}
}
@ -168,7 +166,7 @@ void *SDL_GetClipboardData(const char *mime_type, size_t *size)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this == NULL) {
if (!_this) {
SDL_SetError("Video subsystem must be initialized to get clipboard data");
return NULL;
}
@ -215,7 +213,7 @@ SDL_bool SDL_HasClipboardData(const char *mime_type)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this == NULL) {
if (!_this) {
SDL_SetError("Video subsystem must be initialized to check clipboard data");
return SDL_FALSE;
}
@ -272,7 +270,7 @@ int SDL_SetClipboardText(const char *text)
size_t num_mime_types;
const char **text_mime_types;
if (_this == NULL) {
if (!_this) {
return SDL_SetError("Video subsystem must be initialized to set clipboard text");
}
@ -293,7 +291,7 @@ char *SDL_GetClipboardText(void)
size_t length;
char *text = NULL;
if (_this == NULL) {
if (!_this) {
SDL_SetError("Video subsystem must be initialized to get clipboard text");
return SDL_strdup("");
}
@ -318,7 +316,7 @@ SDL_bool SDL_HasClipboardText(void)
size_t i, num_mime_types;
const char **text_mime_types;
if (_this == NULL) {
if (!_this) {
SDL_SetError("Video subsystem must be initialized to check clipboard text");
return SDL_FALSE;
}
@ -338,11 +336,11 @@ int SDL_SetPrimarySelectionText(const char *text)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this == NULL) {
if (!_this) {
return SDL_SetError("Video subsystem must be initialized to set primary selection text");
}
if (text == NULL) {
if (!text) {
text = "";
}
if (_this->SetPrimarySelectionText) {
@ -362,7 +360,7 @@ char *SDL_GetPrimarySelectionText(void)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this == NULL) {
if (!_this) {
SDL_SetError("Video subsystem must be initialized to get primary selection text");
return SDL_strdup("");
}
@ -371,7 +369,7 @@ char *SDL_GetPrimarySelectionText(void)
return _this->GetPrimarySelectionText(_this);
} else {
const char *text = _this->primary_selection_text;
if (text == NULL) {
if (!text) {
text = "";
}
return SDL_strdup(text);
@ -382,7 +380,7 @@ SDL_bool SDL_HasPrimarySelectionText(void)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this == NULL) {
if (!_this) {
SDL_SetError("Video subsystem must be initialized to check primary selection text");
return SDL_FALSE;
}

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
@ -184,7 +184,7 @@ SDL_bool SDL_EGL_HasExtension(SDL_VideoDevice *_this, SDL_EGL_ExtensionType type
const char *ext_start;
/* Invalid extensions can be rejected early */
if (ext == NULL || *ext == 0 || SDL_strchr(ext, ' ') != NULL) {
if (!ext || *ext == 0 || SDL_strchr(ext, ' ') != NULL) {
/* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SDL_EGL_HasExtension: Invalid EGL extension"); */
return SDL_FALSE;
}
@ -197,7 +197,7 @@ SDL_bool SDL_EGL_HasExtension(SDL_VideoDevice *_this, SDL_EGL_ExtensionType type
* 1 If set, the client extension is masked and not present to SDL.
*/
ext_override = SDL_getenv(ext);
if (ext_override != NULL) {
if (ext_override) {
int disable_ext = SDL_atoi(ext_override);
if (disable_ext & 0x01 && type == SDL_EGL_DISPLAY_EXTENSION) {
return SDL_FALSE;
@ -223,12 +223,12 @@ SDL_bool SDL_EGL_HasExtension(SDL_VideoDevice *_this, SDL_EGL_ExtensionType type
return SDL_FALSE;
}
if (egl_extstr != NULL) {
if (egl_extstr) {
ext_start = egl_extstr;
while (*ext_start) {
ext_start = SDL_strstr(ext_start, ext);
if (ext_start == NULL) {
if (!ext_start) {
return SDL_FALSE;
}
/* Check if the match is not just a substring of one of the extensions */
@ -251,24 +251,24 @@ SDL_bool SDL_EGL_HasExtension(SDL_VideoDevice *_this, SDL_EGL_ExtensionType type
SDL_FunctionPointer SDL_EGL_GetProcAddressInternal(SDL_VideoDevice *_this, const char *proc)
{
SDL_FunctionPointer retval = NULL;
if (_this->egl_data != NULL) {
if (_this->egl_data) {
const Uint32 eglver = (((Uint32)_this->egl_data->egl_version_major) << 16) | ((Uint32)_this->egl_data->egl_version_minor);
const SDL_bool is_egl_15_or_later = eglver >= ((((Uint32)1) << 16) | 5);
/* EGL 1.5 can use eglGetProcAddress() for any symbol. 1.4 and earlier can't use it for core entry points. */
if (retval == NULL && is_egl_15_or_later && _this->egl_data->eglGetProcAddress) {
if (!retval && is_egl_15_or_later && _this->egl_data->eglGetProcAddress) {
retval = _this->egl_data->eglGetProcAddress(proc);
}
#if !defined(__EMSCRIPTEN__) && !defined(SDL_VIDEO_DRIVER_VITA) /* LoadFunction isn't needed on Emscripten and will call dlsym(), causing other problems. */
/* Try SDL_LoadFunction() first for EGL <= 1.4, or as a fallback for >= 1.5. */
if (retval == NULL) {
if (!retval) {
retval = SDL_LoadFunction(_this->egl_data->opengl_dll_handle, proc);
}
#endif
/* Try eglGetProcAddress if we're on <= 1.4 and still searching... */
if (retval == NULL && !is_egl_15_or_later && _this->egl_data->eglGetProcAddress) {
if (!retval && !is_egl_15_or_later && _this->egl_data->eglGetProcAddress) {
retval = _this->egl_data->eglGetProcAddress(proc);
}
}
@ -342,17 +342,17 @@ static int SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_p
#if !defined(SDL_VIDEO_STATIC_ANGLE) && !defined(SDL_VIDEO_DRIVER_VITA)
/* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */
path = SDL_getenv("SDL_VIDEO_GL_DRIVER");
if (path != NULL) {
if (path) {
opengl_dll_handle = SDL_LoadObject(path);
}
if (opengl_dll_handle == NULL) {
if (!opengl_dll_handle) {
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
if (_this->gl_config.major_version > 1) {
path = DEFAULT_OGL_ES2;
opengl_dll_handle = SDL_LoadObject(path);
#ifdef ALT_OGL_ES2
if (opengl_dll_handle == NULL && !vc4) {
if (!opengl_dll_handle && !vc4) {
path = ALT_OGL_ES2;
opengl_dll_handle = SDL_LoadObject(path);
}
@ -361,12 +361,12 @@ static int SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_p
} else {
path = DEFAULT_OGL_ES;
opengl_dll_handle = SDL_LoadObject(path);
if (opengl_dll_handle == NULL) {
if (!opengl_dll_handle) {
path = DEFAULT_OGL_ES_PVR;
opengl_dll_handle = SDL_LoadObject(path);
}
#ifdef ALT_OGL_ES2
if (opengl_dll_handle == NULL && !vc4) {
if (!opengl_dll_handle && !vc4) {
path = ALT_OGL_ES2;
opengl_dll_handle = SDL_LoadObject(path);
}
@ -378,7 +378,7 @@ static int SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_p
path = DEFAULT_OGL;
opengl_dll_handle = SDL_LoadObject(path);
#ifdef ALT_OGL
if (opengl_dll_handle == NULL) {
if (!opengl_dll_handle) {
path = ALT_OGL;
opengl_dll_handle = SDL_LoadObject(path);
}
@ -388,34 +388,34 @@ static int SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_p
}
_this->egl_data->opengl_dll_handle = opengl_dll_handle;
if (opengl_dll_handle == NULL) {
if (!opengl_dll_handle) {
return SDL_SetError("Could not initialize OpenGL / GLES library");
}
/* Loading libGL* in the previous step took care of loading libEGL.so, but we future proof by double checking */
if (egl_path != NULL) {
if (egl_path) {
egl_dll_handle = SDL_LoadObject(egl_path);
}
/* Try loading a EGL symbol, if it does not work try the default library paths */
if (egl_dll_handle == NULL || SDL_LoadFunction(egl_dll_handle, "eglChooseConfig") == NULL) {
if (egl_dll_handle != NULL) {
if (!egl_dll_handle || SDL_LoadFunction(egl_dll_handle, "eglChooseConfig") == NULL) {
if (egl_dll_handle) {
SDL_UnloadObject(egl_dll_handle);
}
path = SDL_getenv("SDL_VIDEO_EGL_DRIVER");
if (path == NULL) {
if (!path) {
path = DEFAULT_EGL;
}
egl_dll_handle = SDL_LoadObject(path);
#ifdef ALT_EGL
if (egl_dll_handle == NULL && !vc4) {
if (!egl_dll_handle && !vc4) {
path = ALT_EGL;
egl_dll_handle = SDL_LoadObject(path);
}
#endif
if (egl_dll_handle == NULL || SDL_LoadFunction(egl_dll_handle, "eglChooseConfig") == NULL) {
if (egl_dll_handle != NULL) {
if (!egl_dll_handle || SDL_LoadFunction(egl_dll_handle, "eglChooseConfig") == NULL) {
if (egl_dll_handle) {
SDL_UnloadObject(egl_dll_handle);
}
return SDL_SetError("Could not load EGL library");
@ -476,7 +476,7 @@ int SDL_EGL_LoadLibraryOnly(SDL_VideoDevice *_this, const char *egl_path)
_this->egl_data = (struct SDL_EGL_VideoData *)SDL_calloc(1, sizeof(SDL_EGL_VideoData));
if (!_this->egl_data) {
return SDL_OutOfMemory();
return -1;
}
if (SDL_EGL_LoadLibraryInternal(_this, egl_path) < 0) {
@ -550,7 +550,7 @@ int SDL_EGL_LoadLibrary(SDL_VideoDevice *_this, const char *egl_path, NativeDisp
#endif
/* Try the implementation-specific eglGetDisplay even if eglGetPlatformDisplay fails */
if ((_this->egl_data->egl_display == EGL_NO_DISPLAY) &&
(_this->egl_data->eglGetDisplay != NULL) &&
(_this->egl_data->eglGetDisplay) &&
SDL_GetHintBoolean(SDL_HINT_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK, SDL_TRUE)) {
_this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
}
@ -594,11 +594,11 @@ int SDL_EGL_InitializeOffscreen(SDL_VideoDevice *_this, int device)
}
/* Check for all extensions that are optional until used and fail if any is missing */
if (_this->egl_data->eglQueryDevicesEXT == NULL) {
if (!_this->egl_data->eglQueryDevicesEXT) {
return SDL_SetError("eglQueryDevicesEXT is missing (EXT_device_enumeration not supported by the drivers?)");
}
if (_this->egl_data->eglGetPlatformDisplayEXT == NULL) {
if (!_this->egl_data->eglGetPlatformDisplayEXT) {
return SDL_SetError("eglGetPlatformDisplayEXT is missing (EXT_platform_base not supported by the drivers?)");
}

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
@ -231,12 +231,12 @@ static void SDL_FillSurfaceRect4(Uint8 *pixels, int pitch, Uint32 color, int w,
*/
int SDL_FillSurfaceRect(SDL_Surface *dst, const SDL_Rect *rect, Uint32 color)
{
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("SDL_FillSurfaceRect(): dst");
}
/* If 'rect' == NULL, then fill the whole surface */
if (rect == NULL) {
if (!rect) {
rect = &dst->clip_rect;
/* Don't attempt to fill if the surface's clip_rect is empty */
if (SDL_RectEmpty(rect)) {
@ -304,7 +304,7 @@ int SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count,
void (*fill_function)(Uint8 * pixels, int pitch, Uint32 color, int w, int h) = NULL;
int i;
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("SDL_FillSurfaceRects(): dst");
}
@ -318,7 +318,7 @@ int SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count,
return SDL_SetError("SDL_FillSurfaceRects(): You must lock the surface");
}
if (rects == NULL) {
if (!rects) {
return SDL_InvalidParamError("SDL_FillSurfaceRects(): rects");
}
@ -340,7 +340,7 @@ int SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count,
}
#ifdef SDL_ARM_NEON_BLITTERS
if (SDL_HasNEON() && dst->format->BytesPerPixel != 3 && fill_function == NULL) {
if (SDL_HasNEON() && dst->format->BytesPerPixel != 3 && !fill_function) {
switch (dst->format->BytesPerPixel) {
case 1:
fill_function = fill_8_neon;
@ -355,7 +355,7 @@ int SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count,
}
#endif
#ifdef SDL_ARM_SIMD_BLITTERS
if (SDL_HasARMSIMD() && dst->format->BytesPerPixel != 3 && fill_function == NULL) {
if (SDL_HasARMSIMD() && dst->format->BytesPerPixel != 3 && !fill_function) {
switch (dst->format->BytesPerPixel) {
case 1:
fill_function = fill_8_simd;
@ -370,7 +370,7 @@ int SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count,
}
#endif
if (fill_function == NULL) {
if (!fill_function) {
switch (dst->format->BytesPerPixel) {
case 1:
{

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
@ -89,6 +89,8 @@ const char *SDL_GetPixelFormatName(Uint32 format)
CASE(SDL_PIXELFORMAT_INDEX1LSB)
CASE(SDL_PIXELFORMAT_INDEX1MSB)
CASE(SDL_PIXELFORMAT_INDEX2LSB)
CASE(SDL_PIXELFORMAT_INDEX2MSB)
CASE(SDL_PIXELFORMAT_INDEX4LSB)
CASE(SDL_PIXELFORMAT_INDEX4MSB)
CASE(SDL_PIXELFORMAT_INDEX8)
@ -117,7 +119,10 @@ const char *SDL_GetPixelFormatName(Uint32 format)
CASE(SDL_PIXELFORMAT_RGBA8888)
CASE(SDL_PIXELFORMAT_ABGR8888)
CASE(SDL_PIXELFORMAT_BGRA8888)
CASE(SDL_PIXELFORMAT_XRGB2101010)
CASE(SDL_PIXELFORMAT_XBGR2101010)
CASE(SDL_PIXELFORMAT_ARGB2101010)
CASE(SDL_PIXELFORMAT_ABGR2101010)
CASE(SDL_PIXELFORMAT_YV12)
CASE(SDL_PIXELFORMAT_IYUV)
CASE(SDL_PIXELFORMAT_YUY2)
@ -306,6 +311,9 @@ Uint32 SDL_GetPixelFormatEnumForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, Uint3
case 1:
/* SDL defaults to MSB ordering */
return SDL_PIXELFORMAT_INDEX1MSB;
case 2:
/* SDL defaults to MSB ordering */
return SDL_PIXELFORMAT_INDEX2MSB;
case 4:
/* SDL defaults to MSB ordering */
return SDL_PIXELFORMAT_INDEX4MSB;
@ -440,6 +448,20 @@ Uint32 SDL_GetPixelFormatEnumForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, Uint3
#endif
}
break;
case 30:
if (Rmask == 0x3FF00000 &&
Gmask == 0x000FFC00 &&
Bmask == 0x000003FF &&
Amask == 0x00000000) {
return SDL_PIXELFORMAT_XRGB2101010;
}
if (Rmask == 0x000003FF &&
Gmask == 0x000FFC00 &&
Bmask == 0x3FF00000 &&
Amask == 0x00000000) {
return SDL_PIXELFORMAT_XBGR2101010;
}
break;
case 32:
if (Rmask == 0) {
return SDL_PIXELFORMAT_XRGB8888;
@ -492,12 +514,31 @@ Uint32 SDL_GetPixelFormatEnumForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, Uint3
Amask == 0x000000FF) {
return SDL_PIXELFORMAT_BGRA8888;
}
if (Rmask == 0x3FF00000 &&
Gmask == 0x000FFC00 &&
Bmask == 0x000003FF &&
Amask == 0x00000000) {
return SDL_PIXELFORMAT_XRGB2101010;
}
if (Rmask == 0x000003FF &&
Gmask == 0x000FFC00 &&
Bmask == 0x3FF00000 &&
Amask == 0x00000000) {
return SDL_PIXELFORMAT_XBGR2101010;
}
if (Rmask == 0x3FF00000 &&
Gmask == 0x000FFC00 &&
Bmask == 0x000003FF &&
Amask == 0xC0000000) {
return SDL_PIXELFORMAT_ARGB2101010;
}
if (Rmask == 0x000003FF &&
Gmask == 0x000FFC00 &&
Bmask == 0x3FF00000 &&
Amask == 0xC0000000) {
return SDL_PIXELFORMAT_ABGR2101010;
}
break;
}
return SDL_PIXELFORMAT_UNKNOWN;
}
@ -522,9 +563,8 @@ SDL_PixelFormat *SDL_CreatePixelFormat(Uint32 pixel_format)
/* Allocate an empty pixel format structure, and initialize it */
format = SDL_malloc(sizeof(*format));
if (format == NULL) {
if (!format) {
SDL_AtomicUnlock(&formats_lock);
SDL_OutOfMemory();
return NULL;
}
if (SDL_InitFormat(format, pixel_format) < 0) {
@ -620,7 +660,7 @@ void SDL_DestroyPixelFormat(SDL_PixelFormat *format)
{
SDL_PixelFormat *prev;
if (format == NULL) {
if (!format) {
return;
}
@ -663,15 +703,13 @@ SDL_Palette *SDL_CreatePalette(int ncolors)
}
palette = (SDL_Palette *)SDL_malloc(sizeof(*palette));
if (palette == NULL) {
SDL_OutOfMemory();
if (!palette) {
return NULL;
}
palette->colors =
(SDL_Color *)SDL_malloc(ncolors * sizeof(*palette->colors));
if (!palette->colors) {
SDL_free(palette);
SDL_OutOfMemory();
return NULL;
}
palette->ncolors = ncolors;
@ -685,7 +723,7 @@ SDL_Palette *SDL_CreatePalette(int ncolors)
int SDL_SetPixelFormatPalette(SDL_PixelFormat *format, SDL_Palette *palette)
{
if (format == NULL) {
if (!format) {
return SDL_InvalidParamError("SDL_SetPixelFormatPalette(): format");
}
@ -716,7 +754,7 @@ int SDL_SetPaletteColors(SDL_Palette *palette, const SDL_Color *colors,
int status = 0;
/* Verify the parameters */
if (palette == NULL) {
if (!palette) {
return -1;
}
if (ncolors > (palette->ncolors - firstcolor)) {
@ -738,7 +776,7 @@ int SDL_SetPaletteColors(SDL_Palette *palette, const SDL_Color *colors,
void SDL_DestroyPalette(SDL_Palette *palette)
{
if (palette == NULL) {
if (!palette) {
return;
}
if (--palette->refcount > 0) {
@ -859,7 +897,7 @@ Uint32 SDL_MapRGB(const SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b)
SDL_InvalidParamError("format");
return 0;
}
if (format->palette == NULL) {
if (!format->palette) {
return (r >> format->Rloss) << format->Rshift | (g >> format->Gloss) << format->Gshift | (b >> format->Bloss) << format->Bshift | format->Amask;
} else {
return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE);
@ -874,7 +912,7 @@ Uint32 SDL_MapRGBA(const SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b,
SDL_InvalidParamError("format");
return 0;
}
if (format->palette == NULL) {
if (!format->palette) {
return (r >> format->Rloss) << format->Rshift | (g >> format->Gloss) << format->Gshift | (b >> format->Bloss) << format->Bshift | ((Uint32)(a >> format->Aloss) << format->Ashift & format->Amask);
} else {
return SDL_FindColor(format->palette, r, g, b, a);
@ -884,7 +922,7 @@ Uint32 SDL_MapRGBA(const SDL_PixelFormat *format, Uint8 r, Uint8 g, Uint8 b,
void SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat *format, Uint8 *r, Uint8 *g,
Uint8 *b)
{
if (format->palette == NULL) {
if (!format->palette) {
unsigned v;
v = (pixel & format->Rmask) >> format->Rshift;
*r = SDL_expand_byte[format->Rloss][v];
@ -906,7 +944,7 @@ void SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat *format, Uint8 *r, Uint8 *g,
void SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat *format,
Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
{
if (format->palette == NULL) {
if (!format->palette) {
unsigned v;
v = (pixel & format->Rmask) >> format->Rshift;
*r = SDL_expand_byte[format->Rloss][v];
@ -947,8 +985,7 @@ static Uint8 *Map1to1(SDL_Palette *src, SDL_Palette *dst, int *identical)
*identical = 0;
}
map = (Uint8 *)SDL_calloc(256, sizeof(Uint8));
if (map == NULL) {
SDL_OutOfMemory();
if (!map) {
return NULL;
}
for (i = 0; i < src->ncolors; ++i) {
@ -970,8 +1007,7 @@ static Uint8 *Map1toN(SDL_PixelFormat *src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod,
bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
map = (Uint8 *)SDL_calloc(256, bpp);
if (map == NULL) {
SDL_OutOfMemory();
if (!map) {
return NULL;
}
@ -1006,8 +1042,7 @@ SDL_BlitMap *SDL_AllocBlitMap(void)
/* Allocate the empty map */
map = (SDL_BlitMap *)SDL_calloc(1, sizeof(*map));
if (map == NULL) {
SDL_OutOfMemory();
if (!map) {
return NULL;
}
map->info.r = 0xFF;
@ -1035,7 +1070,7 @@ void SDL_InvalidateAllBlitMap(SDL_Surface *surface)
void SDL_InvalidateMap(SDL_BlitMap *map)
{
if (map == NULL) {
if (!map) {
return;
}
if (map->dst) {
@ -1074,7 +1109,7 @@ int SDL_MapSurface(SDL_Surface *src, SDL_Surface *dst)
map->info.table =
Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
if (!map->identity) {
if (map->info.table == NULL) {
if (!map->info.table) {
return -1;
}
}
@ -1086,7 +1121,7 @@ int SDL_MapSurface(SDL_Surface *src, SDL_Surface *dst)
map->info.table =
Map1toN(srcfmt, src->map->info.r, src->map->info.g,
src->map->info.b, src->map->info.a, dstfmt);
if (map->info.table == NULL) {
if (!map->info.table) {
return -1;
}
}
@ -1095,7 +1130,7 @@ int SDL_MapSurface(SDL_Surface *src, SDL_Surface *dst)
/* BitField --> Palette */
map->info.table = MapNto1(srcfmt, dstfmt, &map->identity);
if (!map->identity) {
if (map->info.table == NULL) {
if (!map->info.table) {
return -1;
}
}

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
@ -37,10 +37,10 @@ SDL_bool SDL_GetSpanEnclosingRect(int width, int height,
} else if (height < 1) {
SDL_InvalidParamError("height");
return SDL_FALSE;
} else if (rects == NULL) {
} else if (!rects) {
SDL_InvalidParamError("rects");
return SDL_FALSE;
} else if (span == NULL) {
} else if (!span) {
SDL_InvalidParamError("span");
return SDL_FALSE;
} else if (numrects < 1) {
@ -88,6 +88,7 @@ SDL_bool SDL_GetSpanEnclosingRect(int width, int height,
#define RECTTYPE SDL_Rect
#define POINTTYPE SDL_Point
#define SCALARTYPE int
#define BIGSCALARTYPE Sint64
#define COMPUTEOUTCODE ComputeOutCode
#define SDL_HASINTERSECTION SDL_HasRectIntersection
#define SDL_INTERSECTRECT SDL_GetRectIntersection
@ -100,6 +101,7 @@ SDL_bool SDL_GetSpanEnclosingRect(int width, int height,
#define RECTTYPE SDL_FRect
#define POINTTYPE SDL_FPoint
#define SCALARTYPE float
#define BIGSCALARTYPE double
#define COMPUTEOUTCODE ComputeOutCodeFloat
#define SDL_HASINTERSECTION SDL_HasRectIntersectionFloat
#define SDL_INTERSECTRECT SDL_GetRectIntersectionFloat

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
@ -25,10 +25,10 @@ SDL_bool SDL_HASINTERSECTION(const RECTTYPE *A, const RECTTYPE *B)
{
SCALARTYPE Amin, Amax, Bmin, Bmax;
if (A == NULL) {
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
} else if (B == NULL) {
} else if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
} else if (SDL_RECTEMPTY(A) || SDL_RECTEMPTY(B)) {
@ -70,13 +70,13 @@ SDL_bool SDL_INTERSECTRECT(const RECTTYPE *A, const RECTTYPE *B, RECTTYPE *resul
{
SCALARTYPE Amin, Amax, Bmin, Bmax;
if (A == NULL) {
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
} else if (B == NULL) {
} else if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
} else if (result == NULL) {
} else if (!result) {
SDL_InvalidParamError("result");
return SDL_FALSE;
} else if (SDL_RECTEMPTY(A) || SDL_RECTEMPTY(B)) { /* Special cases for empty rects */
@ -120,11 +120,11 @@ int SDL_UNIONRECT(const RECTTYPE *A, const RECTTYPE *B, RECTTYPE *result)
{
SCALARTYPE Amin, Amax, Bmin, Bmax;
if (A == NULL) {
if (!A) {
return SDL_InvalidParamError("A");
} else if (B == NULL) {
} else if (!B) {
return SDL_InvalidParamError("B");
} else if (result == NULL) {
} else if (!result) {
return SDL_InvalidParamError("result");
} else if (SDL_RECTEMPTY(A)) { /* Special cases for empty Rects */
if (SDL_RECTEMPTY(B)) { /* A and B empty */
@ -178,7 +178,7 @@ SDL_bool SDL_ENCLOSEPOINTS(const POINTTYPE *points, int count, const RECTTYPE *c
SCALARTYPE x, y;
int i;
if (points == NULL) {
if (!points) {
SDL_InvalidParamError("points");
return SDL_FALSE;
} else if (count < 1) {
@ -208,7 +208,7 @@ SDL_bool SDL_ENCLOSEPOINTS(const POINTTYPE *points, int count, const RECTTYPE *c
}
if (!added) {
/* Special case: if no result was requested, we are done */
if (result == NULL) {
if (!result) {
return SDL_TRUE;
}
@ -234,7 +234,7 @@ SDL_bool SDL_ENCLOSEPOINTS(const POINTTYPE *points, int count, const RECTTYPE *c
}
} else {
/* Special case: if no result was requested, we are done */
if (result == NULL) {
if (!result) {
return SDL_TRUE;
}
@ -297,19 +297,19 @@ SDL_bool SDL_INTERSECTRECTANDLINE(const RECTTYPE *rect, SCALARTYPE *X1, SCALARTY
SCALARTYPE recty2;
int outcode1, outcode2;
if (rect == NULL) {
if (!rect) {
SDL_InvalidParamError("rect");
return SDL_FALSE;
} else if (X1 == NULL) {
} else if (!X1) {
SDL_InvalidParamError("X1");
return SDL_FALSE;
} else if (Y1 == NULL) {
} else if (!Y1) {
SDL_InvalidParamError("Y1");
return SDL_FALSE;
} else if (X2 == NULL) {
} else if (!X2) {
SDL_InvalidParamError("X2");
return SDL_FALSE;
} else if (Y2 == NULL) {
} else if (!Y2) {
SDL_InvalidParamError("Y2");
return SDL_FALSE;
} else if (SDL_RECTEMPTY(rect)) {
@ -376,16 +376,16 @@ SDL_bool SDL_INTERSECTRECTANDLINE(const RECTTYPE *rect, SCALARTYPE *X1, SCALARTY
if (outcode1) {
if (outcode1 & CODE_TOP) {
y = recty1;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
x = (SCALARTYPE) (x1 + ((BIGSCALARTYPE)(x2 - x1) * (y - y1)) / (y2 - y1));
} else if (outcode1 & CODE_BOTTOM) {
y = recty2;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
x = (SCALARTYPE) (x1 + ((BIGSCALARTYPE)(x2 - x1) * (y - y1)) / (y2 - y1));
} else if (outcode1 & CODE_LEFT) {
x = rectx1;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
y = (SCALARTYPE) (y1 + ((BIGSCALARTYPE)(y2 - y1) * (x - x1)) / (x2 - x1));
} else if (outcode1 & CODE_RIGHT) {
x = rectx2;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
y = (SCALARTYPE) (y1 + ((BIGSCALARTYPE)(y2 - y1) * (x - x1)) / (x2 - x1));
}
x1 = x;
y1 = y;
@ -394,23 +394,23 @@ SDL_bool SDL_INTERSECTRECTANDLINE(const RECTTYPE *rect, SCALARTYPE *X1, SCALARTY
if (outcode2 & CODE_TOP) {
SDL_assert(y2 != y1); /* if equal: division by zero. */
y = recty1;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
x = (SCALARTYPE) (x1 + ((BIGSCALARTYPE)(x2 - x1) * (y - y1)) / (y2 - y1));
} else if (outcode2 & CODE_BOTTOM) {
SDL_assert(y2 != y1); /* if equal: division by zero. */
y = recty2;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
x = (SCALARTYPE) (x1 + ((BIGSCALARTYPE)(x2 - x1) * (y - y1)) / (y2 - y1));
} else if (outcode2 & CODE_LEFT) {
/* If this assertion ever fires, here's the static analysis that warned about it:
http://buildbot.libsdl.org/sdl-static-analysis/sdl-macosx-static-analysis/sdl-macosx-static-analysis-1101/report-b0d01a.html#EndPath */
SDL_assert(x2 != x1); /* if equal: division by zero. */
x = rectx1;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
y = (SCALARTYPE) (y1 + ((BIGSCALARTYPE)(y2 - y1) * (x - x1)) / (x2 - x1));
} else if (outcode2 & CODE_RIGHT) {
/* If this assertion ever fires, here's the static analysis that warned about it:
http://buildbot.libsdl.org/sdl-static-analysis/sdl-macosx-static-analysis/sdl-macosx-static-analysis-1101/report-39b114.html#EndPath */
SDL_assert(x2 != x1); /* if equal: division by zero. */
x = rectx2;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
y = (SCALARTYPE) (y1 + ((BIGSCALARTYPE)(y2 - y1) * (x - x1)) / (x2 - x1));
}
x2 = x;
y2 = y;
@ -427,6 +427,7 @@ SDL_bool SDL_INTERSECTRECTANDLINE(const RECTTYPE *rect, SCALARTYPE *X1, SCALARTY
#undef RECTTYPE
#undef POINTTYPE
#undef SCALARTYPE
#undef BIGSCALARTYPE
#undef COMPUTEOUTCODE
#undef SDL_HASINTERSECTION
#undef SDL_INTERSECTRECT

View File

@ -1,304 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#include "SDL_sysvideo.h"
#include "SDL_shape_internals.h"
SDL_Window *SDL_CreateShapedWindow(const char *title, int w, int h, Uint32 flags)
{
SDL_Window *result = NULL;
result = SDL_CreateWindow(title, w, h, (flags | SDL_WINDOW_BORDERLESS | SDL_WINDOW_HIDDEN) & (~SDL_WINDOW_FULLSCREEN) & (~SDL_WINDOW_RESIZABLE));
if (result != NULL) {
if (SDL_GetVideoDevice()->shape_driver.CreateShaper == NULL) {
SDL_DestroyWindow(result);
return NULL;
}
result->shaper = SDL_GetVideoDevice()->shape_driver.CreateShaper(result);
if (result->shaper != NULL) {
result->shaper->mode.mode = ShapeModeDefault;
result->shaper->mode.parameters.binarizationCutoff = 1;
result->shaper->hasshape = SDL_FALSE;
return result;
} else {
SDL_DestroyWindow(result);
return NULL;
}
}
return NULL;
}
SDL_bool SDL_IsShapedWindow(const SDL_Window *window)
{
if (window == NULL) {
return SDL_FALSE;
}
return (SDL_bool)(window->shaper != NULL);
}
/* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */
void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb)
{
int x = 0;
int y = 0;
Uint8 r = 0, g = 0, b = 0, alpha = 0;
Uint8 *pixel = NULL;
Uint32 pixel_value = 0, mask_value = 0;
size_t bytes_per_scanline = (size_t)(shape->w + (ppb - 1)) / ppb;
Uint8 *bitmap_scanline;
SDL_Color key;
if (SDL_MUSTLOCK(shape)) {
SDL_LockSurface(shape);
}
SDL_memset(bitmap, 0, shape->h * bytes_per_scanline);
for (y = 0; y < shape->h; y++) {
bitmap_scanline = bitmap + y * bytes_per_scanline;
for (x = 0; x < shape->w; x++) {
alpha = 0;
pixel_value = 0;
pixel = (Uint8 *)(shape->pixels) + (y * shape->pitch) + (x * shape->format->BytesPerPixel);
switch (shape->format->BytesPerPixel) {
case (1):
pixel_value = *pixel;
break;
case (2):
pixel_value = *(Uint16 *)pixel;
break;
case (3):
pixel_value = *(Uint32 *)pixel & (~shape->format->Amask);
break;
case (4):
pixel_value = *(Uint32 *)pixel;
break;
}
SDL_GetRGBA(pixel_value, shape->format, &r, &g, &b, &alpha);
switch (mode.mode) {
case (ShapeModeDefault):
mask_value = (alpha >= 1 ? 1 : 0);
break;
case (ShapeModeBinarizeAlpha):
mask_value = (alpha >= mode.parameters.binarizationCutoff ? 1 : 0);
break;
case (ShapeModeReverseBinarizeAlpha):
mask_value = (alpha <= mode.parameters.binarizationCutoff ? 1 : 0);
break;
case (ShapeModeColorKey):
key = mode.parameters.colorKey;
mask_value = ((key.r != r || key.g != g || key.b != b) ? 1 : 0);
break;
}
bitmap_scanline[x / ppb] |= mask_value << (x % ppb);
}
}
if (SDL_MUSTLOCK(shape)) {
SDL_UnlockSurface(shape);
}
}
static SDL_ShapeTree *RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *mask, SDL_Rect dimensions)
{
int x = 0, y = 0;
Uint8 *pixel = NULL;
Uint32 pixel_value = 0;
Uint8 r = 0, g = 0, b = 0, a = 0;
SDL_bool pixel_opaque = SDL_FALSE;
int last_opaque = -1;
SDL_Color key;
SDL_ShapeTree *result = (SDL_ShapeTree *)SDL_malloc(sizeof(SDL_ShapeTree));
SDL_Rect next = { 0, 0, 0, 0 };
if (result == NULL) {
SDL_OutOfMemory();
return NULL;
}
for (y = dimensions.y; y < dimensions.y + dimensions.h; y++) {
for (x = dimensions.x; x < dimensions.x + dimensions.w; x++) {
pixel_value = 0;
pixel = (Uint8 *)(mask->pixels) + (y * mask->pitch) + (x * mask->format->BytesPerPixel);
switch (mask->format->BytesPerPixel) {
case (1):
pixel_value = *pixel;
break;
case (2):
pixel_value = *(Uint16 *)pixel;
break;
case (3):
pixel_value = *(Uint32 *)pixel & (~mask->format->Amask);
break;
case (4):
pixel_value = *(Uint32 *)pixel;
break;
}
SDL_GetRGBA(pixel_value, mask->format, &r, &g, &b, &a);
switch (mode.mode) {
case (ShapeModeDefault):
pixel_opaque = (a >= 1 ? SDL_TRUE : SDL_FALSE);
break;
case (ShapeModeBinarizeAlpha):
pixel_opaque = (a >= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE);
break;
case (ShapeModeReverseBinarizeAlpha):
pixel_opaque = (a <= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE);
break;
case (ShapeModeColorKey):
key = mode.parameters.colorKey;
pixel_opaque = ((key.r != r || key.g != g || key.b != b) ? SDL_TRUE : SDL_FALSE);
break;
}
if (last_opaque == -1) {
last_opaque = pixel_opaque;
}
if (last_opaque != pixel_opaque) {
const int halfwidth = dimensions.w / 2;
const int halfheight = dimensions.h / 2;
result->kind = QuadShape;
next.x = dimensions.x;
next.y = dimensions.y;
next.w = halfwidth;
next.h = halfheight;
result->data.children.upleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode, mask, next);
next.x = dimensions.x + halfwidth;
next.w = dimensions.w - halfwidth;
result->data.children.upright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode, mask, next);
next.x = dimensions.x;
next.w = halfwidth;
next.y = dimensions.y + halfheight;
next.h = dimensions.h - halfheight;
result->data.children.downleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode, mask, next);
next.x = dimensions.x + halfwidth;
next.w = dimensions.w - halfwidth;
result->data.children.downright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode, mask, next);
return result;
}
}
}
/* If we never recursed, all the pixels in this quadrant have the same "value". */
result->kind = (last_opaque == SDL_TRUE ? OpaqueShape : TransparentShape);
result->data.shape = dimensions;
return result;
}
SDL_ShapeTree *SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *shape)
{
SDL_Rect dimensions;
SDL_ShapeTree *result = NULL;
dimensions.x = 0;
dimensions.y = 0;
dimensions.w = shape->w;
dimensions.h = shape->h;
if (SDL_MUSTLOCK(shape)) {
SDL_LockSurface(shape);
}
result = RecursivelyCalculateShapeTree(mode, shape, dimensions);
if (SDL_MUSTLOCK(shape)) {
SDL_UnlockSurface(shape);
}
return result;
}
void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure)
{
SDL_assert(tree != NULL);
if (tree->kind == QuadShape) {
SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upleft, function, closure);
SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upright, function, closure);
SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.downleft, function, closure);
SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.downright, function, closure);
} else {
function(tree, closure);
}
}
void SDL_FreeShapeTree(SDL_ShapeTree **shape_tree)
{
if ((*shape_tree)->kind == QuadShape) {
SDL_FreeShapeTree((SDL_ShapeTree **)(char *)&(*shape_tree)->data.children.upleft);
SDL_FreeShapeTree((SDL_ShapeTree **)(char *)&(*shape_tree)->data.children.upright);
SDL_FreeShapeTree((SDL_ShapeTree **)(char *)&(*shape_tree)->data.children.downleft);
SDL_FreeShapeTree((SDL_ShapeTree **)(char *)&(*shape_tree)->data.children.downright);
}
SDL_free(*shape_tree);
*shape_tree = NULL;
}
int SDL_SetWindowShape(SDL_Window *window, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
int result;
if (window == NULL || !SDL_IsShapedWindow(window)) {
/* The window given was not a shapeable window. */
return SDL_NONSHAPEABLE_WINDOW;
}
if (shape == NULL) {
/* Invalid shape argument. */
return SDL_INVALID_SHAPE_ARGUMENT;
}
if (shape_mode != NULL) {
window->shaper->mode = *shape_mode;
}
result = _this->shape_driver.SetWindowShape(window->shaper, shape, shape_mode);
if (result == 0) {
window->shaper->hasshape = SDL_TRUE;
SDL_ShowWindow(window);
}
return result;
}
static SDL_bool SDL_WindowHasAShape(SDL_Window *window)
{
if (window == NULL || !SDL_IsShapedWindow(window)) {
return SDL_FALSE;
}
return window->shaper->hasshape;
}
int SDL_GetShapedWindowMode(SDL_Window *window, SDL_WindowShapeMode *shape_mode)
{
if (window != NULL && SDL_IsShapedWindow(window)) {
if (shape_mode == NULL) {
if (SDL_WindowHasAShape(window)) {
return 0; /* The window given has a shape. */
} else {
return SDL_WINDOW_LACKS_SHAPE; /* The window given is shapeable but lacks a shape. */
}
} else {
*shape_mode = window->shaper->mode;
return 0;
}
}
return SDL_NONSHAPEABLE_WINDOW; /* The window given is not a valid shapeable window. */
}

View File

@ -1,59 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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"
#ifndef SDL_shape_internals_h_
#define SDL_shape_internals_h_
struct SDL_ShapeTree;
typedef struct
{
struct SDL_ShapeTree *upleft, *upright, *downleft, *downright;
} SDL_QuadTreeChildren;
typedef union
{
SDL_QuadTreeChildren children;
SDL_Rect shape;
} SDL_ShapeUnion;
typedef enum
{
QuadShape,
TransparentShape,
OpaqueShape
} SDL_ShapeKind;
typedef struct SDL_ShapeTree
{
SDL_ShapeKind kind;
SDL_ShapeUnion data;
} SDL_ShapeTree;
typedef void (*SDL_TraversalFunction)(SDL_ShapeTree *, void *);
extern void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb);
extern SDL_ShapeTree *SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *shape);
extern void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure);
extern void SDL_FreeShapeTree(SDL_ShapeTree **shape_tree);
#endif /* SDL_shape_internals_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
@ -24,22 +24,10 @@
static int SDL_LowerSoftStretchNearest(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect);
static int SDL_LowerSoftStretchLinear(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect);
static int SDL_UpperSoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode);
int SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect,
SDL_Surface *dst, const SDL_Rect *dstrect)
{
return SDL_UpperSoftStretch(src, srcrect, dst, dstrect, SDL_SCALEMODE_NEAREST);
}
int SDL_SoftStretchLinear(SDL_Surface *src, const SDL_Rect *srcrect,
SDL_Surface *dst, const SDL_Rect *dstrect)
{
return SDL_UpperSoftStretch(src, srcrect, dst, dstrect, SDL_SCALEMODE_LINEAR);
}
static int SDL_UpperSoftStretch(SDL_Surface *src, const SDL_Rect *srcrect,
SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode)
SDL_Surface *dst, const SDL_Rect *dstrect,
SDL_ScaleMode scaleMode)
{
int ret;
int src_locked;
@ -47,11 +35,20 @@ static int SDL_UpperSoftStretch(SDL_Surface *src, const SDL_Rect *srcrect,
SDL_Rect full_src;
SDL_Rect full_dst;
if (src->format->format != dst->format->format) {
return SDL_SetError("Only works with same format surfaces");
}
if (scaleMode != SDL_SCALEMODE_NEAREST && scaleMode != SDL_SCALEMODE_LINEAR && scaleMode != SDL_SCALEMODE_BEST) {
return SDL_InvalidParamError("scaleMode");
}
if (scaleMode != SDL_SCALEMODE_NEAREST) {
scaleMode = SDL_SCALEMODE_LINEAR;
}
if (scaleMode == SDL_SCALEMODE_LINEAR) {
if (src->format->BytesPerPixel != 4 || src->format->format == SDL_PIXELFORMAT_ARGB2101010) {
return SDL_SetError("Wrong 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
@ -21,8 +21,10 @@
#include "SDL_internal.h"
#include "SDL_sysvideo.h"
#include "SDL_video_c.h"
#include "SDL_blit.h"
#include "SDL_RLEaccel_c.h"
#include "SDL_surface_pixel_impl.h"
#include "SDL_pixels_c.h"
#include "SDL_yuv_c.h"
#include "../render/SDL_sysrender.h"
@ -34,6 +36,11 @@ SDL_COMPILE_TIME_ASSERT(surface_size_assumptions,
SDL_COMPILE_TIME_ASSERT(can_indicate_overflow, SDL_SIZE_MAX > SDL_MAX_SINT32);
int SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
{
return SDL_ReadSurfacePixel_impl(surface, x, y, r, g, b, a);
}
/* Public routines */
/*
@ -129,14 +136,12 @@ SDL_Surface *SDL_CreateSurface(int width, int height, Uint32 format)
if (SDL_CalculateSize(format, width, height, &size, &pitch, SDL_FALSE /* not minimal pitch */) < 0) {
/* Overflow... */
SDL_OutOfMemory();
return NULL;
}
/* Allocate the surface */
surface = (SDL_Surface *)SDL_calloc(1, sizeof(*surface));
if (surface == NULL) {
SDL_OutOfMemory();
if (!surface) {
return NULL;
}
@ -153,7 +158,7 @@ SDL_Surface *SDL_CreateSurface(int width, int height, Uint32 format)
if (SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
SDL_Palette *palette =
SDL_CreatePalette((1 << surface->format->BitsPerPixel));
if (palette == NULL) {
if (!palette) {
SDL_DestroySurface(surface);
return NULL;
}
@ -175,7 +180,6 @@ SDL_Surface *SDL_CreateSurface(int width, int height, Uint32 format)
surface->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), size);
if (!surface->pixels) {
SDL_DestroySurface(surface);
SDL_OutOfMemory();
return NULL;
}
surface->flags |= SDL_SIMD_ALIGNED;
@ -204,9 +208,7 @@ SDL_Surface *SDL_CreateSurface(int width, int height, Uint32 format)
* Create an RGB surface from an existing memory buffer using the given given
* enum SDL_PIXELFORMAT_* format
*/
SDL_Surface *SDL_CreateSurfaceFrom(void *pixels,
int width, int height, int pitch,
Uint32 format)
SDL_Surface *SDL_CreateSurfaceFrom(void *pixels, int width, int height, int pitch, Uint32 format)
{
SDL_Surface *surface;
@ -220,14 +222,13 @@ SDL_Surface *SDL_CreateSurfaceFrom(void *pixels,
return NULL;
}
if (pitch == 0 && pixels == NULL) {
if (pitch == 0 && !pixels) {
/* The application will fill these in later with valid values */
} else {
size_t minimalPitch;
if (SDL_CalculateSize(format, width, height, NULL, &minimalPitch, SDL_TRUE /* minimal pitch */) < 0) {
/* Overflow... */
SDL_OutOfMemory();
return NULL;
}
@ -238,7 +239,7 @@ SDL_Surface *SDL_CreateSurfaceFrom(void *pixels,
}
surface = SDL_CreateSurface(0, 0, format);
if (surface != NULL) {
if (surface) {
surface->flags |= SDL_PREALLOC;
surface->pixels = pixels;
surface->w = width;
@ -249,10 +250,36 @@ SDL_Surface *SDL_CreateSurfaceFrom(void *pixels,
return surface;
}
SDL_PropertiesID SDL_GetSurfaceProperties(SDL_Surface *surface)
{
SDL_PropertiesID props;
if (!surface) {
SDL_InvalidParamError("surface");
return 0;
}
if (surface->flags & SDL_SURFACE_USES_PROPERTIES) {
props = (SDL_PropertiesID)(uintptr_t)surface->reserved;
} else {
if (surface->reserved != NULL) {
SDL_SetError("Surface has userdata, incompatible with properties");
return 0;
}
props = SDL_CreateProperties();
if (props) {
surface->reserved = (void *)(uintptr_t)props;
surface->flags |= SDL_SURFACE_USES_PROPERTIES;
}
}
return props;
}
int SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette)
{
if (surface == NULL) {
return SDL_InvalidParamError("SDL_SetSurfacePalette(): surface");
if (!surface) {
return SDL_InvalidParamError("surface");
}
if (SDL_SetPixelFormatPalette(surface->format, palette) < 0) {
return -1;
@ -266,8 +293,8 @@ int SDL_SetSurfaceRLE(SDL_Surface *surface, int flag)
{
int flags;
if (surface == NULL) {
return -1;
if (!surface) {
return SDL_InvalidParamError("surface");
}
flags = surface->map->info.flags;
@ -284,7 +311,7 @@ int SDL_SetSurfaceRLE(SDL_Surface *surface, int flag)
SDL_bool SDL_SurfaceHasRLE(SDL_Surface *surface)
{
if (surface == NULL) {
if (!surface) {
return SDL_FALSE;
}
@ -299,7 +326,7 @@ int SDL_SetSurfaceColorKey(SDL_Surface *surface, int flag, Uint32 key)
{
int flags;
if (surface == NULL) {
if (!surface) {
return SDL_InvalidParamError("surface");
}
@ -327,7 +354,7 @@ int SDL_SetSurfaceColorKey(SDL_Surface *surface, int flag, Uint32 key)
SDL_bool SDL_SurfaceHasColorKey(SDL_Surface *surface)
{
if (surface == NULL) {
if (!surface) {
return SDL_FALSE;
}
@ -340,7 +367,7 @@ SDL_bool SDL_SurfaceHasColorKey(SDL_Surface *surface)
int SDL_GetSurfaceColorKey(SDL_Surface *surface, Uint32 *key)
{
if (surface == NULL) {
if (!surface) {
return SDL_InvalidParamError("surface");
}
@ -360,7 +387,7 @@ static void SDL_ConvertColorkeyToAlpha(SDL_Surface *surface, SDL_bool ignore_alp
{
int x, y, bpp;
if (surface == NULL) {
if (!surface) {
return;
}
@ -449,8 +476,8 @@ int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b)
{
int flags;
if (surface == NULL) {
return -1;
if (!surface) {
return SDL_InvalidParamError("surface");
}
surface->map->info.r = r;
@ -471,8 +498,8 @@ int SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b)
int SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 *r, Uint8 *g, Uint8 *b)
{
if (surface == NULL) {
return -1;
if (!surface) {
return SDL_InvalidParamError("surface");
}
if (r) {
@ -491,8 +518,8 @@ int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha)
{
int flags;
if (surface == NULL) {
return -1;
if (!surface) {
return SDL_InvalidParamError("surface");
}
surface->map->info.a = alpha;
@ -511,8 +538,8 @@ int SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha)
int SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 *alpha)
{
if (surface == NULL) {
return -1;
if (!surface) {
return SDL_InvalidParamError("surface");
}
if (alpha) {
@ -525,8 +552,8 @@ int SDL_SetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode blendMode)
{
int flags, status;
if (surface == NULL) {
return -1;
if (!surface) {
return SDL_InvalidParamError("surface");
}
status = 0;
@ -562,11 +589,11 @@ int SDL_SetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode blendMode)
int SDL_GetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode *blendMode)
{
if (surface == NULL) {
return -1;
if (!surface) {
return SDL_InvalidParamError("surface");
}
if (blendMode == NULL) {
if (!blendMode) {
return 0;
}
@ -595,7 +622,7 @@ SDL_bool SDL_SetSurfaceClipRect(SDL_Surface *surface, const SDL_Rect *rect)
SDL_Rect full_rect;
/* Don't do anything if there's no surface to act on */
if (surface == NULL) {
if (!surface) {
return SDL_FALSE;
}
@ -606,7 +633,7 @@ SDL_bool SDL_SetSurfaceClipRect(SDL_Surface *surface, const SDL_Rect *rect)
full_rect.h = surface->h;
/* Set the clipping rectangle */
if (rect == NULL) {
if (!rect) {
surface->clip_rect = full_rect;
return SDL_TRUE;
}
@ -661,10 +688,11 @@ int SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect)
{
SDL_Rect fulldst;
int srcx, srcy, w, h;
int srcx, srcy;
Sint64 w, h;
/* Make sure the surfaces aren't locked */
if (src == NULL || dst == NULL) {
if (!src || !dst) {
return SDL_InvalidParamError("SDL_BlitSurface(): src/dst");
}
if (src->locked || dst->locked) {
@ -672,7 +700,7 @@ int SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect,
}
/* If the destination rectangle is NULL, use the entire dest surface */
if (dstrect == NULL) {
if (!dstrect) {
fulldst.x = fulldst.y = 0;
fulldst.w = dst->w;
fulldst.h = dst->h;
@ -760,13 +788,8 @@ int SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect,
}
int SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect)
{
return SDL_PrivateBlitSurfaceScaled(src, srcrect, dst, dstrect, SDL_SCALEMODE_NEAREST);
}
int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect, SDL_ScaleMode scaleMode)
SDL_Surface *dst, SDL_Rect *dstrect,
SDL_ScaleMode scaleMode)
{
double src_x0, src_y0, src_x1, src_y1;
double dst_x0, dst_y0, dst_x1, dst_y1;
@ -776,14 +799,14 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect,
int dst_w, dst_h;
/* Make sure the surfaces aren't locked */
if (src == NULL || dst == NULL) {
if (!src || !dst) {
return SDL_InvalidParamError("SDL_BlitSurfaceScaled(): src/dst");
}
if (src->locked || dst->locked) {
return SDL_SetError("Surfaces must not be locked during blit");
}
if (srcrect == NULL) {
if (!srcrect) {
src_w = src->w;
src_h = src->h;
} else {
@ -791,7 +814,7 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect,
src_h = srcrect->h;
}
if (dstrect == NULL) {
if (!dstrect) {
dst_w = dst->w;
dst_h = dst->h;
} else {
@ -807,7 +830,7 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect,
scaling_w = (double)dst_w / src_w;
scaling_h = (double)dst_h / src_h;
if (dstrect == NULL) {
if (!dstrect) {
dst_x0 = 0;
dst_y0 = 0;
dst_x1 = dst_w;
@ -819,7 +842,7 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect,
dst_y1 = dst_y0 + dst_h;
}
if (srcrect == NULL) {
if (!srcrect) {
src_x0 = 0;
src_y0 = 0;
src_x1 = src_w;
@ -920,7 +943,7 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect,
return 0;
}
return SDL_PrivateBlitSurfaceUncheckedScaled(src, &final_src, dst, &final_dst, scaleMode);
return SDL_BlitSurfaceUncheckedScaled(src, &final_src, dst, &final_dst, scaleMode);
}
/**
@ -928,18 +951,21 @@ int SDL_PrivateBlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect,
* scaled blitting only.
*/
int SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect,
SDL_Surface *dst, const SDL_Rect *dstrect)
{
return SDL_PrivateBlitSurfaceUncheckedScaled(src, srcrect, dst, dstrect, SDL_SCALEMODE_NEAREST);
}
int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect,
SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode)
SDL_Surface *dst, const SDL_Rect *dstrect,
SDL_ScaleMode scaleMode)
{
static const Uint32 complex_copy_flags = (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA |
SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL |
SDL_COPY_COLORKEY);
if (scaleMode != SDL_SCALEMODE_NEAREST && scaleMode != SDL_SCALEMODE_LINEAR && scaleMode != SDL_SCALEMODE_BEST) {
return SDL_InvalidParamError("scaleMode");
}
if (scaleMode != SDL_SCALEMODE_NEAREST) {
scaleMode = SDL_SCALEMODE_LINEAR;
}
if (srcrect->w > SDL_MAX_UINT16 || srcrect->h > SDL_MAX_UINT16 ||
dstrect->w > SDL_MAX_UINT16 || dstrect->h > SDL_MAX_UINT16) {
return SDL_SetError("Size too large for scaling");
@ -954,7 +980,7 @@ int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcr
if (!(src->map->info.flags & complex_copy_flags) &&
src->format->format == dst->format->format &&
!SDL_ISPIXELFORMAT_INDEXED(src->format->format)) {
return SDL_SoftStretch(src, srcrect, dst, dstrect);
return SDL_SoftStretch(src, srcrect, dst, dstrect, SDL_SCALEMODE_NEAREST);
} else {
return SDL_BlitSurfaceUnchecked(src, srcrect, dst, dstrect);
}
@ -965,7 +991,7 @@ int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcr
src->format->BytesPerPixel == 4 &&
src->format->format != SDL_PIXELFORMAT_ARGB2101010) {
/* fast path */
return SDL_SoftStretchLinear(src, srcrect, dst, dstrect);
return SDL_SoftStretch(src, srcrect, dst, dstrect, SDL_SCALEMODE_LINEAR);
} else {
/* Use intermediate surface(s) */
SDL_Surface *tmp1 = NULL;
@ -1015,7 +1041,7 @@ int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcr
if (is_complex_copy_flags || src->format->format != dst->format->format) {
SDL_Rect tmprect;
SDL_Surface *tmp2 = SDL_CreateSurface(dstrect->w, dstrect->h, src->format->format);
SDL_SoftStretchLinear(src, &srcrect2, tmp2, NULL);
SDL_SoftStretch(src, &srcrect2, tmp2, NULL, SDL_SCALEMODE_LINEAR);
SDL_SetSurfaceColorMod(tmp2, r, g, b);
SDL_SetSurfaceAlphaMod(tmp2, alpha);
@ -1028,7 +1054,7 @@ int SDL_PrivateBlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcr
ret = SDL_BlitSurfaceUnchecked(tmp2, &tmprect, dst, dstrect);
SDL_DestroySurface(tmp2);
} else {
ret = SDL_SoftStretchLinear(src, &srcrect2, dst, dstrect);
ret = SDL_SoftStretch(src, &srcrect2, dst, dstrect, SDL_SCALEMODE_LINEAR);
}
SDL_DestroySurface(tmp1);
@ -1102,17 +1128,17 @@ SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *for
Uint8 *palette_saved_alpha = NULL;
int palette_saved_alpha_ncolors = 0;
if (surface == NULL) {
if (!surface) {
SDL_InvalidParamError("surface");
return NULL;
}
if (format == NULL) {
if (!format) {
SDL_InvalidParamError("format");
return NULL;
}
/* Check for empty destination palette! (results in empty image) */
if (format->palette != NULL) {
if (format->palette) {
int i;
for (i = 0; i < format->palette->ncolors; ++i) {
if ((format->palette->colors[i].r != 0xFF) || (format->palette->colors[i].g != 0xFF) || (format->palette->colors[i].b != 0xFF)) {
@ -1127,7 +1153,7 @@ SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *for
/* Create a new surface with the desired format */
convert = SDL_CreateSurface(surface->w, surface->h, format->format);
if (convert == NULL) {
if (!convert) {
return NULL;
}
@ -1196,10 +1222,12 @@ SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *for
if (set_opaque) {
int i;
palette_saved_alpha_ncolors = surface->format->palette->ncolors;
palette_saved_alpha = SDL_stack_alloc(Uint8, palette_saved_alpha_ncolors);
for (i = 0; i < palette_saved_alpha_ncolors; i++) {
palette_saved_alpha[i] = surface->format->palette->colors[i].a;
surface->format->palette->colors[i].a = SDL_ALPHA_OPAQUE;
if (palette_saved_alpha_ncolors > 0) {
palette_saved_alpha = SDL_stack_alloc(Uint8, palette_saved_alpha_ncolors);
for (i = 0; i < palette_saved_alpha_ncolors; i++) {
palette_saved_alpha[i] = surface->format->palette->colors[i].a;
surface->format->palette->colors[i].a = SDL_ALPHA_OPAQUE;
}
}
}
}
@ -1285,7 +1313,7 @@ SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *for
/* Create a dummy surface to get the colorkey converted */
tmp = SDL_CreateSurface(1, 1, surface->format->format);
if (tmp == NULL) {
if (!tmp) {
SDL_DestroySurface(convert);
return NULL;
}
@ -1301,7 +1329,7 @@ SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *for
/* Conversion of the colorkey */
tmp2 = SDL_ConvertSurface(tmp, format);
if (tmp2 == NULL) {
if (!tmp2) {
SDL_DestroySurface(tmp);
SDL_DestroySurface(convert);
return NULL;
@ -1407,13 +1435,13 @@ int SDL_ConvertPixels(int width, int height,
void *nonconst_src = (void *)src;
int ret;
if (src == NULL) {
if (!src) {
return SDL_InvalidParamError("src");
}
if (!src_pitch) {
return SDL_InvalidParamError("src_pitch");
}
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("dst");
}
if (!dst_pitch) {
@ -1489,13 +1517,13 @@ int SDL_PremultiplyAlpha(int width, int height,
Uint32 dstpixel;
Uint32 dstR, dstG, dstB, dstA;
if (src == NULL) {
if (!src) {
return SDL_InvalidParamError("src");
}
if (!src_pitch) {
return SDL_InvalidParamError("src_pitch");
}
if (dst == NULL) {
if (!dst) {
return SDL_InvalidParamError("dst");
}
if (!dst_pitch) {
@ -1537,19 +1565,24 @@ int SDL_PremultiplyAlpha(int width, int height,
*/
void SDL_DestroySurface(SDL_Surface *surface)
{
if (surface == NULL) {
if (!surface) {
return;
}
if (surface->flags & SDL_DONTFREE) {
return;
}
SDL_InvalidateMap(surface->map);
SDL_InvalidateAllBlitMap(surface);
if (--surface->refcount > 0) {
return;
}
if (surface->flags & SDL_SURFACE_USES_PROPERTIES) {
SDL_PropertiesID props = (SDL_PropertiesID)(uintptr_t)surface->reserved;
SDL_DestroyProperties(props);
}
SDL_InvalidateMap(surface->map);
SDL_InvalidateAllBlitMap(surface);
while (surface->locked > 0) {
SDL_UnlockSurface(surface);
}

View File

@ -0,0 +1,80 @@
/*
Copyright 1997-2024 Sam Lantinga <slouken@libsdl.org>
Copyright 2023 Collabora Ltd.
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 "SDL3/SDL.h"
/* Internal implementation of SDL_ReadSurfacePixel, shared between SDL_shape
* and SDLTest */
static int SDL_ReadSurfacePixel_impl(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
{
Uint32 pixel = 0;
size_t bytes_per_pixel;
void *p;
if (!surface || !surface->format || !surface->pixels) {
return SDL_InvalidParamError("surface");
}
if (x < 0 || x >= surface->w) {
return SDL_InvalidParamError("x");
}
if (y < 0 || y >= surface->h) {
return SDL_InvalidParamError("y");
}
if (!r) {
return SDL_InvalidParamError("r");
}
if (!g) {
return SDL_InvalidParamError("g");
}
if (!b) {
return SDL_InvalidParamError("b");
}
if (!a) {
return SDL_InvalidParamError("a");
}
bytes_per_pixel = surface->format->BytesPerPixel;
if (bytes_per_pixel > sizeof(pixel)) {
return SDL_InvalidParamError("surface->format->BytesPerPixel");
}
SDL_LockSurface(surface);
p = (Uint8 *)surface->pixels + y * surface->pitch + x * bytes_per_pixel;
/* Fill the appropriate number of least-significant bytes of pixel,
* leaving the most-significant bytes set to zero */
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
SDL_memcpy(((Uint8 *) &pixel) + (sizeof(pixel) - bytes_per_pixel), p, bytes_per_pixel);
#else
SDL_memcpy(&pixel, p, bytes_per_pixel);
#endif
SDL_GetRGBA(pixel, surface->format, r, g, b, a);
SDL_UnlockSurface(surface);
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
@ -27,8 +27,6 @@
/* The SDL video driver */
typedef struct SDL_WindowShaper SDL_WindowShaper;
typedef struct SDL_ShapeDriver SDL_ShapeDriver;
typedef struct SDL_VideoDisplay SDL_VideoDisplay;
typedef struct SDL_VideoDevice SDL_VideoDevice;
typedef struct SDL_VideoData SDL_VideoData;
@ -36,35 +34,6 @@ typedef struct SDL_DisplayData SDL_DisplayData;
typedef struct SDL_DisplayModeData SDL_DisplayModeData;
typedef struct SDL_WindowData SDL_WindowData;
/* Define the SDL window-shaper structure */
struct SDL_WindowShaper
{
/* The window associated with the shaper */
SDL_Window *window;
/* The parameters for shape calculation. */
SDL_WindowShapeMode mode;
/* Has this window been assigned a shape? */
SDL_bool hasshape;
void *driverdata;
};
/* Define the SDL shape driver structure */
struct SDL_ShapeDriver
{
SDL_WindowShaper *(*CreateShaper)(SDL_Window *window);
int (*SetWindowShape)(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode);
};
typedef struct SDL_WindowUserData
{
char *name;
void *data;
struct SDL_WindowUserData *next;
} SDL_WindowUserData;
/* Define the SDL window structure, corresponding to toplevel windows */
struct SDL_Window
{
@ -84,9 +53,27 @@ struct SDL_Window
SDL_DisplayID last_fullscreen_exclusive_display; /* The last fullscreen_exclusive display */
SDL_DisplayID last_displayID;
/* Stored position and size for windowed mode */
/* Stored position and size for the window in the non-fullscreen state,
* including when the window is maximized or tiled.
*
* This is the size and position to which the window should return when
* leaving the fullscreen state.
*/
SDL_Rect windowed;
/* Stored position and size for the window in the base 'floating' state;
* when not fullscreen, nor in a state such as maximized or tiled.
*
* This is the size and position to which the window should return when
* it's maximized and SDL_RestoreWindow() is called.
*/
SDL_Rect floating;
/* Toggle for drivers to indicate that the current window state is
* not floating, but may not have any fixed-size flags (e.g. tiled)
*/
SDL_bool state_not_floating;
/* Whether or not the initial position was defined */
SDL_bool undefined_x;
SDL_bool undefined_y;
@ -106,12 +93,10 @@ struct SDL_Window
SDL_Rect mouse_rect;
SDL_WindowShaper *shaper;
SDL_HitTest hit_test;
void *hit_test_data;
SDL_WindowUserData *data;
SDL_PropertiesID props;
SDL_WindowData *driverdata;
@ -128,10 +113,9 @@ struct SDL_Window
(((W)->flags & SDL_WINDOW_HIDDEN) == 0) && \
(((W)->flags & SDL_WINDOW_MINIMIZED) == 0))
#define SDL_WINDOW_IS_POPUP(W) \
((((W)->flags & SDL_WINDOW_TOOLTIP) != 0) || \
(((W)->flags & SDL_WINDOW_POPUP_MENU) != 0)) \
\
#define SDL_WINDOW_IS_POPUP(W) \
(((W)->flags & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU)) != 0)
/*
* Define the SDL display structure.
* This corresponds to physical monitors attached to the system.
@ -153,19 +137,18 @@ struct SDL_VideoDisplay
SDL_VideoDevice *device;
SDL_PropertiesID props;
SDL_DisplayData *driverdata;
};
/* Forward declaration */
struct SDL_SysWMinfo;
/* Video device flags */
typedef enum
{
VIDEO_DEVICE_QUIRK_MODE_SWITCHING_EMULATED = 0x01,
VIDEO_DEVICE_QUIRK_DISABLE_UNSET_FULLSCREEN_ON_MINIMIZE = 0x02,
VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT = 0x04,
} DeviceQuirkFlags;
VIDEO_DEVICE_CAPS_MODE_SWITCHING_EMULATED = 0x01,
VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT = 0x02,
VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS = 0x04
} DeviceCaps;
struct SDL_VideoDevice
{
@ -230,8 +213,7 @@ struct SDL_VideoDevice
/*
* Window functions
*/
int (*CreateSDLWindow)(SDL_VideoDevice *_this, SDL_Window *window);
int (*CreateSDLWindowFrom)(SDL_VideoDevice *_this, SDL_Window *window, const void *data);
int (*CreateSDLWindow)(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props);
void (*SetWindowTitle)(SDL_VideoDevice *_this, SDL_Window *window);
int (*SetWindowIcon)(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon);
int (*SetWindowPosition)(SDL_VideoDevice *_this, SDL_Window *window);
@ -252,7 +234,7 @@ struct SDL_VideoDevice
void (*SetWindowBordered)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered);
void (*SetWindowResizable)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable);
void (*SetWindowAlwaysOnTop)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top);
void (*SetWindowFullscreen)(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
int (*SetWindowFullscreen)(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
void *(*GetWindowICCProfile)(SDL_VideoDevice *_this, SDL_Window *window, size_t *size);
SDL_DisplayID (*GetDisplayForWindow)(SDL_VideoDevice *_this, SDL_Window *window);
void (*SetWindowMouseRect)(SDL_VideoDevice *_this, SDL_Window *window);
@ -265,15 +247,7 @@ struct SDL_VideoDevice
void (*OnWindowEnter)(SDL_VideoDevice *_this, SDL_Window *window);
int (*FlashWindow)(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);
int (*SetWindowFocusable)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool focusable);
/* * * */
/*
* Shaped-window functions
*/
SDL_ShapeDriver shape_driver;
/* Get some platform dependent window information */
int (*GetWindowWMInfo)(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info);
int (*SyncWindow)(SDL_VideoDevice *_this, SDL_Window *window);
/* * * */
/*
@ -297,8 +271,8 @@ struct SDL_VideoDevice
*/
int (*Vulkan_LoadLibrary)(SDL_VideoDevice *_this, const char *path);
void (*Vulkan_UnloadLibrary)(SDL_VideoDevice *_this);
SDL_bool (*Vulkan_GetInstanceExtensions)(SDL_VideoDevice *_this, unsigned *count, const char **names);
SDL_bool (*Vulkan_CreateSurface)(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, VkSurfaceKHR *surface);
char const* const* (*Vulkan_GetInstanceExtensions)(SDL_VideoDevice *_this, Uint32 *count);
SDL_bool (*Vulkan_CreateSurface)(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface);
/* * * */
/*
@ -371,7 +345,6 @@ struct SDL_VideoDevice
SDL_Window *windows;
SDL_Window *grabbed_window;
Uint8 window_magic;
SDL_WindowID next_object_id;
Uint32 clipboard_sequence;
SDL_ClipboardDataCallback clipboard_callback;
SDL_ClipboardCleanupCallback clipboard_cleanup;
@ -380,7 +353,7 @@ struct SDL_VideoDevice
size_t num_clipboard_mime_types;
char *primary_selection_text;
SDL_bool setting_display_mode;
Uint32 quirk_flags;
Uint32 device_caps;
SDL_SystemTheme system_theme;
/* * * */
@ -514,8 +487,10 @@ extern void SDL_ResetFullscreenDisplayModes(SDL_VideoDisplay *display);
extern void SDL_SetDesktopDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode);
extern void SDL_SetCurrentDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode);
extern void SDL_SetDisplayContentScale(SDL_VideoDisplay *display, float scale);
extern int SDL_SetDisplayModeForDisplay(SDL_VideoDisplay *display, SDL_DisplayMode *mode);
extern SDL_VideoDisplay *SDL_GetVideoDisplay(SDL_DisplayID display);
extern SDL_VideoDisplay *SDL_GetVideoDisplayForWindow(SDL_Window *window);
extern SDL_VideoDisplay *SDL_GetVideoDisplayForFullscreenWindow(SDL_Window *window);
extern int SDL_GetDisplayIndex(SDL_DisplayID displayID);
extern SDL_DisplayData *SDL_GetDisplayDriverData(SDL_DisplayID display);
extern SDL_DisplayData *SDL_GetDisplayDriverDataForWindow(SDL_Window *window);
@ -528,7 +503,7 @@ extern SDL_bool SDL_HasWindows(void);
extern void SDL_RelativeToGlobalForWindow(SDL_Window *window, int rel_x, int rel_y, int *abs_x, int *abs_y);
extern void SDL_GlobalToRelativeForWindow(SDL_Window *window, int abs_x, int abs_y, int *rel_x, int *rel_y);
extern void SDL_OnDisplayConnected(SDL_VideoDisplay *display);
extern void SDL_OnDisplayAdded(SDL_VideoDisplay *display);
extern void SDL_OnWindowShown(SDL_Window *window);
extern void SDL_OnWindowHidden(SDL_Window *window);
extern void SDL_OnWindowMoved(SDL_Window *window);
@ -544,6 +519,7 @@ extern void SDL_OnWindowFocusGained(SDL_Window *window);
extern void SDL_OnWindowFocusLost(SDL_Window *window);
extern void SDL_OnWindowDisplayChanged(SDL_Window *window);
extern void SDL_UpdateWindowGrab(SDL_Window *window);
extern int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen, SDL_bool commit);
extern SDL_Window *SDL_GetToplevelForKeyboardFocus(void);
extern SDL_bool SDL_ShouldAllowTopmost(void);

View File

@ -0,0 +1,92 @@
/*
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"
#ifndef SDL_sysvideocapture_h_
#define SDL_sysvideocapture_h_
#include "../SDL_list.h"
/* The SDL video_capture driver */
typedef struct SDL_VideoCaptureDevice SDL_VideoCaptureDevice;
/* Define the SDL video_capture driver structure */
struct SDL_VideoCaptureDevice
{
/* * * */
/* Data common to all devices */
/* The device's current video_capture specification */
SDL_VideoCaptureSpec spec;
/* Device name */
char *dev_name;
/* Current state flags */
SDL_AtomicInt shutdown;
SDL_AtomicInt enabled;
SDL_bool is_spec_set;
/* A mutex for locking the queue buffers */
SDL_Mutex *device_lock;
SDL_Mutex *acquiring_lock;
/* A thread to feed the video_capture device */
SDL_Thread *thread;
SDL_threadID threadid;
/* Queued buffers (if app not using callback). */
SDL_ListNode *buffer_queue;
/* * * */
/* Data private to this driver */
struct SDL_PrivateVideoCaptureData *hidden;
};
extern int SDL_SYS_VideoCaptureInit(void);
extern int SDL_SYS_VideoCaptureQuit(void);
extern int OpenDevice(SDL_VideoCaptureDevice *_this);
extern void CloseDevice(SDL_VideoCaptureDevice *_this);
extern int InitDevice(SDL_VideoCaptureDevice *_this);
extern int GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec);
extern int StartCapture(SDL_VideoCaptureDevice *_this);
extern int StopCapture(SDL_VideoCaptureDevice *_this);
extern int AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame);
extern int ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame);
extern int GetNumFormats(SDL_VideoCaptureDevice *_this);
extern int GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format);
extern int GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format);
extern int GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height);
extern int GetDeviceName(SDL_VideoCaptureDeviceID instance_id, char *buf, int size);
extern SDL_VideoCaptureDeviceID *GetVideoCaptureDevices(int *count);
extern SDL_bool check_all_device_closed(void);
extern SDL_bool check_device_playing(void);
#endif /* SDL_sysvideocapture_h_ */

File diff suppressed because it is too large Load Diff

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
@ -57,4 +57,6 @@ extern void SDL_VideoQuit(void);
extern int SDL_SetWindowTextureVSync(SDL_Window *window, int vsync);
extern int SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a);
#endif /* SDL_video_c_h_ */

View File

@ -0,0 +1,968 @@
/*
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"
#include "SDL3/SDL.h"
#include "SDL3/SDL_video_capture.h"
#include "SDL_sysvideocapture.h"
#include "SDL_video_capture_c.h"
#include "SDL_pixels_c.h"
#include "../thread/SDL_systhread.h"
#define DEBUG_VIDEO_CAPTURE_CAPTURE 0
#ifdef SDL_VIDEO_CAPTURE
/* list node entries to share frames between SDL and user app */
typedef struct entry_t
{
SDL_VideoCaptureFrame frame;
} entry_t;
static SDL_VideoCaptureDevice *open_devices[16];
static void
close_device(SDL_VideoCaptureDevice *device)
{
if (!device) {
return;
}
SDL_AtomicSet(&device->shutdown, 1);
SDL_AtomicSet(&device->enabled, 1);
if (device->thread != NULL) {
SDL_WaitThread(device->thread, NULL);
}
if (device->device_lock != NULL) {
SDL_DestroyMutex(device->device_lock);
}
if (device->acquiring_lock != NULL) {
SDL_DestroyMutex(device->acquiring_lock);
}
{
int i, n = SDL_arraysize(open_devices);
for (i = 0; i < n; i++) {
if (open_devices[i] == device) {
open_devices[i] = NULL;
}
}
}
{
entry_t *entry = NULL;
while (device->buffer_queue != NULL) {
SDL_ListPop(&device->buffer_queue, (void**)&entry);
if (entry) {
SDL_VideoCaptureFrame f = entry->frame;
/* Release frames not acquired, if any */
if (f.timestampNS) {
ReleaseFrame(device, &f);
}
SDL_free(entry);
}
}
}
CloseDevice(device);
SDL_free(device->dev_name);
SDL_free(device);
}
/* Tell if all device are closed */
SDL_bool check_all_device_closed(void)
{
int i, n = SDL_arraysize(open_devices);
int all_closed = SDL_TRUE;
for (i = 0; i < n; i++) {
if (open_devices[i]) {
all_closed = SDL_FALSE;
break;
}
}
return all_closed;
}
/* Tell if at least one device is in playing state */
SDL_bool check_device_playing(void)
{
int i, n = SDL_arraysize(open_devices);
for (i = 0; i < n; i++) {
if (open_devices[i]) {
if (SDL_GetVideoCaptureStatus(open_devices[i]) == SDL_VIDEO_CAPTURE_PLAYING) {
return SDL_TRUE;
}
}
}
return SDL_FALSE;
}
#endif /* SDL_VIDEO_CAPTURE */
void
SDL_CloseVideoCapture(SDL_VideoCaptureDevice *device)
{
#ifdef SDL_VIDEO_CAPTURE
if (!device) {
SDL_InvalidParamError("device");
return;
}
close_device(device);
#endif
}
int
SDL_StartVideoCapture(SDL_VideoCaptureDevice *device)
{
#ifdef SDL_VIDEO_CAPTURE
SDL_VideoCaptureStatus status;
int result;
if (!device) {
return SDL_InvalidParamError("device");
}
if (device->is_spec_set == SDL_FALSE) {
return SDL_SetError("no spec set");
}
status = SDL_GetVideoCaptureStatus(device);
if (status != SDL_VIDEO_CAPTURE_INIT) {
return SDL_SetError("invalid state");
}
result = StartCapture(device);
if (result < 0) {
return result;
}
SDL_AtomicSet(&device->enabled, 1);
return 0;
#else
return SDL_Unsupported();
#endif
}
int
SDL_GetVideoCaptureSpec(SDL_VideoCaptureDevice *device, SDL_VideoCaptureSpec *spec)
{
#ifdef SDL_VIDEO_CAPTURE
if (!device) {
return SDL_InvalidParamError("device");
}
if (!spec) {
return SDL_InvalidParamError("spec");
}
SDL_zerop(spec);
return GetDeviceSpec(device, spec);
#else
return SDL_Unsupported();
#endif
}
int
SDL_StopVideoCapture(SDL_VideoCaptureDevice *device)
{
#ifdef SDL_VIDEO_CAPTURE
SDL_VideoCaptureStatus status;
int ret;
if (!device) {
return SDL_InvalidParamError("device");
}
status = SDL_GetVideoCaptureStatus(device);
if (status != SDL_VIDEO_CAPTURE_PLAYING) {
return SDL_SetError("invalid state");
}
SDL_AtomicSet(&device->enabled, 0);
SDL_AtomicSet(&device->shutdown, 1);
SDL_LockMutex(device->acquiring_lock);
ret = StopCapture(device);
SDL_UnlockMutex(device->acquiring_lock);
if (ret < 0) {
return -1;
}
return 0;
#else
return SDL_Unsupported();
#endif
}
#ifdef SDL_VIDEO_CAPTURE
/* Check spec has valid format and frame size */
static int
prepare_video_capturespec(SDL_VideoCaptureDevice *device, const SDL_VideoCaptureSpec *desired, SDL_VideoCaptureSpec *obtained, int allowed_changes)
{
/* Check format */
{
int i, num = SDL_GetNumVideoCaptureFormats(device);
int is_format_valid = 0;
for (i = 0; i < num; i++) {
Uint32 format;
if (SDL_GetVideoCaptureFormat(device, i, &format) == 0) {
if (format == desired->format && format != SDL_PIXELFORMAT_UNKNOWN) {
is_format_valid = 1;
obtained->format = format;
break;
}
}
}
if (!is_format_valid) {
if (allowed_changes) {
for (i = 0; i < num; i++) {
Uint32 format;
if (SDL_GetVideoCaptureFormat(device, i, &format) == 0) {
if (format != SDL_PIXELFORMAT_UNKNOWN) {
obtained->format = format;
is_format_valid = 1;
break;
}
}
}
} else {
SDL_SetError("Not allowed to change the format");
return -1;
}
}
if (!is_format_valid) {
SDL_SetError("Invalid format");
return -1;
}
}
/* Check frame size */
{
int i, num = SDL_GetNumVideoCaptureFrameSizes(device, obtained->format);
int is_framesize_valid = 0;
for (i = 0; i < num; i++) {
int w, h;
if (SDL_GetVideoCaptureFrameSize(device, obtained->format, i, &w, &h) == 0) {
if (desired->width == w && desired->height == h) {
is_framesize_valid = 1;
obtained->width = w;
obtained->height = h;
break;
}
}
}
if (!is_framesize_valid) {
if (allowed_changes) {
int w, h;
if (SDL_GetVideoCaptureFrameSize(device, obtained->format, 0, &w, &h) == 0) {
is_framesize_valid = 1;
obtained->width = w;
obtained->height = h;
}
} else {
SDL_SetError("Not allowed to change the frame size");
return -1;
}
}
if (!is_framesize_valid) {
SDL_SetError("Invalid frame size");
return -1;
}
}
return 0;
}
#endif /* SDL_VIDEO_CAPTURE */
const char *
SDL_GetVideoCaptureDeviceName(SDL_VideoCaptureDeviceID instance_id)
{
#ifdef SDL_VIDEO_CAPTURE
static char buf[256];
buf[0] = 0;
buf[255] = 0;
if (instance_id == 0) {
SDL_InvalidParamError("instance_id");
return NULL;
}
if (GetDeviceName(instance_id, buf, sizeof (buf)) < 0) {
buf[0] = 0;
}
return buf;
#else
SDL_Unsupported();
return NULL;
#endif
}
SDL_VideoCaptureDeviceID *
SDL_GetVideoCaptureDevices(int *count)
{
int num = 0;
SDL_VideoCaptureDeviceID *ret = NULL;
#ifdef SDL_VIDEO_CAPTURE
ret = GetVideoCaptureDevices(&num);
#endif
if (ret) {
if (count) {
*count = num;
}
return ret;
}
/* return list of 0 ID, null terminated */
num = 0;
ret = (SDL_VideoCaptureDeviceID *)SDL_malloc((num + 1) * sizeof(*ret));
if (ret == NULL) {
SDL_OutOfMemory();
if (count) {
*count = 0;
}
return NULL;
}
ret[num] = 0;
if (count) {
*count = num;
}
return ret;
}
#ifdef SDL_VIDEO_CAPTURE
/* Video capture thread function */
static int SDLCALL
SDL_CaptureVideoThread(void *devicep)
{
const int delay = 20;
SDL_VideoCaptureDevice *device = (SDL_VideoCaptureDevice *) devicep;
#if DEBUG_VIDEO_CAPTURE_CAPTURE
SDL_Log("Start thread 'SDL_CaptureVideo'");
#endif
#ifdef SDL_VIDEO_DRIVER_ANDROID
// TODO
/*
{
// Set thread priority to THREAD_PRIORITY_VIDEO
extern void Android_JNI_VideoCaptureSetThreadPriority(int, int);
Android_JNI_VideoCaptureSetThreadPriority(device->iscapture, device);
}*/
#else
/* The video_capture mixing is always a high priority thread */
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
#endif
/* Perform any thread setup */
device->threadid = SDL_ThreadID();
/* Init state */
while (!SDL_AtomicGet(&device->enabled)) {
SDL_Delay(delay);
}
/* Loop, filling the video_capture buffers */
while (!SDL_AtomicGet(&device->shutdown)) {
SDL_VideoCaptureFrame f;
int ret;
entry_t *entry;
SDL_zero(f);
SDL_LockMutex(device->acquiring_lock);
ret = AcquireFrame(device, &f);
SDL_UnlockMutex(device->acquiring_lock);
if (ret == 0) {
if (f.num_planes == 0) {
continue;
}
}
if (ret < 0) {
/* Flag it as an error */
#if DEBUG_VIDEO_CAPTURE_CAPTURE
SDL_Log("dev[%p] error AcquireFrame: %d %s", (void *)device, ret, SDL_GetError());
#endif
f.num_planes = 0;
}
entry = SDL_malloc(sizeof (entry_t));
if (entry == NULL) {
goto error_mem;
}
entry->frame = f;
SDL_LockMutex(device->device_lock);
ret = SDL_ListAdd(&device->buffer_queue, entry);
SDL_UnlockMutex(device->device_lock);
if (ret < 0) {
SDL_free(entry);
goto error_mem;
}
}
#if DEBUG_VIDEO_CAPTURE_CAPTURE
SDL_Log("dev[%p] End thread 'SDL_CaptureVideo'", (void *)device);
#endif
return 0;
error_mem:
#if DEBUG_VIDEO_CAPTURE_CAPTURE
SDL_Log("dev[%p] End thread 'SDL_CaptureVideo' with error: %s", (void *)device, SDL_GetError());
#endif
SDL_AtomicSet(&device->shutdown, 1);
SDL_OutOfMemory();
return 0;
}
#endif
SDL_VideoCaptureDevice *
SDL_OpenVideoCapture(SDL_VideoCaptureDeviceID instance_id)
{
#ifdef SDL_VIDEO_CAPTURE
int i, n = SDL_arraysize(open_devices);
int id = -1;
SDL_VideoCaptureDevice *device = NULL;
const char *device_name = NULL;
if (!SDL_WasInit(SDL_INIT_VIDEO)) {
SDL_SetError("Video subsystem is not initialized");
goto error;
}
/* !!! FIXME: there is a race condition here if two devices open from two threads at once. */
/* Find an available device ID... */
for (i = 0; i < n; i++) {
if (open_devices[i] == NULL) {
id = i;
break;
}
}
if (id == -1) {
SDL_SetError("Too many open video capture devices");
goto error;
}
if (instance_id != 0) {
device_name = SDL_GetVideoCaptureDeviceName(instance_id);
if (device_name == NULL) {
goto error;
}
} else {
SDL_VideoCaptureDeviceID *devices = SDL_GetVideoCaptureDevices(NULL);
if (devices && devices[0]) {
device_name = SDL_GetVideoCaptureDeviceName(devices[0]);
SDL_free(devices);
}
}
#if 0
// FIXME do we need this ?
/* Let the user override. */
{
const char *dev = SDL_getenv("SDL_VIDEO_CAPTURE_DEVICE_NAME");
if (dev && dev[0]) {
device_name = dev;
}
}
#endif
if (device_name == NULL) {
goto error;
}
device = (SDL_VideoCaptureDevice *) SDL_calloc(1, sizeof (SDL_VideoCaptureDevice));
if (device == NULL) {
SDL_OutOfMemory();
goto error;
}
device->dev_name = SDL_strdup(device_name);
SDL_AtomicSet(&device->shutdown, 0);
SDL_AtomicSet(&device->enabled, 0);
device->device_lock = SDL_CreateMutex();
if (device->device_lock == NULL) {
SDL_SetError("Couldn't create acquiring_lock");
goto error;
}
device->acquiring_lock = SDL_CreateMutex();
if (device->acquiring_lock == NULL) {
SDL_SetError("Couldn't create acquiring_lock");
goto error;
}
if (OpenDevice(device) < 0) {
goto error;
}
/* empty */
device->buffer_queue = NULL;
open_devices[id] = device; /* add it to our list of open devices. */
/* Start the video_capture thread */
{
const size_t stacksize = 64 * 1024;
char threadname[64];
SDL_snprintf(threadname, sizeof (threadname), "SDLVideoC%d", id);
device->thread = SDL_CreateThreadInternal(SDL_CaptureVideoThread, threadname, stacksize, device);
if (device->thread == NULL) {
SDL_SetError("Couldn't create video_capture thread");
goto error;
}
}
return device;
error:
close_device(device);
return NULL;
#else
SDL_Unsupported();
return NULL;
#endif /* SDL_VIDEO_CAPTURE */
}
int
SDL_SetVideoCaptureSpec(SDL_VideoCaptureDevice *device,
const SDL_VideoCaptureSpec *desired,
SDL_VideoCaptureSpec *obtained,
int allowed_changes)
{
#ifdef SDL_VIDEO_CAPTURE
SDL_VideoCaptureSpec _obtained;
SDL_VideoCaptureSpec _desired;
int result;
if (!device) {
return SDL_InvalidParamError("device");
}
if (device->is_spec_set == SDL_TRUE) {
return SDL_SetError("already configured");
}
if (!desired) {
SDL_zero(_desired);
desired = &_desired;
allowed_changes = SDL_VIDEO_CAPTURE_ALLOW_ANY_CHANGE;
} else {
/* in case desired == obtained */
_desired = *desired;
desired = &_desired;
}
if (!obtained) {
obtained = &_obtained;
}
SDL_zerop(obtained);
if (prepare_video_capturespec(device, desired, obtained, allowed_changes) < 0) {
return -1;
}
device->spec = *obtained;
result = InitDevice(device);
if (result < 0) {
return result;
}
*obtained = device->spec;
device->is_spec_set = SDL_TRUE;
return 0;
#else
SDL_zero(*obtained);
return SDL_Unsupported();
#endif /* SDL_VIDEO_CAPTURE */
}
int
SDL_AcquireVideoCaptureFrame(SDL_VideoCaptureDevice *device, SDL_VideoCaptureFrame *frame)
{
#ifdef SDL_VIDEO_CAPTURE
if (!device) {
return SDL_InvalidParamError("device");
}
if (!frame) {
return SDL_InvalidParamError("frame");
}
SDL_zerop(frame);
if (device->thread == NULL) {
int ret;
/* Wait for a frame */
while ((ret = AcquireFrame(device, frame)) == 0) {
if (frame->num_planes) {
return 0;
}
}
return -1;
} else {
entry_t *entry = NULL;
SDL_LockMutex(device->device_lock);
SDL_ListPop(&device->buffer_queue, (void**)&entry);
SDL_UnlockMutex(device->device_lock);
if (entry) {
*frame = entry->frame;
SDL_free(entry);
/* Error from thread */
if (frame->num_planes == 0 && frame->timestampNS == 0) {
return SDL_SetError("error from acquisition thread");
}
} else {
/* Queue is empty. Not an error. */
}
}
return 0;
#else
return SDL_Unsupported();
#endif /* SDL_VIDEO_CAPTURE */
}
int
SDL_ReleaseVideoCaptureFrame(SDL_VideoCaptureDevice *device, SDL_VideoCaptureFrame *frame)
{
#ifdef SDL_VIDEO_CAPTURE
if (!device) {
return SDL_InvalidParamError("device");
}
if (frame == NULL) {
return SDL_InvalidParamError("frame");
}
if (ReleaseFrame(device, frame) < 0) {
return -1;
}
SDL_zerop(frame);
return 0;
#else
return SDL_Unsupported();
#endif /* SDL_VIDEO_CAPTURE */
}
int
SDL_GetNumVideoCaptureFormats(SDL_VideoCaptureDevice *device)
{
#ifdef SDL_VIDEO_CAPTURE
if (!device) {
return SDL_InvalidParamError("device");
}
return GetNumFormats(device);
#else
return 0;
#endif /* SDL_VIDEO_CAPTURE */
}
int
SDL_GetVideoCaptureFormat(SDL_VideoCaptureDevice *device, int index, Uint32 *format)
{
#ifdef SDL_VIDEO_CAPTURE
if (!device) {
return SDL_InvalidParamError("device");
}
if (!format) {
return SDL_InvalidParamError("format");
}
*format = 0;
return GetFormat(device, index, format);
#else
return SDL_Unsupported();
#endif /* SDL_VIDEO_CAPTURE */
}
int
SDL_GetNumVideoCaptureFrameSizes(SDL_VideoCaptureDevice *device, Uint32 format)
{
#ifdef SDL_VIDEO_CAPTURE
if (!device) {
return SDL_InvalidParamError("device");
}
return GetNumFrameSizes(device, format);
#else
return 0;
#endif /* SDL_VIDEO_CAPTURE */
}
int
SDL_GetVideoCaptureFrameSize(SDL_VideoCaptureDevice *device, Uint32 format, int index, int *width, int *height)
{
#ifdef SDL_VIDEO_CAPTURE
if (!device) {
return SDL_InvalidParamError("device");
}
if (!width) {
return SDL_InvalidParamError("width");
}
if (!height) {
return SDL_InvalidParamError("height");
}
*width = 0;
*height = 0;
return GetFrameSize(device, format, index, width, height);
#else
return SDL_Unsupported();
#endif
}
SDL_VideoCaptureDevice *
SDL_OpenVideoCaptureWithSpec(
SDL_VideoCaptureDeviceID instance_id,
const SDL_VideoCaptureSpec *desired,
SDL_VideoCaptureSpec *obtained,
int allowed_changes)
{
#ifdef SDL_VIDEO_CAPTURE
SDL_VideoCaptureDevice *device;
if ((device = SDL_OpenVideoCapture(instance_id)) == NULL) {
return NULL;
}
if (SDL_SetVideoCaptureSpec(device, desired, obtained, allowed_changes) < 0) {
SDL_CloseVideoCapture(device);
return NULL;
}
return device;
#else
SDL_Unsupported();
return NULL;
#endif
}
SDL_VideoCaptureStatus
SDL_GetVideoCaptureStatus(SDL_VideoCaptureDevice *device)
{
#ifdef SDL_VIDEO_CAPTURE
if (device == NULL) {
return SDL_VIDEO_CAPTURE_INIT;
}
if (device->is_spec_set == SDL_FALSE) {
return SDL_VIDEO_CAPTURE_INIT;
}
if (SDL_AtomicGet(&device->shutdown)) {
return SDL_VIDEO_CAPTURE_STOPPED;
}
if (SDL_AtomicGet(&device->enabled)) {
return SDL_VIDEO_CAPTURE_PLAYING;
}
return SDL_VIDEO_CAPTURE_INIT;
#else
SDL_Unsupported();
return SDL_VIDEO_CAPTURE_FAIL;
#endif
}
int
SDL_VideoCaptureInit(void)
{
#ifdef SDL_VIDEO_CAPTURE
SDL_zeroa(open_devices);
SDL_SYS_VideoCaptureInit();
return 0;
#else
return 0;
#endif
}
void
SDL_QuitVideoCapture(void)
{
#ifdef SDL_VIDEO_CAPTURE
int i, n = SDL_arraysize(open_devices);
for (i = 0; i < n; i++) {
close_device(open_devices[i]);
}
SDL_zeroa(open_devices);
SDL_SYS_VideoCaptureQuit();
#endif
}
#ifdef SDL_VIDEO_CAPTURE
#if defined(__linux__) && !defined(__ANDROID__)
/* See SDL_video_capture_v4l2.c */
#elif defined(__ANDROID__) && __ANDROID_API__ >= 24
/* See SDL_android_video_capture.c */
#elif defined(__IOS__) || defined(__MACOS__)
/* See SDL_video_capture_apple.m */
#else
int SDL_SYS_VideoCaptureInit(void)
{
return 0;
}
int SDL_SYS_VideoCaptureQuit(void)
{
return 0;
}
int
OpenDevice(SDL_VideoCaptureDevice *_this)
{
return SDL_SetError("not implemented");
}
void
CloseDevice(SDL_VideoCaptureDevice *_this)
{
return;
}
int
InitDevice(SDL_VideoCaptureDevice *_this)
{
size_t size, pitch;
SDL_CalculateSize(_this->spec.format, _this->spec.width, _this->spec.height, &size, &pitch, SDL_FALSE);
SDL_Log("Buffer size: %d x %d", _this->spec.width, _this->spec.height);
return -1;
}
int
GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec)
{
return SDL_Unsupported();
}
int
StartCapture(SDL_VideoCaptureDevice *_this)
{
return SDL_Unsupported();
}
int
StopCapture(SDL_VideoCaptureDevice *_this)
{
return -1;
}
int
AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame)
{
return -1;
}
int
ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame)
{
return -1;
}
int
GetNumFormats(SDL_VideoCaptureDevice *_this)
{
return -1;
}
int
GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format)
{
return -1;
}
int
GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format)
{
return -1;
}
int
GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height)
{
return -1;
}
int
GetDeviceName(SDL_VideoCaptureDeviceID instance_id, char *buf, int size)
{
return -1;
}
SDL_VideoCaptureDeviceID *
GetVideoCaptureDevices(int *count)
{
return NULL;
}
#endif
#endif /* SDL_VIDEO_CAPTURE */

View File

@ -0,0 +1,659 @@
/*
Simple DirectMedia Layer
Copyright (C) 2021 Valve Corporation
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"
#ifdef SDL_VIDEO_CAPTURE
#include "SDL3/SDL.h"
#include "SDL3/SDL_video_capture.h"
#include "SDL_sysvideocapture.h"
#include "SDL_video_capture_c.h"
#include "../thread/SDL_systhread.h"
#if defined(HAVE_COREMEDIA) && defined(__MACOS__) && (__MAC_OS_X_VERSION_MAX_ALLOWED < 101500)
/* AVCaptureDeviceTypeBuiltInWideAngleCamera requires macOS SDK 10.15 */
#undef HAVE_COREMEDIA
#endif
#if TARGET_OS_TV
#undef HAVE_COREMEDIA
#endif
#ifndef HAVE_COREMEDIA
int InitDevice(SDL_VideoCaptureDevice *_this) {
return -1;
}
int OpenDevice(SDL_VideoCaptureDevice *_this) {
return -1;
}
int AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) {
return -1;
}
void CloseDevice(SDL_VideoCaptureDevice *_this) {
}
int GetDeviceName(SDL_VideoCaptureDeviceID instance_id, char *buf, int size) {
return -1;
}
int GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec) {
return -1;
}
int GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format) {
return -1;
}
int GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height) {
return -1;
}
SDL_VideoCaptureDeviceID *GetVideoCaptureDevices(int *count) {
return NULL;
}
int GetNumFormats(SDL_VideoCaptureDevice *_this) {
return 0;
}
int GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format) {
return 0;
}
int ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame) {
return 0;
}
int StartCapture(SDL_VideoCaptureDevice *_this) {
return 0;
}
int StopCapture(SDL_VideoCaptureDevice *_this) {
return 0;
}
int SDL_SYS_VideoCaptureInit(void) {
return 0;
}
int SDL_SYS_VideoCaptureQuit(void) {
return 0;
}
#else
#import <AVFoundation/AVFoundation.h>
#import <CoreMedia/CoreMedia.h>
/*
* Need to link with:: CoreMedia CoreVideo
*
* Add in pInfo.list:
* <key>NSCameraUsageDescription</key> <string>Access camera</string>
*
*
* MACOSX:
* Add to the Code Sign Entitlement file:
* <key>com.apple.security.device.camera</key> <true/>
*
*
* IOS:
*
* - Need to link with:: CoreMedia CoreVideo
* - Add #define SDL_VIDEO_CAPTURE 1
* to SDL_build_config_ios.h
*/
@class MySampleBufferDelegate;
struct SDL_PrivateVideoCaptureData
{
dispatch_queue_t queue;
MySampleBufferDelegate *delegate;
AVCaptureSession *session;
CMSimpleQueueRef frame_queue;
};
static NSString *
fourcc_to_nstring(Uint32 code)
{
Uint8 buf[4];
*(Uint32 *)buf = code;
return [NSString stringWithFormat:@"%c%c%c%c", buf[3], buf[2], buf[1], buf[0]];
}
static NSArray<AVCaptureDevice *> *
discover_devices()
{
NSArray *deviceType = @[AVCaptureDeviceTypeBuiltInWideAngleCamera];
AVCaptureDeviceDiscoverySession *discoverySession = [AVCaptureDeviceDiscoverySession
discoverySessionWithDeviceTypes:deviceType
mediaType:AVMediaTypeVideo
position:AVCaptureDevicePositionUnspecified];
NSArray<AVCaptureDevice *> *devices = discoverySession.devices;
if ([devices count] > 0) {
return devices;
} else {
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if (captureDevice == nil) {
return devices;
} else {
NSArray<AVCaptureDevice *> *default_device = @[ captureDevice ];
return default_device;
}
}
return devices;
}
static AVCaptureDevice *
get_device_by_name(const char *dev_name)
{
NSArray<AVCaptureDevice *> *devices = discover_devices();
for (AVCaptureDevice *device in devices) {
char buf[1024];
NSString *cameraID = [device localizedName];
const char *str = [cameraID UTF8String];
SDL_snprintf(buf, sizeof (buf) - 1, "%s", str);
if (SDL_strcmp(buf, dev_name) == 0) {
return device;
}
}
return nil;
}
static Uint32
nsfourcc_to_sdlformat(NSString *nsfourcc)
{
const char *str = [nsfourcc UTF8String];
/* FIXME
* on IOS this mode gives 2 planes, and it's NV12
* on macos, 1 plane/ YVYU
*
*/
#ifdef __MACOS__
if (SDL_strcmp("420v", str) == 0) return SDL_PIXELFORMAT_YVYU;
#else
if (SDL_strcmp("420v", str) == 0) return SDL_PIXELFORMAT_NV12;
#endif
if (SDL_strcmp("yuvs", str) == 0) return SDL_PIXELFORMAT_UYVY;
if (SDL_strcmp("420f", str) == 0) return SDL_PIXELFORMAT_UNKNOWN;
SDL_Log("Unknown format '%s'", str);
return SDL_PIXELFORMAT_UNKNOWN;
}
static NSString *
sdlformat_to_nsfourcc(Uint32 fmt)
{
const char *str = "";
NSString *result;
#ifdef __MACOS__
if (fmt == SDL_PIXELFORMAT_YVYU) str = "420v";
#else
if (fmt == SDL_PIXELFORMAT_NV12) str = "420v";
#endif
if (fmt == SDL_PIXELFORMAT_UYVY) str = "yuvs";
result = [[NSString alloc] initWithUTF8String: str];
return result;
}
@interface MySampleBufferDelegate : NSObject<AVCaptureVideoDataOutputSampleBufferDelegate>
@property struct SDL_PrivateVideoCaptureData *hidden;
- (void) set: (struct SDL_PrivateVideoCaptureData *) val;
@end
@implementation MySampleBufferDelegate
- (void) set: (struct SDL_PrivateVideoCaptureData *) val {
_hidden = val;
}
- (void) captureOutput:(AVCaptureOutput *)output
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *) connection {
CFRetain(sampleBuffer);
CMSimpleQueueEnqueue(_hidden->frame_queue, sampleBuffer);
}
- (void)captureOutput:(AVCaptureOutput *)output
didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection {
SDL_Log("Drop frame..");
}
@end
int
OpenDevice(SDL_VideoCaptureDevice *_this)
{
_this->hidden = (struct SDL_PrivateVideoCaptureData *) SDL_calloc(1, sizeof (struct SDL_PrivateVideoCaptureData));
if (_this->hidden == NULL) {
SDL_OutOfMemory();
goto error;
}
return 0;
error:
return -1;
}
void
CloseDevice(SDL_VideoCaptureDevice *_this)
{
if (!_this) {
return;
}
if (_this->hidden) {
AVCaptureSession *session = _this->hidden->session;
if (session) {
AVCaptureInput *input;
AVCaptureVideoDataOutput *output;
input = [session.inputs objectAtIndex:0];
[session removeInput:input];
output = (AVCaptureVideoDataOutput*)[session.outputs objectAtIndex:0];
[session removeOutput:output];
// TODO more cleanup ?
}
if (_this->hidden->frame_queue) {
CFRelease(_this->hidden->frame_queue);
}
SDL_free(_this->hidden);
_this->hidden = NULL;
}
}
int
InitDevice(SDL_VideoCaptureDevice *_this)
{
NSString *fmt = sdlformat_to_nsfourcc(_this->spec.format);
int w = _this->spec.width;
int h = _this->spec.height;
NSError *error = nil;
AVCaptureDevice *device = nil;
AVCaptureDeviceInput *input = nil;
AVCaptureVideoDataOutput *output = nil;
AVCaptureDeviceFormat *spec_format = nil;
#ifdef __MACOS__
if (@available(macOS 10.15, *)) {
/* good. */
} else {
return -1;
}
#endif
device = get_device_by_name(_this->dev_name);
if (!device) {
goto error;
}
_this->hidden->session = [[AVCaptureSession alloc] init];
if (_this->hidden->session == nil) {
goto error;
}
[_this->hidden->session setSessionPreset:AVCaptureSessionPresetHigh];
// Pick format that matches the spec
{
NSArray<AVCaptureDeviceFormat *> *formats = [device formats];
for (AVCaptureDeviceFormat *format in formats) {
CMFormatDescriptionRef formatDescription = [format formatDescription];
FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription);
NSString *str = fourcc_to_nstring(mediaSubType);
if (str == fmt) {
CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDescription);
if (dim.width == w && dim.height == h) {
spec_format = format;
break;
}
}
}
}
if (spec_format == nil) {
SDL_SetError("format not found");
goto error;
}
// Set format
if ([device lockForConfiguration:NULL] == YES) {
device.activeFormat = spec_format;
[device unlockForConfiguration];
} else {
SDL_SetError("Cannot lockForConfiguration");
goto error;
}
// Input
input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
SDL_SetError("Cannot create AVCaptureDeviceInput");
goto error;
}
// Output
output = [[AVCaptureVideoDataOutput alloc] init];
#ifdef __MACOS__
// FIXME this now fail on ios ... but not using anything works...
// Specify the pixel format
output.videoSettings =
[NSDictionary dictionaryWithObject:
[NSNumber numberWithInt:kCVPixelFormatType_422YpCbCr8]
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
#endif
_this->hidden->delegate = [[MySampleBufferDelegate alloc] init];
[_this->hidden->delegate set:_this->hidden];
CMSimpleQueueCreate(kCFAllocatorDefault, 30 /* buffers */, &_this->hidden->frame_queue);
if (_this->hidden->frame_queue == nil) {
goto error;
}
_this->hidden->queue = dispatch_queue_create("my_queue", NULL);
[output setSampleBufferDelegate:_this->hidden->delegate queue:_this->hidden->queue];
if ([_this->hidden->session canAddInput:input] ){
[_this->hidden->session addInput:input];
} else {
SDL_SetError("Cannot add AVCaptureDeviceInput");
goto error;
}
if ([_this->hidden->session canAddOutput:output] ){
[_this->hidden->session addOutput:output];
} else {
SDL_SetError("Cannot add AVCaptureVideoDataOutput");
goto error;
}
[_this->hidden->session commitConfiguration];
return 0;
error:
return -1;
}
int
GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec)
{
if (spec) {
*spec = _this->spec;
return 0;
}
return -1;
}
int
StartCapture(SDL_VideoCaptureDevice *_this)
{
[_this->hidden->session startRunning];
return 0;
}
int
StopCapture(SDL_VideoCaptureDevice *_this)
{
[_this->hidden->session stopRunning];
return 0;
}
int
AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame)
{
if (CMSimpleQueueGetCount(_this->hidden->frame_queue) > 0) {
int i, numPlanes, planar;
CMSampleBufferRef sampleBuffer;
CVImageBufferRef image;
sampleBuffer = (CMSampleBufferRef)CMSimpleQueueDequeue(_this->hidden->frame_queue);
frame->internal = (void *) sampleBuffer;
frame->timestampNS = SDL_GetTicksNS();
i = 0;
image = CMSampleBufferGetImageBuffer(sampleBuffer);
numPlanes = CVPixelBufferGetPlaneCount(image);
planar = CVPixelBufferIsPlanar(image);
#if 0
int w = CVPixelBufferGetWidth(image);
int h = CVPixelBufferGetHeight(image);
int sz = CVPixelBufferGetDataSize(image);
int pitch = CVPixelBufferGetBytesPerRow(image);
SDL_Log("buffer planar=%d count:%d %d x %d sz=%d pitch=%d", planar, numPlanes, w, h, sz, pitch);
#endif
CVPixelBufferLockBaseAddress(image, 0);
if (planar == 0 && numPlanes == 0) {
frame->pitch[0] = CVPixelBufferGetBytesPerRow(image);
frame->data[0] = CVPixelBufferGetBaseAddress(image);
frame->num_planes = 1;
} else {
for (i = 0; i < numPlanes && i < 3; i++) {
int rowStride = 0;
uint8_t *data = NULL;
frame->num_planes += 1;
rowStride = CVPixelBufferGetBytesPerRowOfPlane(image, i);
data = CVPixelBufferGetBaseAddressOfPlane(image, i);
frame->data[i] = data;
frame->pitch[i] = rowStride;
}
}
/* Unlocked when frame is released */
} else {
// no frame
SDL_Delay(20); // TODO fix some delay
}
return 0;
}
int
ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame)
{
if (frame->internal){
CMSampleBufferRef sampleBuffer = (CMSampleBufferRef) frame->internal;
CVImageBufferRef image = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferUnlockBaseAddress(image, 0);
CFRelease(sampleBuffer);
}
return 0;
}
int
GetNumFormats(SDL_VideoCaptureDevice *_this)
{
AVCaptureDevice *device = get_device_by_name(_this->dev_name);
if (device) {
// LIST FORMATS
NSMutableOrderedSet<NSString *> *array_formats = [NSMutableOrderedSet new];
NSArray<AVCaptureDeviceFormat *> *formats = [device formats];
for (AVCaptureDeviceFormat *format in formats) {
// NSLog(@"%@", formats);
CMFormatDescriptionRef formatDescription = [format formatDescription];
//NSLog(@"%@", formatDescription);
FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription);
NSString *str = fourcc_to_nstring(mediaSubType);
[array_formats addObject:str];
}
return [array_formats count];
}
return 0;
}
int
GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format)
{
AVCaptureDevice *device = get_device_by_name(_this->dev_name);
if (device) {
// LIST FORMATS
NSMutableOrderedSet<NSString *> *array_formats = [NSMutableOrderedSet new];
NSArray<AVCaptureDeviceFormat *> *formats = [device formats];
NSString *str;
for (AVCaptureDeviceFormat *f in formats) {
FourCharCode mediaSubType;
CMFormatDescriptionRef formatDescription;
formatDescription = [f formatDescription];
mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription);
str = fourcc_to_nstring(mediaSubType);
[array_formats addObject:str];
}
str = array_formats[index];
*format = nsfourcc_to_sdlformat(str);
return 0;
}
return -1;
}
int
GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format)
{
AVCaptureDevice *device = get_device_by_name(_this->dev_name);
if (device) {
NSString *fmt = sdlformat_to_nsfourcc(format);
int count = 0;
NSArray<AVCaptureDeviceFormat *> *formats = [device formats];
for (AVCaptureDeviceFormat *f in formats) {
CMFormatDescriptionRef formatDescription = [f formatDescription];
FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription);
NSString *str = fourcc_to_nstring(mediaSubType);
if (str == fmt) {
count += 1;
}
}
return count;
}
return 0;
}
int
GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height)
{
AVCaptureDevice *device = get_device_by_name(_this->dev_name);
if (device) {
NSString *fmt = sdlformat_to_nsfourcc(format);
int count = 0;
NSArray<AVCaptureDeviceFormat *> *formats = [device formats];
for (AVCaptureDeviceFormat *f in formats) {
CMFormatDescriptionRef formatDescription = [f formatDescription];
FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription);
NSString *str = fourcc_to_nstring(mediaSubType);
if (str == fmt) {
if (index == count) {
CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDescription);
*width = dim.width;
*height = dim.height;
return 0;
}
count += 1;
}
}
}
return -1;
}
int
GetDeviceName(SDL_VideoCaptureDeviceID instance_id, char *buf, int size)
{
int index = instance_id - 1;
NSArray<AVCaptureDevice *> *devices = discover_devices();
if (index < [devices count]) {
AVCaptureDevice *device = devices[index];
NSString *cameraID = [device localizedName];
const char *str = [cameraID UTF8String];
SDL_snprintf(buf, size, "%s", str);
return 0;
}
return -1;
}
static int
GetNumDevices(void)
{
NSArray<AVCaptureDevice *> *devices = discover_devices();
return [devices count];
}
SDL_VideoCaptureDeviceID *GetVideoCaptureDevices(int *count)
{
/* hard-coded list of ID */
int i;
int num = GetNumDevices();
SDL_VideoCaptureDeviceID *ret;
ret = (SDL_VideoCaptureDeviceID *)SDL_malloc((num + 1) * sizeof(*ret));
if (ret == NULL) {
SDL_OutOfMemory();
*count = 0;
return NULL;
}
for (i = 0; i < num; i++) {
ret[i] = i + 1;
}
ret[num] = 0;
*count = num;
return ret;
}
int SDL_SYS_VideoCaptureInit(void)
{
return 0;
}
int SDL_SYS_VideoCaptureQuit(void)
{
return 0;
}
#endif /* HAVE_COREMEDIA */
#endif /* SDL_VIDEO_CAPTURE */

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,20 +18,16 @@
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"
#include "../../include/SDL3/SDL_video_capture.h"
#ifndef SDL_x11shape_h_
#define SDL_x11shape_h_
#ifndef SDL_video_capture_c_h_
#define SDL_video_capture_c_h_
#include "../SDL_sysvideo.h"
/* Initialize the video_capture subsystem */
int SDL_VideoCaptureInit(void);
typedef struct
{
void *bitmap;
Uint32 bitmapsize;
} SDL_ShapeData;
/* Shutdown the video_capture subsystem */
void SDL_QuitVideoCapture(void);
extern SDL_WindowShaper *X11_CreateShaper(SDL_Window *window);
extern int X11_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode);
#endif /* SDL_x11shape_h_ */
#endif /* SDL_video_capture_c_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,91 @@
/*
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"
#ifndef SDL_VIDEO_DRIVER_WINDOWS
DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo(SDL_DisplayID displayID, int *adapterIndex, int *outputIndex);
SDL_bool SDL_DXGIGetOutputInfo(SDL_DisplayID displayID, int *adapterIndex, int *outputIndex)
{
(void)displayID;
(void)adapterIndex;
(void)outputIndex;
SDL_Unsupported();
return SDL_FALSE;
}
DECLSPEC int SDLCALL SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID);
int SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID)
{
(void)displayID;
return SDL_Unsupported();
}
#endif
#ifndef __GDK__
DECLSPEC int SDLCALL SDL_GDKGetTaskQueue(void *outTaskQueue);
int SDL_GDKGetTaskQueue(void *outTaskQueue)
{
(void)outTaskQueue;
return SDL_Unsupported();
}
#endif
#ifndef SDL_VIDEO_DRIVER_UIKIT
DECLSPEC void SDLCALL SDL_OnApplicationDidChangeStatusBarOrientation(void);
void SDL_OnApplicationDidChangeStatusBarOrientation(void)
{
SDL_Unsupported();
}
#endif
#ifndef SDL_VIDEO_DRIVER_UIKIT
DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window *window, int interval, void (*callback)(void *), void *callbackParam);
int SDL_iPhoneSetAnimationCallback(SDL_Window *window, int interval, void (*callback)(void *), void *callbackParam)
{
(void)window;
(void)interval;
(void)callback;
(void)callbackParam;
return SDL_Unsupported();
}
DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled);
void SDL_iPhoneSetEventPump(SDL_bool enabled)
{
(void)enabled;
SDL_Unsupported();
}
#endif
#if defined(__XBOXONE__) || defined(__XBOXSERIES__)
int SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID)
{
(void)displayID;
return SDL_Unsupported();
}
#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
@ -63,19 +63,13 @@ extern VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList(
PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties,
Uint32 *extensionCount); /* free returned list with SDL_free */
/* Implements functionality of SDL_Vulkan_GetInstanceExtensions for a list of
* names passed in nameCount and names. */
extern SDL_bool SDL_Vulkan_GetInstanceExtensions_Helper(unsigned *userCount,
const char **userNames,
unsigned nameCount,
const char *const *names);
/* Create a surface directly from a display connected to a physical device
* using the DisplayKHR extension.
* This needs to be passed an instance that was created with the VK_KHR_DISPLAY_EXTENSION_NAME
* extension. */
extern SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
#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
@ -148,8 +148,7 @@ VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList(
retval = SDL_calloc(count, sizeof(VkExtensionProperties));
}
if (retval == NULL) {
SDL_OutOfMemory();
if (!retval) {
return NULL;
}
@ -167,27 +166,6 @@ VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList(
return retval;
}
SDL_bool SDL_Vulkan_GetInstanceExtensions_Helper(unsigned *userCount,
const char **userNames,
unsigned nameCount,
const char *const *names)
{
if (userNames) {
unsigned i;
if (*userCount < nameCount) {
SDL_SetError("Output array for SDL_Vulkan_GetInstanceExtensions needs to be at least %d big", nameCount);
return SDL_FALSE;
}
for (i = 0; i < nameCount; i++) {
userNames[i] = names[i];
}
}
*userCount = nameCount;
return SDL_TRUE;
}
/* Alpha modes, in order of preference */
static const VkDisplayPlaneAlphaFlagBitsKHR alphaModes[4] = {
VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR,
@ -198,6 +176,7 @@ static const VkDisplayPlaneAlphaFlagBitsKHR alphaModes[4] = {
SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface)
{
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
@ -231,7 +210,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
goto error;
}
chosenDisplayId = SDL_getenv("SDL_VULKAN_DISPLAY");
if (chosenDisplayId != NULL) {
if (chosenDisplayId) {
displayId = SDL_atoi(chosenDisplayId);
}
@ -248,8 +227,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
}
physicalDevices = SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
if (physicalDevices == NULL) {
SDL_OutOfMemory();
if (!physicalDevices) {
goto error;
}
@ -291,8 +269,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
}
displayProperties = SDL_malloc(sizeof(VkDisplayPropertiesKHR) * displayPropertiesCount);
if (displayProperties == NULL) {
SDL_OutOfMemory();
if (!displayProperties) {
goto error;
}
@ -320,8 +297,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of display modes: %u", displayModePropertiesCount);
displayModeProperties = SDL_malloc(sizeof(VkDisplayModePropertiesKHR) * displayModePropertiesCount);
if (displayModeProperties == NULL) {
SDL_OutOfMemory();
if (!displayModeProperties) {
goto error;
}
@ -367,8 +343,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of display planes: %u", displayPlanePropertiesCount);
displayPlaneProperties = SDL_malloc(sizeof(VkDisplayPlanePropertiesKHR) * displayPlanePropertiesCount);
if (displayPlaneProperties == NULL) {
SDL_OutOfMemory();
if (!displayPlaneProperties) {
goto error;
}
@ -398,9 +373,8 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of supported displays for plane %u: %u", i, planeSupportedDisplaysCount);
planeSupportedDisplays = SDL_malloc(sizeof(VkDisplayKHR) * planeSupportedDisplaysCount);
if (planeSupportedDisplays == NULL) {
if (!planeSupportedDisplays) {
SDL_free(displayPlaneProperties);
SDL_OutOfMemory();
goto error;
}
@ -434,7 +408,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
if (extent.width >= planeCaps.minDstExtent.width && extent.height >= planeCaps.minDstExtent.height &&
extent.width <= planeCaps.maxDstExtent.width && extent.height <= planeCaps.maxDstExtent.height) {
/* If it does, choose this plane. */
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Choosing plane %d, minimum extent %dx%d maximum extent %dx%d", i,
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Choosing plane %u, minimum extent %ux%u maximum extent %ux%u", i,
planeCaps.minDstExtent.width, planeCaps.minDstExtent.height,
planeCaps.maxDstExtent.width, planeCaps.maxDstExtent.height);
planeIndex = i;
@ -480,7 +454,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
createInfo.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
createInfo.globalAlpha = 1.0f;
result = vkCreateDisplayPlaneSurfaceKHR(instance, &createInfo, NULL, surface);
result = vkCreateDisplayPlaneSurfaceKHR(instance, &createInfo, allocator, surface);
if (result != VK_SUCCESS) {
SDL_SetError("vkCreateDisplayPlaneSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result));
return SDL_FALSE;

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
@ -615,8 +615,8 @@ int SDL_ConvertPixels_YUV_to_RGB(int width, int height,
int tmp_pitch = (width * sizeof(Uint32));
tmp = SDL_malloc((size_t)tmp_pitch * height);
if (tmp == NULL) {
return SDL_OutOfMemory();
if (!tmp) {
return -1;
}
/* convert src/src_format to tmp/ARGB8888 */
@ -996,8 +996,8 @@ int SDL_ConvertPixels_RGB_to_YUV(int width, int height,
int tmp_pitch = (width * sizeof(Uint32));
tmp = SDL_malloc((size_t)tmp_pitch * height);
if (tmp == NULL) {
return SDL_OutOfMemory();
if (!tmp) {
return -1;
}
/* convert src/src_format to tmp/ARGB8888 */
@ -1085,8 +1085,8 @@ static int SDL_ConvertPixels_SwapUVPlanes(int width, int height, const void *src
/* Allocate a temporary row for the swap */
tmp = (Uint8 *)SDL_malloc(UVwidth);
if (tmp == NULL) {
return SDL_OutOfMemory();
if (!tmp) {
return -1;
}
for (y = 0; y < UVheight; ++y) {
SDL_memcpy(tmp, row1, UVwidth);
@ -1144,7 +1144,7 @@ static int SDL_TARGETING("sse2") SDL_ConvertPixels_PackUVPlanes_to_NV_SSE2(int w
/* Need to make a copy of the buffer so we don't clobber it while converting */
tmp = (Uint8 *)SDL_malloc((size_t)2 * UVheight * srcUVPitch);
if (tmp == NULL) {
return SDL_OutOfMemory();
return -1;
}
SDL_memcpy(tmp, src, (size_t)2 * UVheight * srcUVPitch);
src = tmp;
@ -1210,7 +1210,7 @@ static int SDL_TARGETING("sse2") SDL_ConvertPixels_SplitNV_to_UVPlanes_SSE2(int
/* Need to make a copy of the buffer so we don't clobber it while converting */
tmp = (Uint8 *)SDL_malloc((size_t)UVheight * srcUVPitch);
if (tmp == NULL) {
return SDL_OutOfMemory();
return -1;
}
SDL_memcpy(tmp, src, (size_t)UVheight * srcUVPitch);
src = tmp;
@ -1321,8 +1321,8 @@ static int SDL_ConvertPixels_PackUVPlanes_to_NV_std(int width, int height, const
if (src == dst) {
/* Need to make a copy of the buffer so we don't clobber it while converting */
tmp = (Uint8 *)SDL_malloc((size_t)2 * UVheight * srcUVPitch);
if (tmp == NULL) {
return SDL_OutOfMemory();
if (!tmp) {
return -1;
}
SDL_memcpy(tmp, src, (size_t)2 * UVheight * srcUVPitch);
src = tmp;
@ -1375,8 +1375,8 @@ static int SDL_ConvertPixels_SplitNV_to_UVPlanes_std(int width, int height, cons
if (src == dst) {
/* Need to make a copy of the buffer so we don't clobber it while converting */
tmp = (Uint8 *)SDL_malloc((size_t)UVheight * srcUVPitch);
if (tmp == NULL) {
return SDL_OutOfMemory();
if (!tmp) {
return -1;
}
SDL_memcpy(tmp, src, (size_t)UVheight * srcUVPitch);
src = tmp;

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

@ -0,0 +1,713 @@
/*
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"
#include "SDL3/SDL.h"
#include "SDL3/SDL_video_capture.h"
#include "../SDL_sysvideocapture.h"
#include "../SDL_video_capture_c.h"
#include "../SDL_pixels_c.h"
#include "../../thread/SDL_systhread.h"
#define DEBUG_VIDEO_CAPTURE_CAPTURE 0
#if defined(__ANDROID__) && __ANDROID_API__ >= 24
/*
* APP_PLATFORM=android-24
* minSdkVersion=24
*
* link with: -lcamera2ndk -lmediandk
*
* AndroidManifest.xml:
* <uses-permission android:name="android.permission.CAMERA"></uses-permission>
* <uses-feature android:name="android.hardware.camera" />
*
*
* Add: #define SDL_VIDEO_CAPTURE 1
* in: include/build_config/SDL_build_config_android.h
*
*
* Very likely SDL must be build with YUV support (done by default)
*
* https://developer.android.com/reference/android/hardware/camera2/CameraManager
* "All camera devices intended to be operated concurrently, must be opened using openCamera(String, CameraDevice.StateCallback, Handler),
* before configuring sessions on any of the camera devices. * "
*/
#include <camera/NdkCameraDevice.h>
#include <camera/NdkCameraManager.h>
#include <media/NdkImage.h>
#include <media/NdkImageReader.h>
#include "../../core/android/SDL_android.h"
static ACameraManager *cameraMgr = NULL;
static ACameraIdList *cameraIdList = NULL;
static void
create_cameraMgr(void)
{
if (cameraMgr == NULL) {
if (!Android_JNI_RequestPermission("android.permission.CAMERA")) {
SDL_SetError("This app doesn't have CAMERA permission");
return;
}
cameraMgr = ACameraManager_create();
if (cameraMgr == NULL) {
SDL_Log("Error creating ACameraManager");
} else {
SDL_Log("Create ACameraManager");
}
}
}
static void
delete_cameraMgr(void)
{
if (cameraIdList) {
ACameraManager_deleteCameraIdList(cameraIdList);
cameraIdList = NULL;
}
if (cameraMgr) {
ACameraManager_delete(cameraMgr);
cameraMgr = NULL;
}
}
struct SDL_PrivateVideoCaptureData
{
ACameraDevice *device;
ACameraCaptureSession *session;
ACameraDevice_StateCallbacks dev_callbacks;
ACameraCaptureSession_stateCallbacks capture_callbacks;
ACaptureSessionOutputContainer *sessionOutputContainer;
AImageReader *reader;
int num_formats;
int count_formats[6]; // see format_2_id
};
/**/
#define FORMAT_SDL SDL_PIXELFORMAT_NV12
static int
format_2_id(int fmt) {
switch (fmt) {
#define CASE(x, y) case x: return y
CASE(FORMAT_SDL, 0);
CASE(SDL_PIXELFORMAT_RGB565, 1);
CASE(SDL_PIXELFORMAT_XRGB8888, 2);
CASE(SDL_PIXELFORMAT_RGBA8888, 3);
CASE(SDL_PIXELFORMAT_RGBX8888, 4);
CASE(SDL_PIXELFORMAT_UNKNOWN, 5);
#undef CASE
default:
return 5;
}
}
static int
id_2_format(int fmt) {
switch (fmt) {
#define CASE(x, y) case y: return x
CASE(FORMAT_SDL, 0);
CASE(SDL_PIXELFORMAT_RGB565, 1);
CASE(SDL_PIXELFORMAT_XRGB8888, 2);
CASE(SDL_PIXELFORMAT_RGBA8888, 3);
CASE(SDL_PIXELFORMAT_RGBX8888, 4);
CASE(SDL_PIXELFORMAT_UNKNOWN, 5);
#undef CASE
default:
return SDL_PIXELFORMAT_UNKNOWN;
}
}
static Uint32
format_android_2_sdl(Uint32 fmt)
{
switch (fmt) {
#define CASE(x, y) case x: return y
CASE(AIMAGE_FORMAT_YUV_420_888, FORMAT_SDL);
CASE(AIMAGE_FORMAT_RGB_565, SDL_PIXELFORMAT_RGB565);
CASE(AIMAGE_FORMAT_RGB_888, SDL_PIXELFORMAT_XRGB8888);
CASE(AIMAGE_FORMAT_RGBA_8888, SDL_PIXELFORMAT_RGBA8888);
CASE(AIMAGE_FORMAT_RGBX_8888, SDL_PIXELFORMAT_RGBX8888);
CASE(AIMAGE_FORMAT_RGBA_FP16, SDL_PIXELFORMAT_UNKNOWN); // 64bits
CASE(AIMAGE_FORMAT_RAW_PRIVATE, SDL_PIXELFORMAT_UNKNOWN);
CASE(AIMAGE_FORMAT_JPEG, SDL_PIXELFORMAT_UNKNOWN);
#undef CASE
default:
SDL_Log("Unknown format AIMAGE_FORMAT '%d'", fmt);
return SDL_PIXELFORMAT_UNKNOWN;
}
}
static Uint32
format_sdl_2_android(Uint32 fmt)
{
switch (fmt) {
#define CASE(x, y) case y: return x
CASE(AIMAGE_FORMAT_YUV_420_888, FORMAT_SDL);
CASE(AIMAGE_FORMAT_RGB_565, SDL_PIXELFORMAT_RGB565);
CASE(AIMAGE_FORMAT_RGB_888, SDL_PIXELFORMAT_XRGB8888);
CASE(AIMAGE_FORMAT_RGBA_8888, SDL_PIXELFORMAT_RGBA8888);
CASE(AIMAGE_FORMAT_RGBX_8888, SDL_PIXELFORMAT_RGBX8888);
#undef CASE
default:
return 0;
}
}
static void
onDisconnected(void *context, ACameraDevice *device)
{
// SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context;
SDL_Log("CB onDisconnected");
}
static void
onError(void *context, ACameraDevice *device, int error)
{
// SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context;
SDL_Log("CB onError");
}
static void
onClosed(void* context, ACameraCaptureSession *session)
{
// SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context;
SDL_Log("CB onClosed");
}
static void
onReady(void* context, ACameraCaptureSession *session)
{
// SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context;
SDL_Log("CB onReady");
}
static void
onActive(void* context, ACameraCaptureSession *session)
{
// SDL_VideoCaptureDevice *_this = (SDL_VideoCaptureDevice *) context;
SDL_Log("CB onActive");
}
int
OpenDevice(SDL_VideoCaptureDevice *_this)
{
camera_status_t res;
/* Cannot open a second camera, while the first one is opened.
* If you want to play several camera, they must all be opened first, then played.
*
* https://developer.android.com/reference/android/hardware/camera2/CameraManager
* "All camera devices intended to be operated concurrently, must be opened using openCamera(String, CameraDevice.StateCallback, Handler),
* before configuring sessions on any of the camera devices. * "
*
*/
if (check_device_playing()) {
return SDL_SetError("A camera is already playing");
}
_this->hidden = (struct SDL_PrivateVideoCaptureData *) SDL_calloc(1, sizeof (struct SDL_PrivateVideoCaptureData));
if (_this->hidden == NULL) {
return SDL_OutOfMemory();
}
create_cameraMgr();
_this->hidden->dev_callbacks.context = (void *) _this;
_this->hidden->dev_callbacks.onDisconnected = onDisconnected;
_this->hidden->dev_callbacks.onError = onError;
res = ACameraManager_openCamera(cameraMgr, _this->dev_name, &_this->hidden->dev_callbacks, &_this->hidden->device);
if (res != ACAMERA_OK) {
return SDL_SetError("Failed to open camera");
}
return 0;
}
void
CloseDevice(SDL_VideoCaptureDevice *_this)
{
if (_this && _this->hidden) {
if (_this->hidden->session) {
ACameraCaptureSession_close(_this->hidden->session);
}
if (_this->hidden->sessionOutputContainer) {
ACaptureSessionOutputContainer_free(_this->hidden->sessionOutputContainer);
}
if (_this->hidden->reader) {
AImageReader_delete(_this->hidden->reader);
}
if (_this->hidden->device) {
ACameraDevice_close(_this->hidden->device);
}
SDL_free(_this->hidden);
_this->hidden = NULL;
}
if (check_all_device_closed()) {
delete_cameraMgr();
}
}
int
InitDevice(SDL_VideoCaptureDevice *_this)
{
size_t size, pitch;
SDL_CalculateSize(_this->spec.format, _this->spec.width, _this->spec.height, &size, &pitch, SDL_FALSE);
SDL_Log("Buffer size: %d x %d", _this->spec.width, _this->spec.height);
return 0;
}
int
GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec)
{
if (spec) {
*spec = _this->spec;
return 0;
}
return -1;
}
int
StartCapture(SDL_VideoCaptureDevice *_this)
{
camera_status_t res;
media_status_t res2;
ANativeWindow *window = NULL;
ACaptureSessionOutput *sessionOutput;
ACameraOutputTarget *outputTarget;
ACaptureRequest *request;
res2 = AImageReader_new(_this->spec.width, _this->spec.height, format_sdl_2_android(_this->spec.format), 10 /* nb buffers */, &_this->hidden->reader);
if (res2 != AMEDIA_OK) {
SDL_SetError("Error AImageReader_new");
goto error;
}
res2 = AImageReader_getWindow(_this->hidden->reader, &window);
if (res2 != AMEDIA_OK) {
SDL_SetError("Error AImageReader_new");
goto error;
}
res = ACaptureSessionOutput_create(window, &sessionOutput);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACaptureSessionOutput_create");
goto error;
}
res = ACaptureSessionOutputContainer_create(&_this->hidden->sessionOutputContainer);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACaptureSessionOutputContainer_create");
goto error;
}
res = ACaptureSessionOutputContainer_add(_this->hidden->sessionOutputContainer, sessionOutput);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACaptureSessionOutputContainer_add");
goto error;
}
res = ACameraOutputTarget_create(window, &outputTarget);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACameraOutputTarget_create");
goto error;
}
res = ACameraDevice_createCaptureRequest(_this->hidden->device, TEMPLATE_RECORD, &request);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACameraDevice_createCaptureRequest");
goto error;
}
res = ACaptureRequest_addTarget(request, outputTarget);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACaptureRequest_addTarget");
goto error;
}
_this->hidden->capture_callbacks.context = (void *) _this;
_this->hidden->capture_callbacks.onClosed = onClosed;
_this->hidden->capture_callbacks.onReady = onReady;
_this->hidden->capture_callbacks.onActive = onActive;
res = ACameraDevice_createCaptureSession(_this->hidden->device,
_this->hidden->sessionOutputContainer,
&_this->hidden->capture_callbacks,
&_this->hidden->session);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACameraDevice_createCaptureSession");
goto error;
}
res = ACameraCaptureSession_setRepeatingRequest(_this->hidden->session, NULL, 1, &request, NULL);
if (res != ACAMERA_OK) {
SDL_SetError("Error ACameraDevice_createCaptureSession");
goto error;
}
return 0;
error:
return -1;
}
int
StopCapture(SDL_VideoCaptureDevice *_this)
{
ACameraCaptureSession_close(_this->hidden->session);
_this->hidden->session = NULL;
return 0;
}
int
AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame)
{
media_status_t res;
AImage *image;
res = AImageReader_acquireNextImage(_this->hidden->reader, &image);
/* We could also use this one:
res = AImageReader_acquireLatestImage(_this->hidden->reader, &image);
*/
if (res == AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE ) {
SDL_Delay(20); // TODO fix some delay
#if DEBUG_VIDEO_CAPTURE_CAPTURE
// SDL_Log("AImageReader_acquireNextImage: AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE");
#endif
return 0;
} else if (res == AMEDIA_OK ) {
int i = 0;
int32_t numPlanes = 0;
AImage_getNumberOfPlanes(image, &numPlanes);
frame->timestampNS = SDL_GetTicksNS();
for (i = 0; i < numPlanes && i < 3; i++) {
int dataLength = 0;
int rowStride = 0;
uint8_t *data = NULL;
frame->num_planes += 1;
AImage_getPlaneRowStride(image, i, &rowStride);
res = AImage_getPlaneData(image, i, &data, &dataLength);
if (res == AMEDIA_OK) {
frame->data[i] = data;
frame->pitch[i] = rowStride;
}
}
if (frame->num_planes == 3) {
/* plane 2 and 3 are interleaved NV12. SDL only takes two planes for this format */
int pixelStride = 0;
AImage_getPlanePixelStride(image, 1, &pixelStride);
if (pixelStride == 2) {
frame->num_planes -= 1;
}
}
frame->internal = (void*)image;
return 0;
} else if (res == AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED) {
SDL_SetError("AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED");
} else {
SDL_SetError("AImageReader_acquireNextImage: %d", res);
}
return -1;
}
int
ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame)
{
if (frame->internal){
AImage_delete((AImage *)frame->internal);
}
return 0;
}
int
GetNumFormats(SDL_VideoCaptureDevice *_this)
{
camera_status_t res;
int i;
int unknown = 0;
ACameraMetadata *metadata;
ACameraMetadata_const_entry entry;
if (_this->hidden->num_formats != 0) {
return _this->hidden->num_formats;
}
res = ACameraManager_getCameraCharacteristics(cameraMgr, _this->dev_name, &metadata);
if (res != ACAMERA_OK) {
return -1;
}
res = ACameraMetadata_getConstEntry(metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
if (res != ACAMERA_OK) {
return -1;
}
SDL_Log("got entry ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS");
for (i = 0; i < entry.count; i += 4) {
int32_t format = entry.data.i32[i + 0];
int32_t type = entry.data.i32[i + 3];
Uint32 fmt;
if (type == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
continue;
}
fmt = format_android_2_sdl(format);
_this->hidden->count_formats[format_2_id(fmt)] += 1;
#if DEBUG_VIDEO_CAPTURE_CAPTURE
if (fmt != SDL_PIXELFORMAT_UNKNOWN) {
int w = entry.data.i32[i + 1];
int h = entry.data.i32[i + 2];
SDL_Log("Got format android 0x%08x -> %s %d x %d", format, SDL_GetPixelFormatName(fmt), w, h);
} else {
unknown += 1;
}
#endif
}
#if DEBUG_VIDEO_CAPTURE_CAPTURE
if (unknown) {
SDL_Log("Got unknown android");
}
#endif
if ( _this->hidden->count_formats[0]) _this->hidden->num_formats += 1;
if ( _this->hidden->count_formats[1]) _this->hidden->num_formats += 1;
if ( _this->hidden->count_formats[2]) _this->hidden->num_formats += 1;
if ( _this->hidden->count_formats[3]) _this->hidden->num_formats += 1;
if ( _this->hidden->count_formats[4]) _this->hidden->num_formats += 1;
if ( _this->hidden->count_formats[5]) _this->hidden->num_formats += 1;
return _this->hidden->num_formats;
}
int
GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format)
{
int i;
int i2 = 0;
if (_this->hidden->num_formats == 0) {
GetNumFormats(_this);
}
if (index < 0 || index >= _this->hidden->num_formats) {
return -1;
}
for (i = 0; i < SDL_arraysize(_this->hidden->count_formats); i++) {
if (_this->hidden->count_formats[i] == 0) {
continue;
}
if (i2 == index) {
*format = id_2_format(i);
}
i2++;
}
return 0;
}
int
GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format)
{
int i, i2 = 0, index;
if (_this->hidden->num_formats == 0) {
GetNumFormats(_this);
}
index = format_2_id(format);
for (i = 0; i < SDL_arraysize(_this->hidden->count_formats); i++) {
if (_this->hidden->count_formats[i] == 0) {
continue;
}
if (i2 == index) {
/* number of resolution for this format */
return _this->hidden->count_formats[i];
}
i2++;
}
return -1;
}
int
GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height)
{
camera_status_t res;
int i, i2 = 0;
ACameraMetadata *metadata;
ACameraMetadata_const_entry entry;
if (_this->hidden->num_formats == 0) {
GetNumFormats(_this);
}
res = ACameraManager_getCameraCharacteristics(cameraMgr, _this->dev_name, &metadata);
if (res != ACAMERA_OK) {
return -1;
}
res = ACameraMetadata_getConstEntry(metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
if (res != ACAMERA_OK) {
return -1;
}
for (i = 0; i < entry.count; i += 4) {
int32_t f = entry.data.i32[i + 0];
int w = entry.data.i32[i + 1];
int h = entry.data.i32[i + 2];
int32_t type = entry.data.i32[i + 3];
Uint32 fmt;
if (type == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {
continue;
}
fmt = format_android_2_sdl(f);
if (fmt != format) {
continue;
}
if (i2 == index) {
*width = w;
*height = h;
return 0;
}
i2++;
}
return -1;
}
static int GetNumDevices(void);
int
GetDeviceName(SDL_VideoCaptureDeviceID instance_id, char *buf, int size)
{
int index = instance_id - 1;
create_cameraMgr();
if (cameraIdList == NULL) {
GetNumDevices();
}
if (cameraIdList) {
if (index >= 0 && index < cameraIdList->numCameras) {
SDL_snprintf(buf, size, "%s", cameraIdList->cameraIds[index]);
return 0;
}
}
return -1;
}
static int
GetNumDevices(void)
{
camera_status_t res;
create_cameraMgr();
if (cameraIdList) {
ACameraManager_deleteCameraIdList(cameraIdList);
cameraIdList = NULL;
}
res = ACameraManager_getCameraIdList(cameraMgr, &cameraIdList);
if (res == ACAMERA_OK) {
if (cameraIdList) {
return cameraIdList->numCameras;
}
}
return -1;
}
SDL_VideoCaptureDeviceID *GetVideoCaptureDevices(int *count)
{
/* hard-coded list of ID */
int i;
int num = GetNumDevices();
SDL_VideoCaptureDeviceID *ret;
ret = (SDL_VideoCaptureDeviceID *)SDL_malloc((num + 1) * sizeof(*ret));
if (ret == NULL) {
SDL_OutOfMemory();
*count = 0;
return NULL;
}
for (i = 0; i < num; i++) {
ret[i] = i + 1;
}
ret[num] = 0;
*count = num;
return ret;
}
int SDL_SYS_VideoCaptureInit(void) {
return 0;
}
int SDL_SYS_VideoCaptureQuit(void) {
return 0;
}
#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
@ -45,6 +45,7 @@ static void android_egl_context_restore(SDL_Window *window)
if (window) {
SDL_Event event;
SDL_WindowData *data = window->driverdata;
SDL_GL_MakeCurrent(window, NULL);
if (SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context) < 0) {
/* The context is no longer valid, create a new one */
data->egl_context = (EGLContext)SDL_GL_CreateContext(window);
@ -107,7 +108,7 @@ void Android_PumpEvents_Blocking(SDL_VideoDevice *_this)
#endif
ANDROIDAUDIO_PauseDevices();
openslES_PauseDevices();
OPENSLES_PauseDevices();
AAUDIO_PauseDevices();
if (SDL_WaitSemaphore(Android_ResumeSem) == 0) {
@ -118,7 +119,7 @@ void Android_PumpEvents_Blocking(SDL_VideoDevice *_this)
SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND);
ANDROIDAUDIO_ResumeDevices();
openslES_ResumeDevices();
OPENSLES_ResumeDevices();
AAUDIO_ResumeDevices();
/* Restore the GL Context from here, as this operation is thread dependent */
@ -131,8 +132,9 @@ void Android_PumpEvents_Blocking(SDL_VideoDevice *_this)
#endif
/* Make sure SW Keyboard is restored when an app becomes foreground */
if (SDL_TextInputActive()) {
Android_StartTextInput(_this); /* Only showTextInput */
if (SDL_TextInputActive() &&
SDL_GetHintBoolean(SDL_HINT_ENABLE_SCREEN_KEYBOARD, SDL_TRUE)) {
Android_ShowScreenKeyboard(_this, Android_Window); /* Only showTextInput */
}
SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND);
@ -159,11 +161,6 @@ void Android_PumpEvents_Blocking(SDL_VideoDevice *_this)
}
}
}
if (AAUDIO_DetectBrokenPlayState()) {
AAUDIO_PauseDevices();
AAUDIO_ResumeDevices();
}
}
void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this)
@ -186,7 +183,7 @@ void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this)
if (videodata->pauseAudio) {
ANDROIDAUDIO_PauseDevices();
openslES_PauseDevices();
OPENSLES_PauseDevices();
AAUDIO_PauseDevices();
}
@ -202,7 +199,7 @@ void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this)
if (videodata->pauseAudio) {
ANDROIDAUDIO_ResumeDevices();
openslES_ResumeDevices();
OPENSLES_ResumeDevices();
AAUDIO_ResumeDevices();
}
@ -216,8 +213,9 @@ void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this)
#endif
/* Make sure SW Keyboard is restored when an app becomes foreground */
if (SDL_TextInputActive()) {
Android_StartTextInput(_this); /* Only showTextInput */
if (SDL_TextInputActive() &&
SDL_GetHintBoolean(SDL_HINT_ENABLE_SCREEN_KEYBOARD, SDL_TRUE)) {
Android_ShowScreenKeyboard(_this, Android_Window); /* Only showTextInput */
}
SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND);
@ -245,11 +243,6 @@ void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this)
}
}
}
if (AAUDIO_DetectBrokenPlayState()) {
AAUDIO_PauseDevices();
AAUDIO_ResumeDevices();
}
}
#endif /* SDL_VIDEO_DRIVER_ANDROID */

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
@ -341,22 +341,22 @@ SDL_bool Android_HasScreenKeyboardSupport(SDL_VideoDevice *_this)
return SDL_TRUE;
}
void Android_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_VideoData *videodata = _this->driverdata;
Android_JNI_ShowScreenKeyboard(&videodata->textRect);
}
void Android_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window)
{
Android_JNI_HideScreenKeyboard();
}
SDL_bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window)
{
return Android_JNI_IsScreenKeyboardShown();
}
void Android_StartTextInput(SDL_VideoDevice *_this)
{
SDL_VideoData *videodata = _this->driverdata;
Android_JNI_ShowTextInput(&videodata->textRect);
}
void Android_StopTextInput(SDL_VideoDevice *_this)
{
Android_JNI_HideTextInput();
}
int Android_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect)
{
SDL_VideoData *videodata = _this->driverdata;

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
@ -26,8 +26,7 @@ extern int Android_OnKeyDown(int keycode);
extern int Android_OnKeyUp(int keycode);
extern SDL_bool Android_HasScreenKeyboardSupport(SDL_VideoDevice *_this);
extern void Android_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
extern void Android_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
extern SDL_bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window);
extern void Android_StartTextInput(SDL_VideoDevice *_this);
extern void Android_StopTextInput(SDL_VideoDevice *_this);
extern int Android_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect);

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
@ -68,10 +68,7 @@ static SDL_Cursor *Android_WrapCursor(int custom_cursor, int system_cursor)
} else {
SDL_free(cursor);
cursor = NULL;
SDL_OutOfMemory();
}
} else {
SDL_OutOfMemory();
}
return cursor;
@ -88,7 +85,7 @@ static SDL_Cursor *Android_CreateCursor(SDL_Surface *surface, int hot_x, int hot
SDL_Surface *converted;
converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888);
if (converted == NULL) {
if (!converted) {
return NULL;
}
custom_cursor = Android_JNI_CreateCustomCursor(converted, hot_x, hot_y);
@ -117,7 +114,7 @@ static void Android_FreeCursor(SDL_Cursor *cursor)
static SDL_Cursor *Android_CreateEmptyCursor()
{
if (empty_cursor == NULL) {
if (!empty_cursor) {
SDL_Surface *empty_surface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ARGB8888);
if (empty_surface) {
SDL_memset(empty_surface->pixels, 0, (size_t)empty_surface->h * empty_surface->pitch);
@ -138,7 +135,7 @@ static void Android_DestroyEmptyCursor()
static int Android_ShowCursor(SDL_Cursor *cursor)
{
if (cursor == NULL) {
if (!cursor) {
cursor = Android_CreateEmptyCursor();
}
if (cursor) {
@ -215,7 +212,7 @@ void Android_OnMouse(SDL_Window *window, int state, int action, float x, float y
int changes;
Uint8 button;
if (window == NULL) {
if (!window) {
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

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
@ -52,7 +52,7 @@ void Android_OnTouch(SDL_Window *window, int touch_device_id_in, int pointer_fin
SDL_TouchID touchDeviceId = 0;
SDL_FingerID fingerId = 0;
if (window == NULL) {
if (!window) {
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

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,14 +86,12 @@ static SDL_VideoDevice *Android_CreateDevice(void)
/* Initialize all variables that we clean on shutdown */
device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
if (device == NULL) {
SDL_OutOfMemory();
if (!device) {
return NULL;
}
data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData));
if (data == NULL) {
SDL_OutOfMemory();
if (!data) {
SDL_free(device);
return NULL;
}
@ -117,7 +115,6 @@ static SDL_VideoDevice *Android_CreateDevice(void)
device->MinimizeWindow = Android_MinimizeWindow;
device->SetWindowResizable = Android_SetWindowResizable;
device->DestroyWindow = Android_DestroyWindow;
device->GetWindowWMInfo = Android_GetWindowWMInfo;
device->free = Android_DeleteDevice;
@ -145,12 +142,12 @@ static SDL_VideoDevice *Android_CreateDevice(void)
device->SuspendScreenSaver = Android_SuspendScreenSaver;
/* Text input */
device->StartTextInput = Android_StartTextInput;
device->StopTextInput = Android_StopTextInput;
device->SetTextInputRect = Android_SetTextInputRect;
/* Screen keyboard */
device->HasScreenKeyboardSupport = Android_HasScreenKeyboardSupport;
device->ShowScreenKeyboard = Android_ShowScreenKeyboard;
device->HideScreenKeyboard = Android_HideScreenKeyboard;
device->IsScreenKeyboardShown = Android_IsScreenKeyboardShown;
/* Clipboard */
@ -158,6 +155,8 @@ static SDL_VideoDevice *Android_CreateDevice(void)
device->GetClipboardText = Android_GetClipboardText;
device->HasClipboardText = Android_HasClipboardText;
device->device_caps = VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS;
return device;
}

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
@ -35,7 +35,6 @@
#include "SDL_androidvulkan.h"
#include <SDL3/SDL_syswm.h>
int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path)
{
@ -49,10 +48,10 @@ int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path)
}
/* Load the Vulkan loader library */
if (path == NULL) {
if (!path) {
path = SDL_getenv("SDL_VULKAN_LIBRARY");
}
if (path == NULL) {
if (!path) {
path = "libvulkan.so";
}
_this->vulkan_config.loader_handle = SDL_LoadObject(path);
@ -77,7 +76,7 @@ int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path)
(PFN_vkEnumerateInstanceExtensionProperties)
_this->vulkan_config.vkEnumerateInstanceExtensionProperties,
&extensionCount);
if (extensions == NULL) {
if (!extensions) {
goto fail;
}
for (i = 0; i < extensionCount; i++) {
@ -111,25 +110,22 @@ void Android_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
}
}
SDL_bool Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
unsigned *count,
const char **names)
char const* const* Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count)
{
static const char *const extensionsForAndroid[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
};
if (!_this->vulkan_config.loader_handle) {
SDL_SetError("Vulkan is not loaded");
return SDL_FALSE;
if(count) {
*count = SDL_arraysize(extensionsForAndroid);
}
return SDL_Vulkan_GetInstanceExtensions_Helper(
count, names, SDL_arraysize(extensionsForAndroid),
extensionsForAndroid);
return extensionsForAndroid;
}
SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this,
SDL_Window *window,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface)
{
SDL_WindowData *windowData = window->driverdata;
@ -157,8 +153,7 @@ SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this,
createInfo.pNext = NULL;
createInfo.flags = 0;
createInfo.window = windowData->native_window;
result = vkCreateAndroidSurfaceKHR(instance, &createInfo,
NULL, surface);
result = vkCreateAndroidSurfaceKHR(instance, &createInfo, allocator, surface);
if (result != VK_SUCCESS) {
SDL_SetError("vkCreateAndroidSurfaceKHR failed: %s",
SDL_Vulkan_GetResultString(result));

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
@ -36,12 +36,12 @@
int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path);
void Android_Vulkan_UnloadLibrary(SDL_VideoDevice *_this);
SDL_bool Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
unsigned *count,
const char **names);
char const* const* Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count);
SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this,
SDL_Window *window,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
#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
@ -31,12 +31,11 @@
#include "SDL_androidvideo.h"
#include "SDL_androidwindow.h"
#include <SDL3/SDL_syswm.h>
/* Currently only one window */
SDL_Window *Android_Window = NULL;
int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props)
{
SDL_WindowData *data;
int retval = 0;
@ -62,18 +61,18 @@ int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
SDL_SetKeyboardFocus(window);
data = (SDL_WindowData *)SDL_calloc(1, sizeof(*data));
if (data == NULL) {
retval = SDL_OutOfMemory();
if (!data) {
retval = -1;
goto endfunction;
}
data->native_window = Android_JNI_GetNativeWindow();
if (!data->native_window) {
SDL_free(data);
retval = SDL_SetError("Could not fetch native window");
goto endfunction;
}
SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_ANDROID_WINDOW_POINTER, data->native_window);
/* Do not create EGLSurface for Vulkan window since it will then make the window
incompatible with vkCreateAndroidSurfaceKHR */
@ -88,6 +87,7 @@ int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
goto endfunction;
}
}
SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROPERTY_WINDOW_ANDROID_SURFACE_POINTER, data->egl_surface);
#endif
window->driverdata = data;
@ -105,7 +105,7 @@ void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window)
Android_JNI_SetActivityTitle(window->title);
}
void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
int Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
{
SDL_LockMutex(Android_ActivityMutex);
@ -129,7 +129,7 @@ void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL
}
data = window->driverdata;
if (data == NULL || !data->native_window) {
if (!data || !data->native_window) {
if (data && !data->native_window) {
SDL_SetError("Missing native window");
}
@ -154,6 +154,7 @@ void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL
endfunction:
SDL_UnlockMutex(Android_ActivityMutex);
return 0;
}
void Android_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
@ -194,18 +195,4 @@ void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
SDL_UnlockMutex(Android_ActivityMutex);
}
int Android_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info)
{
SDL_WindowData *data = window->driverdata;
info->subsystem = SDL_SYSWM_ANDROID;
info->info.android.window = data->native_window;
#ifdef SDL_VIDEO_OPENGL_EGL
info->info.android.surface = data->egl_surface;
#endif
return 0;
}
#endif /* SDL_VIDEO_DRIVER_ANDROID */

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
@ -26,14 +26,13 @@
#include "../../core/android/SDL_android.h"
#include "../SDL_egl_c.h"
extern int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props);
extern void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window);
extern void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
extern int Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
extern void Android_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void Android_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable);
extern void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern int Android_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info);
extern SDL_Window *Android_Window;
struct SDL_WindowData

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
@ -148,8 +148,6 @@ void *Cocoa_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size
if (data) {
[itemData getBytes: data length: length];
SDL_memset((Uint8 *)data + length, 0, sizeof(Uint32));
} else {
SDL_OutOfMemory();
}
break;
}

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
@ -133,6 +133,7 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context;
- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app;
@end
@implementation SDLAppDelegate : NSObject
@ -141,18 +142,21 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
self = [super init];
if (self) {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
SDL_bool registerActivationHandlers = SDL_GetHintBoolean("SDL_MAC_REGISTER_ACTIVATION_HANDLERS", SDL_TRUE);
seenFirstActivate = NO;
[center addObserver:self
selector:@selector(windowWillClose:)
name:NSWindowWillCloseNotification
object:nil];
if (registerActivationHandlers) {
[center addObserver:self
selector:@selector(windowWillClose:)
name:NSWindowWillCloseNotification
object:nil];
[center addObserver:self
selector:@selector(focusSomeWindow:)
name:NSApplicationDidBecomeActiveNotification
object:nil];
[center addObserver:self
selector:@selector(focusSomeWindow:)
name:NSApplicationDidBecomeActiveNotification
object:nil];
}
[center addObserver:self
selector:@selector(localeDidChange:)
@ -287,11 +291,14 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
{
return (BOOL)SDL_SendDropFile(NULL, [filename UTF8String]) && SDL_SendDropComplete(NULL);
return (BOOL)SDL_SendDropFile(NULL, NULL, [filename UTF8String]) && SDL_SendDropComplete(NULL);
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
if (!SDL_GetHintBoolean("SDL_MAC_REGISTER_ACTIVATION_HANDLERS", SDL_TRUE))
return;
/* The menu bar of SDL apps which don't have the typical .app bundle
* structure fails to work the first time a window is created (until it's
* de-focused and re-focused), if this call is in Cocoa_RegisterApp instead
@ -315,10 +322,26 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
- (void)handleURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
NSString *path = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
SDL_SendDropFile(NULL, [path UTF8String]);
SDL_SendDropFile(NULL, NULL, [path UTF8String]);
SDL_SendDropComplete(NULL);
}
- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app
{
// This just tells Cocoa that we didn't do any custom save state magic for the app,
// so the system is safe to use NSSecureCoding internally, instead of using unencrypted
// save states for backwards compatibility. If we don't return YES here, we'll get a
// warning on the console at startup:
//
// ```
// WARNING: Secure coding is not enabled for restorable state! Enable secure coding by implementing NSApplicationDelegate.applicationSupportsSecureRestorableState: and returning YES.
// ```
//
// More-detailed explanation:
// https://stackoverflow.com/questions/77283578/sonoma-and-nsapplicationdelegate-applicationsupportssecurerestorablestate/77320845#77320845
return YES;
}
@end
static SDLAppDelegate *appDelegate = nil;

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
@ -435,9 +435,19 @@ void Cocoa_HandleKeyEvent(SDL_VideoDevice *_this, NSEvent *event)
case NSEventTypeKeyUp:
SDL_SendKeyboardKey(Cocoa_GetEventTimestamp([event timestamp]), SDL_RELEASED, code);
break;
case NSEventTypeFlagsChanged:
HandleModifiers(_this, code, (unsigned int)[event modifierFlags]);
case NSEventTypeFlagsChanged: {
// see if the new modifierFlags mean any existing keys should be pressed/released...
const unsigned int modflags = (unsigned int)[event modifierFlags];
HandleModifiers(_this, SDL_SCANCODE_LSHIFT, modflags);
HandleModifiers(_this, SDL_SCANCODE_LCTRL, modflags);
HandleModifiers(_this, SDL_SCANCODE_LALT, modflags);
HandleModifiers(_this, SDL_SCANCODE_LGUI, modflags);
HandleModifiers(_this, SDL_SCANCODE_RSHIFT, modflags);
HandleModifiers(_this, SDL_SCANCODE_RCTRL, modflags);
HandleModifiers(_this, SDL_SCANCODE_RALT, modflags);
HandleModifiers(_this, SDL_SCANCODE_RGUI, modflags);
break;
}
default: /* just to avoid compiler warnings */
break;
}

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
@ -30,8 +30,6 @@
#if defined(SDL_VIDEO_DRIVER_COCOA) && (defined(SDL_VIDEO_VULKAN) || defined(SDL_VIDEO_METAL))
#include <SDL3/SDL_syswm.h>
static int SDLCALL SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
{
/* Update the drawable size when SDL receives a size changed event for

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
@ -489,6 +489,8 @@ int Cocoa_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_
CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
CGError result = kCGErrorSuccess;
b_inModeTransition = SDL_TRUE;
/* Fade to black to hide resolution-switching flicker */
if (CGAcquireDisplayFadeReservation(5, &fade_token) == kCGErrorSuccess) {
CGDisplayFade(fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
@ -508,6 +510,8 @@ int Cocoa_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_
CGReleaseDisplayFadeReservation(fade_token);
}
b_inModeTransition = SDL_FALSE;
if (result != kCGErrorSuccess) {
CG_SetError("CGDisplaySwitchToMode()", result);
return -1;

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
@ -188,6 +188,30 @@ static SDL_Cursor *Cocoa_CreateSystemCursor(SDL_SystemCursor id)
case SDL_SYSTEM_CURSOR_HAND:
nscursor = [NSCursor pointingHandCursor];
break;
case SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT:
nscursor = LoadHiddenSystemCursor(@"resizenorthwestsoutheast", @selector(closedHandCursor));
break;
case SDL_SYSTEM_CURSOR_WINDOW_TOP:
nscursor = LoadHiddenSystemCursor(@"resizenorthsouth", @selector(resizeUpDownCursor));
break;
case SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT:
nscursor = LoadHiddenSystemCursor(@"resizenortheastsouthwest", @selector(closedHandCursor));
break;
case SDL_SYSTEM_CURSOR_WINDOW_RIGHT:
nscursor = LoadHiddenSystemCursor(@"resizeeastwest", @selector(resizeLeftRightCursor));
break;
case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT:
nscursor = LoadHiddenSystemCursor(@"resizenorthwestsoutheast", @selector(closedHandCursor));
break;
case SDL_SYSTEM_CURSOR_WINDOW_BOTTOM:
nscursor = LoadHiddenSystemCursor(@"resizenorthsouth", @selector(resizeUpDownCursor));
break;
case SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT:
nscursor = LoadHiddenSystemCursor(@"resizenortheastsouthwest", @selector(closedHandCursor));
break;
case SDL_SYSTEM_CURSOR_WINDOW_LEFT:
nscursor = LoadHiddenSystemCursor(@"resizeeastwest", @selector(resizeLeftRightCursor));
break;
default:
SDL_assert(!"Unknown system cursor");
return NULL;
@ -219,15 +243,11 @@ static int Cocoa_ShowCursor(SDL_Cursor *cursor)
SDL_VideoDevice *device = SDL_GetVideoDevice();
SDL_Window *window = (device ? device->windows : NULL);
for (; window != NULL; window = window->next) {
SDL_Mouse *mouse = SDL_GetMouse();
if(mouse->focus) {
if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) {
[(__bridge NSCursor*)mouse->cur_cursor->driverdata set];
} else {
[[NSCursor invisibleCursor] set];
}
} else {
[[NSCursor arrowCursor] set];
SDL_CocoaWindowData *driverdata = (__bridge SDL_CocoaWindowData *)window->driverdata;
if (driverdata) {
[driverdata.nswindow performSelectorOnMainThread:@selector(invalidateCursorRectsForView:)
withObject:[driverdata.nswindow contentView]
waitUntilDone:NO];
}
}
return 0;
@ -373,7 +393,7 @@ int Cocoa_InitMouse(SDL_VideoDevice *_this)
SDL_Mouse *mouse = SDL_GetMouse();
SDL_MouseData *driverdata = (SDL_MouseData *)SDL_calloc(1, sizeof(SDL_MouseData));
if (driverdata == NULL) {
return SDL_OutOfMemory();
return -1;
}
mouse->driverdata = driverdata;

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

View File

@ -1,38 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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"
#ifndef SDL_cocoashape_h_
#define SDL_cocoashape_h_
#include "../SDL_shape_internals.h"
@interface SDL_ShapeData : NSObject
@property(nonatomic) NSGraphicsContext *context;
@property(nonatomic) SDL_bool saved;
@property(nonatomic) SDL_ShapeTree *shape;
@end
extern SDL_WindowShaper *Cocoa_CreateShaper(SDL_Window *window);
extern int Cocoa_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode);
#endif /* SDL_cocoashape_h_ */

View File

@ -1,115 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 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"
#ifdef SDL_VIDEO_DRIVER_COCOA
#include "SDL_cocoavideo.h"
#include "SDL_cocoashape.h"
#include "../SDL_sysvideo.h"
@implementation SDL_ShapeData
@end
@interface SDL_CocoaClosure : NSObject
@property(nonatomic) NSView *view;
@property(nonatomic) NSBezierPath *path;
@property(nonatomic) SDL_Window *window;
@end
@implementation SDL_CocoaClosure
@end
SDL_WindowShaper *Cocoa_CreateShaper(SDL_Window *window)
{
@autoreleasepool {
SDL_WindowShaper *result;
SDL_ShapeData *data;
SDL_CocoaWindowData *windata = (__bridge SDL_CocoaWindowData *)window->driverdata;
result = (SDL_WindowShaper *)SDL_malloc(sizeof(SDL_WindowShaper));
if (!result) {
SDL_OutOfMemory();
return NULL;
}
[windata.nswindow setOpaque:NO];
[windata.nswindow setStyleMask:NSWindowStyleMaskBorderless];
result->window = window;
result->mode.mode = ShapeModeDefault;
result->mode.parameters.binarizationCutoff = 1;
window->shaper = result;
data = [[SDL_ShapeData alloc] init];
data.context = [windata.nswindow graphicsContext];
data.saved = SDL_FALSE;
data.shape = NULL;
/* TODO: There's no place to release this... */
result->driverdata = (void *)CFBridgingRetain(data);
return result;
}
}
void ConvertRects(SDL_ShapeTree *tree, void *closure)
{
SDL_CocoaClosure *data = (__bridge SDL_CocoaClosure *)closure;
if (tree->kind == OpaqueShape) {
NSRect rect = NSMakeRect(tree->data.shape.x, data.window->h - tree->data.shape.y, tree->data.shape.w, tree->data.shape.h);
[data.path appendBezierPathWithRect:[data.view convertRect:rect toView:nil]];
}
}
int Cocoa_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode)
{
@autoreleasepool {
SDL_ShapeData *data = (__bridge SDL_ShapeData *)shaper->driverdata;
SDL_CocoaWindowData *windata = (__bridge SDL_CocoaWindowData *)shaper->window->driverdata;
SDL_CocoaClosure *closure;
if (data.saved == SDL_TRUE) {
[data.context restoreGraphicsState];
data.saved = SDL_FALSE;
}
/*[data.context saveGraphicsState];*/
/*data.saved = SDL_TRUE;*/
[NSGraphicsContext setCurrentContext:data.context];
[[NSColor clearColor] set];
NSRectFill([windata.sdlContentView frame]);
data.shape = SDL_CalculateShapeTree(*shape_mode, shape);
closure = [[SDL_CocoaClosure alloc] init];
closure.view = windata.sdlContentView;
closure.path = [NSBezierPath bezierPath];
closure.window = shaper->window;
SDL_TraverseShapeTree(data.shape, &ConvertRects, (__bridge void *)closure);
[closure.path addClip];
return 0;
}
}
#endif /* SDL_VIDEO_DRIVER_COCOA */

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,6 @@
#endif
#include "SDL_cocoavideo.h"
#include "SDL_cocoashape.h"
#include "SDL_cocoavulkan.h"
#include "SDL_cocoametalview.h"
#include "SDL_cocoaopengles.h"
@ -69,7 +68,6 @@ static SDL_VideoDevice *Cocoa_CreateDevice(void)
data = nil;
}
if (!data) {
SDL_OutOfMemory();
SDL_free(device);
return NULL;
}
@ -90,7 +88,6 @@ static SDL_VideoDevice *Cocoa_CreateDevice(void)
device->SuspendScreenSaver = Cocoa_SuspendScreenSaver;
device->CreateSDLWindow = Cocoa_CreateWindow;
device->CreateSDLWindowFrom = Cocoa_CreateWindowFrom;
device->SetWindowTitle = Cocoa_SetWindowTitle;
device->SetWindowIcon = Cocoa_SetWindowIcon;
device->SetWindowPosition = Cocoa_SetWindowPosition;
@ -115,14 +112,11 @@ static SDL_VideoDevice *Cocoa_CreateDevice(void)
device->SetWindowMouseGrab = Cocoa_SetWindowMouseGrab;
device->SetWindowKeyboardGrab = Cocoa_SetWindowKeyboardGrab;
device->DestroyWindow = Cocoa_DestroyWindow;
device->GetWindowWMInfo = Cocoa_GetWindowWMInfo;
device->SetWindowHitTest = Cocoa_SetWindowHitTest;
device->AcceptDragAndDrop = Cocoa_AcceptDragAndDrop;
device->FlashWindow = Cocoa_FlashWindow;
device->SetWindowFocusable = Cocoa_SetWindowFocusable;
device->shape_driver.CreateShaper = Cocoa_CreateShaper;
device->shape_driver.SetWindowShape = Cocoa_SetWindowShape;
device->SyncWindow = Cocoa_SyncWindow;
#ifdef SDL_VIDEO_OPENGL_CGL
device->GL_LoadLibrary = Cocoa_GL_LoadLibrary;
@ -178,8 +172,8 @@ static SDL_VideoDevice *Cocoa_CreateDevice(void)
device->free = Cocoa_DeleteDevice;
device->quirk_flags = VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT;
device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT |
VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS;
return device;
}
}

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
@ -36,12 +36,12 @@
int Cocoa_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path);
void Cocoa_Vulkan_UnloadLibrary(SDL_VideoDevice *_this);
SDL_bool Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
unsigned *count,
const char **names);
char const* const* Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count);
SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this,
SDL_Window *window,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
#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
@ -33,8 +33,6 @@
#include "SDL_cocoametalview.h"
#include "SDL_cocoavulkan.h"
#include <SDL3/SDL_syswm.h>
#include <dlfcn.h>
const char *defaultPaths[] = {
@ -163,25 +161,22 @@ void Cocoa_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
}
}
SDL_bool Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
unsigned *count,
const char **names)
char const* const* Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count)
{
static const char *const extensionsForCocoa[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_METAL_SURFACE_EXTENSION_NAME
};
if (!_this->vulkan_config.loader_handle) {
SDL_SetError("Vulkan is not loaded");
return SDL_FALSE;
if(count) {
*count = SDL_arraysize(extensionsForCocoa);
}
return SDL_Vulkan_GetInstanceExtensions_Helper(
count, names, SDL_arraysize(extensionsForCocoa),
extensionsForCocoa);
return extensionsForCocoa;
}
static SDL_bool Cocoa_Vulkan_CreateSurfaceViaMetalView(SDL_VideoDevice *_this,
SDL_Window *window,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface,
PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT,
PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK)
@ -199,7 +194,7 @@ static SDL_bool Cocoa_Vulkan_CreateSurfaceViaMetalView(SDL_VideoDevice *_this,
createInfo.flags = 0;
createInfo.pLayer = (__bridge const CAMetalLayer *)
Cocoa_Metal_GetLayer(_this, metalview);
result = vkCreateMetalSurfaceEXT(instance, &createInfo, NULL, surface);
result = vkCreateMetalSurfaceEXT(instance, &createInfo, allocator, surface);
if (result != VK_SUCCESS) {
Cocoa_Metal_DestroyView(_this, metalview);
SDL_SetError("vkCreateMetalSurfaceEXT failed: %s",
@ -235,6 +230,7 @@ static SDL_bool Cocoa_Vulkan_CreateSurfaceViaMetalView(SDL_VideoDevice *_this,
SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this,
SDL_Window *window,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface)
{
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
@ -260,7 +256,7 @@ SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this,
return SDL_FALSE;
}
if (window->flags & SDL_WINDOW_FOREIGN) {
if (window->flags & SDL_WINDOW_EXTERNAL) {
@autoreleasepool {
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata;
if (![data.sdlContentView.layer isKindOfClass:[CAMetalLayer class]]) {
@ -273,7 +269,7 @@ SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this,
createInfo.pNext = NULL;
createInfo.flags = 0;
createInfo.pLayer = (CAMetalLayer *)data.sdlContentView.layer;
result = vkCreateMetalSurfaceEXT(instance, &createInfo, NULL, surface);
result = vkCreateMetalSurfaceEXT(instance, &createInfo, allocator, surface);
if (result != VK_SUCCESS) {
SDL_SetError("vkCreateMetalSurfaceEXT failed: %s",
SDL_Vulkan_GetResultString(result));
@ -286,7 +282,7 @@ SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this,
createInfo.flags = 0;
createInfo.pView = (__bridge const void *)data.sdlContentView;
result = vkCreateMacOSSurfaceMVK(instance, &createInfo,
NULL, surface);
allocator, surface);
if (result != VK_SUCCESS) {
SDL_SetError("vkCreateMacOSSurfaceMVK failed: %s",
SDL_Vulkan_GetResultString(result));
@ -295,7 +291,7 @@ SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this,
}
}
} else {
return Cocoa_Vulkan_CreateSurfaceViaMetalView(_this, window, instance, surface, vkCreateMetalSurfaceEXT, vkCreateMacOSSurfaceMVK);
return Cocoa_Vulkan_CreateSurfaceViaMetalView(_this, window, instance, allocator, surface, vkCreateMetalSurfaceEXT, vkCreateMacOSSurfaceMVK);
}
return SDL_TRUE;

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
@ -29,14 +29,16 @@
#include "../SDL_egl_c.h"
#endif
#define SDL_METALVIEW_TAG 255
@class SDL_CocoaWindowData;
typedef enum
{
PENDING_OPERATION_NONE,
PENDING_OPERATION_ENTER_FULLSCREEN,
PENDING_OPERATION_LEAVE_FULLSCREEN,
PENDING_OPERATION_MINIMIZE
PENDING_OPERATION_NONE = 0x00,
PENDING_OPERATION_ENTER_FULLSCREEN = 0x01,
PENDING_OPERATION_LEAVE_FULLSCREEN = 0x02,
PENDING_OPERATION_MINIMIZE = 0x04
} PendingWindowOperation;
@interface Cocoa_WindowListener : NSResponder <NSWindowDelegate>
@ -52,6 +54,7 @@ typedef enum
BOOL inFullscreenTransition;
PendingWindowOperation pendingWindowOperation;
BOOL isMoving;
BOOL isMiniaturizing;
NSInteger focusClickPending;
float pendingWindowWarpX, pendingWindowWarpY;
BOOL isDragAreaRunning;
@ -128,20 +131,25 @@ typedef enum
@property(nonatomic) NSView *sdlContentView;
@property(nonatomic) NSMutableArray *nscontexts;
@property(nonatomic) SDL_bool created;
@property(nonatomic) SDL_bool inWindowFullscreenTransition;
@property(nonatomic) BOOL in_blocking_transition;
@property(nonatomic) BOOL was_zoomed;
@property(nonatomic) NSInteger window_number;
@property(nonatomic) NSInteger flash_request;
@property(nonatomic) SDL_Window *keyboard_focus;
@property(nonatomic) Cocoa_WindowListener *listener;
@property(nonatomic) SDL_CocoaVideoData *videodata;
@property(nonatomic) SDL_bool send_floating_size;
@property(nonatomic) SDL_bool send_floating_position;
@property(nonatomic) SDL_bool border_toggled;
@property(nonatomic) BOOL checking_zoom;
#ifdef SDL_VIDEO_OPENGL_EGL
@property(nonatomic) EGLSurface egl_surface;
#endif
@end
extern int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern int Cocoa_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window,
const void *data);
extern SDL_bool b_inModeTransition;
extern int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props);
extern void Cocoa_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window);
extern int Cocoa_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon);
extern int Cocoa_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window);
@ -159,16 +167,16 @@ extern void Cocoa_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void Cocoa_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered);
extern void Cocoa_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable);
extern void Cocoa_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top);
extern void Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
extern int Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
extern void *Cocoa_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size);
extern SDL_DisplayID Cocoa_GetDisplayForWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void Cocoa_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window);
extern void Cocoa_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
extern void Cocoa_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern int Cocoa_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info);
extern int Cocoa_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
extern void Cocoa_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept);
extern int Cocoa_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);
extern int Cocoa_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool focusable);
extern int Cocoa_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window);
#endif /* SDL_cocoawindow_h_ */

File diff suppressed because it is too large Load Diff

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
@ -25,7 +25,14 @@
#include "../SDL_sysvideo.h"
#include "SDL_nullframebuffer_c.h"
#define DUMMY_SURFACE "_SDL_DummySurface"
#define DUMMY_SURFACE "SDL.internal.window.surface"
static void CleanupSurface(void *userdata, void *value)
{
SDL_Surface *surface = (SDL_Surface *)value;
SDL_DestroySurface(surface);
}
int SDL_DUMMY_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, Uint32 *format, void **pixels, int *pitch)
{
@ -33,18 +40,15 @@ int SDL_DUMMY_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window
const Uint32 surface_format = SDL_PIXELFORMAT_XRGB8888;
int w, h;
/* Free the old framebuffer surface */
SDL_DUMMY_DestroyWindowFramebuffer(_this, window);
/* Create a new one */
/* Create a new framebuffer */
SDL_GetWindowSizeInPixels(window, &w, &h);
surface = SDL_CreateSurface(w, h, surface_format);
if (surface == NULL) {
if (!surface) {
return -1;
}
/* Save the info and return! */
SDL_SetWindowData(window, DUMMY_SURFACE, surface);
SDL_SetPropertyWithCleanup(SDL_GetWindowProperties(window), DUMMY_SURFACE, surface, CleanupSurface, NULL);
*format = surface_format;
*pixels = surface->pixels;
*pitch = surface->pitch;
@ -56,8 +60,8 @@ int SDL_DUMMY_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window
static int frame_number;
SDL_Surface *surface;
surface = (SDL_Surface *)SDL_GetWindowData(window, DUMMY_SURFACE);
if (surface == NULL) {
surface = (SDL_Surface *)SDL_GetProperty(SDL_GetWindowProperties(window), DUMMY_SURFACE, NULL);
if (!surface) {
return SDL_SetError("Couldn't find dummy surface for window");
}
@ -73,10 +77,7 @@ int SDL_DUMMY_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window
void SDL_DUMMY_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_Surface *surface;
surface = (SDL_Surface *)SDL_SetWindowData(window, DUMMY_SURFACE, NULL);
SDL_DestroySurface(surface);
SDL_ClearProperty(SDL_GetWindowProperties(window), DUMMY_SURFACE);
}
#endif /* SDL_VIDEO_DRIVER_DUMMY */

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
@ -55,6 +55,17 @@
static int DUMMY_VideoInit(SDL_VideoDevice *_this);
static void DUMMY_VideoQuit(SDL_VideoDevice *_this);
static int DUMMY_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, window->floating.x, window->floating.y);
return 0;
}
static void DUMMY_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, window->floating.w, window->floating.h);
}
/* DUMMY driver bootstrap functions */
static int DUMMY_Available(const char *enable_hint)
@ -83,8 +94,7 @@ static SDL_VideoDevice *DUMMY_InternalCreateDevice(const char *enable_hint)
/* Initialize all variables that we clean on shutdown */
device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
if (device == NULL) {
SDL_OutOfMemory();
if (!device) {
return 0;
}
device->is_dummy = SDL_TRUE;
@ -93,6 +103,8 @@ static SDL_VideoDevice *DUMMY_InternalCreateDevice(const char *enable_hint)
device->VideoInit = DUMMY_VideoInit;
device->VideoQuit = DUMMY_VideoQuit;
device->PumpEvents = DUMMY_PumpEvents;
device->SetWindowSize = DUMMY_SetWindowSize;
device->SetWindowPosition = DUMMY_SetWindowPosition;
device->CreateWindowFramebuffer = SDL_DUMMY_CreateWindowFramebuffer;
device->UpdateWindowFramebuffer = SDL_DUMMY_UpdateWindowFramebuffer;
device->DestroyWindowFramebuffer = SDL_DUMMY_DestroyWindowFramebuffer;

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
@ -759,8 +759,16 @@ static EM_BOOL Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent
}
id = touchEvent->touches[i].identifier;
x = touchEvent->touches[i].targetX / client_w;
y = touchEvent->touches[i].targetY / client_h;
if (client_w <= 1) {
x = 0.5f;
} else {
x = touchEvent->touches[i].targetX / (client_w - 1);
}
if (client_h <= 1) {
y = 0.5f;
} else {
y = touchEvent->touches[i].targetY / (client_h - 1);
}
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) {
SDL_SendTouch(0, deviceId, id, window_data->window, SDL_TRUE, x, y, 1.0f);
@ -835,23 +843,16 @@ static EM_BOOL Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboard
static EM_BOOL Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData)
{
SDL_WindowData *window_data = userData;
SDL_VideoDisplay *display;
if (fullscreenChangeEvent->isFullscreen) {
window_data->window->flags |= window_data->fullscreen_mode_flags;
SDL_SendWindowEvent(window_data->window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0);
window_data->fullscreen_mode_flags = 0;
} else {
window_data->window->flags &= ~SDL_WINDOW_FULLSCREEN;
/* reset fullscreen window if the browser left fullscreen */
display = SDL_GetVideoDisplayForWindow(window_data->window);
if (display->fullscreen_window == window_data->window) {
display->fullscreen_window = NULL;
}
SDL_SendWindowEvent(window_data->window, SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0);
}
SDL_UpdateFullscreenMode(window_data->window, fullscreenChangeEvent->isFullscreen, SDL_FALSE);
return 0;
}
@ -956,7 +957,7 @@ void Emscripten_RegisterEventHandlers(SDL_WindowData *data)
/* Keyboard events are awkward */
keyElement = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
if (keyElement == NULL) {
if (!keyElement) {
keyElement = EMSCRIPTEN_EVENT_TARGET_WINDOW;
}
@ -999,7 +1000,7 @@ void Emscripten_UnregisterEventHandlers(SDL_WindowData *data)
emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, 0, NULL);
target = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
if (target == NULL) {
if (!target) {
target = EMSCRIPTEN_EVENT_TARGET_WINDOW;
}

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,7 +42,7 @@ int Emscripten_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *windo
SDL_GetWindowSizeInPixels(window, &w, &h);
surface = SDL_CreateSurface(w, h, surface_format);
if (surface == NULL) {
if (!surface) {
return -1;
}
@ -60,7 +60,7 @@ int Emscripten_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *windo
SDL_WindowData *data = window->driverdata;
surface = data->surface;
if (surface == NULL) {
if (!surface) {
return SDL_SetError("Couldn't find framebuffer surface for window");
}

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

Some files were not shown because too many files have changed in this diff Show More