This commit is contained in:
AzaezelX 2022-03-23 01:43:08 -05:00
parent ee4253c982
commit 2614274639
1225 changed files with 148950 additions and 51674 deletions

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -1227,7 +1227,7 @@ RLEAlphaSurface(SDL_Surface * surface)
surface->flags &= ~SDL_SIMD_ALIGNED;
}
/* realloc the buffer to release unused memory */
/* reallocate the buffer to release unused memory */
{
Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf);
if (!p)
@ -1391,9 +1391,9 @@ RLEColorkeySurface(SDL_Surface * surface)
surface->flags &= ~SDL_SIMD_ALIGNED;
}
/* realloc the buffer to release unused memory */
/* reallocate the buffer to release unused memory */
{
/* If realloc returns NULL, the original block is left intact */
/* If SDL_realloc returns NULL, the original block is left intact */
Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf);
if (!p)
p = rlebuf;
@ -1423,9 +1423,13 @@ SDL_RLESurface(SDL_Surface * surface)
return -1;
}
/* If we don't have colorkey or blending, nothing to do... */
flags = surface->map->info.flags;
if (!(flags & (SDL_COPY_COLORKEY | SDL_COPY_BLEND))) {
if (flags & SDL_COPY_COLORKEY) {
/* ok */
} else if ((flags & SDL_COPY_BLEND) && surface->format->Amask) {
/* ok */
} else {
/* If we don't have colorkey or blending, nothing to do... */
return -1;
}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,9 +231,7 @@ SDL_CalculateBlit(SDL_Surface * surface)
if (map->identity && !(map->info.flags & ~SDL_COPY_RLE_DESIRED)) {
blit = SDL_BlitCopy;
} else if (surface->format->Rloss > 8 || dst->format->Rloss > 8) {
/* Greater than 8 bits per channel not supported yet */
SDL_InvalidateMap(map);
return SDL_SetError("Blit combination not supported");
blit = SDL_Blit_Slow;
}
#if SDL_HAVE_BLIT_0
else if (surface->format->BitsPerPixel < 8 &&

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,6 +27,12 @@
#include "SDL_endian.h"
#include "SDL_surface.h"
/* pixman ARM blitters are 32 bit only : */
#if defined(__aarch64__)||defined(_M_ARM64)
#undef SDL_ARM_SIMD_BLITTERS
#undef SDL_ARM_NEON_BLITTERS
#endif
/* Table to do pixel byte expansion */
extern Uint8* SDL_expand_byte[9];
@ -263,18 +269,18 @@ do { \
{ \
switch (bpp) { \
case 1: { \
Uint8 _Pixel; \
Uint8 _pixel; \
\
PIXEL_FROM_RGB(_Pixel, fmt, r, g, b); \
*((Uint8 *)(buf)) = _Pixel; \
PIXEL_FROM_RGB(_pixel, fmt, r, g, b); \
*((Uint8 *)(buf)) = _pixel; \
} \
break; \
\
case 2: { \
Uint16 _Pixel; \
Uint16 _pixel; \
\
PIXEL_FROM_RGB(_Pixel, fmt, r, g, b); \
*((Uint16 *)(buf)) = _Pixel; \
PIXEL_FROM_RGB(_pixel, fmt, r, g, b); \
*((Uint16 *)(buf)) = _pixel; \
} \
break; \
\
@ -292,10 +298,10 @@ do { \
break; \
\
case 4: { \
Uint32 _Pixel; \
Uint32 _pixel; \
\
PIXEL_FROM_RGB(_Pixel, fmt, r, g, b); \
*((Uint32 *)(buf)) = _Pixel; \
PIXEL_FROM_RGB(_pixel, fmt, r, g, b); \
*((Uint32 *)(buf)) = _pixel; \
} \
break; \
} \
@ -473,14 +479,14 @@ do { \
#define DUFFS_LOOP8(pixel_copy_increment, width) \
{ int n = (width+7)/8; \
switch (width & 7) { \
case 0: do { pixel_copy_increment; /* fallthrough */ \
case 7: pixel_copy_increment; /* fallthrough */ \
case 6: pixel_copy_increment; /* fallthrough */ \
case 5: pixel_copy_increment; /* fallthrough */ \
case 4: pixel_copy_increment; /* fallthrough */ \
case 3: pixel_copy_increment; /* fallthrough */ \
case 2: pixel_copy_increment; /* fallthrough */ \
case 1: pixel_copy_increment; /* fallthrough */ \
case 0: do { pixel_copy_increment; SDL_FALLTHROUGH; \
case 7: pixel_copy_increment; SDL_FALLTHROUGH; \
case 6: pixel_copy_increment; SDL_FALLTHROUGH; \
case 5: pixel_copy_increment; SDL_FALLTHROUGH; \
case 4: pixel_copy_increment; SDL_FALLTHROUGH; \
case 3: pixel_copy_increment; SDL_FALLTHROUGH; \
case 2: pixel_copy_increment; SDL_FALLTHROUGH; \
case 1: pixel_copy_increment; \
} while ( --n > 0 ); \
} \
}
@ -489,10 +495,10 @@ do { \
#define DUFFS_LOOP4(pixel_copy_increment, width) \
{ int n = (width+3)/4; \
switch (width & 3) { \
case 0: do { pixel_copy_increment; /* fallthrough */ \
case 3: pixel_copy_increment; /* fallthrough */ \
case 2: pixel_copy_increment; /* fallthrough */ \
case 1: pixel_copy_increment; /* fallthrough */ \
case 0: do { pixel_copy_increment; SDL_FALLTHROUGH; \
case 3: pixel_copy_increment; SDL_FALLTHROUGH; \
case 2: pixel_copy_increment; SDL_FALLTHROUGH; \
case 1: pixel_copy_increment; \
} while (--n > 0); \
} \
}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -452,11 +452,94 @@ static const SDL_BlitFunc colorkey_blit[] = {
(SDL_BlitFunc) NULL, BlitBto1Key, BlitBto2Key, BlitBto3Key, BlitBto4Key
};
static void
Blit4bto4(SDL_BlitInfo * info)
{
int width = info->dst_w;
int height = info->dst_h;
Uint8 *src = info->src;
Uint32 *dst = (Uint32 *) info->dst;
int srcskip = info->src_skip;
int dstskip = info->dst_skip;
Uint32 *map = (Uint32 *) info->table;
int c;
/* Set up some basic variables */
srcskip += width - (width + 1) / 2;
while (height--) {
Uint8 byte = 0, bit;
for (c = 0; c < width; ++c) {
if ((c & 0x1) == 0) {
byte = *src++;
}
bit = (byte & 0xF0) >> 4;
if (1) {
*dst = map[bit];
}
byte <<= 4;
dst++;
}
src += srcskip;
dst = (Uint32 *) ((Uint8 *) dst + dstskip);
}
}
static void
Blit4bto4Key(SDL_BlitInfo * info)
{
int width = info->dst_w;
int height = info->dst_h;
Uint8 *src = info->src;
Uint32 *dst = (Uint32 *) info->dst;
int srcskip = info->src_skip;
int dstskip = info->dst_skip;
Uint32 ckey = info->colorkey;
Uint32 *map = (Uint32 *) info->table;
int c;
/* Set up some basic variables */
srcskip += width - (width + 1) / 2;
while (height--) {
Uint8 byte = 0, bit;
for (c = 0; c < width; ++c) {
if ((c & 0x1) == 0) {
byte = *src++;
}
bit = (byte & 0xF0) >> 4;
if (bit != ckey) {
*dst = map[bit];
}
byte <<= 4;
dst++;
}
src += srcskip;
dst = (Uint32 *) ((Uint8 *) dst + dstskip);
}
}
SDL_BlitFunc
SDL_CalculateBlit0(SDL_Surface * surface)
{
int which;
/* 4bits to 32bits */
if (surface->format->BitsPerPixel == 4) {
if (surface->map->dst->format->BytesPerPixel == 4) {
switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) {
case 0:
return Blit4bto4;
case SDL_COPY_COLORKEY:
return Blit4bto4Key;
}
}
/* We don't fully support 4-bit packed pixel modes */
return NULL;
}
if (surface->format->BitsPerPixel != 1) {
/* We don't support sub 8-bit packed pixel modes */
return (SDL_BlitFunc) NULL;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -397,14 +397,14 @@ void BlitARGBto565PixelAlphaARMSIMDAsm(int32_t w, int32_t h, uint16_t *dst, int3
static void
BlitARGBto565PixelAlphaARMSIMD(SDL_BlitInfo * info)
{
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint16_t *dstp = (uint16_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 1);
uint32_t *srcp = (uint32_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 2);
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint16_t *dstp = (uint16_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 1);
uint32_t *srcp = (uint32_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 2);
BlitARGBto565PixelAlphaARMSIMDAsm(width, height, dstp, dststride, srcp, srcstride);
BlitARGBto565PixelAlphaARMSIMDAsm(width, height, dstp, dststride, srcp, srcstride);
}
void BlitRGBtoRGBPixelAlphaARMSIMDAsm(int32_t w, int32_t h, uint32_t *dst, int32_t dst_stride, uint32_t *src, int32_t src_stride);
@ -444,14 +444,14 @@ void BlitRGBtoRGBPixelAlphaARMNEONAsm(int32_t w, int32_t h, uint32_t *dst, int32
static void
BlitRGBtoRGBPixelAlphaARMNEON(SDL_BlitInfo * info)
{
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint32_t *dstp = (uint32_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 2);
uint32_t *srcp = (uint32_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 2);
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint32_t *dstp = (uint32_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 2);
uint32_t *srcp = (uint32_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 2);
BlitRGBtoRGBPixelAlphaARMNEONAsm(width, height, dstp, dststride, srcp, srcstride);
BlitRGBtoRGBPixelAlphaARMNEONAsm(width, height, dstp, dststride, srcp, srcstride);
}
#endif
@ -575,6 +575,61 @@ BlitRGBtoRGBPixelAlpha(SDL_BlitInfo * info)
}
}
/* fast ARGB888->(A)BGR888 blending with pixel alpha */
static void
BlitRGBtoBGRPixelAlpha(SDL_BlitInfo * info)
{
int width = info->dst_w;
int height = info->dst_h;
Uint32 *srcp = (Uint32 *) info->src;
int srcskip = info->src_skip >> 2;
Uint32 *dstp = (Uint32 *) info->dst;
int dstskip = info->dst_skip >> 2;
while (height--) {
/* *INDENT-OFF* */
DUFFS_LOOP4({
Uint32 dalpha;
Uint32 d;
Uint32 s1;
Uint32 d1;
Uint32 s = *srcp;
Uint32 alpha = s >> 24;
/* FIXME: Here we special-case opaque alpha since the
compositioning used (>>8 instead of /255) doesn't handle
it correctly. Also special-case alpha=0 for speed?
Benchmark this! */
if (alpha) {
/*
* take out the middle component (green), and process
* the other two in parallel. One multiply less.
*/
s1 = s & 0xff00ff;
s1 = (s1 >> 16) | (s1 << 16);
s &= 0xff00;
if (alpha == SDL_ALPHA_OPAQUE) {
*dstp = 0xff000000 | s | s1;
} else {
d = *dstp;
dalpha = d >> 24;
d1 = d & 0xff00ff;
d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff;
d &= 0xff00;
d = (d + ((s - d) * alpha >> 8)) & 0xff00;
dalpha = alpha + (dalpha * (alpha ^ 0xFF) >> 8);
*dstp = d1 | d | (dalpha << 24);
}
}
++srcp;
++dstp;
}, width);
/* *INDENT-ON* */
srcp += srcskip;
dstp += dstskip;
}
}
#ifdef __3dNOW__
/* fast (as in MMX with prefetch) ARGB888->(A)RGB888 blending with pixel alpha */
static void
@ -1407,6 +1462,12 @@ SDL_CalculateBlitA(SDL_Surface * surface)
#endif
return BlitRGBtoRGBPixelAlpha;
}
} else if (sf->Rmask == df->Bmask
&& sf->Gmask == df->Gmask
&& sf->Bmask == df->Rmask && sf->BytesPerPixel == 4) {
if (sf->Amask == 0xff000000) {
return BlitRGBtoBGRPixelAlpha;
}
}
return BlitNtoNPixelAlpha;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -40,11 +40,11 @@
/* Functions to blit from N-bit surfaces to other surfaces */
enum blit_features {
BLIT_FEATURE_NONE = 0,
BLIT_FEATURE_HAS_MMX = 1,
BLIT_FEATURE_HAS_ALTIVEC = 2,
BLIT_FEATURE_ALTIVEC_DONT_USE_PREFETCH = 4,
BLIT_FEATURE_HAS_ARM_SIMD = 8
BLIT_FEATURE_NONE = 0,
BLIT_FEATURE_HAS_MMX = 1,
BLIT_FEATURE_HAS_ALTIVEC = 2,
BLIT_FEATURE_ALTIVEC_DONT_USE_PREFETCH = 4,
BLIT_FEATURE_HAS_ARM_SIMD = 8
};
#if SDL_ALTIVEC_BLITTERS
@ -128,7 +128,7 @@ calc_swizzle32(const SDL_PixelFormat * srcfmt, const SDL_PixelFormat * dstfmt)
* leave alpha with a zero mask, but we should still swizzle the bits.
*/
/* ARGB */
const static const struct SDL_PixelFormat default_pixel_format = {
static const struct SDL_PixelFormat default_pixel_format = {
0, NULL, 0, 0,
{0, 0},
0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000,
@ -943,14 +943,14 @@ void Blit_BGR888_RGB888ARMSIMDAsm(int32_t w, int32_t h, uint32_t *dst, int32_t d
static void
Blit_BGR888_RGB888ARMSIMD(SDL_BlitInfo * info)
{
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint32_t *dstp = (uint32_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 2);
uint32_t *srcp = (uint32_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 2);
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint32_t *dstp = (uint32_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 2);
uint32_t *srcp = (uint32_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 2);
Blit_BGR888_RGB888ARMSIMDAsm(width, height, dstp, dststride, srcp, srcstride);
Blit_BGR888_RGB888ARMSIMDAsm(width, height, dstp, dststride, srcp, srcstride);
}
void Blit_RGB444_RGB888ARMSIMDAsm(int32_t w, int32_t h, uint32_t *dst, int32_t dst_stride, uint16_t *src, int32_t src_stride);
@ -958,14 +958,14 @@ void Blit_RGB444_RGB888ARMSIMDAsm(int32_t w, int32_t h, uint32_t *dst, int32_t d
static void
Blit_RGB444_RGB888ARMSIMD(SDL_BlitInfo * info)
{
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint32_t *dstp = (uint32_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 2);
uint16_t *srcp = (uint16_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 1);
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint32_t *dstp = (uint32_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 2);
uint16_t *srcp = (uint16_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 1);
Blit_RGB444_RGB888ARMSIMDAsm(width, height, dstp, dststride, srcp, srcstride);
Blit_RGB444_RGB888ARMSIMDAsm(width, height, dstp, dststride, srcp, srcstride);
}
#endif
@ -2073,6 +2073,35 @@ Blit_RGB565_BGRA8888(SDL_BlitInfo * info)
#endif /* SDL_HAVE_BLIT_N_RGB565 */
/* RGB555->ARGB1555, and BGR555->ABGR1555, SET_ALPHA */
static void
Blit_RGB555_ARGB1555(SDL_BlitInfo * info)
{
int width = info->dst_w;
int height = info->dst_h;
Uint16 *src = (Uint16 *) info->src;
int srcskip = info->src_skip;
Uint16 *dst = (Uint16 *) info->dst;
int dstskip = info->dst_skip;
SDL_PixelFormat *dstfmt = info->dst_fmt;
Uint16 mask = ((Uint32)info->a >> dstfmt->Aloss) << dstfmt->Ashift;
while (height--) {
/* *INDENT-OFF* */
DUFFS_LOOP(
{
*dst = *src | mask;
++dst;
++src;
},
width);
/* *INDENT-ON* */
src = (Uint16 *) ((Uint8 *) src + srcskip);
dst = (Uint16 *) ((Uint8 *) dst + dstskip);
}
}
static void
BlitNto1(SDL_BlitInfo * info)
{
@ -3259,6 +3288,10 @@ static const struct blit_table normal_blit_2[] = {
{0x0000F800, 0x000007E0, 0x0000001F, 4, 0x0000FF00, 0x00FF0000, 0xFF000000,
0, Blit_RGB565_BGRA8888, NO_ALPHA | COPY_ALPHA | SET_ALPHA},
#endif
{0x00007C00, 0x000003E0, 0x0000001F, 2, 0x00007C00, 0x000003E0, 0x0000001F,
0, Blit_RGB555_ARGB1555, SET_ALPHA},
{0x0000001F, 0x000003E0, 0x00007C00, 2, 0x0000001F, 0x000003E0, 0x00007C00,
0, Blit_RGB555_ARGB1555, SET_ALPHA},
/* Default for 16-bit RGB source, used if no other blitter matches */
{0, 0, 0, 0, 0, 0, 0, 0, BlitNtoN, 0}

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/* DO NOT EDIT! This file is generated by sdlgenblit.pl */
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -34,7 +34,7 @@ SDL_memcpySSE(Uint8 * dst, const Uint8 * src, int len)
__m128 values[4];
for (i = len / 64; i--;) {
_mm_prefetch(src, _MM_HINT_NTA);
_mm_prefetch((const char *)src, _MM_HINT_NTA);
values[0] = *(__m128 *) (src + 0);
values[1] = *(__m128 *) (src + 16);
values[2] = *(__m128 *) (src + 32);

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,6 +24,21 @@
#include "SDL_blit.h"
#include "SDL_blit_slow.h"
#define FORMAT_ALPHA 0
#define FORMAT_NO_ALPHA -1
#define FORMAT_2101010 1
#define FORMAT_HAS_ALPHA(format) format == 0
#define FORMAT_HAS_NO_ALPHA(format) format < 0
static int SDL_INLINE detect_format(SDL_PixelFormat *pf) {
if (pf->format == SDL_PIXELFORMAT_ARGB2101010) {
return FORMAT_2101010;
} else if (pf->Amask) {
return FORMAT_ALPHA;
} else {
return FORMAT_NO_ALPHA;
}
}
/* The ONE TRUE BLITTER
* This puppy has to handle all the unoptimized cases - yes, it's slow.
*/
@ -40,47 +55,45 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
Uint32 dstpixel;
Uint32 dstR, dstG, dstB, dstA;
int srcy, srcx;
int posy, posx;
Uint32 posy, posx;
int incy, incx;
SDL_PixelFormat *src_fmt = info->src_fmt;
SDL_PixelFormat *dst_fmt = info->dst_fmt;
int srcbpp = src_fmt->BytesPerPixel;
int dstbpp = dst_fmt->BytesPerPixel;
int srcfmt_val;
int dstfmt_val;
Uint32 rgbmask = ~src_fmt->Amask;
Uint32 ckey = info->colorkey & rgbmask;
srcy = 0;
posy = 0;
srcfmt_val = detect_format(src_fmt);
dstfmt_val = detect_format(dst_fmt);
incy = (info->src_h << 16) / info->dst_h;
incx = (info->src_w << 16) / info->dst_w;
posy = incy / 2; /* start at the middle of pixel */
while (info->dst_h--) {
Uint8 *src = 0;
Uint8 *dst = info->dst;
int n = info->dst_w;
srcx = -1;
posx = 0x10000L;
while (posy >= 0x10000L) {
++srcy;
posy -= 0x10000L;
}
posx = incx / 2; /* start at the middle of pixel */
srcy = posy >> 16;
while (n--) {
if (posx >= 0x10000L) {
while (posx >= 0x10000L) {
++srcx;
posx -= 0x10000L;
}
src =
(info->src + (srcy * info->src_pitch) + (srcx * srcbpp));
}
if (src_fmt->Amask) {
DISEMBLE_RGBA(src, srcbpp, src_fmt, srcpixel, srcR, srcG,
srcB, srcA);
} else {
DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG,
srcB);
srcx = posx >> 16;
src = (info->src + (srcy * info->src_pitch) + (srcx * srcbpp));
if (FORMAT_HAS_ALPHA(srcfmt_val)) {
DISEMBLE_RGBA(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB, srcA);
} else if (FORMAT_HAS_NO_ALPHA(srcfmt_val)) {
DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB);
srcA = 0xFF;
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
srcpixel = *((Uint32 *)(src));
RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA);
}
if (flags & SDL_COPY_COLORKEY) {
/* srcpixel isn't set for 24 bpp */
if (srcbpp == 3) {
@ -93,13 +106,15 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
continue;
}
}
if (dst_fmt->Amask) {
DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG,
dstB, dstA);
} else {
DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG,
dstB);
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);
}
if (flags & SDL_COPY_MODULATE_COLOR) {
@ -162,10 +177,15 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
dstA = 255;
break;
}
if (dst_fmt->Amask) {
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
ASSEMBLE_RGBA(dst, dstbpp, dst_fmt, dstR, dstG, dstB, dstA);
} else {
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB);
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
Uint32 pixel;
ARGB2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA);
*(Uint32 *)dst = pixel;
}
posx += incx;
dst += dstbpp;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -53,7 +53,7 @@
#define LCS_WINDOWS_COLOR_SPACE 0x57696E20
#endif
static int readRlePixels(SDL_Surface * surface, SDL_RWops * src, int isRle8)
static SDL_bool readRlePixels(SDL_Surface * surface, SDL_RWops * src, int isRle8)
{
/*
| Sets the surface pixels from src. A bmp image is upside down.
@ -70,14 +70,14 @@ static int readRlePixels(SDL_Surface * surface, SDL_RWops * src, int isRle8)
#define COPY_PIXEL(x) spot = &bits[ofs++]; if(spot >= start && spot < end) *spot = (x)
for (;;) {
if (!SDL_RWread(src, &ch, 1, 1)) return 1;
if (!SDL_RWread(src, &ch, 1, 1)) return SDL_TRUE;
/*
| encoded mode starts with a run length, and then a byte
| with two colour indexes to alternate between for the run
*/
if (ch) {
Uint8 pixel;
if (!SDL_RWread(src, &pixel, 1, 1)) return 1;
if (!SDL_RWread(src, &pixel, 1, 1)) return SDL_TRUE;
if (isRle8) { /* 256-color bitmap, compressed */
do {
COPY_PIXEL(pixel);
@ -98,18 +98,18 @@ static int readRlePixels(SDL_Surface * surface, SDL_RWops * src, int isRle8)
| a cursor move, or some absolute data.
| zero tag may be absolute mode or an escape
*/
if (!SDL_RWread(src, &ch, 1, 1)) return 1;
if (!SDL_RWread(src, &ch, 1, 1)) return SDL_TRUE;
switch (ch) {
case 0: /* end of line */
ofs = 0;
bits -= pitch; /* go to previous */
break;
case 1: /* end of bitmap */
return 0; /* success! */
return SDL_FALSE; /* success! */
case 2: /* delta */
if (!SDL_RWread(src, &ch, 1, 1)) return 1;
if (!SDL_RWread(src, &ch, 1, 1)) return SDL_TRUE;
ofs += ch;
if (!SDL_RWread(src, &ch, 1, 1)) return 1;
if (!SDL_RWread(src, &ch, 1, 1)) return SDL_TRUE;
bits -= (ch * pitch);
break;
default: /* no compression */
@ -117,14 +117,14 @@ static int readRlePixels(SDL_Surface * surface, SDL_RWops * src, int isRle8)
needsPad = (ch & 1);
do {
Uint8 pixel;
if (!SDL_RWread(src, &pixel, 1, 1)) return 1;
if (!SDL_RWread(src, &pixel, 1, 1)) return SDL_TRUE;
COPY_PIXEL(pixel);
} while (--ch);
} else {
needsPad = (((ch+1)>>1) & 1); /* (ch+1)>>1: bytes size */
for (;;) {
Uint8 pixel;
if (!SDL_RWread(src, &pixel, 1, 1)) return 1;
if (!SDL_RWread(src, &pixel, 1, 1)) return SDL_TRUE;
COPY_PIXEL(pixel >> 4);
if (!--ch) break;
COPY_PIXEL(pixel & 0x0F);
@ -132,7 +132,7 @@ static int readRlePixels(SDL_Surface * surface, SDL_RWops * src, int isRle8)
}
}
/* pad at even boundary */
if (needsPad && !SDL_RWread(src, &ch, 1, 1)) return 1;
if (needsPad && !SDL_RWread(src, &ch, 1, 1)) return SDL_TRUE;
break;
}
}
@ -213,12 +213,17 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
surface = NULL;
was_error = SDL_FALSE;
if (src == NULL) {
SDL_InvalidParamError("src");
was_error = SDL_TRUE;
goto done;
}
/* Read in the BMP file header */
fp_offset = SDL_RWtell(src);
if (fp_offset < 0) {
was_error = SDL_TRUE;
goto done;
}
SDL_ClearError();
if (SDL_RWread(src, magic, 1, 2) != 2) {
SDL_Error(SDL_EFREAD);
@ -306,7 +311,7 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
}
}
if (biWidth <= 0 || biHeight == 0) {
SDL_SetError("BMP file with bad dimensions (%dx%d)", biWidth, biHeight);
SDL_SetError("BMP file with bad dimensions (%" SDL_PRIs32 "x%" SDL_PRIs32 ")", biWidth, biHeight);
was_error = SDL_TRUE;
goto done;
}
@ -407,14 +412,20 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
goto done;
}
/*
| guich: always use 1<<bpp b/c some bitmaps can bring wrong information
| for colorsUsed
*/
/* if (biClrUsed == 0) { */
biClrUsed = 1 << biBitCount;
/* } */
if (biSize == 12) {
if (biClrUsed == 0) {
biClrUsed = 1 << biBitCount;
}
if (biClrUsed > (Uint32)palette->ncolors) {
biClrUsed = 1 << biBitCount; /* try forcing it? */
if (biClrUsed > (Uint32)palette->ncolors) {
SDL_SetError("Unsupported or incorrect biClrUsed field");
was_error = SDL_TRUE;
goto done;
}
}
if (biSize == 12) {
for (i = 0; i < (int) biClrUsed; ++i) {
SDL_RWread(src, &palette->colors[i].b, 1, 1);
SDL_RWread(src, &palette->colors[i].g, 1, 1);
@ -445,8 +456,8 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
goto done;
}
if ((biCompression == BI_RLE4) || (biCompression == BI_RLE8)) {
was_error = (SDL_bool)readRlePixels(surface, src, biCompression == BI_RLE8);
if (was_error) SDL_SetError("Error reading from BMP");
was_error = readRlePixels(surface, src, biCompression == BI_RLE8);
if (was_error) SDL_Error(SDL_EFREAD);
goto done;
}
top = (Uint8 *)surface->pixels;
@ -478,7 +489,7 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
for (i = 0; i < surface->w; ++i) {
if (i % (8 / ExpandBMP) == 0) {
if (!SDL_RWread(src, &pixel, 1, 1)) {
SDL_SetError("Error reading from BMP");
SDL_Error(SDL_EFREAD);
was_error = SDL_TRUE;
goto done;
}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
* Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@ -28,6 +28,10 @@
#if SDL_VIDEO_DRIVER_ANDROID
#include <android/native_window.h>
#include "../core/android/SDL_android.h"
#include "../video/android/SDL_androidvideo.h"
#endif
#if SDL_VIDEO_DRIVER_RPI
#include <unistd.h>
#endif
#include "SDL_sysvideo.h"
@ -42,6 +46,11 @@
#endif
#endif /* EGL_KHR_create_context */
#ifndef EGL_EXT_present_opaque
#define EGL_EXT_present_opaque 1
#define EGL_PRESENT_OPAQUE_EXT 0x31DF
#endif /* EGL_EXT_present_opaque */
#if SDL_VIDEO_DRIVER_RPI
/* Raspbian places the OpenGL ES/EGL binaries in a non standard path */
#define DEFAULT_EGL ( vc4 ? "libEGL.so.1" : "libbrcmEGL.so" )
@ -73,6 +82,7 @@
#define DEFAULT_OGL_ES "libGLESv1_CM.dylib" //???
#elif defined(__OpenBSD__)
/* OpenBSD */
#define DEFAULT_OGL "libGL.so"
#define DEFAULT_EGL "libEGL.so"
#define DEFAULT_OGL_ES2 "libGLESv2.so"
@ -80,9 +90,10 @@
#define DEFAULT_OGL_ES "libGLESv1_CM.so"
#else
/* Desktop Linux */
/* Desktop Linux/Unix-like */
#define DEFAULT_OGL "libGL.so.1"
#define DEFAULT_EGL "libEGL.so.1"
#define ALT_OGL "libOpenGL.so.0"
#define DEFAULT_OGL_ES2 "libGLESv2.so.2"
#define DEFAULT_OGL_ES_PVR "libGLES_CM.so.1"
#define DEFAULT_OGL_ES "libGLESv1_CM.so.1"
@ -99,7 +110,7 @@
#define EGL_PLATFORM_DEVICE_EXT 0x0
#endif
#ifdef SDL_VIDEO_STATIC_ANGLE
#if defined(SDL_VIDEO_STATIC_ANGLE) || defined(SDL_VIDEO_DRIVER_VITA)
#define LOAD_FUNC(NAME) \
_this->egl_data->NAME = (void *)NAME;
#else
@ -115,7 +126,6 @@ if (!_this->egl_data->NAME) \
#define LOAD_FUNC_EGLEXT(NAME) \
_this->egl_data->NAME = _this->egl_data->eglGetProcAddress(#NAME);
static const char * SDL_EGL_GetErrorName(EGLint eglErrorCode)
{
#define SDL_EGL_ERROR_TRANSLATE(e) case e: return #e;
@ -237,7 +247,7 @@ SDL_EGL_GetProcAddress(_THIS, const char *proc)
retval = _this->egl_data->eglGetProcAddress(proc);
}
#ifndef __EMSCRIPTEN__ /* LoadFunction isn't needed on Emscripten and will call dlsym(), causing other problems. */
#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) {
static char procname[64];
@ -336,7 +346,7 @@ SDL_EGL_LoadLibraryOnly(_THIS, const char *egl_path)
}
#endif
#ifndef SDL_VIDEO_STATIC_ANGLE
#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) {
@ -374,6 +384,12 @@ SDL_EGL_LoadLibraryOnly(_THIS, const char *egl_path)
else {
path = DEFAULT_OGL;
egl_dll_handle = SDL_LoadObject(path);
#ifdef ALT_OGL
if (egl_dll_handle == NULL) {
path = ALT_OGL;
egl_dll_handle = SDL_LoadObject(path);
}
#endif
}
#endif
}
@ -416,6 +432,9 @@ SDL_EGL_LoadLibraryOnly(_THIS, const char *egl_path)
#endif
_this->egl_data->dll_handle = dll_handle;
#if SDL_VIDEO_DRIVER_VITA
_this->egl_data->egl_dll_handle = egl_dll_handle;
#endif
/* Load new function pointers */
LOAD_FUNC(eglGetDisplay);
@ -476,36 +495,40 @@ SDL_EGL_GetVersion(_THIS) {
int
SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display, EGLenum platform)
{
int egl_version_major, egl_version_minor;
int library_load_retcode = SDL_EGL_LoadLibraryOnly(_this, egl_path);
if (library_load_retcode != 0) {
return library_load_retcode;
}
/* EGL 1.5 allows querying for client version with EGL_NO_DISPLAY */
SDL_EGL_GetVersion(_this);
egl_version_major = _this->egl_data->egl_version_major;
egl_version_minor = _this->egl_data->egl_version_minor;
if (egl_version_major == 1 && egl_version_minor == 5) {
LOAD_FUNC(eglGetPlatformDisplay);
}
_this->egl_data->egl_display = EGL_NO_DISPLAY;
#if !defined(__WINRT__)
#if !defined(SDL_VIDEO_DRIVER_VITA)
if (platform) {
if (egl_version_major == 1 && egl_version_minor == 5) {
_this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(size_t)native_display, NULL);
/* EGL 1.5 allows querying for client version with EGL_NO_DISPLAY
* --
* Khronos doc: "EGL_BAD_DISPLAY is generated if display is not an EGL display connection, unless display is EGL_NO_DISPLAY and name is EGL_EXTENSIONS."
* Therefore SDL_EGL_GetVersion() shouldn't work with uninitialized display.
* - it actually doesn't work on Android that has 1.5 egl client
* - it works on desktop X11 (using SDL_VIDEO_X11_FORCE_EGL=1) */
SDL_EGL_GetVersion(_this);
if (_this->egl_data->egl_version_major == 1 && _this->egl_data->egl_version_minor == 5) {
LOAD_FUNC(eglGetPlatformDisplay);
}
if (_this->egl_data->eglGetPlatformDisplay) {
_this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(uintptr_t)native_display, NULL);
} else {
if (SDL_EGL_HasExtension(_this, SDL_EGL_CLIENT_EXTENSION, "EGL_EXT_platform_base")) {
_this->egl_data->eglGetPlatformDisplayEXT = SDL_EGL_GetProcAddress(_this, "eglGetPlatformDisplayEXT");
if (_this->egl_data->eglGetPlatformDisplayEXT) {
_this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(platform, (void *)(size_t)native_display, NULL);
_this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(platform, (void *)(uintptr_t)native_display, NULL);
}
}
}
}
#endif
/* Try the implementation-specific eglGetDisplay even if eglGetPlatformDisplay fails */
if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
_this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
@ -515,7 +538,7 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
*_this->gl_config.driver_path = '\0';
return SDL_SetError("Could not get EGL display");
}
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
_this->gl_config.driver_loaded = 0;
*_this->gl_config.driver_path = '\0';
@ -526,7 +549,7 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
/* Get the EGL version with a valid egl_display, for EGL <= 1.4 */
SDL_EGL_GetVersion(_this);
_this->egl_data->is_offscreen = 0;
_this->egl_data->is_offscreen = SDL_FALSE;
return 0;
}
@ -546,7 +569,7 @@ SDL_EGL_InitializeOffscreen(_THIS, int device)
EGLint num_egl_devices = 0;
const char *egl_device_hint;
if (_this->gl_config.driver_loaded != 1) {
if (_this->gl_config.driver_loaded <= 0) {
return SDL_SetError("SDL_EGL_LoadLibraryOnly() has not been called or has failed.");
}
@ -614,7 +637,7 @@ SDL_EGL_InitializeOffscreen(_THIS, int device)
/* Get the EGL version with a valid egl_display, for EGL <= 1.4 */
SDL_EGL_GetVersion(_this);
_this->egl_data->is_offscreen = 1;
_this->egl_data->is_offscreen = SDL_TRUE;
return 0;
}
@ -634,7 +657,8 @@ typedef struct {
char const* name;
} Attribute;
Attribute attributes[] = {
static
Attribute all_attributes[] = {
ATTRIBUTE( EGL_BUFFER_SIZE ),
ATTRIBUTE( EGL_ALPHA_SIZE ),
ATTRIBUTE( EGL_BLUE_SIZE ),
@ -674,31 +698,27 @@ Attribute attributes[] = {
static void dumpconfig(_THIS, EGLConfig config)
{
int attr;
for (attr = 0 ; attr<sizeof(attributes)/sizeof(Attribute) ; attr++) {
for (attr = 0 ; attr<sizeof(all_attributes)/sizeof(Attribute) ; attr++) {
EGLint value;
_this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, config, attributes[attr].attribute, &value);
SDL_Log("\t%-32s: %10d (0x%08x)\n", attributes[attr].name, value, value);
_this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, config, all_attributes[attr].attribute, &value);
SDL_Log("\t%-32s: %10d (0x%08x)\n", all_attributes[attr].name, value, value);
}
}
#endif /* DUMP_EGL_CONFIG */
int
SDL_EGL_ChooseConfig(_THIS)
static int
SDL_EGL_PrivateChooseConfig(_THIS, SDL_bool set_config_caveat_none)
{
/* 64 seems nice. */
/* 64 seems nice. */
EGLint attribs[64];
EGLint found_configs = 0, value;
/* 128 seems even nicer here */
EGLConfig configs[128];
SDL_bool has_matching_format = SDL_FALSE;
int i, j, best_bitdiff = -1, bitdiff;
if (!_this->egl_data) {
/* The EGL library wasn't loaded, SDL_GetError() should have info */
return -1;
}
int i, j, best_bitdiff = -1, best_truecolor_bitdiff = -1;
int truecolor_config_idx = -1;
/* Get a valid EGL configuration */
i = 0;
attribs[i++] = EGL_RED_SIZE;
@ -707,30 +727,37 @@ SDL_EGL_ChooseConfig(_THIS)
attribs[i++] = _this->gl_config.green_size;
attribs[i++] = EGL_BLUE_SIZE;
attribs[i++] = _this->gl_config.blue_size;
if (set_config_caveat_none) {
attribs[i++] = EGL_CONFIG_CAVEAT;
attribs[i++] = EGL_NONE;
}
if (_this->gl_config.alpha_size) {
attribs[i++] = EGL_ALPHA_SIZE;
attribs[i++] = _this->gl_config.alpha_size;
}
if (_this->gl_config.buffer_size) {
attribs[i++] = EGL_BUFFER_SIZE;
attribs[i++] = _this->gl_config.buffer_size;
}
attribs[i++] = EGL_DEPTH_SIZE;
attribs[i++] = _this->gl_config.depth_size;
if (_this->gl_config.depth_size) {
attribs[i++] = EGL_DEPTH_SIZE;
attribs[i++] = _this->gl_config.depth_size;
}
if (_this->gl_config.stencil_size) {
attribs[i++] = EGL_STENCIL_SIZE;
attribs[i++] = _this->gl_config.stencil_size;
}
if (_this->gl_config.multisamplebuffers) {
attribs[i++] = EGL_SAMPLE_BUFFERS;
attribs[i++] = _this->gl_config.multisamplebuffers;
}
if (_this->gl_config.multisamplesamples) {
attribs[i++] = EGL_SAMPLES;
attribs[i++] = _this->gl_config.multisamplesamples;
@ -767,24 +794,28 @@ SDL_EGL_ChooseConfig(_THIS)
attribs[i++] = EGL_NONE;
SDL_assert(i < SDL_arraysize(attribs));
if (_this->egl_data->eglChooseConfig(_this->egl_data->egl_display,
attribs,
configs, SDL_arraysize(configs),
&found_configs) == EGL_FALSE ||
found_configs == 0) {
return SDL_EGL_SetError("Couldn't find matching EGL config", "eglChooseConfig");
return -1;
}
/* first ensure that a found config has a matching format, or the function will fall through. */
for (i = 0; i < found_configs; i++ ) {
if (_this->egl_data->egl_required_visual_id)
{
if (_this->egl_data->egl_required_visual_id)
{
for (i = 0; i < found_configs; i++ ) {
EGLint format;
_this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display,
configs[i],
EGL_NATIVE_VISUAL_ID, &format);
if (_this->egl_data->egl_required_visual_id == format)
if (_this->egl_data->egl_required_visual_id == format) {
has_matching_format = SDL_TRUE;
break;
}
}
}
@ -792,22 +823,35 @@ SDL_EGL_ChooseConfig(_THIS)
/* From those, we select the one that matches our requirements more closely via a makeshift algorithm */
for (i = 0; i < found_configs; i++ ) {
if (has_matching_format && _this->egl_data->egl_required_visual_id)
{
SDL_bool is_truecolor = SDL_FALSE;
int bitdiff = 0;
if (has_matching_format && _this->egl_data->egl_required_visual_id) {
EGLint format;
_this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display,
configs[i],
configs[i],
EGL_NATIVE_VISUAL_ID, &format);
if (_this->egl_data->egl_required_visual_id != format)
if (_this->egl_data->egl_required_visual_id != format) {
continue;
}
}
_this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, configs[i], EGL_RED_SIZE, &value);
if (value == 8) {
_this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, configs[i], EGL_GREEN_SIZE, &value);
if (value == 8) {
_this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, configs[i], EGL_BLUE_SIZE, &value);
if (value == 8) {
is_truecolor = SDL_TRUE;
}
}
}
bitdiff = 0;
for (j = 0; j < SDL_arraysize(attribs) - 1; j += 2) {
if (attribs[j] == EGL_NONE) {
break;
}
if ( attribs[j+1] != EGL_DONT_CARE && (
attribs[j] == EGL_RED_SIZE ||
attribs[j] == EGL_GREEN_SIZE ||
@ -820,24 +864,70 @@ SDL_EGL_ChooseConfig(_THIS)
}
}
if (bitdiff < best_bitdiff || best_bitdiff == -1) {
if ((bitdiff < best_bitdiff) || (best_bitdiff == -1)) {
_this->egl_data->egl_config = configs[i];
best_bitdiff = bitdiff;
}
if (bitdiff == 0) {
break; /* we found an exact match! */
if (is_truecolor && ((bitdiff < best_truecolor_bitdiff) || (best_truecolor_bitdiff == -1))) {
truecolor_config_idx = i;
best_truecolor_bitdiff = bitdiff;
}
}
#define FAVOR_TRUECOLOR 1
#if FAVOR_TRUECOLOR
/* Some apps request a low color depth, either because they _assume_
they'll get a larger one but don't want to fail if only smaller ones
are available, or they just never called SDL_GL_SetAttribute at all and
got a tiny default. For these cases, a game that would otherwise run
at 24-bit color might get dithered down to something smaller, which is
worth avoiding. If the app requested <= 16 bit color and an exact 24-bit
match is available, favor that. Otherwise, we look for the closest
match. Note that while the API promises what you request _or better_,
it's feasible this can be disastrous for performance for custom software
on small hardware that all expected to actually get 16-bit color. In this
case, turn off FAVOR_TRUECOLOR (and maybe send a patch to make this more
flexible). */
if ( ((_this->gl_config.red_size + _this->gl_config.blue_size + _this->gl_config.green_size) <= 16) ) {
if (truecolor_config_idx != -1) {
_this->egl_data->egl_config = configs[truecolor_config_idx];
}
}
#endif
#ifdef DUMP_EGL_CONFIG
dumpconfig(_this, _this->egl_data->egl_config);
#endif
return 0;
}
int
SDL_EGL_ChooseConfig(_THIS)
{
int ret;
if (!_this->egl_data) {
return SDL_SetError("EGL not initialized");
}
/* Try with EGL_CONFIG_CAVEAT set to EGL_NONE, to avoid any EGL_SLOW_CONFIG or EGL_NON_CONFORMANT_CONFIG */
ret = SDL_EGL_PrivateChooseConfig(_this, SDL_TRUE);
if (ret == 0) {
return 0;
}
/* Fallback with all configs */
ret = SDL_EGL_PrivateChooseConfig(_this, SDL_FALSE);
if (ret == 0) {
SDL_Log("SDL_EGL_ChooseConfig: found a slow EGL config");
return 0;
}
return SDL_EGL_SetError("Couldn't find matching EGL config", "eglChooseConfig");
}
SDL_GLContext
SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
{
@ -852,7 +942,7 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
SDL_bool profile_es = (profile_mask == SDL_GL_CONTEXT_PROFILE_ES);
if (!_this->egl_data) {
/* The EGL library wasn't loaded, SDL_GetError() should have info */
SDL_SetError("EGL not initialized");
return NULL;
}
@ -922,27 +1012,24 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
}
}
if (_this->gl_config.no_error) {
#ifdef EGL_KHR_create_context_no_error
if (_this->gl_config.no_error) {
if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_create_context_no_error")) {
attribs[attr++] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
attribs[attr++] = _this->gl_config.no_error;
} else
#endif
{
SDL_SetError("EGL implementation does not support no_error contexts");
return NULL;
}
}
#endif
attribs[attr++] = EGL_NONE;
/* Bind the API */
if (profile_es) {
_this->egl_data->eglBindAPI(EGL_OPENGL_ES_API);
_this->egl_data->apitype = EGL_OPENGL_ES_API;
} else {
_this->egl_data->eglBindAPI(EGL_OPENGL_API);
_this->egl_data->apitype = EGL_OPENGL_API;
}
_this->egl_data->eglBindAPI(_this->egl_data->apitype);
egl_context = _this->egl_data->eglCreateContext(_this->egl_data->egl_display,
_this->egl_data->egl_config,
@ -956,16 +1043,8 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
_this->egl_data->egl_swapinterval = 0;
if (SDL_EGL_MakeCurrent(_this, egl_surface, egl_context) < 0) {
/* Save the SDL error set by SDL_EGL_MakeCurrent */
char errorText[1024];
SDL_strlcpy(errorText, SDL_GetError(), SDL_arraysize(errorText));
/* Delete the context, which may alter the value returned by SDL_GetError() */
/* Delete the context */
SDL_EGL_DeleteContext(_this, egl_context);
/* Restore the SDL error */
SDL_SetError("%s", errorText);
return NULL;
}
@ -1008,9 +1087,23 @@ SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context)
EGLContext egl_context = (EGLContext) context;
if (!_this->egl_data) {
return SDL_SetError("OpenGL not initialized");
return SDL_SetError("EGL not initialized");
}
if (!_this->egl_data->eglMakeCurrent) {
if (!egl_surface && !context) {
/* Can't do the nothing there is to do? Probably trying to cleanup a failed startup, just return. */
return 0;
} else {
return SDL_SetError("EGL not initialized"); /* something clearly went wrong somewhere. */
}
}
/* Make sure current thread has a valid API bound to it. */
if (_this->egl_data->eglBindAPI) {
_this->egl_data->eglBindAPI(_this->egl_data->apitype);
}
/* The android emulator crashes badly if you try to eglMakeCurrent
* with a valid context and invalid surface, so we have to check for both here.
*/
@ -1022,7 +1115,7 @@ SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context)
return SDL_EGL_SetError("Unable to make EGL context current", "eglMakeCurrent");
}
}
return 0;
}
@ -1034,6 +1127,13 @@ SDL_EGL_SetSwapInterval(_THIS, int interval)
if (!_this->egl_data) {
return SDL_SetError("EGL not initialized");
}
/* FIXME: Revisit this check when EGL_EXT_swap_control_tear is published:
* https://github.com/KhronosGroup/EGL-Registry/pull/113
*/
if (interval < 0) {
return SDL_SetError("Late swap tearing currently unsupported");
}
status = _this->egl_data->eglSwapInterval(_this->egl_data->egl_display, interval);
if (status == EGL_TRUE) {
@ -1083,8 +1183,12 @@ SDL_EGL_DeleteContext(_THIS, SDL_GLContext context)
EGLSurface *
SDL_EGL_CreateSurface(_THIS, NativeWindowType nw)
{
/* max 2 values plus terminator. */
EGLint attribs[3];
#if SDL_VIDEO_DRIVER_ANDROID
EGLint format_wanted;
EGLint format_got;
#endif
/* max 2 key+value pairs, plus terminator. */
EGLint attribs[5];
int attr = 0;
EGLSurface * surface;
@ -1092,24 +1196,18 @@ SDL_EGL_CreateSurface(_THIS, NativeWindowType nw)
if (SDL_EGL_ChooseConfig(_this) != 0) {
return EGL_NO_SURFACE;
}
#if SDL_VIDEO_DRIVER_ANDROID
{
/* Android docs recommend doing this!
* Ref: http://developer.android.com/reference/android/app/NativeActivity.html
*/
EGLint format;
_this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display,
_this->egl_data->egl_config,
EGL_NATIVE_VISUAL_ID, &format);
/* On Android, EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
* guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). */
_this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display,
_this->egl_data->egl_config,
EGL_NATIVE_VISUAL_ID, &format_wanted);
ANativeWindow_setBuffersGeometry(nw, 0, 0, format);
/* Format based on selected egl config. */
ANativeWindow_setBuffersGeometry(nw, 0, 0, format_wanted);
#endif
/* Update SurfaceView holder format.
* May triggers a sequence surfaceDestroyed(), surfaceCreated(), surfaceChanged(). */
Android_JNI_SetSurfaceViewFormat(format);
}
#endif
if (_this->gl_config.framebuffer_srgb_capable) {
#ifdef EGL_KHR_gl_colorspace
if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_gl_colorspace")) {
@ -1123,6 +1221,14 @@ SDL_EGL_CreateSurface(_THIS, NativeWindowType nw)
}
}
#ifdef EGL_EXT_present_opaque
if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_EXT_present_opaque")) {
const SDL_bool allow_transparent = SDL_GetHintBoolean(SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY, SDL_FALSE);
attribs[attr++] = EGL_PRESENT_OPAQUE_EXT;
attribs[attr++] = allow_transparent ? EGL_FALSE : EGL_TRUE;
}
#endif
attribs[attr++] = EGL_NONE;
surface = _this->egl_data->eglCreateWindowSurface(
@ -1132,6 +1238,12 @@ SDL_EGL_CreateSurface(_THIS, NativeWindowType nw)
if (surface == EGL_NO_SURFACE) {
SDL_EGL_SetError("unable to create an EGL window surface", "eglCreateWindowSurface");
}
#if SDL_VIDEO_DRIVER_ANDROID
format_got = ANativeWindow_getFormat(nw);
Android_SetFormat(format_wanted, format_got);
#endif
return surface;
}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -40,6 +40,8 @@ typedef struct SDL_EGL_VideoData
int egl_surfacetype;
int egl_version_major, egl_version_minor;
EGLint egl_required_visual_id;
SDL_bool is_offscreen; /* whether EGL display was offscreen */
EGLenum apitype; /* EGL_OPENGL_ES_API, EGL_OPENGL_API, etc */
EGLDisplay(EGLAPIENTRY *eglGetDisplay) (NativeDisplayType display);
EGLDisplay(EGLAPIENTRY *eglGetPlatformDisplay) (EGLenum platform,
@ -114,11 +116,6 @@ typedef struct SDL_EGL_VideoData
EGLint(EGLAPIENTRY *eglClientWaitSyncKHR)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
/* Atomic functions end */
/* whether EGL display was offscreen */
int is_offscreen;
} SDL_EGL_VideoData;
/* OpenGLES functions */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -28,7 +28,7 @@
#ifdef __SSE__
/* *INDENT-OFF* */
#ifdef _MSC_VER
#if defined(_MSC_VER) && !defined(__clang__)
#define SSE_BEGIN \
__m128 c128; \
c128.m128_u32[0] = color; \
@ -145,13 +145,13 @@ SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
switch ((uintptr_t) p & 3) {
case 1:
*p++ = (Uint8) color;
--n; /* fallthrough */
--n; SDL_FALLTHROUGH;
case 2:
*p++ = (Uint8) color;
--n; /* fallthrough */
--n; SDL_FALLTHROUGH;
case 3:
*p++ = (Uint8) color;
--n; /* fallthrough */
--n;
}
SDL_memset4(p, color, (n >> 2));
}
@ -159,11 +159,11 @@ SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
p += (n & ~3);
switch (n & 3) {
case 3:
*p++ = (Uint8) color; /* fallthrough */
*p++ = (Uint8) color; SDL_FALLTHROUGH;
case 2:
*p++ = (Uint8) color; /* fallthrough */
*p++ = (Uint8) color; SDL_FALLTHROUGH;
case 1:
*p++ = (Uint8) color; /* fallthrough */
*p++ = (Uint8) color;
}
}
pixels += pitch;
@ -238,7 +238,7 @@ int
SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color)
{
if (!dst) {
return SDL_SetError("Passed NULL destination surface");
return SDL_InvalidParamError("SDL_FillRect(): dst");
}
/* If 'rect' == NULL, then fill the whole surface */
@ -306,12 +306,7 @@ SDL_FillRects(SDL_Surface * dst, const SDL_Rect * rects, int count,
int i;
if (!dst) {
return SDL_SetError("Passed NULL destination surface");
}
/* This function doesn't work on surfaces < 8 bpp */
if (dst->format->BitsPerPixel < 8) {
return SDL_SetError("SDL_FillRect(): Unsupported surface format");
return SDL_InvalidParamError("SDL_FillRects(): dst");
}
/* Nothing to do */
@ -321,11 +316,28 @@ SDL_FillRects(SDL_Surface * dst, const SDL_Rect * rects, int count,
/* Perform software fill */
if (!dst->pixels) {
return SDL_SetError("SDL_FillRect(): You must lock the surface");
return SDL_SetError("SDL_FillRects(): You must lock the surface");
}
if (!rects) {
return SDL_SetError("SDL_FillRects() passed NULL rects");
return SDL_InvalidParamError("SDL_FillRects(): rects");
}
/* This function doesn't usually work on surfaces < 8 bpp
* Except: support for 4bits, when filling full size.
*/
if (dst->format->BitsPerPixel < 8) {
if (count == 1) {
const SDL_Rect *r = &rects[0];
if (r->x == 0 && r->y == 0 && r->w == dst->w && r->w == dst->h) {
if (dst->format->BitsPerPixel == 4) {
Uint8 b = (((Uint8) color << 4) | (Uint8) color);
SDL_memset(dst->pixels, b, dst->h * dst->pitch);
return 1;
}
}
}
return SDL_SetError("SDL_FillRects(): Unsupported surface format");
}
#if SDL_ARM_NEON_BLITTERS

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -333,7 +333,7 @@ SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
if (Rmask == 0) {
return SDL_PIXELFORMAT_RGB555;
}
/* fallthrough */
SDL_FALLTHROUGH;
case 16:
if (Rmask == 0) {
return SDL_PIXELFORMAT_RGB565;
@ -677,7 +677,7 @@ int
SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette)
{
if (!format) {
return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format");
return SDL_InvalidParamError("SDL_SetPixelFormatPalette(): format");
}
if (palette && palette->ncolors > (1 << format->BitsPerPixel)) {
@ -871,7 +871,7 @@ SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b,
return (r >> format->Rloss) << format->Rshift
| (g >> format->Gloss) << format->Gshift
| (b >> format->Bloss) << format->Bshift
| ((a >> format->Aloss) << format->Ashift & format->Amask);
| ((Uint32)(a >> format->Aloss) << format->Ashift & format->Amask);
} else {
return SDL_FindColor(format->palette, r, g, b, a);
}
@ -947,7 +947,7 @@ Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
}
*identical = 0;
}
map = (Uint8 *) SDL_malloc(src->ncolors);
map = (Uint8 *) SDL_calloc(256, sizeof(Uint8));
if (map == NULL) {
SDL_OutOfMemory();
return (NULL);
@ -971,7 +971,7 @@ Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
SDL_Palette *pal = src->palette;
bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
map = (Uint8 *) SDL_malloc(pal->ncolors * bpp);
map = (Uint8 *) SDL_calloc(256, bpp);
if (map == NULL) {
SDL_OutOfMemory();
return (NULL);
@ -983,7 +983,7 @@ Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
Uint8 G = (Uint8) ((pal->colors[i].g * Gmod) / 255);
Uint8 B = (Uint8) ((pal->colors[i].b * Bmod) / 255);
Uint8 A = (Uint8) ((pal->colors[i].a * Amod) / 255);
ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, R, G, B, A);
ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, (Uint32)R, (Uint32)G, (Uint32)B, (Uint32)A);
}
return (map);
}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -23,447 +23,8 @@
#include "SDL_rect.h"
#include "SDL_rect_c.h"
SDL_bool
SDL_HasIntersection(const SDL_Rect * A, const SDL_Rect * B)
{
int Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
}
if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
}
/* Special cases for empty rects */
if (SDL_RectEmpty(A) || SDL_RectEmpty(B)) {
return SDL_FALSE;
}
/* Horizontal intersection */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin > Amin)
Amin = Bmin;
if (Bmax < Amax)
Amax = Bmax;
if (Amax <= Amin)
return SDL_FALSE;
/* Vertical intersection */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin > Amin)
Amin = Bmin;
if (Bmax < Amax)
Amax = Bmax;
if (Amax <= Amin)
return SDL_FALSE;
return SDL_TRUE;
}
SDL_bool
SDL_IntersectRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result)
{
int Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
}
if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
}
if (!result) {
SDL_InvalidParamError("result");
return SDL_FALSE;
}
/* Special cases for empty rects */
if (SDL_RectEmpty(A) || SDL_RectEmpty(B)) {
result->w = 0;
result->h = 0;
return SDL_FALSE;
}
/* Horizontal intersection */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin > Amin)
Amin = Bmin;
result->x = Amin;
if (Bmax < Amax)
Amax = Bmax;
result->w = Amax - Amin;
/* Vertical intersection */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin > Amin)
Amin = Bmin;
result->y = Amin;
if (Bmax < Amax)
Amax = Bmax;
result->h = Amax - Amin;
return !SDL_RectEmpty(result);
}
void
SDL_UnionRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result)
{
int Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return;
}
if (!B) {
SDL_InvalidParamError("B");
return;
}
if (!result) {
SDL_InvalidParamError("result");
return;
}
/* Special cases for empty Rects */
if (SDL_RectEmpty(A)) {
if (SDL_RectEmpty(B)) {
/* A and B empty */
return;
} else {
/* A empty, B not empty */
*result = *B;
return;
}
} else {
if (SDL_RectEmpty(B)) {
/* A not empty, B empty */
*result = *A;
return;
}
}
/* Horizontal union */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin < Amin)
Amin = Bmin;
result->x = Amin;
if (Bmax > Amax)
Amax = Bmax;
result->w = Amax - Amin;
/* Vertical union */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin < Amin)
Amin = Bmin;
result->y = Amin;
if (Bmax > Amax)
Amax = Bmax;
result->h = Amax - Amin;
}
SDL_bool
SDL_EnclosePoints(const SDL_Point * points, int count, const SDL_Rect * clip,
SDL_Rect * result)
{
int minx = 0;
int miny = 0;
int maxx = 0;
int maxy = 0;
int x, y, i;
if (!points) {
SDL_InvalidParamError("points");
return SDL_FALSE;
}
if (count < 1) {
SDL_InvalidParamError("count");
return SDL_FALSE;
}
if (clip) {
SDL_bool added = SDL_FALSE;
const int clip_minx = clip->x;
const int clip_miny = clip->y;
const int clip_maxx = clip->x+clip->w-1;
const int clip_maxy = clip->y+clip->h-1;
/* Special case for empty rectangle */
if (SDL_RectEmpty(clip)) {
return SDL_FALSE;
}
for (i = 0; i < count; ++i) {
x = points[i].x;
y = points[i].y;
if (x < clip_minx || x > clip_maxx ||
y < clip_miny || y > clip_maxy) {
continue;
}
if (!added) {
/* Special case: if no result was requested, we are done */
if (result == NULL) {
return SDL_TRUE;
}
/* First point added */
minx = maxx = x;
miny = maxy = y;
added = SDL_TRUE;
continue;
}
if (x < minx) {
minx = x;
} else if (x > maxx) {
maxx = x;
}
if (y < miny) {
miny = y;
} else if (y > maxy) {
maxy = y;
}
}
if (!added) {
return SDL_FALSE;
}
} else {
/* Special case: if no result was requested, we are done */
if (result == NULL) {
return SDL_TRUE;
}
/* No clipping, always add the first point */
minx = maxx = points[0].x;
miny = maxy = points[0].y;
for (i = 1; i < count; ++i) {
x = points[i].x;
y = points[i].y;
if (x < minx) {
minx = x;
} else if (x > maxx) {
maxx = x;
}
if (y < miny) {
miny = y;
} else if (y > maxy) {
maxy = y;
}
}
}
if (result) {
result->x = minx;
result->y = miny;
result->w = (maxx-minx)+1;
result->h = (maxy-miny)+1;
}
return SDL_TRUE;
}
/* Use the Cohen-Sutherland algorithm for line clipping */
#define CODE_BOTTOM 1
#define CODE_TOP 2
#define CODE_LEFT 4
#define CODE_RIGHT 8
static int
ComputeOutCode(const SDL_Rect * rect, int x, int y)
{
int code = 0;
if (y < rect->y) {
code |= CODE_TOP;
} else if (y >= rect->y + rect->h) {
code |= CODE_BOTTOM;
}
if (x < rect->x) {
code |= CODE_LEFT;
} else if (x >= rect->x + rect->w) {
code |= CODE_RIGHT;
}
return code;
}
SDL_bool
SDL_IntersectRectAndLine(const SDL_Rect * rect, int *X1, int *Y1, int *X2,
int *Y2)
{
int x = 0;
int y = 0;
int x1, y1;
int x2, y2;
int rectx1;
int recty1;
int rectx2;
int recty2;
int outcode1, outcode2;
if (!rect) {
SDL_InvalidParamError("rect");
return SDL_FALSE;
}
if (!X1) {
SDL_InvalidParamError("X1");
return SDL_FALSE;
}
if (!Y1) {
SDL_InvalidParamError("Y1");
return SDL_FALSE;
}
if (!X2) {
SDL_InvalidParamError("X2");
return SDL_FALSE;
}
if (!Y2) {
SDL_InvalidParamError("Y2");
return SDL_FALSE;
}
/* Special case for empty rect */
if (SDL_RectEmpty(rect)) {
return SDL_FALSE;
}
x1 = *X1;
y1 = *Y1;
x2 = *X2;
y2 = *Y2;
rectx1 = rect->x;
recty1 = rect->y;
rectx2 = rect->x + rect->w - 1;
recty2 = rect->y + rect->h - 1;
/* Check to see if entire line is inside rect */
if (x1 >= rectx1 && x1 <= rectx2 && x2 >= rectx1 && x2 <= rectx2 &&
y1 >= recty1 && y1 <= recty2 && y2 >= recty1 && y2 <= recty2) {
return SDL_TRUE;
}
/* Check to see if entire line is to one side of rect */
if ((x1 < rectx1 && x2 < rectx1) || (x1 > rectx2 && x2 > rectx2) ||
(y1 < recty1 && y2 < recty1) || (y1 > recty2 && y2 > recty2)) {
return SDL_FALSE;
}
if (y1 == y2) {
/* Horizontal line, easy to clip */
if (x1 < rectx1) {
*X1 = rectx1;
} else if (x1 > rectx2) {
*X1 = rectx2;
}
if (x2 < rectx1) {
*X2 = rectx1;
} else if (x2 > rectx2) {
*X2 = rectx2;
}
return SDL_TRUE;
}
if (x1 == x2) {
/* Vertical line, easy to clip */
if (y1 < recty1) {
*Y1 = recty1;
} else if (y1 > recty2) {
*Y1 = recty2;
}
if (y2 < recty1) {
*Y2 = recty1;
} else if (y2 > recty2) {
*Y2 = recty2;
}
return SDL_TRUE;
}
/* More complicated Cohen-Sutherland algorithm */
outcode1 = ComputeOutCode(rect, x1, y1);
outcode2 = ComputeOutCode(rect, x2, y2);
while (outcode1 || outcode2) {
if (outcode1 & outcode2) {
return SDL_FALSE;
}
if (outcode1) {
if (outcode1 & CODE_TOP) {
y = recty1;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode1 & CODE_BOTTOM) {
y = recty2;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode1 & CODE_LEFT) {
x = rectx1;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
} else if (outcode1 & CODE_RIGHT) {
x = rectx2;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
}
x1 = x;
y1 = y;
outcode1 = ComputeOutCode(rect, x, y);
} else {
if (outcode2 & CODE_TOP) {
y = recty1;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode2 & CODE_BOTTOM) {
y = recty2;
x = x1 + ((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);
} 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);
}
x2 = x;
y2 = y;
outcode2 = ComputeOutCode(rect, x, y);
}
}
*X1 = x1;
*Y1 = y1;
*X2 = x2;
*Y2 = y2;
return SDL_TRUE;
}
/* There's no float version of this at the moment, because it's not a public API
and internally we only need the int version. */
SDL_bool
SDL_GetSpanEnclosingRect(int width, int height,
int numrects, const SDL_Rect * rects, SDL_Rect *span)
@ -475,24 +36,16 @@ SDL_GetSpanEnclosingRect(int width, int height,
if (width < 1) {
SDL_InvalidParamError("width");
return SDL_FALSE;
}
if (height < 1) {
} else if (height < 1) {
SDL_InvalidParamError("height");
return SDL_FALSE;
}
if (!rects) {
} else if (!rects) {
SDL_InvalidParamError("rects");
return SDL_FALSE;
}
if (!span) {
} else if (!span) {
SDL_InvalidParamError("span");
return SDL_FALSE;
}
if (numrects < 1) {
} else if (numrects < 1) {
SDL_InvalidParamError("numrects");
return SDL_FALSE;
}
@ -527,4 +80,36 @@ SDL_GetSpanEnclosingRect(int width, int height,
return SDL_FALSE;
}
/* For use with the Cohen-Sutherland algorithm for line clipping, in SDL_rect_impl.h */
#define CODE_BOTTOM 1
#define CODE_TOP 2
#define CODE_LEFT 4
#define CODE_RIGHT 8
/* Same code twice, for float and int versions... */
#define RECTTYPE SDL_Rect
#define POINTTYPE SDL_Point
#define SCALARTYPE int
#define COMPUTEOUTCODE ComputeOutCode
#define SDL_HASINTERSECTION SDL_HasIntersection
#define SDL_INTERSECTRECT SDL_IntersectRect
#define SDL_RECTEMPTY SDL_RectEmpty
#define SDL_UNIONRECT SDL_UnionRect
#define SDL_ENCLOSEPOINTS SDL_EnclosePoints
#define SDL_INTERSECTRECTANDLINE SDL_IntersectRectAndLine
#include "SDL_rect_impl.h"
#define RECTTYPE SDL_FRect
#define POINTTYPE SDL_FPoint
#define SCALARTYPE float
#define COMPUTEOUTCODE ComputeOutCodeF
#define SDL_HASINTERSECTION SDL_HasIntersectionF
#define SDL_INTERSECTRECT SDL_IntersectFRect
#define SDL_RECTEMPTY SDL_FRectEmpty
#define SDL_UNIONRECT SDL_UnionFRect
#define SDL_ENCLOSEPOINTS SDL_EncloseFPoints
#define SDL_INTERSECTRECTANDLINE SDL_IntersectFRectAndLine
#include "SDL_rect_impl.h"
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,444 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 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.
*/
/* This file is #included twice to support int and float versions with the same code. */
SDL_bool
SDL_HASINTERSECTION(const RECTTYPE * A, const RECTTYPE * B)
{
SCALARTYPE Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
} else if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
} else if (SDL_RECTEMPTY(A) || SDL_RECTEMPTY(B)) {
return SDL_FALSE; /* Special cases for empty rects */
}
/* Horizontal intersection */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin > Amin) {
Amin = Bmin;
}
if (Bmax < Amax) {
Amax = Bmax;
}
if (Amax <= Amin) {
return SDL_FALSE;
}
/* Vertical intersection */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin > Amin) {
Amin = Bmin;
}
if (Bmax < Amax) {
Amax = Bmax;
}
if (Amax <= Amin) {
return SDL_FALSE;
}
return SDL_TRUE;
}
SDL_bool
SDL_INTERSECTRECT(const RECTTYPE * A, const RECTTYPE * B, RECTTYPE * result)
{
SCALARTYPE Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
} else if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
} else if (!result) {
SDL_InvalidParamError("result");
return SDL_FALSE;
} else if (SDL_RECTEMPTY(A) || SDL_RECTEMPTY(B)) { /* Special cases for empty rects */
result->w = 0;
result->h = 0;
return SDL_FALSE;
}
/* Horizontal intersection */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin > Amin) {
Amin = Bmin;
}
result->x = Amin;
if (Bmax < Amax) {
Amax = Bmax;
}
result->w = Amax - Amin;
/* Vertical intersection */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin > Amin) {
Amin = Bmin;
}
result->y = Amin;
if (Bmax < Amax) {
Amax = Bmax;
}
result->h = Amax - Amin;
return !SDL_RECTEMPTY(result);
}
void
SDL_UNIONRECT(const RECTTYPE * A, const RECTTYPE * B, RECTTYPE * result)
{
SCALARTYPE Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return;
} else if (!B) {
SDL_InvalidParamError("B");
return;
} else if (!result) {
SDL_InvalidParamError("result");
return;
} else if (SDL_RECTEMPTY(A)) { /* Special cases for empty Rects */
if (SDL_RECTEMPTY(B)) { /* A and B empty */
SDL_zerop(result);
} else { /* A empty, B not empty */
*result = *B;
}
return;
} else if (SDL_RECTEMPTY(B)) { /* A not empty, B empty */
*result = *A;
return;
}
/* Horizontal union */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin < Amin) {
Amin = Bmin;
}
result->x = Amin;
if (Bmax > Amax) {
Amax = Bmax;
}
result->w = Amax - Amin;
/* Vertical union */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin < Amin) {
Amin = Bmin;
}
result->y = Amin;
if (Bmax > Amax) {
Amax = Bmax;
}
result->h = Amax - Amin;
}
SDL_bool SDL_ENCLOSEPOINTS(const POINTTYPE * points, int count, const RECTTYPE * clip,
RECTTYPE * result)
{
SCALARTYPE minx = 0;
SCALARTYPE miny = 0;
SCALARTYPE maxx = 0;
SCALARTYPE maxy = 0;
SCALARTYPE x, y;
int i;
if (!points) {
SDL_InvalidParamError("points");
return SDL_FALSE;
} else if (count < 1) {
SDL_InvalidParamError("count");
return SDL_FALSE;
}
if (clip) {
SDL_bool added = SDL_FALSE;
const SCALARTYPE clip_minx = clip->x;
const SCALARTYPE clip_miny = clip->y;
const SCALARTYPE clip_maxx = clip->x+clip->w-1;
const SCALARTYPE clip_maxy = clip->y+clip->h-1;
/* Special case for empty rectangle */
if (SDL_RECTEMPTY(clip)) {
return SDL_FALSE;
}
for (i = 0; i < count; ++i) {
x = points[i].x;
y = points[i].y;
if (x < clip_minx || x > clip_maxx ||
y < clip_miny || y > clip_maxy) {
continue;
}
if (!added) {
/* Special case: if no result was requested, we are done */
if (result == NULL) {
return SDL_TRUE;
}
/* First point added */
minx = maxx = x;
miny = maxy = y;
added = SDL_TRUE;
continue;
}
if (x < minx) {
minx = x;
} else if (x > maxx) {
maxx = x;
}
if (y < miny) {
miny = y;
} else if (y > maxy) {
maxy = y;
}
}
if (!added) {
return SDL_FALSE;
}
} else {
/* Special case: if no result was requested, we are done */
if (result == NULL) {
return SDL_TRUE;
}
/* No clipping, always add the first point */
minx = maxx = points[0].x;
miny = maxy = points[0].y;
for (i = 1; i < count; ++i) {
x = points[i].x;
y = points[i].y;
if (x < minx) {
minx = x;
} else if (x > maxx) {
maxx = x;
}
if (y < miny) {
miny = y;
} else if (y > maxy) {
maxy = y;
}
}
}
if (result) {
result->x = minx;
result->y = miny;
result->w = (maxx-minx)+1;
result->h = (maxy-miny)+1;
}
return SDL_TRUE;
}
/* Use the Cohen-Sutherland algorithm for line clipping */
static int
COMPUTEOUTCODE(const RECTTYPE * rect, SCALARTYPE x, SCALARTYPE y)
{
int code = 0;
if (y < rect->y) {
code |= CODE_TOP;
} else if (y >= rect->y + rect->h) {
code |= CODE_BOTTOM;
}
if (x < rect->x) {
code |= CODE_LEFT;
} else if (x >= rect->x + rect->w) {
code |= CODE_RIGHT;
}
return code;
}
SDL_bool
SDL_INTERSECTRECTANDLINE(const RECTTYPE * rect, SCALARTYPE *X1, SCALARTYPE *Y1, SCALARTYPE *X2,
SCALARTYPE *Y2)
{
SCALARTYPE x = 0;
SCALARTYPE y = 0;
SCALARTYPE x1, y1;
SCALARTYPE x2, y2;
SCALARTYPE rectx1;
SCALARTYPE recty1;
SCALARTYPE rectx2;
SCALARTYPE recty2;
int outcode1, outcode2;
if (!rect) {
SDL_InvalidParamError("rect");
return SDL_FALSE;
} else if (!X1) {
SDL_InvalidParamError("X1");
return SDL_FALSE;
} else if (!Y1) {
SDL_InvalidParamError("Y1");
return SDL_FALSE;
} else if (!X2) {
SDL_InvalidParamError("X2");
return SDL_FALSE;
} else if (!Y2) {
SDL_InvalidParamError("Y2");
return SDL_FALSE;
} else if (SDL_RECTEMPTY(rect)) {
return SDL_FALSE; /* Special case for empty rect */
}
x1 = *X1;
y1 = *Y1;
x2 = *X2;
y2 = *Y2;
rectx1 = rect->x;
recty1 = rect->y;
rectx2 = rect->x + rect->w - 1;
recty2 = rect->y + rect->h - 1;
/* Check to see if entire line is inside rect */
if (x1 >= rectx1 && x1 <= rectx2 && x2 >= rectx1 && x2 <= rectx2 &&
y1 >= recty1 && y1 <= recty2 && y2 >= recty1 && y2 <= recty2) {
return SDL_TRUE;
}
/* Check to see if entire line is to one side of rect */
if ((x1 < rectx1 && x2 < rectx1) || (x1 > rectx2 && x2 > rectx2) ||
(y1 < recty1 && y2 < recty1) || (y1 > recty2 && y2 > recty2)) {
return SDL_FALSE;
}
if (y1 == y2) { /* Horizontal line, easy to clip */
if (x1 < rectx1) {
*X1 = rectx1;
} else if (x1 > rectx2) {
*X1 = rectx2;
}
if (x2 < rectx1) {
*X2 = rectx1;
} else if (x2 > rectx2) {
*X2 = rectx2;
}
return SDL_TRUE;
}
if (x1 == x2) { /* Vertical line, easy to clip */
if (y1 < recty1) {
*Y1 = recty1;
} else if (y1 > recty2) {
*Y1 = recty2;
}
if (y2 < recty1) {
*Y2 = recty1;
} else if (y2 > recty2) {
*Y2 = recty2;
}
return SDL_TRUE;
}
/* More complicated Cohen-Sutherland algorithm */
outcode1 = COMPUTEOUTCODE(rect, x1, y1);
outcode2 = COMPUTEOUTCODE(rect, x2, y2);
while (outcode1 || outcode2) {
if (outcode1 & outcode2) {
return SDL_FALSE;
}
if (outcode1) {
if (outcode1 & CODE_TOP) {
y = recty1;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode1 & CODE_BOTTOM) {
y = recty2;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode1 & CODE_LEFT) {
x = rectx1;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
} else if (outcode1 & CODE_RIGHT) {
x = rectx2;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
}
x1 = x;
y1 = y;
outcode1 = COMPUTEOUTCODE(rect, x, y);
} else {
if (outcode2 & CODE_TOP) {
y = recty1;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode2 & CODE_BOTTOM) {
y = recty2;
x = x1 + ((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);
} 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);
}
x2 = x;
y2 = y;
outcode2 = COMPUTEOUTCODE(rect, x, y);
}
}
*X1 = x1;
*Y1 = y1;
*X2 = x2;
*Y2 = y2;
return SDL_TRUE;
}
#undef RECTTYPE
#undef POINTTYPE
#undef SCALARTYPE
#undef COMPUTEOUTCODE
#undef SDL_HASINTERSECTION
#undef SDL_INTERSECTRECT
#undef SDL_RECTEMPTY
#undef SDL_UNIONRECT
#undef SDL_ENCLOSEPOINTS
#undef SDL_INTERSECTRECTANDLINE
/* vi: set ts=4 sw=4 expandtab: */

View file

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

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,6 +26,7 @@
#include "SDL_RLEaccel_c.h"
#include "SDL_pixels_c.h"
#include "SDL_yuv_c.h"
#include "../render/SDL_sysrender.h"
/* Check to make sure we can safely check multiplication of surface w and pitch and it won't overflow size_t */
@ -218,7 +219,7 @@ int
SDL_SetSurfacePalette(SDL_Surface * surface, SDL_Palette * palette)
{
if (!surface) {
return SDL_SetError("SDL_SetSurfacePalette() passed a NULL surface");
return SDL_InvalidParamError("SDL_SetSurfacePalette(): surface");
}
if (SDL_SetPixelFormatPalette(surface->format, palette) < 0) {
return -1;
@ -325,11 +326,12 @@ SDL_GetColorKey(SDL_Surface * surface, Uint32 * key)
return 0;
}
/* This is a fairly slow function to switch from colorkey to alpha */
/* This is a fairly slow function to switch from colorkey to alpha
NB: it doesn't handle bpp 1 or 3, because they have no alpha channel */
static void
SDL_ConvertColorkeyToAlpha(SDL_Surface * surface, SDL_bool ignore_alpha)
{
int x, y;
int x, y, bpp;
if (!surface) {
return;
@ -340,82 +342,74 @@ SDL_ConvertColorkeyToAlpha(SDL_Surface * surface, SDL_bool ignore_alpha)
return;
}
bpp = surface->format->BytesPerPixel;
SDL_LockSurface(surface);
switch (surface->format->BytesPerPixel) {
case 2:
{
Uint16 *row, *spot;
Uint16 ckey = (Uint16) surface->map->info.colorkey;
Uint16 mask = (Uint16) (~surface->format->Amask);
if (bpp == 2) {
Uint16 *row, *spot;
Uint16 ckey = (Uint16) surface->map->info.colorkey;
Uint16 mask = (Uint16) (~surface->format->Amask);
/* Ignore, or not, alpha in colorkey comparison */
if (ignore_alpha) {
ckey &= mask;
row = (Uint16 *) surface->pixels;
for (y = surface->h; y--;) {
spot = row;
for (x = surface->w; x--;) {
if ((*spot & mask) == ckey) {
*spot &= mask;
}
++spot;
/* Ignore, or not, alpha in colorkey comparison */
if (ignore_alpha) {
ckey &= mask;
row = (Uint16 *) surface->pixels;
for (y = surface->h; y--;) {
spot = row;
for (x = surface->w; x--;) {
if ((*spot & mask) == ckey) {
*spot &= mask;
}
row += surface->pitch / 2;
++spot;
}
} else {
row = (Uint16 *) surface->pixels;
for (y = surface->h; y--;) {
spot = row;
for (x = surface->w; x--;) {
if (*spot == ckey) {
*spot &= mask;
}
++spot;
row += surface->pitch / 2;
}
} else {
row = (Uint16 *) surface->pixels;
for (y = surface->h; y--;) {
spot = row;
for (x = surface->w; x--;) {
if (*spot == ckey) {
*spot &= mask;
}
row += surface->pitch / 2;
++spot;
}
row += surface->pitch / 2;
}
}
break;
case 3:
/* FIXME */
break;
case 4:
{
Uint32 *row, *spot;
Uint32 ckey = surface->map->info.colorkey;
Uint32 mask = ~surface->format->Amask;
} else if (bpp == 4) {
Uint32 *row, *spot;
Uint32 ckey = surface->map->info.colorkey;
Uint32 mask = ~surface->format->Amask;
/* Ignore, or not, alpha in colorkey comparison */
if (ignore_alpha) {
ckey &= mask;
row = (Uint32 *) surface->pixels;
for (y = surface->h; y--;) {
spot = row;
for (x = surface->w; x--;) {
if ((*spot & mask) == ckey) {
*spot &= mask;
}
++spot;
/* Ignore, or not, alpha in colorkey comparison */
if (ignore_alpha) {
ckey &= mask;
row = (Uint32 *) surface->pixels;
for (y = surface->h; y--;) {
spot = row;
for (x = surface->w; x--;) {
if ((*spot & mask) == ckey) {
*spot &= mask;
}
row += surface->pitch / 4;
++spot;
}
} else {
row = (Uint32 *) surface->pixels;
for (y = surface->h; y--;) {
spot = row;
for (x = surface->w; x--;) {
if (*spot == ckey) {
*spot &= mask;
}
++spot;
row += surface->pitch / 4;
}
} else {
row = (Uint32 *) surface->pixels;
for (y = surface->h; y--;) {
spot = row;
for (x = surface->w; x--;) {
if (*spot == ckey) {
*spot &= mask;
}
row += surface->pitch / 4;
++spot;
}
row += surface->pitch / 4;
}
}
break;
}
SDL_UnlockSurface(surface);
@ -652,7 +646,7 @@ SDL_UpperBlit(SDL_Surface * src, const SDL_Rect * srcrect,
/* Make sure the surfaces aren't locked */
if (!src || !dst) {
return SDL_SetError("SDL_UpperBlit: passed a NULL surface");
return SDL_InvalidParamError("SDL_UpperBlit(): src/dst");
}
if (src->locked || dst->locked) {
return SDL_SetError("Surfaces must not be locked during blit");
@ -745,6 +739,14 @@ SDL_UpperBlit(SDL_Surface * src, const SDL_Rect * srcrect,
int
SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect)
{
return SDL_PrivateUpperBlitScaled(src, srcrect, dst, dstrect, SDL_ScaleModeNearest);
}
int
SDL_PrivateUpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
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;
@ -755,7 +757,7 @@ SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
/* Make sure the surfaces aren't locked */
if (!src || !dst) {
return SDL_SetError("SDL_UpperBlitScaled: passed a NULL surface");
return SDL_InvalidParamError("SDL_UpperBlitScaled(): src/dst");
}
if (src->locked || dst->locked) {
return SDL_SetError("Surfaces must not be locked during blit");
@ -788,25 +790,25 @@ SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
if (NULL == dstrect) {
dst_x0 = 0;
dst_y0 = 0;
dst_x1 = dst_w - 1;
dst_y1 = dst_h - 1;
dst_x1 = dst_w;
dst_y1 = dst_h;
} else {
dst_x0 = dstrect->x;
dst_y0 = dstrect->y;
dst_x1 = dst_x0 + dst_w - 1;
dst_y1 = dst_y0 + dst_h - 1;
dst_x1 = dst_x0 + dst_w;
dst_y1 = dst_y0 + dst_h;
}
if (NULL == srcrect) {
src_x0 = 0;
src_y0 = 0;
src_x1 = src_w - 1;
src_y1 = src_h - 1;
src_x1 = src_w;
src_y1 = src_h;
} else {
src_x0 = srcrect->x;
src_y0 = srcrect->y;
src_x1 = src_x0 + src_w - 1;
src_y1 = src_y0 + src_h - 1;
src_x1 = src_x0 + src_w;
src_y1 = src_y0 + src_h;
/* Clip source rectangle to the source surface */
@ -815,9 +817,9 @@ SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
src_x0 = 0;
}
if (src_x1 >= src->w) {
dst_x1 -= (src_x1 - src->w + 1) * scaling_w;
src_x1 = src->w - 1;
if (src_x1 > src->w) {
dst_x1 -= (src_x1 - src->w) * scaling_w;
src_x1 = src->w;
}
if (src_y0 < 0) {
@ -825,9 +827,9 @@ SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
src_y0 = 0;
}
if (src_y1 >= src->h) {
dst_y1 -= (src_y1 - src->h + 1) * scaling_h;
src_y1 = src->h - 1;
if (src_y1 > src->h) {
dst_y1 -= (src_y1 - src->h) * scaling_h;
src_y1 = src->h;
}
}
@ -844,9 +846,9 @@ SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
dst_x0 = 0;
}
if (dst_x1 >= dst->clip_rect.w) {
src_x1 -= (dst_x1 - dst->clip_rect.w + 1) / scaling_w;
dst_x1 = dst->clip_rect.w - 1;
if (dst_x1 > dst->clip_rect.w) {
src_x1 -= (dst_x1 - dst->clip_rect.w) / scaling_w;
dst_x1 = dst->clip_rect.w;
}
if (dst_y0 < 0) {
@ -854,9 +856,9 @@ SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
dst_y0 = 0;
}
if (dst_y1 >= dst->clip_rect.h) {
src_y1 -= (dst_y1 - dst->clip_rect.h + 1) / scaling_h;
dst_y1 = dst->clip_rect.h - 1;
if (dst_y1 > dst->clip_rect.h) {
src_y1 -= (dst_y1 - dst->clip_rect.h) / scaling_h;
dst_y1 = dst->clip_rect.h;
}
/* Translate back to surface coordinates */
@ -865,23 +867,32 @@ SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
dst_y0 += dst->clip_rect.y;
dst_y1 += dst->clip_rect.y;
final_src.x = (int)SDL_floor(src_x0 + 0.5);
final_src.y = (int)SDL_floor(src_y0 + 0.5);
final_src.w = (int)SDL_floor(src_x1 + 1 + 0.5) - (int)SDL_floor(src_x0 + 0.5);
final_src.h = (int)SDL_floor(src_y1 + 1 + 0.5) - (int)SDL_floor(src_y0 + 0.5);
final_src.x = (int)SDL_round(src_x0);
final_src.y = (int)SDL_round(src_y0);
final_src.w = (int)SDL_round(src_x1 - src_x0);
final_src.h = (int)SDL_round(src_y1 - src_y0);
final_dst.x = (int)SDL_floor(dst_x0 + 0.5);
final_dst.y = (int)SDL_floor(dst_y0 + 0.5);
final_dst.w = (int)SDL_floor(dst_x1 - dst_x0 + 1.5);
final_dst.h = (int)SDL_floor(dst_y1 - dst_y0 + 1.5);
final_dst.x = (int)SDL_round(dst_x0);
final_dst.y = (int)SDL_round(dst_y0);
final_dst.w = (int)SDL_round(dst_x1 - dst_x0);
final_dst.h = (int)SDL_round(dst_y1 - dst_y0);
if (final_dst.w < 0)
final_dst.w = 0;
if (final_dst.h < 0)
final_dst.h = 0;
/* Clip again */
{
SDL_Rect tmp;
tmp.x = 0;
tmp.y = 0;
tmp.w = src->w;
tmp.h = src->h;
SDL_IntersectRect(&tmp, &final_src, &final_src);
}
if (dstrect)
/* Clip again */
SDL_IntersectRect(&dst->clip_rect, &final_dst, &final_dst);
if (dstrect) {
*dstrect = final_dst;
}
if (final_dst.w == 0 || final_dst.h == 0 ||
final_src.w <= 0 || final_src.h <= 0) {
@ -889,7 +900,7 @@ SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
return 0;
}
return SDL_LowerBlitScaled(src, &final_src, dst, &final_dst);
return SDL_PrivateLowerBlitScaled(src, &final_src, dst, &final_dst, scaleMode);
}
/**
@ -899,6 +910,13 @@ SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
int
SDL_LowerBlitScaled(SDL_Surface * src, SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect)
{
return SDL_PrivateLowerBlitScaled(src, srcrect, dst, dstrect, SDL_ScaleModeNearest);
}
int
SDL_PrivateLowerBlitScaled(SDL_Surface * src, SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect, SDL_ScaleMode scaleMode)
{
static const Uint32 complex_copy_flags = (
SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA |
@ -906,17 +924,103 @@ SDL_LowerBlitScaled(SDL_Surface * src, SDL_Rect * srcrect,
SDL_COPY_COLORKEY
);
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");
}
if (!(src->map->info.flags & SDL_COPY_NEAREST)) {
src->map->info.flags |= SDL_COPY_NEAREST;
SDL_InvalidateMap(src->map);
}
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 );
if (scaleMode == SDL_ScaleModeNearest) {
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 );
} else {
return SDL_LowerBlit( src, srcrect, dst, dstrect );
}
} else {
return SDL_LowerBlit( src, srcrect, dst, dstrect );
if ( !(src->map->info.flags & complex_copy_flags) &&
src->format->format == dst->format->format &&
!SDL_ISPIXELFORMAT_INDEXED(src->format->format) &&
src->format->BytesPerPixel == 4 &&
src->format->format != SDL_PIXELFORMAT_ARGB2101010) {
/* fast path */
return SDL_SoftStretchLinear(src, srcrect, dst, dstrect);
} else {
/* Use intermediate surface(s) */
SDL_Surface *tmp1 = NULL;
int ret;
SDL_Rect srcrect2;
int is_complex_copy_flags = (src->map->info.flags & complex_copy_flags);
Uint32 flags;
Uint8 r, g, b;
Uint8 alpha;
SDL_BlendMode blendMode;
/* Save source infos */
flags = src->flags;
SDL_GetSurfaceColorMod(src, &r, &g, &b);
SDL_GetSurfaceAlphaMod(src, &alpha);
SDL_GetSurfaceBlendMode(src, &blendMode);
srcrect2.x = srcrect->x;
srcrect2.y = srcrect->y;
srcrect2.w = srcrect->w;
srcrect2.h = srcrect->h;
/* Change source format if not appropriate for scaling */
if (src->format->BytesPerPixel != 4 || src->format->format == SDL_PIXELFORMAT_ARGB2101010) {
SDL_Rect tmprect;
int fmt;
tmprect.x = 0;
tmprect.y = 0;
tmprect.w = src->w;
tmprect.h = src->h;
if (dst->format->BytesPerPixel == 4 && dst->format->format != SDL_PIXELFORMAT_ARGB2101010) {
fmt = dst->format->format;
} else {
fmt = SDL_PIXELFORMAT_ARGB8888;
}
tmp1 = SDL_CreateRGBSurfaceWithFormat(flags, src->w, src->h, 0, fmt);
SDL_LowerBlit(src, srcrect, tmp1, &tmprect);
srcrect2.x = 0;
srcrect2.y = 0;
SDL_SetSurfaceColorMod(tmp1, r, g, b);
SDL_SetSurfaceAlphaMod(tmp1, alpha);
SDL_SetSurfaceBlendMode(tmp1, blendMode);
src = tmp1;
}
/* Intermediate scaling */
if (is_complex_copy_flags || src->format->format != dst->format->format) {
SDL_Rect tmprect;
SDL_Surface *tmp2 = SDL_CreateRGBSurfaceWithFormat(flags, dstrect->w, dstrect->h, 0, src->format->format);
SDL_SoftStretchLinear(src, &srcrect2, tmp2, NULL);
SDL_SetSurfaceColorMod(tmp2, r, g, b);
SDL_SetSurfaceAlphaMod(tmp2, alpha);
SDL_SetSurfaceBlendMode(tmp2, blendMode);
tmprect.x = 0;
tmprect.y = 0;
tmprect.w = dstrect->w;
tmprect.h = dstrect->h;
ret = SDL_LowerBlit(tmp2, &tmprect, dst, dstrect);
SDL_FreeSurface(tmp2);
} else {
ret = SDL_SoftStretchLinear(src, &srcrect2, dst, dstrect);
}
SDL_FreeSurface(tmp1);
return ret;
}
}
}
@ -988,6 +1092,7 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
int palette_ck_value = 0;
SDL_bool palette_has_alpha = SDL_FALSE;
Uint8 *palette_saved_alpha = NULL;
int palette_saved_alpha_ncolors = 0;
if (!surface) {
SDL_InvalidParamError("surface");
@ -1069,8 +1174,9 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
/* Set opaque and backup palette alpha values */
if (set_opaque) {
int i;
palette_saved_alpha = SDL_stack_alloc(Uint8, surface->format->palette->ncolors);
for (i = 0; i < surface->format->palette->ncolors; 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;
}
@ -1097,7 +1203,7 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
/* Restore palette alpha values */
if (palette_saved_alpha) {
int i;
for (i = 0; i < surface->format->palette->ncolors; i++) {
for (i = 0; i < palette_saved_alpha_ncolors; i++) {
surface->format->palette->colors[i].a = palette_saved_alpha[i];
}
SDL_stack_free(palette_saved_alpha);
@ -1275,7 +1381,12 @@ int SDL_ConvertPixels(int width, int height,
void *nonconst_src = (void *) src;
int ret;
/* Check to make sure we are blitting somewhere, so we don't crash */
if (!src) {
return SDL_InvalidParamError("src");
}
if (!src_pitch) {
return SDL_InvalidParamError("src_pitch");
}
if (!dst) {
return SDL_InvalidParamError("dst");
}
@ -1293,8 +1404,7 @@ int SDL_ConvertPixels(int width, int height,
}
#else
if (SDL_ISPIXELFORMAT_FOURCC(src_format) || SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
SDL_SetError("SDL not built with YUV support");
return -1;
return SDL_SetError("SDL not built with YUV support");
}
#endif
@ -1334,6 +1444,68 @@ int SDL_ConvertPixels(int width, int height,
return ret;
}
/*
* Premultiply the alpha on a block of pixels
*
* This is currently only implemented for SDL_PIXELFORMAT_ARGB8888
*
* Here are some ideas for optimization:
* https://github.com/Wizermil/premultiply_alpha/tree/master/premultiply_alpha
* https://developer.arm.com/documentation/101964/0201/Pre-multiplied-alpha-channel-data
*/
int SDL_PremultiplyAlpha(int width, int height,
Uint32 src_format, const void * src, int src_pitch,
Uint32 dst_format, void * dst, int dst_pitch)
{
int c;
Uint32 srcpixel;
Uint32 srcR, srcG, srcB, srcA;
Uint32 dstpixel;
Uint32 dstR, dstG, dstB, dstA;
if (!src) {
return SDL_InvalidParamError("src");
}
if (!src_pitch) {
return SDL_InvalidParamError("src_pitch");
}
if (!dst) {
return SDL_InvalidParamError("dst");
}
if (!dst_pitch) {
return SDL_InvalidParamError("dst_pitch");
}
if (src_format != SDL_PIXELFORMAT_ARGB8888) {
return SDL_InvalidParamError("src_format");
}
if (dst_format != SDL_PIXELFORMAT_ARGB8888) {
return SDL_InvalidParamError("dst_format");
}
while (height--) {
const Uint32 *src_px = (const Uint32 *)src;
Uint32 *dst_px = (Uint32 *)dst;
for (c = width; c; --c) {
/* Component bytes extraction. */
srcpixel = *src_px++;
RGBA_FROM_ARGB8888(srcpixel, srcR, srcG, srcB, srcA);
/* Alpha pre-multiplication of each component. */
dstA = srcA;
dstR = (srcA * srcR) / 255;
dstG = (srcA * srcG) / 255;
dstB = (srcA * srcB) / 255;
/* ARGB8888 pixel recomposition. */
ARGB8888_FROM_RGBA(dstpixel, dstR, dstG, dstB, dstA);
*dst_px++ = dstpixel;
}
src = (const Uint8 *)src + src_pitch;
dst = (Uint8 *)dst + dst_pitch;
}
return 0;
}
/*
* Free a surface created by the above function.
*/

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -83,6 +83,7 @@ struct SDL_Window
int max_w, max_h;
Uint32 flags;
Uint32 last_fullscreen_flags;
Uint32 display_index;
/* Stored position and size for windowed mode */
SDL_Rect windowed;
@ -102,6 +103,8 @@ struct SDL_Window
SDL_bool is_destroying;
SDL_bool is_dropping; /* drag/drop in progress, expecting SDL_SendDropComplete(). */
SDL_Rect mouse_rect;
SDL_WindowShaper *shaper;
SDL_HitTest hit_test;
@ -229,15 +232,20 @@ struct SDL_VideoDevice
void (*RestoreWindow) (_THIS, SDL_Window * window);
void (*SetWindowBordered) (_THIS, SDL_Window * window, SDL_bool bordered);
void (*SetWindowResizable) (_THIS, SDL_Window * window, SDL_bool resizable);
void (*SetWindowAlwaysOnTop) (_THIS, SDL_Window * window, SDL_bool on_top);
void (*SetWindowFullscreen) (_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
int (*SetWindowGammaRamp) (_THIS, SDL_Window * window, const Uint16 * ramp);
int (*GetWindowGammaRamp) (_THIS, SDL_Window * window, Uint16 * ramp);
void (*SetWindowGrab) (_THIS, SDL_Window * window, SDL_bool grabbed);
void* (*GetWindowICCProfile) (_THIS, SDL_Window * window, size_t* size);
void (*SetWindowMouseRect)(_THIS, SDL_Window * window);
void (*SetWindowMouseGrab) (_THIS, SDL_Window * window, SDL_bool grabbed);
void (*SetWindowKeyboardGrab) (_THIS, SDL_Window * window, SDL_bool grabbed);
void (*DestroyWindow) (_THIS, SDL_Window * window);
int (*CreateWindowFramebuffer) (_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch);
int (*UpdateWindowFramebuffer) (_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects);
void (*DestroyWindowFramebuffer) (_THIS, SDL_Window * window);
void (*OnWindowEnter) (_THIS, SDL_Window * window);
int (*FlashWindow) (_THIS, SDL_Window * window, SDL_FlashOperation operation);
/* * * */
/*
@ -288,6 +296,8 @@ struct SDL_VideoDevice
/*
* Event manager functions
*/
int (*WaitEventTimeout) (_THIS, int timeout);
void (*SendWakeupEvent) (_THIS, SDL_Window *window);
void (*PumpEvents) (_THIS);
/* Suspend the screensaver */
@ -297,6 +307,8 @@ struct SDL_VideoDevice
void (*StartTextInput) (_THIS);
void (*StopTextInput) (_THIS);
void (*SetTextInputRect) (_THIS, SDL_Rect *rect);
void (*ClearComposition) (_THIS);
SDL_bool (*IsTextInputShown) (_THIS);
/* Screen keyboard */
SDL_bool (*HasScreenKeyboardSupport) (_THIS);
@ -320,8 +332,11 @@ struct SDL_VideoDevice
/* * * */
/* Data common to all drivers */
SDL_bool checked_texture_framebuffer;
SDL_bool is_dummy;
SDL_bool suspend_screensaver;
SDL_Window *wakeup_window;
SDL_mutex *wakeup_lock; /* Initialized only if WaitEventTimeout/SendWakeupEvent are supported */
int num_displays;
SDL_VideoDisplay *displays;
SDL_Window *windows;
@ -329,6 +344,7 @@ struct SDL_VideoDevice
Uint8 window_magic;
Uint32 next_object_id;
char *clipboard_text;
SDL_bool setting_display_mode;
/* * * */
/* Data used by the GL drivers */
@ -427,6 +443,8 @@ extern VideoBootStrap PND_bootstrap;
extern VideoBootStrap UIKIT_bootstrap;
extern VideoBootStrap Android_bootstrap;
extern VideoBootStrap PSP_bootstrap;
extern VideoBootStrap VITA_bootstrap;
extern VideoBootStrap RISCOS_bootstrap;
extern VideoBootStrap RPI_bootstrap;
extern VideoBootStrap KMSDRM_bootstrap;
extern VideoBootStrap KMSDRM_LEGACY_bootstrap;
@ -445,6 +463,9 @@ extern int SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode);
extern int SDL_AddVideoDisplay(const SDL_VideoDisplay * display, SDL_bool send_event);
extern void SDL_DelVideoDisplay(int index);
extern SDL_bool SDL_AddDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode * mode);
extern void SDL_SetCurrentDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode * mode);
extern void SDL_SetDesktopDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode * mode);
extern void SDL_ResetDisplayModes(int displayIndex);
extern int SDL_GetIndexOfDisplay(SDL_VideoDisplay *display);
extern SDL_VideoDisplay *SDL_GetDisplay(int displayIndex);
extern SDL_VideoDisplay *SDL_GetDisplayForWindow(SDL_Window *window);
@ -458,6 +479,7 @@ extern SDL_bool SDL_HasWindows(void);
extern void SDL_OnWindowShown(SDL_Window * window);
extern void SDL_OnWindowHidden(SDL_Window * window);
extern void SDL_OnWindowMoved(SDL_Window * window);
extern void SDL_OnWindowResized(SDL_Window * window);
extern void SDL_OnWindowMinimized(SDL_Window * window);
extern void SDL_OnWindowRestored(SDL_Window * window);

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,12 +25,10 @@
#include "SDL_stdinc.h"
#if defined(SDL_LOADSO_DISABLED)
#undef SDL_VIDEO_VULKAN
#define SDL_VIDEO_VULKAN 0
#endif
#if SDL_VIDEO_VULKAN
#if SDL_LOADSO_DISABLED || SDL_LOADSO_DUMMY
#error You should not be here.
#endif
#if SDL_VIDEO_DRIVER_ANDROID
#define VK_USE_PLATFORM_ANDROID_KHR

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -23,97 +23,97 @@
#include "SDL_vulkan_internal.h"
#include "SDL_error.h"
/* !!! FIXME: this file doesn't match coding standards for SDL (brace position, etc). */
#if SDL_VIDEO_VULKAN
const char *SDL_Vulkan_GetResultString(VkResult result)
{
switch((int)result)
{
case VK_SUCCESS:
return "VK_SUCCESS";
case VK_NOT_READY:
return "VK_NOT_READY";
case VK_TIMEOUT:
return "VK_TIMEOUT";
case VK_EVENT_SET:
return "VK_EVENT_SET";
case VK_EVENT_RESET:
return "VK_EVENT_RESET";
case VK_INCOMPLETE:
return "VK_INCOMPLETE";
case VK_ERROR_OUT_OF_HOST_MEMORY:
return "VK_ERROR_OUT_OF_HOST_MEMORY";
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
case VK_ERROR_INITIALIZATION_FAILED:
return "VK_ERROR_INITIALIZATION_FAILED";
case VK_ERROR_DEVICE_LOST:
return "VK_ERROR_DEVICE_LOST";
case VK_ERROR_MEMORY_MAP_FAILED:
return "VK_ERROR_MEMORY_MAP_FAILED";
case VK_ERROR_LAYER_NOT_PRESENT:
return "VK_ERROR_LAYER_NOT_PRESENT";
case VK_ERROR_EXTENSION_NOT_PRESENT:
return "VK_ERROR_EXTENSION_NOT_PRESENT";
case VK_ERROR_FEATURE_NOT_PRESENT:
return "VK_ERROR_FEATURE_NOT_PRESENT";
case VK_ERROR_INCOMPATIBLE_DRIVER:
return "VK_ERROR_INCOMPATIBLE_DRIVER";
case VK_ERROR_TOO_MANY_OBJECTS:
return "VK_ERROR_TOO_MANY_OBJECTS";
case VK_ERROR_FORMAT_NOT_SUPPORTED:
return "VK_ERROR_FORMAT_NOT_SUPPORTED";
case VK_ERROR_FRAGMENTED_POOL:
return "VK_ERROR_FRAGMENTED_POOL";
case VK_ERROR_UNKNOWN:
return "VK_ERROR_UNKNOWN";
case VK_ERROR_OUT_OF_POOL_MEMORY:
return "VK_ERROR_OUT_OF_POOL_MEMORY";
case VK_ERROR_INVALID_EXTERNAL_HANDLE:
return "VK_ERROR_INVALID_EXTERNAL_HANDLE";
case VK_ERROR_FRAGMENTATION:
return "VK_ERROR_FRAGMENTATION";
case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS:
return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS";
case VK_ERROR_SURFACE_LOST_KHR:
return "VK_ERROR_SURFACE_LOST_KHR";
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
case VK_SUBOPTIMAL_KHR:
return "VK_SUBOPTIMAL_KHR";
case VK_ERROR_OUT_OF_DATE_KHR:
return "VK_ERROR_OUT_OF_DATE_KHR";
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
case VK_ERROR_VALIDATION_FAILED_EXT:
return "VK_ERROR_VALIDATION_FAILED_EXT";
case VK_ERROR_INVALID_SHADER_NV:
return "VK_ERROR_INVALID_SHADER_NV";
case VK_ERROR_INCOMPATIBLE_VERSION_KHR:
return "VK_ERROR_INCOMPATIBLE_VERSION_KHR";
case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
case VK_ERROR_NOT_PERMITTED_EXT:
return "VK_ERROR_NOT_PERMITTED_EXT";
case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";
case VK_THREAD_IDLE_KHR:
return "VK_THREAD_IDLE_KHR";
case VK_THREAD_DONE_KHR:
return "VK_THREAD_DONE_KHR";
case VK_OPERATION_DEFERRED_KHR:
return "VK_OPERATION_DEFERRED_KHR";
case VK_OPERATION_NOT_DEFERRED_KHR:
return "VK_OPERATION_NOT_DEFERRED_KHR";
case VK_PIPELINE_COMPILE_REQUIRED_EXT:
return "VK_PIPELINE_COMPILE_REQUIRED_EXT";
default:
break;
switch ((int)result) {
case VK_SUCCESS:
return "VK_SUCCESS";
case VK_NOT_READY:
return "VK_NOT_READY";
case VK_TIMEOUT:
return "VK_TIMEOUT";
case VK_EVENT_SET:
return "VK_EVENT_SET";
case VK_EVENT_RESET:
return "VK_EVENT_RESET";
case VK_INCOMPLETE:
return "VK_INCOMPLETE";
case VK_ERROR_OUT_OF_HOST_MEMORY:
return "VK_ERROR_OUT_OF_HOST_MEMORY";
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
case VK_ERROR_INITIALIZATION_FAILED:
return "VK_ERROR_INITIALIZATION_FAILED";
case VK_ERROR_DEVICE_LOST:
return "VK_ERROR_DEVICE_LOST";
case VK_ERROR_MEMORY_MAP_FAILED:
return "VK_ERROR_MEMORY_MAP_FAILED";
case VK_ERROR_LAYER_NOT_PRESENT:
return "VK_ERROR_LAYER_NOT_PRESENT";
case VK_ERROR_EXTENSION_NOT_PRESENT:
return "VK_ERROR_EXTENSION_NOT_PRESENT";
case VK_ERROR_FEATURE_NOT_PRESENT:
return "VK_ERROR_FEATURE_NOT_PRESENT";
case VK_ERROR_INCOMPATIBLE_DRIVER:
return "VK_ERROR_INCOMPATIBLE_DRIVER";
case VK_ERROR_TOO_MANY_OBJECTS:
return "VK_ERROR_TOO_MANY_OBJECTS";
case VK_ERROR_FORMAT_NOT_SUPPORTED:
return "VK_ERROR_FORMAT_NOT_SUPPORTED";
case VK_ERROR_FRAGMENTED_POOL:
return "VK_ERROR_FRAGMENTED_POOL";
case VK_ERROR_UNKNOWN:
return "VK_ERROR_UNKNOWN";
case VK_ERROR_OUT_OF_POOL_MEMORY:
return "VK_ERROR_OUT_OF_POOL_MEMORY";
case VK_ERROR_INVALID_EXTERNAL_HANDLE:
return "VK_ERROR_INVALID_EXTERNAL_HANDLE";
case VK_ERROR_FRAGMENTATION:
return "VK_ERROR_FRAGMENTATION";
case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS:
return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS";
case VK_ERROR_SURFACE_LOST_KHR:
return "VK_ERROR_SURFACE_LOST_KHR";
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
case VK_SUBOPTIMAL_KHR:
return "VK_SUBOPTIMAL_KHR";
case VK_ERROR_OUT_OF_DATE_KHR:
return "VK_ERROR_OUT_OF_DATE_KHR";
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
case VK_ERROR_VALIDATION_FAILED_EXT:
return "VK_ERROR_VALIDATION_FAILED_EXT";
case VK_ERROR_INVALID_SHADER_NV:
return "VK_ERROR_INVALID_SHADER_NV";
#if VK_HEADER_VERSION >= 135 && VK_HEADER_VERSION < 162
case VK_ERROR_INCOMPATIBLE_VERSION_KHR:
return "VK_ERROR_INCOMPATIBLE_VERSION_KHR";
#endif
case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
case VK_ERROR_NOT_PERMITTED_EXT:
return "VK_ERROR_NOT_PERMITTED_EXT";
case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";
case VK_THREAD_IDLE_KHR:
return "VK_THREAD_IDLE_KHR";
case VK_THREAD_DONE_KHR:
return "VK_THREAD_DONE_KHR";
case VK_OPERATION_DEFERRED_KHR:
return "VK_OPERATION_DEFERRED_KHR";
case VK_OPERATION_NOT_DEFERRED_KHR:
return "VK_OPERATION_NOT_DEFERRED_KHR";
case VK_PIPELINE_COMPILE_REQUIRED_EXT:
return "VK_PIPELINE_COMPILE_REQUIRED_EXT";
default:
break;
}
if(result < 0)
if (result < 0) {
return "VK_ERROR_<Unknown>";
}
return "VK_<Unknown>";
}
@ -124,11 +124,9 @@ VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList(
Uint32 count = 0;
VkResult result = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
VkExtensionProperties *retval;
if(result == VK_ERROR_INCOMPATIBLE_DRIVER)
{
/* Avoid the ERR_MAX_STRLEN limit by passing part of the message
* as a string argument.
*/
if (result == VK_ERROR_INCOMPATIBLE_DRIVER) {
/* Avoid the ERR_MAX_STRLEN limit by passing part of the message as a string argument. */
SDL_SetError(
"You probably don't have a working Vulkan driver installed. %s %s %s(%d)",
"Getting Vulkan extensions failed:",
@ -136,9 +134,7 @@ VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList(
SDL_Vulkan_GetResultString(result),
(int)result);
return NULL;
}
else if(result != VK_SUCCESS)
{
} else if (result != VK_SUCCESS) {
SDL_SetError(
"Getting Vulkan extensions failed: vkEnumerateInstanceExtensionProperties returned "
"%s(%d)",
@ -146,22 +142,20 @@ VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList(
(int)result);
return NULL;
}
if(count == 0)
{
if (count == 0) {
retval = SDL_calloc(1, sizeof(VkExtensionProperties)); // so we can return non-null
}
else
{
} else {
retval = SDL_calloc(count, sizeof(VkExtensionProperties));
}
if(!retval)
{
if (!retval) {
SDL_OutOfMemory();
return NULL;
}
result = vkEnumerateInstanceExtensionProperties(NULL, &count, retval);
if(result != VK_SUCCESS)
{
if (result != VK_SUCCESS) {
SDL_SetError(
"Getting Vulkan extensions failed: vkEnumerateInstanceExtensionProperties returned "
"%s(%d)",
@ -186,6 +180,7 @@ SDL_bool SDL_Vulkan_GetInstanceExtensions_Helper(unsigned *userCount,
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];
}
@ -226,55 +221,47 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
const char *chosenDisplayId;
int displayId = 0; /* Counting from physical device 0, display 0 */
if(!vkEnumeratePhysicalDevices ||
if (!vkEnumeratePhysicalDevices ||
!vkGetPhysicalDeviceDisplayPropertiesKHR ||
!vkGetDisplayModePropertiesKHR ||
!vkGetPhysicalDeviceDisplayPlanePropertiesKHR ||
!vkGetDisplayPlaneCapabilitiesKHR ||
!vkGetDisplayPlaneSupportedDisplaysKHR ||
!vkCreateDisplayPlaneSurfaceKHR)
{
SDL_SetError(VK_KHR_DISPLAY_EXTENSION_NAME
" extension is not enabled in the Vulkan instance.");
!vkCreateDisplayPlaneSurfaceKHR) {
SDL_SetError(VK_KHR_DISPLAY_EXTENSION_NAME " extension is not enabled in the Vulkan instance.");
goto error;
}
if ((chosenDisplayId = SDL_getenv("SDL_VULKAN_DISPLAY")) != NULL)
{
if ((chosenDisplayId = SDL_getenv("SDL_VULKAN_DISPLAY")) != NULL) {
displayId = SDL_atoi(chosenDisplayId);
}
/* Enumerate physical devices */
result =
vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, NULL);
if(result != VK_SUCCESS)
{
result = vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, NULL);
if (result != VK_SUCCESS) {
SDL_SetError("Could not enumerate Vulkan physical devices");
goto error;
}
if(physicalDeviceCount == 0)
{
if (physicalDeviceCount == 0) {
SDL_SetError("No Vulkan physical devices");
goto error;
}
physicalDevices = SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
if(!physicalDevices)
{
if (!physicalDevices) {
SDL_OutOfMemory();
goto error;
}
result =
vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices);
if(result != VK_SUCCESS)
{
result = vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices);
if (result != VK_SUCCESS) {
SDL_SetError("Error enumerating physical devices");
goto error;
}
for(physicalDeviceIndex = 0; physicalDeviceIndex < physicalDeviceCount;
physicalDeviceIndex++)
{
VkPhysicalDevice physicalDevice = physicalDevices[physicalDeviceIndex];
for (physicalDeviceIndex = 0; physicalDeviceIndex < physicalDeviceCount; physicalDeviceIndex++) {
VkPhysicalDevice physicalDevice = physicalDevices[physicalDeviceIndex];
uint32_t displayPropertiesCount = 0;
VkDisplayPropertiesKHR *displayProperties = NULL;
uint32_t displayModePropertiesCount = 0;
@ -290,32 +277,27 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
VkDisplayPlaneCapabilitiesKHR planeCaps;
/* Get information about the physical displays */
result =
vkGetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, &displayPropertiesCount, NULL);
if (result != VK_SUCCESS || displayPropertiesCount == 0)
{
result = vkGetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, &displayPropertiesCount, NULL);
if (result != VK_SUCCESS || displayPropertiesCount == 0) {
/* This device has no physical device display properties, move on to next. */
continue;
}
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of display properties for device %u: %u",
physicalDeviceIndex, displayPropertiesCount);
if ( (displayId < 0) || (((uint32_t) displayId) >= displayPropertiesCount) )
{
if (displayId < 0 || (uint32_t) displayId >= displayPropertiesCount) {
/* Display id specified was higher than number of available displays, move to next physical device. */
displayId -= displayPropertiesCount;
continue;
}
displayProperties = SDL_malloc(sizeof(VkDisplayPropertiesKHR) * displayPropertiesCount);
if(!displayProperties)
{
if (!displayProperties) {
SDL_OutOfMemory();
goto error;
}
result =
vkGetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, &displayPropertiesCount, displayProperties);
result = vkGetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, &displayPropertiesCount, displayProperties);
if (result != VK_SUCCESS || displayPropertiesCount == 0) {
SDL_free(displayProperties);
SDL_SetError("Error enumerating physical device displays");
@ -331,8 +313,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
displayProperties = NULL;
/* Get display mode properties for the chosen display */
result =
vkGetDisplayModePropertiesKHR(physicalDevice, display, &displayModePropertiesCount, NULL);
result = vkGetDisplayModePropertiesKHR(physicalDevice, display, &displayModePropertiesCount, NULL);
if (result != VK_SUCCESS || displayModePropertiesCount == 0)
{
SDL_SetError("Error enumerating display modes");
@ -341,14 +322,12 @@ 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)
{
if (!displayModeProperties) {
SDL_OutOfMemory();
goto error;
}
result =
vkGetDisplayModePropertiesKHR(physicalDevice, display, &displayModePropertiesCount, displayModeProperties);
result = vkGetDisplayModePropertiesKHR(physicalDevice, display, &displayModePropertiesCount, displayModeProperties);
if (result != VK_SUCCESS || displayModePropertiesCount == 0) {
SDL_SetError("Error enumerating display modes");
SDL_free(displayModeProperties);
@ -356,18 +335,16 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
}
/* Try to find a display mode that matches the native resolution */
for (i = 0; i < displayModePropertiesCount; ++i)
{
for (i = 0; i < displayModePropertiesCount; ++i) {
if (displayModeProperties[i].parameters.visibleRegion.width == extent.width &&
displayModeProperties[i].parameters.visibleRegion.height == extent.height &&
displayModeProperties[i].parameters.refreshRate > refreshRate)
{
displayModeProperties[i].parameters.refreshRate > refreshRate) {
bestMatchIndex = i;
refreshRate = displayModeProperties[i].parameters.refreshRate;
}
}
if (bestMatchIndex < 0)
{
if (bestMatchIndex < 0) {
SDL_SetError("Found no matching display mode");
SDL_free(displayModeProperties);
goto error;
@ -384,62 +361,53 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
displayModeProperties = NULL;
/* Try to find a plane index that supports our display */
result =
vkGetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, &displayPlanePropertiesCount, NULL);
if (result != VK_SUCCESS || displayPlanePropertiesCount == 0)
{
result = vkGetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, &displayPlanePropertiesCount, NULL);
if (result != VK_SUCCESS || displayPlanePropertiesCount == 0) {
SDL_SetError("Error enumerating display planes");
goto error;
}
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of display planes: %u", displayPlanePropertiesCount);
displayPlaneProperties = SDL_malloc(sizeof(VkDisplayPlanePropertiesKHR) * displayPlanePropertiesCount);
if(!displayPlaneProperties)
{
if (!displayPlaneProperties) {
SDL_OutOfMemory();
goto error;
}
result =
vkGetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, &displayPlanePropertiesCount, displayPlaneProperties);
if (result != VK_SUCCESS || displayPlanePropertiesCount == 0)
{
result = vkGetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, &displayPlanePropertiesCount, displayPlaneProperties);
if (result != VK_SUCCESS || displayPlanePropertiesCount == 0) {
SDL_SetError("Error enumerating display plane properties");
SDL_free(displayPlaneProperties);
goto error;
}
for (i = 0; i < displayPlanePropertiesCount; ++i)
{
for (i = 0; i < displayPlanePropertiesCount; ++i) {
uint32_t planeSupportedDisplaysCount = 0;
VkDisplayKHR *planeSupportedDisplays = NULL;
uint32_t j;
/* Check if plane is attached to a display, if not, continue. */
if (displayPlaneProperties[i].currentDisplay == VK_NULL_HANDLE)
if (displayPlaneProperties[i].currentDisplay == VK_NULL_HANDLE) {
continue;
}
/* Check supported displays for this plane. */
result =
vkGetDisplayPlaneSupportedDisplaysKHR(physicalDevice, i, &planeSupportedDisplaysCount, NULL);
if (result != VK_SUCCESS || planeSupportedDisplaysCount == 0)
{
result = vkGetDisplayPlaneSupportedDisplaysKHR(physicalDevice, i, &planeSupportedDisplaysCount, NULL);
if (result != VK_SUCCESS || planeSupportedDisplaysCount == 0) {
continue; /* No supported displays, on to next plane. */
}
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)
{
if (!planeSupportedDisplays) {
SDL_free(displayPlaneProperties);
SDL_OutOfMemory();
goto error;
}
result =
vkGetDisplayPlaneSupportedDisplaysKHR(physicalDevice, i, &planeSupportedDisplaysCount, planeSupportedDisplays);
if (result != VK_SUCCESS || planeSupportedDisplaysCount == 0)
{
result = vkGetDisplayPlaneSupportedDisplaysKHR(physicalDevice, i, &planeSupportedDisplaysCount, planeSupportedDisplays);
if (result != VK_SUCCESS || planeSupportedDisplaysCount == 0) {
SDL_SetError("Error enumerating supported displays, or no supported displays");
SDL_free(planeSupportedDisplays);
SDL_free(displayPlaneProperties);
@ -447,20 +415,19 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
}
for (j = 0; j < planeSupportedDisplaysCount && planeSupportedDisplays[j] != display; ++j)
;
{
}
SDL_free(planeSupportedDisplays);
planeSupportedDisplays = NULL;
if (j == planeSupportedDisplaysCount)
{
if (j == planeSupportedDisplaysCount) {
/* This display is not supported for this plane, move on. */
continue;
}
result = vkGetDisplayPlaneCapabilitiesKHR(physicalDevice, createInfo.displayMode, i, &planeCaps);
if (result != VK_SUCCESS)
{
if (result != VK_SUCCESS) {
SDL_SetError("Error getting display plane capabilities");
SDL_free(displayPlaneProperties);
goto error;
@ -468,8 +435,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
/* Check if plane fulfills extent requirements. */
if (extent.width >= planeCaps.minDstExtent.width && extent.height >= planeCaps.minDstExtent.height &&
extent.width <= planeCaps.maxDstExtent.width && extent.height <= planeCaps.maxDstExtent.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,
planeCaps.minDstExtent.width, planeCaps.minDstExtent.height,
@ -479,8 +445,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
}
}
if (planeIndex < 0)
{
if (planeIndex < 0) {
SDL_SetError("No plane supports the selected resolution");
SDL_free(displayPlaneProperties);
goto error;
@ -509,8 +474,7 @@ SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
SDL_free(physicalDevices);
physicalDevices = NULL;
if (physicalDeviceIndex == physicalDeviceCount)
{
if (physicalDeviceIndex == physicalDeviceCount) {
SDL_SetError("No usable displays found or requested display out of range");
return SDL_FALSE;
}
@ -519,16 +483,14 @@ 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);
if(result != VK_SUCCESS)
{
SDL_SetError("vkCreateDisplayPlaneSurfaceKHR failed: %s",
SDL_Vulkan_GetResultString(result));
result = vkCreateDisplayPlaneSurfaceKHR(instance, &createInfo, NULL, surface);
if (result != VK_SUCCESS) {
SDL_SetError("vkCreateDisplayPlaneSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result));
return SDL_FALSE;
}
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Created surface");
return SDL_TRUE;
error:
SDL_free(physicalDevices);
return SDL_FALSE;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -1839,7 +1839,7 @@ SDL_ConvertPixels_YUV_to_YUV(int width, int height,
return SDL_SetError("SDL_ConvertPixels_YUV_to_YUV: Unsupported YUV conversion: %s -> %s", SDL_GetPixelFormatName(src_format), SDL_GetPixelFormatName(dst_format));
}
#else
return SDL_SetError("SDL not built with YUV support");
return SDL_SetError("SDL not built with YUV support");
#endif
}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -48,6 +48,18 @@ static void openslES_ResumeDevices(void) {}
static void openslES_PauseDevices(void) {}
#endif
#if !SDL_AUDIO_DISABLED && SDL_AUDIO_DRIVER_AAUDIO
extern void aaudio_ResumeDevices(void);
extern void aaudio_PauseDevices(void);
SDL_bool aaudio_DetectBrokenPlayState( void );
#else
static void aaudio_ResumeDevices(void) {}
static void aaudio_PauseDevices(void) {}
static SDL_bool aaudio_DetectBrokenPlayState( void ) { return SDL_FALSE; }
#endif
/* Number of 'type' events in the event queue */
static int
SDL_NumberOfEvents(Uint32 type)
@ -55,6 +67,7 @@ SDL_NumberOfEvents(Uint32 type)
return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type);
}
#if SDL_VIDEO_OPENGL_EGL
static void
android_egl_context_restore(SDL_Window *window)
{
@ -84,7 +97,7 @@ android_egl_context_backup(SDL_Window *window)
data->backup_done = 1;
}
}
#endif
/*
* Android_ResumeSem and Android_PauseSem are signaled from Java_org_libsdl_app_SDLActivity_nativePause and Java_org_libsdl_app_SDLActivity_nativeResume
@ -101,15 +114,18 @@ Android_PumpEvents_Blocking(_THIS)
if (videodata->isPaused) {
SDL_bool isContextExternal = SDL_IsVideoContextExternal();
#if SDL_VIDEO_OPENGL_EGL
/* Make sure this is the last thing we do before pausing */
if (!isContextExternal) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_backup(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
}
#endif
ANDROIDAUDIO_PauseDevices();
openslES_PauseDevices();
aaudio_PauseDevices();
if (SDL_SemWait(Android_ResumeSem) == 0) {
@ -122,13 +138,16 @@ Android_PumpEvents_Blocking(_THIS)
ANDROIDAUDIO_ResumeDevices();
openslES_ResumeDevices();
aaudio_ResumeDevices();
/* Restore the GL Context from here, as this operation is thread dependent */
#if SDL_VIDEO_OPENGL_EGL
if (!isContextExternal && !SDL_HasEvent(SDL_QUIT)) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_restore(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
}
#endif
/* Make sure SW Keyboard is restored when an app becomes foreground */
if (SDL_IsTextInputActive()) {
@ -156,6 +175,11 @@ Android_PumpEvents_Blocking(_THIS)
}
}
}
if ( aaudio_DetectBrokenPlayState() ) {
aaudio_PauseDevices();
aaudio_ResumeDevices();
}
}
void
@ -169,15 +193,18 @@ Android_PumpEvents_NonBlocking(_THIS)
SDL_bool isContextExternal = SDL_IsVideoContextExternal();
if (backup_context) {
#if SDL_VIDEO_OPENGL_EGL
if (!isContextExternal) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_backup(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
}
#endif
if (videodata->pauseAudio) {
ANDROIDAUDIO_PauseDevices();
openslES_PauseDevices();
aaudio_PauseDevices();
}
backup_context = 0;
@ -196,14 +223,17 @@ Android_PumpEvents_NonBlocking(_THIS)
if (videodata->pauseAudio) {
ANDROIDAUDIO_ResumeDevices();
openslES_ResumeDevices();
aaudio_ResumeDevices();
}
#if SDL_VIDEO_OPENGL_EGL
/* Restore the GL Context from here, as this operation is thread dependent */
if (!isContextExternal && !SDL_HasEvent(SDL_QUIT)) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_restore(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
}
#endif
/* Make sure SW Keyboard is restored when an app becomes foreground */
if (SDL_IsTextInputActive()) {
@ -232,6 +262,11 @@ Android_PumpEvents_NonBlocking(_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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -20,7 +20,7 @@
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_ANDROID
#if SDL_VIDEO_DRIVER_ANDROID && SDL_VIDEO_OPENGL_EGL
/* Android SDL video driver implementation */
@ -69,7 +69,7 @@ Android_GLES_SwapWindow(_THIS, SDL_Window * window)
/* The following two calls existed in the original Java code
* If you happen to have a device that's affected by their removal,
* please report to Bugzilla. -- Gabriel
* please report to our bug tracker. -- Gabriel
*/
/*_this->egl_data->eglWaitNative(EGL_CORE_NATIVE_ENGINE);

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -113,6 +113,10 @@ Android_CreateSystemCursor(SDL_SystemCursor id)
static void
Android_FreeCursor(SDL_Cursor * cursor)
{
SDL_AndroidCursorData *data = (SDL_AndroidCursorData*) cursor->driverdata;
if (data->custom_cursor != 0) {
Android_JNI_DestroyCustomCursor(data->custom_cursor);
}
SDL_free(cursor->driverdata);
SDL_free(cursor);
}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -64,7 +64,7 @@ int Android_SurfaceWidth = 0;
int Android_SurfaceHeight = 0;
static int Android_DeviceWidth = 0;
static int Android_DeviceHeight = 0;
static Uint32 Android_ScreenFormat = SDL_PIXELFORMAT_UNKNOWN;
static Uint32 Android_ScreenFormat = SDL_PIXELFORMAT_RGB565; /* Default SurfaceView format, in case this is queried before being filled */
static int Android_ScreenRate = 0;
SDL_sem *Android_PauseSem = NULL;
SDL_sem *Android_ResumeSem = NULL;
@ -128,6 +128,7 @@ Android_CreateDevice(int devindex)
device->free = Android_DeleteDevice;
/* GL pointers */
#if SDL_VIDEO_OPENGL_EGL
device->GL_LoadLibrary = Android_GLES_LoadLibrary;
device->GL_GetProcAddress = Android_GLES_GetProcAddress;
device->GL_UnloadLibrary = Android_GLES_UnloadLibrary;
@ -137,6 +138,7 @@ Android_CreateDevice(int devindex)
device->GL_GetSwapInterval = Android_GLES_GetSwapInterval;
device->GL_SwapWindow = Android_GLES_SwapWindow;
device->GL_DeleteContext = Android_GLES_DeleteContext;
#endif
#if SDL_VIDEO_VULKAN
device->Vulkan_LoadLibrary = Android_Vulkan_LoadLibrary;
@ -194,7 +196,7 @@ Android_VideoInit(_THIS)
return -1;
}
display = SDL_GetDisplay(display_index);
display->orientation = Android_JNI_GetDisplayOrientation();
display->orientation = Android_JNI_GetDisplayOrientation();
SDL_AddDisplayMode(&_this->displays[0], &mode);
@ -222,16 +224,54 @@ Android_GetDisplayDPI(_THIS, SDL_VideoDisplay *display, float *ddpi, float *hdpi
}
void
Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, Uint32 format, float rate)
Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, float rate)
{
Android_SurfaceWidth = surfaceWidth;
Android_SurfaceHeight = surfaceHeight;
Android_DeviceWidth = deviceWidth;
Android_DeviceHeight = deviceHeight;
Android_ScreenFormat = format;
Android_ScreenRate = (int)rate;
}
static
Uint32 format_to_pixelFormat(int format) {
Uint32 pf;
if (format == AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM) { /* 1 */
pf = SDL_PIXELFORMAT_RGBA8888;
} else if (format == AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM) { /* 2 */
pf = SDL_PIXELFORMAT_RGBX8888;
} else if (format == AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM) { /* 3 */
pf = SDL_PIXELFORMAT_RGB24;
} else if (format == AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM) { /* 4*/
pf = SDL_PIXELFORMAT_RGB565;
} else if (format == 5) {
pf = SDL_PIXELFORMAT_BGRA8888;
} else if (format == 6) {
pf = SDL_PIXELFORMAT_RGBA5551;
} else if (format == 7) {
pf = SDL_PIXELFORMAT_RGBA4444;
} else {
pf = SDL_PIXELFORMAT_UNKNOWN;
}
return pf;
}
void
Android_SetFormat(int format_wanted, int format_got)
{
Uint32 pf_wanted;
Uint32 pf_got;
pf_wanted = format_to_pixelFormat(format_wanted);
pf_got = format_to_pixelFormat(format_got);
Android_ScreenFormat = pf_got;
SDL_Log("pixel format wanted %s (%d), got %s (%d)",
SDL_GetPixelFormatName(pf_wanted), format_wanted,
SDL_GetPixelFormatName(pf_got), format_got);
}
void Android_SendResize(SDL_Window *window)
{
/*

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -28,7 +28,8 @@
#include "../SDL_sysvideo.h"
/* Called by the JNI layer when the screen changes size or format */
extern void Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, Uint32 format, float rate);
extern void Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, float rate);
extern void Android_SetFormat(int format_wanted, int format_got);
extern void Android_SendResize(SDL_Window *window);
/* Private display data */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -81,6 +81,7 @@ Android_CreateWindow(_THIS, SDL_Window * window)
/* Do not create EGLSurface for Vulkan window since it will then make the window
incompatible with vkCreateAndroidSurfaceKHR */
#if SDL_VIDEO_OPENGL_EGL
if ((window->flags & SDL_WINDOW_OPENGL) != 0) {
data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window);
@ -91,6 +92,7 @@ Android_CreateWindow(_THIS, SDL_Window * window)
goto endfunction;
}
}
#endif
window->driverdata = data;
Android_Window = window;
@ -175,9 +177,13 @@ Android_DestroyWindow(_THIS, SDL_Window *window)
if (window->driverdata) {
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
#if SDL_VIDEO_OPENGL_EGL
if (data->egl_surface != EGL_NO_SURFACE) {
SDL_EGL_DestroySurface(_this, data->egl_surface);
}
#endif
if (data->native_window) {
ANativeWindow_release(data->native_window);
}
@ -198,7 +204,11 @@ Android_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
info->version.minor == SDL_MINOR_VERSION) {
info->subsystem = SDL_SYSWM_ANDROID;
info->info.android.window = data->native_window;
#if SDL_VIDEO_OPENGL_EGL
info->info.android.surface = data->egl_surface;
#endif
return SDL_TRUE;
} else {
SDL_SetError("Application not compiled with SDL %d.%d",

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,8 +37,10 @@ extern SDL_Window *Android_Window;
typedef struct
{
#if SDL_VIDEO_OPENGL_EGL
EGLSurface egl_surface;
EGLContext egl_context; /* We use this to preserve the context when losing focus */
#endif
SDL_bool backup_done;
ANativeWindow *native_window;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -32,10 +32,14 @@ Cocoa_SetClipboardText(_THIS, const char *text)
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
NSPasteboard *pasteboard;
NSString *format = NSPasteboardTypeString;
NSString *nsstr = [NSString stringWithUTF8String:text];
if (nsstr == nil) {
return SDL_SetError("Couldn't create NSString; is your string data in UTF-8 format?");
}
pasteboard = [NSPasteboard generalPasteboard];
data->clipboard_count = [pasteboard declareTypes:[NSArray arrayWithObject:format] owner:nil];
[pasteboard setString:[NSString stringWithUTF8String:text] forType:format];
[pasteboard setString:nsstr forType:format];
return 0;
}}
@ -61,7 +65,7 @@ Cocoa_GetClipboardText(_THIS)
} else {
utf8 = [string UTF8String];
}
text = SDL_strdup(utf8);
text = SDL_strdup(utf8 ? utf8 : "");
} else {
text = SDL_strdup("");
}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,6 +25,8 @@
extern void Cocoa_RegisterApp(void);
extern void Cocoa_PumpEvents(_THIS);
extern int Cocoa_WaitEventTimeout(_THIS, int timeout);
extern void Cocoa_SendWakeupEvent(_THIS, SDL_Window *window);
extern void Cocoa_SuspendScreenSaver(_THIS);
#endif /* SDL_cocoaevents_h_ */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,6 +35,24 @@
#ifndef NSAppKitVersionNumber10_8
#define NSAppKitVersionNumber10_8 1187
#endif
#ifndef MAC_OS_X_VERSION_10_12
#define NSEventTypeApplicationDefined NSApplicationDefined
#endif
static SDL_Window *FindSDLWindowForNSWindow(NSWindow *win)
{
SDL_Window *sdlwindow = NULL;
SDL_VideoDevice *device = SDL_GetVideoDevice();
if (device && device->windows) {
for (sdlwindow = device->windows; sdlwindow; sdlwindow = sdlwindow->next) {
NSWindow *nswindow = ((SDL_WindowData *) sdlwindow->driverdata)->nswindow;
if (win == nswindow)
return sdlwindow;
}
}
return sdlwindow;
}
@interface SDLApplication : NSApplication
@ -158,6 +176,13 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
[center removeObserver:self name:NSApplicationDidBecomeActiveNotification object:nil];
[center removeObserver:self name:NSCurrentLocaleDidChangeNotification object:nil];
/* Remove our URL event handler only if we set it */
if ([NSApp delegate] == self) {
[[NSAppleEventManager sharedAppleEventManager]
removeEventHandlerForEventClass:kInternetEventClass
andEventID:kAEGetURL];
}
[super dealloc];
}
@ -169,6 +194,10 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
return;
}
/* Don't do anything if this was not an SDL window that was closed */
if (FindSDLWindowForNSWindow(win) == NULL)
return;
/* HACK: Make the next window in the z-order key when the key window is
* closed. The custom event loop and/or windowing code we have seems to
* prevent the normal behavior: https://bugzilla.libsdl.org/show_bug.cgi?id=1825
@ -213,6 +242,13 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
return;
}
/* Don't do anything if the application already has a key window
* that is not an SDL window.
*/
if ([NSApp keyWindow] && FindSDLWindowForNSWindow([NSApp keyWindow]) == NULL) {
return;
}
SDL_VideoDevice *device = SDL_GetVideoDevice();
if (device && device->windows) {
SDL_Window *window = device->windows;
@ -262,12 +298,6 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
[NSApp activateIgnoringOtherApps:YES];
}
[[NSAppleEventManager sharedAppleEventManager]
setEventHandler:self
andSelector:@selector(handleURLEvent:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
/* If we call this before NSApp activation, macOS might print a complaint
* about ApplePersistenceIgnoreState. */
[SDLApplication registerUserDefaults];
@ -469,6 +499,15 @@ Cocoa_RegisterApp(void)
* termination into SDL_Quit, and we can't handle application:openFile:
*/
if (![NSApp delegate]) {
/* Only register the URL event handler if we are being set as the
* app delegate to avoid replacing any existing event handler.
*/
[[NSAppleEventManager sharedAppleEventManager]
setEventHandler:appDelegate
andSelector:@selector(handleURLEvent:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
[(NSApplication *)NSApp setDelegate:appDelegate];
} else {
appDelegate->seenFirstActivate = YES;
@ -476,9 +515,8 @@ Cocoa_RegisterApp(void)
}
}}
void
Cocoa_PumpEvents(_THIS)
{ @autoreleasepool
int
Cocoa_PumpEventsUntilDate(_THIS, NSDate *expiration, bool accumulate)
{
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
/* Update activity every 30 seconds to prevent screensaver */
@ -494,9 +532,9 @@ Cocoa_PumpEvents(_THIS)
#endif
for ( ; ; ) {
NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES ];
NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:expiration inMode:NSDefaultRunLoopMode dequeue:YES ];
if ( event == nil ) {
break;
return 0;
}
if (!s_bShouldHandleEventsInSDLApplication) {
@ -505,7 +543,52 @@ Cocoa_PumpEvents(_THIS)
// Pass events down to SDLApplication to be handled in sendEvent:
[NSApp sendEvent:event];
if ( !accumulate) {
break;
}
}
return 1;
}
int
Cocoa_WaitEventTimeout(_THIS, int timeout)
{ @autoreleasepool
{
if (timeout > 0) {
NSDate *limitDate = [NSDate dateWithTimeIntervalSinceNow: (double) timeout / 1000.0];
return Cocoa_PumpEventsUntilDate(_this, limitDate, false);
} else if (timeout == 0) {
return Cocoa_PumpEventsUntilDate(_this, [NSDate distantPast], false);
} else {
while (Cocoa_PumpEventsUntilDate(_this, [NSDate distantFuture], false) == 0) {
}
}
return 1;
}}
void
Cocoa_PumpEvents(_THIS)
{ @autoreleasepool
{
Cocoa_PumpEventsUntilDate(_this, [NSDate distantPast], true);
}}
void Cocoa_SendWakeupEvent(_THIS, SDL_Window *window)
{ @autoreleasepool
{
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
NSEvent* event = [NSEvent otherEventWithType: NSEventTypeApplicationDefined
location: NSMakePoint(0,0)
modifierFlags: 0
timestamp: 0.0
windowNumber: nswindow.windowNumber
context: nil
subtype: 0
data1: 0
data2: 0];
[NSApp postEvent: event atStart: YES];
}}
void

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,6 +31,8 @@ extern void Cocoa_StartTextInput(_THIS);
extern void Cocoa_StopTextInput(_THIS);
extern void Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect);
extern void Cocoa_SetWindowKeyboardGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
#endif /* SDL_cocoakeyboard_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -602,6 +602,23 @@ Cocoa_QuitKeyboard(_THIS)
{
}
typedef int CGSConnection;
typedef enum {
CGSGlobalHotKeyEnable = 0,
CGSGlobalHotKeyDisable = 1,
} CGSGlobalHotKeyOperatingMode;
extern CGSConnection _CGSDefaultConnection(void);
extern CGError CGSSetGlobalHotKeyOperatingMode(CGSConnection connection, CGSGlobalHotKeyOperatingMode mode);
void
Cocoa_SetWindowKeyboardGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
{
#if SDL_MAC_NO_SANDBOX
CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), grabbed ? CGSGlobalHotKeyDisable : CGSGlobalHotKeyEnable);
#endif
}
#endif /* SDL_VIDEO_DRIVER_COCOA */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,10 +89,8 @@
@end
/* Display a Cocoa message box */
int
Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
{ @autoreleasepool
static void
Cocoa_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid, int *returnValue)
{
Cocoa_RegisterApp();
@ -133,11 +131,8 @@ Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
SDLMessageBoxPresenter* presenter = [[[SDLMessageBoxPresenter alloc] initWithParentWindow:messageboxdata->window] autorelease];
[presenter performSelectorOnMainThread:@selector(showAlert:)
withObject:alert
waitUntilDone:YES];
[presenter showAlert:alert];
int returnValue = 0;
NSInteger clicked = presenter->clicked;
if (clicked >= NSAlertFirstButtonReturn) {
clicked -= NSAlertFirstButtonReturn;
@ -145,10 +140,24 @@ Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
clicked = messageboxdata->numbuttons - 1 - clicked;
}
*buttonid = buttons[clicked].buttonid;
*returnValue = 0;
} else {
returnValue = SDL_SetError("Did not get a valid `clicked button' id: %ld", (long)clicked);
*returnValue = SDL_SetError("Did not get a valid `clicked button' id: %ld", (long)clicked);
}
}
/* Display a Cocoa message box */
int
Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
{ @autoreleasepool
{
__block int returnValue = 0;
if ([NSThread isMainThread]) {
Cocoa_ShowMessageBoxImpl(messageboxdata, buttonid, &returnValue);
} else {
dispatch_sync(dispatch_get_main_queue(), ^{ Cocoa_ShowMessageBoxImpl(messageboxdata, buttonid, &returnValue); });
}
return returnValue;
}}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -39,7 +39,6 @@
#import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
#define METALVIEW_TAG 255
@interface SDL_cocoametalview : NSView

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,6 +31,8 @@
#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL)
#include "SDL_events.h"
#include "SDL_syswm.h"
static int SDLCALL
SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
@ -103,7 +105,7 @@ SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
- (NSInteger)tag
{
return METALVIEW_TAG;
return SDL_METALVIEW_TAG;
}
- (void)updateDrawableSize
@ -172,8 +174,8 @@ void
Cocoa_Metal_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
{ @autoreleasepool {
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
NSView *view = data->nswindow.contentView;
SDL_cocoametalview* metalview = [view viewWithTag:METALVIEW_TAG];
NSView *contentView = data->sdlContentView;
SDL_cocoametalview* metalview = [contentView viewWithTag:SDL_METALVIEW_TAG];
if (metalview) {
CAMetalLayer *layer = (CAMetalLayer*)metalview.layer;
SDL_assert(layer != NULL);
@ -184,7 +186,21 @@ Cocoa_Metal_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
*h = layer.drawableSize.height;
}
} else {
SDL_GetWindowSize(window, w, h);
/* Fall back to the viewport size. */
NSRect viewport = [contentView bounds];
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
/* This gives us the correct viewport for a Retina-enabled view, only
* supported on 10.7+. */
if ([contentView respondsToSelector:@selector(convertRectToBacking:)]) {
viewport = [contentView convertRectToBacking:viewport];
}
}
if (w) {
*w = viewport.size.width;
}
if (h) {
*h = viewport.size.height;
}
}
}}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -40,6 +40,9 @@
#ifndef MAC_OS_X_VERSION_10_13
#define NSAppKitVersionNumber10_12 1504
#endif
#if (IOGRAPHICSTYPES_REV < 40)
#define kDisplayModeNativeFlag 0x02000000
#endif
static void
@ -162,7 +165,7 @@ GetDisplayModePixelFormat(CGDisplayModeRef vidmode)
}
static SDL_bool
GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CFArrayRef modelist, CVDisplayLinkRef link, SDL_DisplayMode *mode)
GetDisplayMode(_THIS, CGDisplayModeRef vidmode, SDL_bool vidmodeCurrent, CFArrayRef modelist, CVDisplayLinkRef link, SDL_DisplayMode *mode)
{
SDL_DisplayModeData *data;
bool usableForGUI = CGDisplayModeIsUsableForDesktopGUI(vidmode);
@ -178,7 +181,9 @@ GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CFArrayRef modelist, CVDisplayLi
return SDL_FALSE;
}
if (!HasValidDisplayModeFlags(vidmode)) {
/* Don't fail the current mode based on flags because this could prevent Cocoa_InitModes from
* succeeding if the current mode lacks certain flags (esp kDisplayModeSafeFlag). */
if (!vidmodeCurrent && !HasValidDisplayModeFlags(vidmode)) {
return SDL_FALSE;
}
@ -375,7 +380,7 @@ Cocoa_InitModes(_THIS)
SDL_zero(display);
/* this returns a stddup'ed string */
display.name = (char *)Cocoa_GetDisplayName(displays[i]);
if (!GetDisplayMode(_this, moderef, NULL, link, &mode)) {
if (!GetDisplayMode(_this, moderef, SDL_TRUE, NULL, link, &mode)) {
CVDisplayLinkRelease(link);
CGDisplayModeRelease(moderef);
SDL_free(display.name);
@ -452,28 +457,68 @@ Cocoa_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdp
/* we need the backingScaleFactor for Retina displays, which is only exposed through NSScreen, not CGDisplay, afaik, so find our screen... */
CGFloat scaleFactor = 1.0f;
NSArray *screens = [NSScreen screens];
NSSize displayNativeSize;
displayNativeSize.width = (int) CGDisplayPixelsWide(data->display);
displayNativeSize.height = (int) CGDisplayPixelsHigh(data->display);
for (NSScreen *screen in screens) {
const CGDirectDisplayID dpyid = (const CGDirectDisplayID ) [[[screen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
if (dpyid == data->display) {
if ([screen respondsToSelector:@selector(backingScaleFactor)]) { // Mac OS X 10.7 and later
#ifdef MAC_OS_X_VERSION_10_8
/* Neither CGDisplayScreenSize(description's NSScreenNumber) nor [NSScreen backingScaleFactor] can calculate the correct dpi in macOS. E.g. backingScaleFactor is always 2 in all display modes for rMBP 16" */
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_7) {
CFStringRef dmKeys[1] = { kCGDisplayShowDuplicateLowResolutionModes };
CFBooleanRef dmValues[1] = { kCFBooleanTrue };
CFDictionaryRef dmOptions = CFDictionaryCreate(kCFAllocatorDefault, (const void**) dmKeys, (const void**) dmValues, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
CFArrayRef allDisplayModes = CGDisplayCopyAllDisplayModes(dpyid, dmOptions);
CFIndex n = CFArrayGetCount(allDisplayModes);
for(CFIndex i = 0; i < n; ++i) {
CGDisplayModeRef m = (CGDisplayModeRef)CFArrayGetValueAtIndex(allDisplayModes, i);
CGFloat width = CGDisplayModeGetPixelWidth(m);
CGFloat height = CGDisplayModeGetPixelHeight(m);
CGFloat HiDPIWidth = CGDisplayModeGetWidth(m);
//Only check 1x mode
if(width == HiDPIWidth) {
if (CGDisplayModeGetIOFlags(m) & kDisplayModeNativeFlag) {
displayNativeSize.width = width;
displayNativeSize.height = height;
break;
}
//Get the largest size even if kDisplayModeNativeFlag is not present e.g. iMac 27-Inch with 5K Retina
if(width > displayNativeSize.width) {
displayNativeSize.width = width;
displayNativeSize.height = height;
}
}
}
CFRelease(allDisplayModes);
CFRelease(dmOptions);
} else
#endif
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) {
// fallback for 10.7
scaleFactor = [screen backingScaleFactor];
displayNativeSize.width = displayNativeSize.width * scaleFactor;
displayNativeSize.height = displayNativeSize.height * scaleFactor;
break;
}
}
}
const CGSize displaySize = CGDisplayScreenSize(data->display);
const int pixelWidth = (int) CGDisplayPixelsWide(data->display);
const int pixelHeight = (int) CGDisplayPixelsHigh(data->display);
const int pixelWidth = displayNativeSize.width;
const int pixelHeight = displayNativeSize.height;
if (ddpi) {
*ddpi = (SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH)) * scaleFactor;
*ddpi = (SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH));
}
if (hdpi) {
*hdpi = (pixelWidth * MM_IN_INCH / displaySize.width) * scaleFactor;
*hdpi = (pixelWidth * MM_IN_INCH / displaySize.width);
}
if (vdpi) {
*vdpi = (pixelHeight * MM_IN_INCH / displaySize.height) * scaleFactor;
*vdpi = (pixelHeight * MM_IN_INCH / displaySize.height);
}
return 0;
@ -499,7 +544,7 @@ Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
* sure there are no duplicates so it's safe to always add the desktop mode
* even in cases where it is in the CopyAllDisplayModes list.
*/
if (desktopmoderef && GetDisplayMode(_this, desktopmoderef, NULL, link, &desktopmode)) {
if (desktopmoderef && GetDisplayMode(_this, desktopmoderef, SDL_TRUE, NULL, link, &desktopmode)) {
if (!SDL_AddDisplayMode(display, &desktopmode)) {
CFRelease(((SDL_DisplayModeData*)desktopmode.driverdata)->modes);
SDL_free(desktopmode.driverdata);
@ -546,7 +591,7 @@ Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
CGDisplayModeRef moderef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
SDL_DisplayMode mode;
if (GetDisplayMode(_this, moderef, modes, link, &mode)) {
if (GetDisplayMode(_this, moderef, SDL_FALSE, modes, link, &mode)) {
if (!SDL_AddDisplayMode(display, &mode)) {
CFRelease(((SDL_DisplayModeData*)mode.driverdata)->modes);
SDL_free(mode.driverdata);

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -40,7 +40,6 @@ typedef struct {
/* What location we last saw the cursor move to. */
CGFloat lastMoveX;
CGFloat lastMoveY;
void *tapdata;
} SDL_MouseData;
@interface NSCursor (InvisibleCursor)

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,7 +24,6 @@
#include "SDL_events.h"
#include "SDL_cocoamouse.h"
#include "SDL_cocoamousetap.h"
#include "SDL_cocoavideo.h"
#include "../../events/SDL_mouse_c.h"
@ -216,8 +215,8 @@ Cocoa_WarpMouseGlobal(int x, int y)
SDL_Mouse *mouse = SDL_GetMouse();
if (mouse->focus) {
SDL_WindowData *data = (SDL_WindowData *) mouse->focus->driverdata;
if ([data->listener isMoving]) {
DLog("Postponing warp, window being moved.");
if ([data->listener isMovingOrFocusClickPending]) {
DLog("Postponing warp, window being moved or focused.");
[data->listener setPendingMoveX:x Y:y];
return 0;
}
@ -254,7 +253,7 @@ Cocoa_WarpMouseGlobal(int x, int y)
static void
Cocoa_WarpMouse(SDL_Window * window, int x, int y)
{
Cocoa_WarpMouseGlobal(x + window->x, y + window->y);
Cocoa_WarpMouseGlobal(window->x + x, window->y + y);
}
static int
@ -263,16 +262,16 @@ Cocoa_SetRelativeMouseMode(SDL_bool enabled)
/* We will re-apply the relative mode when the window gets focus, if it
* doesn't have focus right now.
*/
SDL_Window *window = SDL_GetMouseFocus();
SDL_Window *window = SDL_GetKeyboardFocus();
if (!window) {
return 0;
return 0;
}
/* We will re-apply the relative mode when the window finishes being moved,
* if it is being moved right now.
*/
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if ([data->listener isMoving]) {
if ([data->listener isMovingOrFocusClickPending]) {
return 0;
}
@ -348,14 +347,40 @@ Cocoa_InitMouse(_THIS)
SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
Cocoa_InitMouseEventTap(driverdata);
const NSPoint location = [NSEvent mouseLocation];
driverdata->lastMoveX = location.x;
driverdata->lastMoveY = location.y;
return 0;
}
static void
Cocoa_HandleTitleButtonEvent(_THIS, NSEvent *event)
{
SDL_Window *window;
NSWindow *nswindow = [event window];
for (window = _this->windows; window; window = window->next) {
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
if (data && data->nswindow == nswindow) {
switch ([event type]) {
case NSEventTypeLeftMouseDown:
case NSEventTypeRightMouseDown:
case NSEventTypeOtherMouseDown:
[data->listener setFocusClickPending:[event buttonNumber]];
break;
case NSEventTypeLeftMouseUp:
case NSEventTypeRightMouseUp:
case NSEventTypeOtherMouseUp:
[data->listener clearFocusClickPending:[event buttonNumber]];
break;
default:
break;
}
break;
}
}
}
void
Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
{
@ -366,6 +391,21 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
case NSEventTypeOtherMouseDragged:
break;
case NSEventTypeLeftMouseDown:
case NSEventTypeLeftMouseUp:
case NSEventTypeRightMouseDown:
case NSEventTypeRightMouseUp:
case NSEventTypeOtherMouseDown:
case NSEventTypeOtherMouseUp:
if ([event window]) {
NSRect windowRect = [[[event window] contentView] frame];
if (!NSMouseInRect([event locationInWindow], windowRect, NO)) {
Cocoa_HandleTitleButtonEvent(_this, event);
return;
}
}
return;
default:
/* Ignore any other events. */
return;
@ -433,15 +473,19 @@ Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
}
}
if (x > 0) {
x = SDL_ceil(x);
} else if (x < 0) {
x = SDL_floor(x);
}
if (y > 0) {
y = SDL_ceil(y);
} else if (y < 0) {
y = SDL_floor(y);
/* For discrete scroll events from conventional mice, always send a full tick.
For continuous scroll events from trackpads, send fractional deltas for smoother scrolling. */
if (![event respondsToSelector:@selector(hasPreciseScrollingDeltas)] || ![event hasPreciseScrollingDeltas]) {
if (x > 0) {
x = SDL_ceil(x);
} else if (x < 0) {
x = SDL_floor(x);
}
if (y > 0) {
y = SDL_ceil(y);
} else if (y < 0) {
y = SDL_floor(y);
}
}
SDL_SendMouseWheel(window, mouseID, x, y, direction);
@ -467,8 +511,6 @@ Cocoa_QuitMouse(_THIS)
SDL_Mouse *mouse = SDL_GetMouse();
if (mouse) {
if (mouse->driverdata) {
Cocoa_QuitMouseEventTap(((SDL_MouseData*)mouse->driverdata));
SDL_free(mouse->driverdata);
mouse->driverdata = NULL;
}

View file

@ -1,286 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 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"
#if SDL_VIDEO_DRIVER_COCOA
#include "SDL_cocoamousetap.h"
/* Event taps are forbidden in the Mac App Store, so we can only enable this
* code if your app doesn't need to ship through the app store.
* This code makes it so that a grabbed cursor cannot "leak" a mouse click
* past the edge of the window if moving the cursor too fast.
*/
#if SDL_MAC_NO_SANDBOX
#include "SDL_keyboard.h"
#include "SDL_cocoavideo.h"
#include "../../thread/SDL_systhread.h"
#include "../../events/SDL_mouse_c.h"
typedef struct {
CFMachPortRef tap;
CFRunLoopRef runloop;
CFRunLoopSourceRef runloopSource;
SDL_Thread *thread;
SDL_sem *runloopStartedSemaphore;
} SDL_MouseEventTapData;
static const CGEventMask movementEventsMask =
CGEventMaskBit(kCGEventLeftMouseDragged)
| CGEventMaskBit(kCGEventRightMouseDragged)
| CGEventMaskBit(kCGEventMouseMoved);
static const CGEventMask allGrabbedEventsMask =
CGEventMaskBit(kCGEventLeftMouseDown) | CGEventMaskBit(kCGEventLeftMouseUp)
| CGEventMaskBit(kCGEventRightMouseDown) | CGEventMaskBit(kCGEventRightMouseUp)
| CGEventMaskBit(kCGEventOtherMouseDown) | CGEventMaskBit(kCGEventOtherMouseUp)
| CGEventMaskBit(kCGEventLeftMouseDragged) | CGEventMaskBit(kCGEventRightMouseDragged)
| CGEventMaskBit(kCGEventMouseMoved);
static CGEventRef
Cocoa_MouseTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
{
SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)refcon;
SDL_Mouse *mouse = SDL_GetMouse();
SDL_Window *window = SDL_GetKeyboardFocus();
NSWindow *nswindow;
NSRect windowRect;
CGPoint eventLocation;
switch (type) {
case kCGEventTapDisabledByTimeout:
{
CGEventTapEnable(tapdata->tap, true);
return NULL;
}
case kCGEventTapDisabledByUserInput:
{
return NULL;
}
default:
break;
}
if (!window || !mouse) {
return event;
}
if (mouse->relative_mode) {
return event;
}
if (!(window->flags & SDL_WINDOW_INPUT_GRABBED)) {
return event;
}
/* This is the same coordinate system as Cocoa uses. */
nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
eventLocation = CGEventGetUnflippedLocation(event);
windowRect = [nswindow contentRectForFrameRect:[nswindow frame]];
if (!NSMouseInRect(NSPointFromCGPoint(eventLocation), windowRect, NO)) {
/* This is in CGs global screenspace coordinate system, which has a
* flipped Y.
*/
CGPoint newLocation = CGEventGetLocation(event);
if (eventLocation.x < NSMinX(windowRect)) {
newLocation.x = NSMinX(windowRect);
} else if (eventLocation.x >= NSMaxX(windowRect)) {
newLocation.x = NSMaxX(windowRect) - 1.0;
}
if (eventLocation.y <= NSMinY(windowRect)) {
newLocation.y -= (NSMinY(windowRect) - eventLocation.y + 1);
} else if (eventLocation.y > NSMaxY(windowRect)) {
newLocation.y += (eventLocation.y - NSMaxY(windowRect));
}
CGWarpMouseCursorPosition(newLocation);
CGAssociateMouseAndMouseCursorPosition(YES);
if ((CGEventMaskBit(type) & movementEventsMask) == 0) {
/* For click events, we just constrain the event to the window, so
* no other app receives the click event. We can't due the same to
* movement events, since they mean that our warp cursor above
* behaves strangely.
*/
CGEventSetLocation(event, newLocation);
}
}
return event;
}
static void
SemaphorePostCallback(CFRunLoopTimerRef timer, void *info)
{
SDL_SemPost((SDL_sem*)info);
}
static int
Cocoa_MouseTapThread(void *data)
{
SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)data;
/* Tap was created on main thread but we own it now. */
CFMachPortRef eventTap = tapdata->tap;
if (eventTap) {
/* Try to create a runloop source we can schedule. */
CFRunLoopSourceRef runloopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
if (runloopSource) {
tapdata->runloopSource = runloopSource;
} else {
CFRelease(eventTap);
SDL_SemPost(tapdata->runloopStartedSemaphore);
/* TODO: Both here and in the return below, set some state in
* tapdata to indicate that initialization failed, which we should
* check in InitMouseEventTap, after we move the semaphore check
* from Quit to Init.
*/
return 1;
}
} else {
SDL_SemPost(tapdata->runloopStartedSemaphore);
return 1;
}
tapdata->runloop = CFRunLoopGetCurrent();
CFRunLoopAddSource(tapdata->runloop, tapdata->runloopSource, kCFRunLoopCommonModes);
CFRunLoopTimerContext context = {.info = tapdata->runloopStartedSemaphore};
/* We signal the runloop started semaphore *after* the run loop has started, indicating it's safe to CFRunLoopStop it. */
CFRunLoopTimerRef timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent(), 0, 0, 0, &SemaphorePostCallback, &context);
CFRunLoopAddTimer(tapdata->runloop, timer, kCFRunLoopCommonModes);
CFRelease(timer);
/* Run the event loop to handle events in the event tap. */
CFRunLoopRun();
/* Make sure this is signaled so that SDL_QuitMouseEventTap knows it can safely SDL_WaitThread for us. */
if (SDL_SemValue(tapdata->runloopStartedSemaphore) < 1) {
SDL_SemPost(tapdata->runloopStartedSemaphore);
}
CFRunLoopRemoveSource(tapdata->runloop, tapdata->runloopSource, kCFRunLoopCommonModes);
/* Clean up. */
CGEventTapEnable(tapdata->tap, false);
CFRelease(tapdata->runloopSource);
CFRelease(tapdata->tap);
tapdata->runloopSource = NULL;
tapdata->tap = NULL;
return 0;
}
void
Cocoa_InitMouseEventTap(SDL_MouseData* driverdata)
{
SDL_MouseEventTapData *tapdata;
driverdata->tapdata = SDL_calloc(1, sizeof(SDL_MouseEventTapData));
tapdata = (SDL_MouseEventTapData*)driverdata->tapdata;
tapdata->runloopStartedSemaphore = SDL_CreateSemaphore(0);
if (tapdata->runloopStartedSemaphore) {
tapdata->tap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap,
kCGEventTapOptionDefault, allGrabbedEventsMask,
&Cocoa_MouseTapCallback, tapdata);
if (tapdata->tap) {
/* Tap starts disabled, until app requests mouse grab */
CGEventTapEnable(tapdata->tap, false);
tapdata->thread = SDL_CreateThreadInternal(&Cocoa_MouseTapThread, "Event Tap Loop", 512 * 1024, tapdata);
if (tapdata->thread) {
/* Success - early out. Ownership transferred to thread. */
return;
}
CFRelease(tapdata->tap);
}
SDL_DestroySemaphore(tapdata->runloopStartedSemaphore);
}
SDL_free(driverdata->tapdata);
driverdata->tapdata = NULL;
}
void
Cocoa_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled)
{
SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)driverdata->tapdata;
if (tapdata && tapdata->tap)
{
CGEventTapEnable(tapdata->tap, !!enabled);
}
}
void
Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata)
{
SDL_MouseEventTapData *tapdata = (SDL_MouseEventTapData*)driverdata->tapdata;
int status;
if (tapdata == NULL) {
/* event tap was already cleaned up (possibly due to CGEventTapCreate
* returning null.)
*/
return;
}
/* Ensure that the runloop has been started first.
* TODO: Move this to InitMouseEventTap, check for error conditions that can
* happen in Cocoa_MouseTapThread, and fall back to the non-EventTap way of
* grabbing the mouse if it fails to Init.
*/
status = SDL_SemWaitTimeout(tapdata->runloopStartedSemaphore, 5000);
if (status > -1) {
/* Then stop it, which will cause Cocoa_MouseTapThread to return. */
CFRunLoopStop(tapdata->runloop);
/* And then wait for Cocoa_MouseTapThread to finish cleaning up. It
* releases some of the pointers in tapdata. */
SDL_WaitThread(tapdata->thread, &status);
}
SDL_free(driverdata->tapdata);
driverdata->tapdata = NULL;
}
#else /* SDL_MAC_NO_SANDBOX */
void
Cocoa_InitMouseEventTap(SDL_MouseData *unused)
{
}
void
Cocoa_EnableMouseEventTap(SDL_MouseData *driverdata, SDL_bool enabled)
{
}
void
Cocoa_QuitMouseEventTap(SDL_MouseData *driverdata)
{
}
#endif /* !SDL_MAC_NO_SANDBOX */
#endif /* SDL_VIDEO_DRIVER_COCOA */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -135,7 +135,7 @@
if ([NSThread isMainThread]) {
[super update];
} else {
dispatch_sync(dispatch_get_main_queue(), ^{ [super update]; });
dispatch_async(dispatch_get_main_queue(), ^{ [super update]; });
}
}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -109,7 +109,10 @@ Cocoa_GLES_SetupWindow(_THIS, SDL_Window * window)
if (_this->egl_data == NULL) {
/* !!! FIXME: commenting out this assertion is (I think) incorrect; figure out why driver_loaded is wrong for ANGLE instead. --ryan. */
#if 0 /* When hint SDL_HINT_OPENGL_ES_DRIVER is set to "1" (e.g. for ANGLE support), _this->gl_config.driver_loaded can be 1, while the below lines function. */
SDL_assert(!_this->gl_config.driver_loaded);
#endif
if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0) < 0) {
SDL_EGL_UnloadLibrary(_this);
return -1;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -38,6 +38,9 @@ static void Cocoa_VideoQuit(_THIS);
static void
Cocoa_DeleteDevice(SDL_VideoDevice * device)
{
if (device->wakeup_lock) {
SDL_DestroyMutex(device->wakeup_lock);
}
SDL_free(device->driverdata);
SDL_free(device);
}
@ -63,6 +66,7 @@ Cocoa_CreateDevice(int devindex)
return NULL;
}
device->driverdata = data;
device->wakeup_lock = SDL_CreateMutex();
/* Set the function pointers */
device->VideoInit = Cocoa_VideoInit;
@ -73,6 +77,8 @@ Cocoa_CreateDevice(int devindex)
device->GetDisplayModes = Cocoa_GetDisplayModes;
device->SetDisplayMode = Cocoa_SetDisplayMode;
device->PumpEvents = Cocoa_PumpEvents;
device->WaitEventTimeout = Cocoa_WaitEventTimeout;
device->SendWakeupEvent = Cocoa_SendWakeupEvent;
device->SuspendScreenSaver = Cocoa_SuspendScreenSaver;
device->CreateSDLWindow = Cocoa_CreateWindow;
@ -92,14 +98,19 @@ Cocoa_CreateDevice(int devindex)
device->RestoreWindow = Cocoa_RestoreWindow;
device->SetWindowBordered = Cocoa_SetWindowBordered;
device->SetWindowResizable = Cocoa_SetWindowResizable;
device->SetWindowAlwaysOnTop = Cocoa_SetWindowAlwaysOnTop;
device->SetWindowFullscreen = Cocoa_SetWindowFullscreen;
device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp;
device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp;
device->SetWindowGrab = Cocoa_SetWindowGrab;
device->GetWindowICCProfile = Cocoa_GetWindowICCProfile;
device->SetWindowMouseRect = Cocoa_SetWindowMouseRect;
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->shape_driver.CreateShaper = Cocoa_CreateShaper;
device->shape_driver.SetWindowShape = Cocoa_SetWindowShape;
@ -260,7 +271,10 @@ Cocoa_CreateImage(SDL_Surface * surface)
void SDL_NSLog(const char *text)
{
NSLog(@"%s", text);
@autoreleasepool {
NSString *str = [NSString stringWithUTF8String:text];
NSLog(@"%@", str);
}
}
#endif /* SDL_VIDEO_DRIVER_COCOA */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -48,6 +48,7 @@ typedef enum
BOOL inFullscreenTransition;
PendingWindowOperation pendingWindowOperation;
BOOL isMoving;
NSInteger focusClickPending;
int pendingWindowWarpX, pendingWindowWarpY;
BOOL isDragAreaRunning;
}
@ -62,8 +63,12 @@ typedef enum
-(void) close;
-(BOOL) isMoving;
-(BOOL) isMovingOrFocusClickPending;
-(void) setFocusClickPending:(NSInteger) button;
-(void) clearFocusClickPending:(NSInteger) button;
-(void) setPendingMoveX:(int)x Y:(int)y;
-(void) windowDidFinishMoving;
-(void) onMovingOrFocusClickPendingStateCleared;
/* Window delegate functionality */
-(BOOL) windowShouldClose:(id) sender;
@ -75,6 +80,7 @@ typedef enum
-(void) windowDidBecomeKey:(NSNotification *) aNotification;
-(void) windowDidResignKey:(NSNotification *) aNotification;
-(void) windowDidChangeBackingProperties:(NSNotification *) aNotification;
-(void) windowDidChangeScreenProfile:(NSNotification *) aNotification;
-(void) windowWillEnterFullScreen:(NSNotification *) aNotification;
-(void) windowDidEnterFullScreen:(NSNotification *) aNotification;
-(void) windowWillExitFullScreen:(NSNotification *) aNotification;
@ -117,6 +123,7 @@ struct SDL_WindowData
NSMutableArray *nscontexts;
SDL_bool created;
SDL_bool inWindowFullscreenTransition;
NSInteger flash_request;
Cocoa_WindowListener *listener;
struct SDL_VideoData *videodata;
#if SDL_VIDEO_OPENGL_EGL
@ -142,14 +149,18 @@ extern void Cocoa_MinimizeWindow(_THIS, SDL_Window * window);
extern void Cocoa_RestoreWindow(_THIS, SDL_Window * window);
extern void Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
extern void Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable);
extern void Cocoa_SetWindowAlwaysOnTop(_THIS, SDL_Window * window, SDL_bool on_top);
extern void Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
extern int Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
extern void* Cocoa_GetWindowICCProfile(_THIS, SDL_Window * window, size_t * size);
extern int Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
extern void Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
extern void Cocoa_SetWindowMouseRect(_THIS, SDL_Window * window);
extern void Cocoa_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
extern void Cocoa_DestroyWindow(_THIS, SDL_Window * window);
extern SDL_bool Cocoa_GetWindowWMInfo(_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(_THIS, SDL_Window * window, SDL_FlashOperation operation);
#endif /* SDL_cocoawindow_h_ */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -38,7 +38,6 @@
#include "SDL_cocoavideo.h"
#include "SDL_cocoashape.h"
#include "SDL_cocoamouse.h"
#include "SDL_cocoamousetap.h"
#include "SDL_cocoaopengl.h"
#include "SDL_cocoaopengles.h"
@ -56,9 +55,21 @@
#ifndef MAC_OS_X_VERSION_10_12
#define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask
#endif
#ifndef NSAppKitVersionNumber10_14
#define NSAppKitVersionNumber10_14 1671
#ifndef NSAppKitVersionNumber10_13_2
#define NSAppKitVersionNumber10_13_2 1561.2
#endif
#ifndef NSAppKitVersionNumber10_14
#define NSAppKitVersionNumber10_14 1671
#endif
@interface NSWindow (SDL)
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000 /* Added in the 10.10 SDK */
@property (readonly) NSRect contentLayoutRect;
#endif
/* This is available as of 10.13.2, but isn't in public headers */
@property (nonatomic) NSRect mouseConfinementRect;
@end
@interface SDLWindow : NSWindow <NSDraggingDestination>
/* These are needed for borderless/fullscreen windows */
@ -161,6 +172,16 @@
SDL_assert([desiredType isEqualToString:NSFilenamesPboardType]);
NSArray *array = [pasteboard propertyListForType:@"NSFilenamesPboardType"];
/* Code addon to update the mouse location */
NSPoint point = [sender draggingLocation];
SDL_Mouse *mouse = SDL_GetMouse();
int x = (int)point.x;
int y = (int)(sdlwindow->h - point.y);
if (x >= 0 && x < sdlwindow->w && y >= 0 && y < sdlwindow->h) {
SDL_SendMouseMotion(sdlwindow, mouse->mouseID, 0, x, y);
}
/* Code addon to update the mouse location */
for (NSString *path in array) {
NSURL *fileURL = [NSURL fileURLWithPath:path];
NSNumber *isAlias = nil;
@ -313,6 +334,119 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
return SDL_TRUE;
}
static SDL_bool
ShouldAdjustCoordinatesForGrab(SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (!data || [data->listener isMovingOrFocusClickPending]) {
return SDL_FALSE;
}
if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
return SDL_FALSE;
}
if ((window->flags & SDL_WINDOW_MOUSE_GRABBED) || (window->mouse_rect.w > 0 && window->mouse_rect.h > 0)) {
return SDL_TRUE;
}
return SDL_FALSE;
}
static SDL_bool
AdjustCoordinatesForGrab(SDL_Window * window, int x, int y, CGPoint *adjusted)
{
if (window->mouse_rect.w > 0 && window->mouse_rect.h > 0) {
SDL_Rect window_rect;
SDL_Rect mouse_rect;
window_rect.x = 0;
window_rect.y = 0;
window_rect.w = window->w;
window_rect.h = window->h;
if (SDL_IntersectRect(&window->mouse_rect, &window_rect, &mouse_rect)) {
int left = window->x + mouse_rect.x;
int right = left + mouse_rect.w - 1;
int top = window->y + mouse_rect.y;
int bottom = top + mouse_rect.h - 1;
if (x < left || x > right || y < top || y > bottom) {
adjusted->x = SDL_clamp(x, left, right);
adjusted->y = SDL_clamp(y, top, bottom);
return SDL_TRUE;
}
return SDL_FALSE;
}
}
if ((window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0) {
int left = window->x;
int right = left + window->w - 1;
int top = window->y;
int bottom = top + window->h - 1;
if (x < left || x > right || y < top || y > bottom) {
adjusted->x = SDL_clamp(x, left, right);
adjusted->y = SDL_clamp(y, top, bottom);
return SDL_TRUE;
}
}
return SDL_FALSE;
}
static void
Cocoa_UpdateClipCursor(SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_13_2) {
NSWindow *nswindow = data->nswindow;
SDL_Rect mouse_rect;
SDL_zero(mouse_rect);
if (ShouldAdjustCoordinatesForGrab(window)) {
SDL_Rect window_rect;
window_rect.x = 0;
window_rect.y = 0;
window_rect.w = window->w;
window_rect.h = window->h;
if (window->mouse_rect.w > 0 && window->mouse_rect.h > 0) {
SDL_IntersectRect(&window->mouse_rect, &window_rect, &mouse_rect);
}
if ((window->flags & SDL_WINDOW_MOUSE_GRABBED) != 0 &&
SDL_RectEmpty(&mouse_rect)) {
SDL_memcpy(&mouse_rect, &window_rect, sizeof(mouse_rect));
}
}
if (SDL_RectEmpty(&mouse_rect)) {
nswindow.mouseConfinementRect = NSZeroRect;
} else {
NSRect rect;
rect.origin.x = mouse_rect.x;
rect.origin.y = [nswindow contentLayoutRect].size.height - mouse_rect.y - mouse_rect.h;
rect.size.width = mouse_rect.w;
rect.size.height = mouse_rect.h;
nswindow.mouseConfinementRect = rect;
}
} else {
/* Move the cursor to the nearest point in the window */
if (ShouldAdjustCoordinatesForGrab(window)) {
int x, y;
CGPoint cgpoint;
SDL_GetGlobalMouseState(&x, &y);
if (AdjustCoordinatesForGrab(window, x, y, &cgpoint)) {
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
}
}
}
}
@implementation Cocoa_WindowListener
@ -331,6 +465,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
pendingWindowOperation = PENDING_OPERATION_NONE;
isMoving = NO;
isDragAreaRunning = NO;
pendingWindowWarpX = pendingWindowWarpY = INT_MAX;
center = [NSNotificationCenter defaultCenter];
@ -343,6 +478,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
[center addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:window];
[center addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:window];
[center addObserver:self selector:@selector(windowDidChangeBackingProperties:) name:NSWindowDidChangeBackingPropertiesNotification object:window];
[center addObserver:self selector:@selector(windowDidChangeScreenProfile:) name:NSWindowDidChangeScreenProfileNotification object:window];
[center addObserver:self selector:@selector(windowWillEnterFullScreen:) name:NSWindowWillEnterFullScreenNotification object:window];
[center addObserver:self selector:@selector(windowDidEnterFullScreen:) name:NSWindowDidEnterFullScreenNotification object:window];
[center addObserver:self selector:@selector(windowWillExitFullScreen:) name:NSWindowWillExitFullScreenNotification object:window];
@ -474,6 +610,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
[center removeObserver:self name:NSWindowDidBecomeKeyNotification object:window];
[center removeObserver:self name:NSWindowDidResignKeyNotification object:window];
[center removeObserver:self name:NSWindowDidChangeBackingPropertiesNotification object:window];
[center removeObserver:self name:NSWindowDidChangeScreenProfileNotification object:window];
[center removeObserver:self name:NSWindowWillEnterFullScreenNotification object:window];
[center removeObserver:self name:NSWindowDidEnterFullScreenNotification object:window];
[center removeObserver:self name:NSWindowWillExitFullScreenNotification object:window];
@ -499,6 +636,26 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
return isMoving;
}
- (BOOL)isMovingOrFocusClickPending
{
return isMoving || (focusClickPending != 0);
}
-(void) setFocusClickPending:(NSInteger) button
{
focusClickPending |= (1 << button);
}
-(void) clearFocusClickPending:(NSInteger) button
{
if ((focusClickPending & (1 << button)) != 0) {
focusClickPending &= ~(1 << button);
if (focusClickPending == 0) {
[self onMovingOrFocusClickPendingStateCleared];
}
}
}
-(void) setPendingMoveX:(int)x Y:(int)y
{
pendingWindowWarpX = x;
@ -507,16 +664,39 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
- (void)windowDidFinishMoving
{
if ([self isMoving]) {
if (isMoving) {
isMoving = NO;
[self onMovingOrFocusClickPendingStateCleared];
}
}
- (void)onMovingOrFocusClickPendingStateCleared
{
if (![self isMovingOrFocusClickPending]) {
SDL_Mouse *mouse = SDL_GetMouse();
if (pendingWindowWarpX != INT_MAX && pendingWindowWarpY != INT_MAX) {
mouse->WarpMouseGlobal(pendingWindowWarpX, pendingWindowWarpY);
pendingWindowWarpX = pendingWindowWarpY = INT_MAX;
}
if (mouse->relative_mode && !mouse->relative_mode_warp && mouse->focus == _data->window) {
/* Move the cursor to the nearest point in the window */
{
int x, y;
CGPoint cgpoint;
SDL_GetMouseState(&x, &y);
cgpoint.x = _data->window->x + x;
cgpoint.y = _data->window->y + y;
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
DLog("Returning cursor to (%g, %g)", cgpoint.x, cgpoint.y);
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
}
mouse->SetRelativeMouseMode(SDL_TRUE);
} else {
Cocoa_UpdateClipCursor(_data->window);
}
}
}
@ -615,6 +795,10 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
- (void)windowDidMiniaturize:(NSNotification *)aNotification
{
if (focusClickPending) {
focusClickPending = 0;
[self onMovingOrFocusClickPendingStateCleared];
}
SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
}
@ -632,7 +816,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
/* This needs to be done before restoring the relative mouse mode. */
SDL_SetKeyboardFocus(window);
if (mouse->relative_mode && !mouse->relative_mode_warp && ![self isMoving]) {
if (mouse->relative_mode && !mouse->relative_mode_warp && ![self isMovingOrFocusClickPending]) {
mouse->SetRelativeMouseMode(SDL_TRUE);
}
@ -700,6 +884,11 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
}
}
- (void)windowDidChangeScreenProfile:(NSNotification *)aNotification
{
SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_ICCPROF_CHANGED, 0, 0);
}
- (void)windowWillEnterFullScreen:(NSNotification *)aNotification
{
SDL_Window *window = _data->window;
@ -962,16 +1151,43 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
return NO; /* not a special area, carry on. */
}
static int
Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * window, const Uint8 state, const Uint8 button)
{
const SDL_MouseID mouseID = mouse->mouseID;
const int clicks = (int) [theEvent clickCount];
SDL_Window *focus = SDL_GetKeyboardFocus();
int rc;
// macOS will send non-left clicks to background windows without raising them, so we need to
// temporarily adjust the mouse position when this happens, as `mouse` will be tracking
// the position in the currently-focused window. We don't (currently) send a mousemove
// event for the background window, this just makes sure the button is reported at the
// correct position in its own event.
if ( focus && ([theEvent window] == ((SDL_WindowData *) focus->driverdata)->nswindow) ) {
rc = SDL_SendMouseButtonClicks(window, mouseID, state, button, clicks);
} else {
const int orig_x = mouse->x;
const int orig_y = mouse->y;
const NSPoint point = [theEvent locationInWindow];
mouse->x = (int) point.x;
mouse->y = (int) (window->h - point.y);
rc = SDL_SendMouseButtonClicks(window, mouseID, state, button, clicks);
mouse->x = orig_x;
mouse->y = orig_y;
}
return rc;
}
- (void)mouseDown:(NSEvent *)theEvent
{
const SDL_Mouse *mouse = SDL_GetMouse();
SDL_Mouse *mouse = SDL_GetMouse();
if (!mouse) {
return;
}
const SDL_MouseID mouseID = mouse->mouseID;
int button;
int clicks;
/* Ignore events that aren't inside the client area (i.e. title bar.) */
if ([theEvent window]) {
@ -1008,9 +1224,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
break;
}
clicks = (int) [theEvent clickCount];
SDL_SendMouseButtonClicks(_data->window, mouseID, SDL_PRESSED, button, clicks);
Cocoa_SendMouseButtonClicks(mouse, theEvent, _data->window, SDL_PRESSED, button);
}
- (void)rightMouseDown:(NSEvent *)theEvent
@ -1025,14 +1239,12 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
- (void)mouseUp:(NSEvent *)theEvent
{
const SDL_Mouse *mouse = SDL_GetMouse();
SDL_Mouse *mouse = SDL_GetMouse();
if (!mouse) {
return;
}
const SDL_MouseID mouseID = mouse->mouseID;
int button;
int clicks;
if ([self processHitTest:theEvent]) {
SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
@ -1059,9 +1271,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
break;
}
clicks = (int) [theEvent clickCount];
SDL_SendMouseButtonClicks(_data->window, mouseID, SDL_RELEASED, button, clicks);
Cocoa_SendMouseButtonClicks(mouse, theEvent, _data->window, SDL_RELEASED, button);
}
- (void)rightMouseUp:(NSEvent *)theEvent
@ -1099,34 +1309,15 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
x = (int)point.x;
y = (int)(window->h - point.y);
if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
if (x < 0) {
x = 0;
} else if (x >= window->w) {
x = window->w - 1;
}
if (y < 0) {
y = 0;
} else if (y >= window->h) {
y = window->h - 1;
}
#if !SDL_MAC_NO_SANDBOX
CGPoint cgpoint;
/* When SDL_MAC_NO_SANDBOX is set, this is handled by
* SDL_cocoamousetap.m.
*/
cgpoint.x = window->x + x;
cgpoint.y = window->y + y;
if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_13_2) {
/* Mouse grab is taken care of by the confinement rect */
} else {
CGPoint cgpoint;
if (ShouldAdjustCoordinatesForGrab(window) &&
AdjustCoordinatesForGrab(window, window->x + x, window->y + y, &cgpoint)) {
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
CGAssociateMouseAndMouseCursorPosition(YES);
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
#endif
}
}
@ -1157,7 +1348,18 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
{
/* probably a MacBook trackpad; make this look like a synthesized event.
This is backwards from reality, but better matches user expectations. */
const BOOL istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
BOOL istrackpad = NO;
@try {
istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
}
@catch (NSException *e) {
/* if NSEvent type doesn't have subtype, such as NSEventTypeBeginGesture on
* macOS 10.5 to 10.10, then NSInternalInconsistencyException is thrown.
* This still prints a message to terminal so catching it's not an ideal solution.
*
* *** Assertion failure in -[NSEvent subtype]
*/
}
NSSet *touches = [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
const SDL_TouchID touchID = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[[touches anyObject] device];
@ -1208,7 +1410,18 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
/* probably a MacBook trackpad; make this look like a synthesized event.
This is backwards from reality, but better matches user expectations. */
const BOOL istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
BOOL istrackpad = NO;
@try {
istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
}
@catch (NSException *e) {
/* if NSEvent type doesn't have subtype, such as NSEventTypeBeginGesture on
* macOS 10.5 to 10.10, then NSInternalInconsistencyException is thrown.
* This still prints a message to terminal so catching it's not an ideal solution.
*
* *** Assertion failure in -[NSEvent subtype]
*/
}
for (NSTouch *touch in touches) {
const SDL_TouchID touchId = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[touch device];
@ -1403,7 +1616,10 @@ SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, NSView *nsview,
{
unsigned long style = [nswindow styleMask];
if (style == NSWindowStyleMaskBorderless) {
/* NSWindowStyleMaskBorderless is zero, and it's possible to be
Resizeable _and_ borderless, so we can't do a simple bitwise AND
of NSWindowStyleMaskBorderless here. */
if ((style & ~NSWindowStyleMaskResizable) == NSWindowStyleMaskBorderless) {
window->flags |= SDL_WINDOW_BORDERLESS;
} else {
window->flags &= ~SDL_WINDOW_BORDERLESS;
@ -1804,11 +2020,33 @@ Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
*/
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Cocoa_WindowListener *listener = data->listener;
NSWindow *nswindow = data->nswindow;
SDL_VideoData *videodata = ((SDL_WindowData *) window->driverdata)->videodata;
if (![listener isInFullscreenSpace]) {
SetWindowStyle(window, GetWindowStyle(window));
}
if (videodata->allow_spaces) {
if (resizable) {
/* resizable windows are Spaces-friendly: they get the "go fullscreen" toggle button on their titlebar. */
[nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
} else {
[nswindow setCollectionBehavior:NSWindowCollectionBehaviorManaged];
}
}
}}
void
Cocoa_SetWindowAlwaysOnTop(_THIS, SDL_Window * window, SDL_bool on_top)
{ @autoreleasepool
{
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
if (on_top) {
[nswindow setLevel:NSFloatingWindowLevel];
} else {
[nswindow setLevel:kCGNormalWindowLevel];
}
}}
void
Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
{ @autoreleasepool
@ -1923,6 +2161,42 @@ Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
return 0;
}
void*
Cocoa_GetWindowICCProfile(_THIS, SDL_Window * window, size_t * size)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
NSWindow *nswindow = data->nswindow;
NSScreen *screen = [nswindow screen];
NSData* iccProfileData = nil;
void* retIccProfileData = NULL;
if (screen == nil) {
SDL_SetError("Could not get screen of window.");
return NULL;
}
if ([screen colorSpace] == nil) {
SDL_SetError("Could not get colorspace information of screen.");
return NULL;
}
iccProfileData = [[screen colorSpace] ICCProfileData];
if (iccProfileData == nil) {
SDL_SetError("Could not get ICC profile data.");
return NULL;
}
retIccProfileData = SDL_malloc([iccProfileData length]);
if (!retIccProfileData) {
SDL_OutOfMemory();
return NULL;
}
[iccProfileData getBytes:retIccProfileData length:[iccProfileData length]];
*size = [iccProfileData length];
return retIccProfileData;
}
int
Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
{
@ -1948,30 +2222,19 @@ Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
}
void
Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
Cocoa_SetWindowMouseRect(_THIS, SDL_Window * window)
{
Cocoa_UpdateClipCursor(window);
}
void
Cocoa_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
{
SDL_Mouse *mouse = SDL_GetMouse();
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
/* Enable or disable the event tap as necessary */
Cocoa_EnableMouseEventTap(mouse->driverdata, grabbed);
Cocoa_UpdateClipCursor(window);
/* Move the cursor to the nearest point in the window */
if (grabbed && data && ![data->listener isMoving]) {
int x, y;
CGPoint cgpoint;
SDL_GetMouseState(&x, &y);
cgpoint.x = window->x + x;
cgpoint.y = window->y + y;
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
DLog("Returning cursor to (%g, %g)", cgpoint.x, cgpoint.y);
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
}
if ( data && (window->flags & SDL_WINDOW_FULLSCREEN) ) {
if (data && (window->flags & SDL_WINDOW_FULLSCREEN)) {
if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_INPUT_FOCUS)
&& ![data->listener isInFullscreenSpace]) {
/* OpenGL is rendering to the window, so make it visible! */
@ -2103,6 +2366,34 @@ Cocoa_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept)
}
}
int
Cocoa_FlashWindow(_THIS, SDL_Window *window, SDL_FlashOperation operation)
{ @autoreleasepool
{
/* Note that this is app-wide and not window-specific! */
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (data->flash_request) {
[NSApp cancelUserAttentionRequest:data->flash_request];
data->flash_request = 0;
}
switch (operation) {
case SDL_FLASH_CANCEL:
/* Canceled above */
break;
case SDL_FLASH_BRIEFLY:
data->flash_request = [NSApp requestUserAttention:NSInformationalRequest];
break;
case SDL_FLASH_UNTIL_FOCUSED:
data->flash_request = [NSApp requestUserAttention:NSCriticalRequest];
break;
default:
return SDL_Unsupported();
}
return 0;
}}
int
Cocoa_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
{

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -287,9 +287,8 @@ WMPos(DFB_WindowData * p, int x, int y)
int
DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt)
{
SDL_DFB_DEVICEDATA(_this);
SDL_DFB_WINDOWDATA(window);
DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
SDL_Window *grabbed_window = SDL_GetGrabbedWindow();
IDirectFBWindow *dfbwin = windata->dfbwin;
DFBWindowOptions wopts;
@ -324,12 +323,12 @@ DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt)
}
if (window->flags & SDL_WINDOW_MAXIMIZED)
return 1;
/* fall through */
SDL_FALLTHROUGH;
default:
windata->wm_grab = pos;
if (gwindata != NULL)
SDL_DFB_CHECK(gwindata->dfbwin->UngrabPointer(gwindata->dfbwin));
SDL_DFB_CHECK(dfbwin->GrabPointer(dfbwin));
if (grabbed_window != NULL)
DirectFB_SetWindowMouseGrab(_this, grabbed_window, SDL_FALSE);
DirectFB_SetWindowMouseGrab(_this, window, SDL_TRUE);
windata->wm_lastx = evt->cx;
windata->wm_lasty = evt->cy;
}
@ -359,9 +358,9 @@ DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt)
SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx, ch + dy));
}
}
SDL_DFB_CHECK(dfbwin->UngrabPointer(dfbwin));
if (gwindata != NULL)
SDL_DFB_CHECK(gwindata->dfbwin->GrabPointer(gwindata->dfbwin));
DirectFB_SetWindowMouseGrab(_this, window, SDL_FALSE);
if (grabbed_window != NULL)
DirectFB_SetWindowMouseGrab(_this, grabbed_window, SDL_TRUE);
windata->wm_grab = WM_POS_NONE;
return 1;
}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -212,7 +212,7 @@ ProcessWindowEvent(_THIS, SDL_Window *sdlwin, DFBWindowEvent * evt)
case DWET_MOTION:
if (ClientXY(windata, &evt->x, &evt->y)) {
if (!devdata->use_linux_input) {
if (!(sdlwin->flags & SDL_WINDOW_INPUT_GRABBED))
if (!(sdlwin->flags & SDL_WINDOW_MOUSE_GRABBED))
SDL_SendMouseMotion_ex(sdlwin, devdata->mouse_id[0], 0,
evt->x, evt->y, 0);
} else {
@ -261,7 +261,7 @@ ProcessWindowEvent(_THIS, SDL_Window *sdlwin, DFBWindowEvent * evt)
SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_MOVED,
evt->x, evt->y);
}
/* fall throught */
SDL_FALLTHROUGH;
case DWET_SIZE:
/* FIXME: what about < 0 */
evt->w -= (windata->theme.right_size + windata->theme.left_size);
@ -312,15 +312,16 @@ ProcessInputEvent(_THIS, DFBInputEvent * ievt)
int kbd_idx;
Uint32 unicode;
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
SDL_Window* grabbed_window = SDL_GetGrabbedWindow();
if (!devdata->use_linux_input) {
if (ievt->type == DIET_AXISMOTION) {
if ((devdata->grabbed_window != NULL) && (ievt->flags & DIEF_AXISREL)) {
if ((grabbed_window != NULL) && (ievt->flags & DIEF_AXISREL)) {
if (ievt->axis == DIAI_X)
SDL_SendMouseMotion_ex(devdata->grabbed_window, ievt->device_id, 1,
SDL_SendMouseMotion_ex(grabbed_window, ievt->device_id, 1,
ievt->axisrel, 0, 0);
else if (ievt->axis == DIAI_Y)
SDL_SendMouseMotion_ex(devdata->grabbed_window, ievt->device_id, 1, 0,
SDL_SendMouseMotion_ex(grabbed_window, ievt->device_id, 1, 0,
ievt->axisrel, 0);
}
}
@ -339,7 +340,7 @@ ProcessInputEvent(_THIS, DFBInputEvent * ievt)
SDL_Mouse *mouse = SDL_GetMouse(ievt->device_id);
SDL_Window *window = SDL_GetWindowFromID(mouse->focus);
#else
SDL_Window *window = devdata->grabbed_window;
SDL_Window *window = grabbed_window;
#endif
if (window) {
DFB_WindowData *windata =
@ -359,10 +360,10 @@ ProcessInputEvent(_THIS, DFBInputEvent * ievt)
}
} else if (ievt->flags & DIEF_AXISREL) {
if (ievt->axis == DIAI_X)
SDL_SendMouseMotion_ex(devdata->grabbed_window, ievt->device_id, 1,
SDL_SendMouseMotion_ex(grabbed_window, ievt->device_id, 1,
ievt->axisrel, 0, 0);
else if (ievt->axis == DIAI_Y)
SDL_SendMouseMotion_ex(devdata->grabbed_window, ievt->device_id, 1, 0,
SDL_SendMouseMotion_ex(grabbed_window, ievt->device_id, 1, 0,
ievt->axisrel, 0);
}
break;
@ -386,19 +387,19 @@ ProcessInputEvent(_THIS, DFBInputEvent * ievt)
break;
case DIET_BUTTONPRESS:
if (ievt->buttons & DIBM_LEFT)
SDL_SendMouseButton_ex(devdata->grabbed_window, ievt->device_id, SDL_PRESSED, 1);
SDL_SendMouseButton_ex(grabbed_window, ievt->device_id, SDL_PRESSED, 1);
if (ievt->buttons & DIBM_MIDDLE)
SDL_SendMouseButton_ex(devdata->grabbed_window, ievt->device_id, SDL_PRESSED, 2);
SDL_SendMouseButton_ex(grabbed_window, ievt->device_id, SDL_PRESSED, 2);
if (ievt->buttons & DIBM_RIGHT)
SDL_SendMouseButton_ex(devdata->grabbed_window, ievt->device_id, SDL_PRESSED, 3);
SDL_SendMouseButton_ex(grabbed_window, ievt->device_id, SDL_PRESSED, 3);
break;
case DIET_BUTTONRELEASE:
if (!(ievt->buttons & DIBM_LEFT))
SDL_SendMouseButton_ex(devdata->grabbed_window, ievt->device_id, SDL_RELEASED, 1);
SDL_SendMouseButton_ex(grabbed_window, ievt->device_id, SDL_RELEASED, 1);
if (!(ievt->buttons & DIBM_MIDDLE))
SDL_SendMouseButton_ex(devdata->grabbed_window, ievt->device_id, SDL_RELEASED, 2);
SDL_SendMouseButton_ex(grabbed_window, ievt->device_id, SDL_RELEASED, 2);
if (!(ievt->buttons & DIBM_RIGHT))
SDL_SendMouseButton_ex(devdata->grabbed_window, ievt->device_id, SDL_RELEASED, 3);
SDL_SendMouseButton_ex(grabbed_window, ievt->device_id, SDL_RELEASED, 3);
break;
default:
break; /* please gcc */
@ -682,7 +683,7 @@ EnumKeyboards(DFBInputDeviceID device_id,
#endif
devdata->keyboard[devdata->num_keyboard].id = device_id;
devdata->keyboard[devdata->num_keyboard].is_generic = 0;
if (!strncmp("X11", desc.name, 3))
if (!SDL_strncmp("X11", desc.name, 3))
{
devdata->keyboard[devdata->num_keyboard].map = xfree86_scancode_table2;
devdata->keyboard[devdata->num_keyboard].map_size = SDL_arraysize(xfree86_scancode_table2);

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -164,7 +164,7 @@ DirectFB_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
p = surface->pixels;
for (i = 0; i < surface->h; i++)
memcpy((char *) dest + i * pitch,
SDL_memcpy((char *) dest + i * pitch,
(char *) p + i * surface->pitch, 4 * surface->w);
curdata->surf->Unlock(curdata->surf);

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -47,7 +47,7 @@ struct SDL_GLDriverData
};
#define OPENGL_REQUIRS_DLOPEN
#if defined(OPENGL_REQUIRS_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
#if defined(OPENGL_REQUIRS_DLOPEN) && defined(HAVE_DLOPEN)
#include <dlfcn.h>
#define GL_LoadObject(X) dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
#define GL_LoadFunction dlsym

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -324,6 +324,22 @@ DirectFB_AcquireVidLayer(SDL_Renderer * renderer, SDL_Texture * texture)
return 1;
}
/* Copy the SDL_Surface palette to the DirectFB texture palette */
void DirectFB_SetTexturePalette(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Palette *pal)
{
int i;
DFBColor dfbpal[256];
DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
for (i = 0; i < pal->ncolors; i++) {
dfbpal[i].a = pal->colors[i].a;
dfbpal[i].r = pal->colors[i].r;
dfbpal[i].g = pal->colors[i].g;
dfbpal[i].b = pal->colors[i].b;
}
data->palette->SetEntries(data->palette, dfbpal, pal->ncolors, 0);
}
static int
DirectFB_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
@ -615,6 +631,59 @@ DirectFB_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const
return 0;
}
static int
DirectFB_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
const float *xy, int xy_stride, const SDL_Color *color, int color_stride, const float *uv, int uv_stride,
int num_vertices, const void *indices, int num_indices, int size_indices,
float scale_x, float scale_y)
{
int i;
int count = indices ? num_indices : num_vertices;
float *verts;
int sz = 2 + 4 + (texture ? 2 : 0);
verts = (float *) SDL_AllocateRenderVertices(renderer, count * sz * sizeof (float), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
size_indices = indices ? size_indices : 0;
for (i = 0; i < count; i++) {
int j;
float *xy_;
SDL_Color col_;
if (size_indices == 4) {
j = ((const Uint32 *)indices)[i];
} else if (size_indices == 2) {
j = ((const Uint16 *)indices)[i];
} else if (size_indices == 1) {
j = ((const Uint8 *)indices)[i];
} else {
j = i;
}
xy_ = (float *)((char*)xy + j * xy_stride);
col_ = *(SDL_Color *)((char*)color + j * color_stride);
*(verts++) = xy_[0] * scale_x;
*(verts++) = xy_[1] * scale_y;
*(verts++) = col_.r;
*(verts++) = col_.g;
*(verts++) = col_.b;
*(verts++) = col_.a;
if (texture) {
float *uv_ = (float *)((char*)uv + j * uv_stride);
*(verts++) = uv_[0];
*(verts++) = uv_[1];
}
}
return 0;
}
static int
DirectFB_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
{
@ -648,15 +717,6 @@ DirectFB_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture
return 0;
}
static int
DirectFB_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
{
return SDL_Unsupported();
}
static int
DirectFB_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
@ -814,8 +874,145 @@ DirectFB_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *
break;
}
case SDL_RENDERCMD_COPY_EX:
break; /* unsupported */
case SDL_RENDERCMD_GEOMETRY: {
const float *verts = (float *) (((Uint8 *) vertices) + cmd->data.draw.first);
SDL_Texture *texture = cmd->data.draw.texture;
const size_t count = cmd->data.draw.count;
Uint8 save_r = cmd->data.draw.r;
Uint8 save_g = cmd->data.draw.g;
Uint8 save_b = cmd->data.draw.b;
Uint8 save_a = cmd->data.draw.a;
int j;
for (j = 0; j < count; j += 3)
{
float x1, y1, r1, g1, b1, a1, u1, v1;
float x2, y2, r2, g2, b2, a2, u2, v2;
float x3, y3, r3, g3, b3, a3, u3, v3;
x1 = *(verts++);
y1 = *(verts++);
r1 = *(verts++);
g1 = *(verts++);
b1 = *(verts++);
a1 = *(verts++);
if (texture) {
u1 = *(verts++);
v1 = *(verts++);
}
x2 = *(verts++);
y2 = *(verts++);
r2 = *(verts++);
g2 = *(verts++);
b2 = *(verts++);
a2 = *(verts++);
if (texture) {
u2 = *(verts++);
v2 = *(verts++);
}
x3 = *(verts++);
y3 = *(verts++);
r3 = *(verts++);
g3 = *(verts++);
b3 = *(verts++);
a3 = *(verts++);
if (texture) {
u3 = *(verts++);
v3 = *(verts++);
}
if (texture) {
DFBVertex vertices[3];
DirectFB_TextureData *texturedata = (DirectFB_TextureData *) texture->driverdata;
DFBSurfaceBlittingFlags flags = 0;
int r = (r1 + r2 + r3) / 3;
int g = (g1 + g2 + g3) / 3;
int b = (b1 + b2 + b3) / 3;
int a = (a1 + a2 + a3) / 3;
if (texturedata->isDirty) {
const SDL_Rect rect = { 0, 0, texture->w, texture->h };
DirectFB_UpdateTexture(renderer, texture, &rect, texturedata->pixels, texturedata->pitch);
}
if (a != 0xFF) {
flags |= DSBLIT_BLEND_COLORALPHA;
}
if ((r & g & b) != 0xFF) {
flags |= DSBLIT_COLORIZE;
}
destsurf->SetColor(destsurf, r, g, b, a);
/* ???? flags |= DSBLIT_SRC_PREMULTCOLOR; */
SetBlendMode(data, texture->blendMode, texturedata);
destsurf->SetBlittingFlags(destsurf, data->blitFlags | flags);
#if (DFB_VERSION_ATLEAST(1,2,0))
destsurf->SetRenderOptions(destsurf, texturedata->render_options);
#endif
vertices[0].x = x1;
vertices[0].y = y1;
vertices[0].z = 0;
vertices[0].w = 0;
vertices[0].s = u1;
vertices[0].t = v1;
vertices[1].x = x2;
vertices[1].y = y2;
vertices[1].z = 0;
vertices[1].w = 0;
vertices[1].s = u2;
vertices[1].t = v2;
vertices[2].x = x3;
vertices[2].y = y3;
vertices[2].z = 0;
vertices[2].w = 0;
vertices[2].s = u3;
vertices[2].t = v3;
destsurf->TextureTriangles(destsurf, texturedata->surface, vertices, NULL, 3, DTTF_LIST);
} else {
DFBTriangle tris;
tris.x1 = x1;
tris.y1 = y1;
tris.x2 = x2;
tris.y2 = y2;
tris.x3 = x3;
tris.y3 = y3;
cmd->data.draw.r = (r1 + r2 + r3) / 3;
cmd->data.draw.g = (g1 + g2 + g3) / 3;
cmd->data.draw.b = (b1 + b2 + b3) / 3;
cmd->data.draw.a = (a1 + a2 + a3) / 3;
PrepareDraw(renderer, cmd);
destsurf->FillTriangles(destsurf, &tris, 1);
}
}
cmd->data.draw.r = save_r;
cmd->data.draw.g = save_g;
cmd->data.draw.b = save_b;
cmd->data.draw.a = save_a;
break;
}
case SDL_RENDERCMD_COPY_EX: /* unused */
break;
case SDL_RENDERCMD_NO_OP:
break;
@ -984,9 +1181,9 @@ DirectFB_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->QueueSetDrawColor = DirectFB_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = DirectFB_QueueDrawPoints;
renderer->QueueDrawLines = DirectFB_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueGeometry = DirectFB_QueueGeometry;
renderer->QueueFillRects = DirectFB_QueueFillRects;
renderer->QueueCopy = DirectFB_QueueCopy;
renderer->QueueCopyEx = DirectFB_QueueCopyEx;
renderer->RunCommandQueue = DirectFB_RunCommandQueue;
renderer->RenderPresent = DirectFB_RenderPresent;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -34,7 +34,7 @@ DirectFB_CreateShaper(SDL_Window* window) {
SDL_ShapeData* data;
int resized_properly;
result = malloc(sizeof(SDL_WindowShaper));
result = SDL_malloc(sizeof(SDL_WindowShaper));
result->window = window;
result->mode.mode = ShapeModeDefault;
result->mode.parameters.binarizationCutoff = 1;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -113,7 +113,8 @@ DirectFB_CreateDevice(int devindex)
device->MaximizeWindow = DirectFB_MaximizeWindow;
device->MinimizeWindow = DirectFB_MinimizeWindow;
device->RestoreWindow = DirectFB_RestoreWindow;
device->SetWindowGrab = DirectFB_SetWindowGrab;
device->SetWindowMouseGrab = DirectFB_SetWindowMouseGrab;
device->SetWindowKeyboardGrab = DirectFB_SetWindowKeyboardGrab;
device->DestroyWindow = DirectFB_DestroyWindow;
device->GetWindowWMInfo = DirectFB_GetWindowWMInfo;
@ -200,7 +201,7 @@ static int readBoolEnv(const char *env_name, int def_val)
stemp = SDL_getenv(env_name);
if (stemp)
return atoi(stemp);
return SDL_atoi(stemp);
else
return def_val;
}
@ -260,7 +261,6 @@ DirectFB_VideoInit(_THIS)
devdata->dfb = dfb;
devdata->firstwin = NULL;
devdata->grabbed_window = NULL;
_this->driverdata = devdata;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@ -153,10 +153,6 @@ struct _DFB_DeviceData
int use_linux_input;
int has_own_wm;
/* window grab */
SDL_Window *grabbed_window;
/* global events */
IDirectFBEventBuffer *events;
};

View file

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