Merge commit 'dec0d4ec4153bf9fc2b78ae6c2df45b6ea8dde7a' as 'external/sdl/SDL'
This commit is contained in:
1602
external/sdl/SDL/src/video/SDL_RLEaccel.c
vendored
Normal file
1602
external/sdl/SDL/src/video/SDL_RLEaccel.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
32
external/sdl/SDL/src/video/SDL_RLEaccel_c.h
vendored
Normal file
32
external/sdl/SDL/src/video/SDL_RLEaccel_c.h
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_RLEaccel_c_h_
|
||||
#define SDL_RLEaccel_c_h_
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
/* Useful functions and variables from SDL_RLEaccel.c */
|
||||
|
||||
extern int SDL_RLESurface(SDL_Surface *surface);
|
||||
extern void SDL_UnRLESurface(SDL_Surface *surface, int recode);
|
||||
|
||||
#endif /* SDL_RLEaccel_c_h_ */
|
283
external/sdl/SDL/src/video/SDL_blit.c
vendored
Normal file
283
external/sdl/SDL/src/video/SDL_blit.c
vendored
Normal file
@ -0,0 +1,283 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_sysvideo.h"
|
||||
#include "SDL_blit.h"
|
||||
#include "SDL_blit_auto.h"
|
||||
#include "SDL_blit_copy.h"
|
||||
#include "SDL_blit_slow.h"
|
||||
#include "SDL_RLEaccel_c.h"
|
||||
#include "SDL_pixels_c.h"
|
||||
|
||||
/* The general purpose software blit routine */
|
||||
static int SDLCALL SDL_SoftBlit(SDL_Surface *src, const SDL_Rect *srcrect,
|
||||
SDL_Surface *dst, const SDL_Rect *dstrect)
|
||||
{
|
||||
int okay;
|
||||
int src_locked;
|
||||
int dst_locked;
|
||||
|
||||
/* Everything is okay at the beginning... */
|
||||
okay = 1;
|
||||
|
||||
/* Lock the destination if it's in hardware */
|
||||
dst_locked = 0;
|
||||
if (SDL_MUSTLOCK(dst)) {
|
||||
if (SDL_LockSurface(dst) < 0) {
|
||||
okay = 0;
|
||||
} else {
|
||||
dst_locked = 1;
|
||||
}
|
||||
}
|
||||
/* Lock the source if it's in hardware */
|
||||
src_locked = 0;
|
||||
if (SDL_MUSTLOCK(src)) {
|
||||
if (SDL_LockSurface(src) < 0) {
|
||||
okay = 0;
|
||||
} else {
|
||||
src_locked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up source and destination buffer pointers, and BLIT! */
|
||||
if (okay && !SDL_RectEmpty(srcrect)) {
|
||||
SDL_BlitFunc RunBlit;
|
||||
SDL_BlitInfo *info = &src->map->info;
|
||||
|
||||
/* Set up the blit information */
|
||||
info->src = (Uint8 *)src->pixels +
|
||||
(Uint16)srcrect->y * src->pitch +
|
||||
(Uint16)srcrect->x * info->src_fmt->BytesPerPixel;
|
||||
info->src_w = srcrect->w;
|
||||
info->src_h = srcrect->h;
|
||||
info->src_pitch = src->pitch;
|
||||
info->src_skip =
|
||||
info->src_pitch - info->src_w * info->src_fmt->BytesPerPixel;
|
||||
info->dst =
|
||||
(Uint8 *)dst->pixels + (Uint16)dstrect->y * dst->pitch +
|
||||
(Uint16)dstrect->x * info->dst_fmt->BytesPerPixel;
|
||||
info->dst_w = dstrect->w;
|
||||
info->dst_h = dstrect->h;
|
||||
info->dst_pitch = dst->pitch;
|
||||
info->dst_skip =
|
||||
info->dst_pitch - info->dst_w * info->dst_fmt->BytesPerPixel;
|
||||
RunBlit = (SDL_BlitFunc)src->map->data;
|
||||
|
||||
/* Run the actual software blit */
|
||||
RunBlit(info);
|
||||
}
|
||||
|
||||
/* We need to unlock the surfaces if they're locked */
|
||||
if (dst_locked) {
|
||||
SDL_UnlockSurface(dst);
|
||||
}
|
||||
if (src_locked) {
|
||||
SDL_UnlockSurface(src);
|
||||
}
|
||||
/* Blit is done! */
|
||||
return okay ? 0 : -1;
|
||||
}
|
||||
|
||||
#if SDL_HAVE_BLIT_AUTO
|
||||
|
||||
#ifdef __MACOS__
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
static SDL_bool SDL_UseAltivecPrefetch(void)
|
||||
{
|
||||
const char key[] = "hw.l3cachesize";
|
||||
u_int64_t result = 0;
|
||||
size_t typeSize = sizeof(result);
|
||||
|
||||
if (sysctlbyname(key, &result, &typeSize, NULL, 0) == 0 && result > 0) {
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static SDL_bool SDL_UseAltivecPrefetch(void)
|
||||
{
|
||||
/* Just guess G4 */
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif /* __MACOS__ */
|
||||
|
||||
static SDL_BlitFunc SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int flags,
|
||||
SDL_BlitFuncEntry *entries)
|
||||
{
|
||||
int i, flagcheck = (flags & (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL | SDL_COPY_COLORKEY | SDL_COPY_NEAREST));
|
||||
static int features = 0x7fffffff;
|
||||
|
||||
/* Get the available CPU features */
|
||||
if (features == 0x7fffffff) {
|
||||
const char *override = SDL_getenv("SDL_BLIT_CPU_FEATURES");
|
||||
|
||||
features = SDL_CPU_ANY;
|
||||
|
||||
/* Allow an override for testing .. */
|
||||
if (override) {
|
||||
(void)SDL_sscanf(override, "%u", &features);
|
||||
} else {
|
||||
if (SDL_HasMMX()) {
|
||||
features |= SDL_CPU_MMX;
|
||||
}
|
||||
if (SDL_HasSSE()) {
|
||||
features |= SDL_CPU_SSE;
|
||||
}
|
||||
if (SDL_HasSSE2()) {
|
||||
features |= SDL_CPU_SSE2;
|
||||
}
|
||||
if (SDL_HasAltiVec()) {
|
||||
if (SDL_UseAltivecPrefetch()) {
|
||||
features |= SDL_CPU_ALTIVEC_PREFETCH;
|
||||
} else {
|
||||
features |= SDL_CPU_ALTIVEC_NOPREFETCH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; entries[i].func; ++i) {
|
||||
/* Check for matching pixel formats */
|
||||
if (src_format != entries[i].src_format) {
|
||||
continue;
|
||||
}
|
||||
if (dst_format != entries[i].dst_format) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check flags */
|
||||
if ((flagcheck & entries[i].flags) != flagcheck) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check CPU features */
|
||||
if ((entries[i].cpu & features) != entries[i].cpu) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We found the best one! */
|
||||
return entries[i].func;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif /* SDL_HAVE_BLIT_AUTO */
|
||||
|
||||
/* Figure out which of many blit routines to set up on a surface */
|
||||
int SDL_CalculateBlit(SDL_Surface *surface)
|
||||
{
|
||||
SDL_BlitFunc blit = NULL;
|
||||
SDL_BlitMap *map = surface->map;
|
||||
SDL_Surface *dst = map->dst;
|
||||
|
||||
/* We don't currently support blitting to < 8 bpp surfaces */
|
||||
if (dst->format->BitsPerPixel < 8) {
|
||||
SDL_InvalidateMap(map);
|
||||
return SDL_SetError("Blit combination not supported");
|
||||
}
|
||||
|
||||
#if SDL_HAVE_RLE
|
||||
/* Clean everything out to start */
|
||||
if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
|
||||
SDL_UnRLESurface(surface, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
map->blit = SDL_SoftBlit;
|
||||
map->info.src_fmt = surface->format;
|
||||
map->info.src_pitch = surface->pitch;
|
||||
map->info.dst_fmt = dst->format;
|
||||
map->info.dst_pitch = dst->pitch;
|
||||
|
||||
#if SDL_HAVE_RLE
|
||||
/* See if we can do RLE acceleration */
|
||||
if (map->info.flags & SDL_COPY_RLE_DESIRED) {
|
||||
if (SDL_RLESurface(surface) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Choose a standard blit function */
|
||||
if (map->identity && !(map->info.flags & ~SDL_COPY_RLE_DESIRED)) {
|
||||
blit = SDL_BlitCopy;
|
||||
} else if (surface->format->Rloss > 8 || dst->format->Rloss > 8) {
|
||||
blit = SDL_Blit_Slow;
|
||||
}
|
||||
#if SDL_HAVE_BLIT_0
|
||||
else if (surface->format->BitsPerPixel < 8 &&
|
||||
SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
|
||||
blit = SDL_CalculateBlit0(surface);
|
||||
}
|
||||
#endif
|
||||
#if SDL_HAVE_BLIT_1
|
||||
else if (surface->format->BytesPerPixel == 1 &&
|
||||
SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
|
||||
blit = SDL_CalculateBlit1(surface);
|
||||
}
|
||||
#endif
|
||||
#if SDL_HAVE_BLIT_A
|
||||
else if (map->info.flags & SDL_COPY_BLEND) {
|
||||
blit = SDL_CalculateBlitA(surface);
|
||||
}
|
||||
#endif
|
||||
#if SDL_HAVE_BLIT_N
|
||||
else {
|
||||
blit = SDL_CalculateBlitN(surface);
|
||||
}
|
||||
#endif
|
||||
#if SDL_HAVE_BLIT_AUTO
|
||||
if (blit == NULL) {
|
||||
Uint32 src_format = surface->format->format;
|
||||
Uint32 dst_format = dst->format->format;
|
||||
|
||||
blit =
|
||||
SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags,
|
||||
SDL_GeneratedBlitFuncTable);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TEST_SLOW_BLIT
|
||||
if (blit == NULL)
|
||||
#endif
|
||||
{
|
||||
Uint32 src_format = surface->format->format;
|
||||
Uint32 dst_format = dst->format->format;
|
||||
|
||||
if (!SDL_ISPIXELFORMAT_INDEXED(src_format) &&
|
||||
!SDL_ISPIXELFORMAT_FOURCC(src_format) &&
|
||||
!SDL_ISPIXELFORMAT_INDEXED(dst_format) &&
|
||||
!SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
|
||||
blit = SDL_Blit_Slow;
|
||||
}
|
||||
}
|
||||
map->data = blit;
|
||||
|
||||
/* Make sure we have a blit function */
|
||||
if (blit == NULL) {
|
||||
SDL_InvalidateMap(map);
|
||||
return SDL_SetError("Blit combination not supported");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
581
external/sdl/SDL/src/video/SDL_blit.h
vendored
Normal file
581
external/sdl/SDL/src/video/SDL_blit.h
vendored
Normal file
@ -0,0 +1,581 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_blit_h_
|
||||
#define SDL_blit_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];
|
||||
|
||||
/* SDL blit copy flags */
|
||||
#define SDL_COPY_MODULATE_COLOR 0x00000001
|
||||
#define SDL_COPY_MODULATE_ALPHA 0x00000002
|
||||
#define SDL_COPY_BLEND 0x00000010
|
||||
#define SDL_COPY_ADD 0x00000020
|
||||
#define SDL_COPY_MOD 0x00000040
|
||||
#define SDL_COPY_MUL 0x00000080
|
||||
#define SDL_COPY_COLORKEY 0x00000100
|
||||
#define SDL_COPY_NEAREST 0x00000200
|
||||
#define SDL_COPY_RLE_DESIRED 0x00001000
|
||||
#define SDL_COPY_RLE_COLORKEY 0x00002000
|
||||
#define SDL_COPY_RLE_ALPHAKEY 0x00004000
|
||||
#define SDL_COPY_RLE_MASK (SDL_COPY_RLE_DESIRED | SDL_COPY_RLE_COLORKEY | SDL_COPY_RLE_ALPHAKEY)
|
||||
|
||||
/* SDL blit CPU flags */
|
||||
#define SDL_CPU_ANY 0x00000000
|
||||
#define SDL_CPU_MMX 0x00000001
|
||||
#define SDL_CPU_SSE 0x00000002
|
||||
#define SDL_CPU_SSE2 0x00000004
|
||||
#define SDL_CPU_ALTIVEC_PREFETCH 0x00000008
|
||||
#define SDL_CPU_ALTIVEC_NOPREFETCH 0x00000010
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Uint8 *src;
|
||||
int src_w, src_h;
|
||||
int src_pitch;
|
||||
int src_skip;
|
||||
Uint8 *dst;
|
||||
int dst_w, dst_h;
|
||||
int dst_pitch;
|
||||
int dst_skip;
|
||||
SDL_PixelFormat *src_fmt;
|
||||
SDL_PixelFormat *dst_fmt;
|
||||
Uint8 *table;
|
||||
int flags;
|
||||
Uint32 colorkey;
|
||||
Uint8 r, g, b, a;
|
||||
} SDL_BlitInfo;
|
||||
|
||||
typedef void (*SDL_BlitFunc)(SDL_BlitInfo *info);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Uint32 src_format;
|
||||
Uint32 dst_format;
|
||||
int flags;
|
||||
int cpu;
|
||||
SDL_BlitFunc func;
|
||||
} SDL_BlitFuncEntry;
|
||||
|
||||
/* Blit mapping definition */
|
||||
/* typedef'ed in SDL_surface.h */
|
||||
struct SDL_BlitMap
|
||||
{
|
||||
SDL_Surface *dst;
|
||||
int identity;
|
||||
SDL_blit blit;
|
||||
void *data;
|
||||
SDL_BlitInfo info;
|
||||
|
||||
/* the version count matches the destination; mismatch indicates
|
||||
an invalid mapping */
|
||||
Uint32 dst_palette_version;
|
||||
Uint32 src_palette_version;
|
||||
};
|
||||
|
||||
/* Functions found in SDL_blit.c */
|
||||
extern int SDL_CalculateBlit(SDL_Surface *surface);
|
||||
|
||||
/* Functions found in SDL_blit_*.c */
|
||||
extern SDL_BlitFunc SDL_CalculateBlit0(SDL_Surface *surface);
|
||||
extern SDL_BlitFunc SDL_CalculateBlit1(SDL_Surface *surface);
|
||||
extern SDL_BlitFunc SDL_CalculateBlitN(SDL_Surface *surface);
|
||||
extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface);
|
||||
|
||||
/*
|
||||
* Useful macros for blitting routines
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define DECLARE_ALIGNED(t, v, a) t __attribute__((aligned(a))) v
|
||||
#elif defined(_MSC_VER)
|
||||
#define DECLARE_ALIGNED(t, v, a) __declspec(align(a)) t v
|
||||
#else
|
||||
#define DECLARE_ALIGNED(t, v, a) t v
|
||||
#endif
|
||||
|
||||
/* Load pixel of the specified format from a buffer and get its R-G-B values */
|
||||
#define RGB_FROM_PIXEL(Pixel, fmt, r, g, b) \
|
||||
{ \
|
||||
r = SDL_expand_byte[fmt->Rloss][((Pixel & fmt->Rmask) >> fmt->Rshift)]; \
|
||||
g = SDL_expand_byte[fmt->Gloss][((Pixel & fmt->Gmask) >> fmt->Gshift)]; \
|
||||
b = SDL_expand_byte[fmt->Bloss][((Pixel & fmt->Bmask) >> fmt->Bshift)]; \
|
||||
}
|
||||
#define RGB_FROM_RGB565(Pixel, r, g, b) \
|
||||
{ \
|
||||
r = SDL_expand_byte[3][((Pixel & 0xF800) >> 11)]; \
|
||||
g = SDL_expand_byte[2][((Pixel & 0x07E0) >> 5)]; \
|
||||
b = SDL_expand_byte[3][(Pixel & 0x001F)]; \
|
||||
}
|
||||
#define RGB_FROM_RGB555(Pixel, r, g, b) \
|
||||
{ \
|
||||
r = SDL_expand_byte[3][((Pixel & 0x7C00) >> 10)]; \
|
||||
g = SDL_expand_byte[3][((Pixel & 0x03E0) >> 5)]; \
|
||||
b = SDL_expand_byte[3][(Pixel & 0x001F)]; \
|
||||
}
|
||||
#define RGB_FROM_XRGB8888(Pixel, r, g, b) \
|
||||
{ \
|
||||
r = ((Pixel & 0xFF0000) >> 16); \
|
||||
g = ((Pixel & 0xFF00) >> 8); \
|
||||
b = (Pixel & 0xFF); \
|
||||
}
|
||||
#define RETRIEVE_RGB_PIXEL(buf, bpp, Pixel) \
|
||||
do { \
|
||||
switch (bpp) { \
|
||||
case 1: \
|
||||
Pixel = *((Uint8 *)(buf)); \
|
||||
break; \
|
||||
\
|
||||
case 2: \
|
||||
Pixel = *((Uint16 *)(buf)); \
|
||||
break; \
|
||||
\
|
||||
case 3: \
|
||||
{ \
|
||||
Uint8 *B = (Uint8 *)(buf); \
|
||||
if (SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
|
||||
Pixel = B[0] + (B[1] << 8) + (B[2] << 16); \
|
||||
} else { \
|
||||
Pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \
|
||||
} \
|
||||
} break; \
|
||||
\
|
||||
case 4: \
|
||||
Pixel = *((Uint32 *)(buf)); \
|
||||
break; \
|
||||
\
|
||||
default: \
|
||||
Pixel = 0; /* stop gcc complaints */ \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DISEMBLE_RGB(buf, bpp, fmt, Pixel, r, g, b) \
|
||||
do { \
|
||||
switch (bpp) { \
|
||||
case 1: \
|
||||
Pixel = *((Uint8 *)(buf)); \
|
||||
RGB_FROM_PIXEL(Pixel, fmt, r, g, b); \
|
||||
break; \
|
||||
\
|
||||
case 2: \
|
||||
Pixel = *((Uint16 *)(buf)); \
|
||||
RGB_FROM_PIXEL(Pixel, fmt, r, g, b); \
|
||||
break; \
|
||||
\
|
||||
case 3: \
|
||||
{ \
|
||||
Pixel = 0; \
|
||||
if (SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
|
||||
r = *((buf) + fmt->Rshift / 8); \
|
||||
g = *((buf) + fmt->Gshift / 8); \
|
||||
b = *((buf) + fmt->Bshift / 8); \
|
||||
} else { \
|
||||
r = *((buf) + 2 - fmt->Rshift / 8); \
|
||||
g = *((buf) + 2 - fmt->Gshift / 8); \
|
||||
b = *((buf) + 2 - fmt->Bshift / 8); \
|
||||
} \
|
||||
} break; \
|
||||
\
|
||||
case 4: \
|
||||
Pixel = *((Uint32 *)(buf)); \
|
||||
RGB_FROM_PIXEL(Pixel, fmt, r, g, b); \
|
||||
break; \
|
||||
\
|
||||
default: \
|
||||
/* stop gcc complaints */ \
|
||||
Pixel = 0; \
|
||||
r = g = b = 0; \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Assemble R-G-B values into a specified pixel format and store them */
|
||||
#define PIXEL_FROM_RGB(Pixel, fmt, r, g, b) \
|
||||
{ \
|
||||
Pixel = ((r >> fmt->Rloss) << fmt->Rshift) | \
|
||||
((g >> fmt->Gloss) << fmt->Gshift) | \
|
||||
((b >> fmt->Bloss) << fmt->Bshift) | \
|
||||
fmt->Amask; \
|
||||
}
|
||||
#define RGB565_FROM_RGB(Pixel, r, g, b) \
|
||||
{ \
|
||||
Pixel = (Uint16)(((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)); \
|
||||
}
|
||||
#define RGB555_FROM_RGB(Pixel, r, g, b) \
|
||||
{ \
|
||||
Pixel = (Uint16)(((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)); \
|
||||
}
|
||||
#define XRGB8888_FROM_RGB(Pixel, r, g, b) \
|
||||
{ \
|
||||
Pixel = (r << 16) | (g << 8) | b; \
|
||||
}
|
||||
#define ARGB8888_FROM_RGBA(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
Pixel = (a << 24) | (r << 16) | (g << 8) | b; \
|
||||
}
|
||||
#define RGBA8888_FROM_RGBA(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
Pixel = (r << 24) | (g << 16) | (b << 8) | a; \
|
||||
}
|
||||
#define ABGR8888_FROM_RGBA(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
Pixel = (a << 24) | (b << 16) | (g << 8) | r; \
|
||||
}
|
||||
#define BGRA8888_FROM_RGBA(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
Pixel = (b << 24) | (g << 16) | (r << 8) | a; \
|
||||
}
|
||||
#define ARGB2101010_FROM_RGBA(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
r = r ? ((r << 2) | 0x3) : 0; \
|
||||
g = g ? ((g << 2) | 0x3) : 0; \
|
||||
b = b ? ((b << 2) | 0x3) : 0; \
|
||||
a = (a * 3) / 255; \
|
||||
Pixel = (a << 30) | (r << 20) | (g << 10) | b; \
|
||||
}
|
||||
#define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) \
|
||||
{ \
|
||||
switch (bpp) { \
|
||||
case 1: \
|
||||
{ \
|
||||
Uint8 _pixel; \
|
||||
\
|
||||
PIXEL_FROM_RGB(_pixel, fmt, r, g, b); \
|
||||
*((Uint8 *)(buf)) = _pixel; \
|
||||
} break; \
|
||||
\
|
||||
case 2: \
|
||||
{ \
|
||||
Uint16 _pixel; \
|
||||
\
|
||||
PIXEL_FROM_RGB(_pixel, fmt, r, g, b); \
|
||||
*((Uint16 *)(buf)) = _pixel; \
|
||||
} break; \
|
||||
\
|
||||
case 3: \
|
||||
{ \
|
||||
if (SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
|
||||
*((buf) + fmt->Rshift / 8) = r; \
|
||||
*((buf) + fmt->Gshift / 8) = g; \
|
||||
*((buf) + fmt->Bshift / 8) = b; \
|
||||
} else { \
|
||||
*((buf) + 2 - fmt->Rshift / 8) = r; \
|
||||
*((buf) + 2 - fmt->Gshift / 8) = g; \
|
||||
*((buf) + 2 - fmt->Bshift / 8) = b; \
|
||||
} \
|
||||
} break; \
|
||||
\
|
||||
case 4: \
|
||||
{ \
|
||||
Uint32 _pixel; \
|
||||
\
|
||||
PIXEL_FROM_RGB(_pixel, fmt, r, g, b); \
|
||||
*((Uint32 *)(buf)) = _pixel; \
|
||||
} break; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* FIXME: Should we rescale alpha into 0..255 here? */
|
||||
#define RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a) \
|
||||
{ \
|
||||
r = SDL_expand_byte[fmt->Rloss][((Pixel & fmt->Rmask) >> fmt->Rshift)]; \
|
||||
g = SDL_expand_byte[fmt->Gloss][((Pixel & fmt->Gmask) >> fmt->Gshift)]; \
|
||||
b = SDL_expand_byte[fmt->Bloss][((Pixel & fmt->Bmask) >> fmt->Bshift)]; \
|
||||
a = SDL_expand_byte[fmt->Aloss][((Pixel & fmt->Amask) >> fmt->Ashift)]; \
|
||||
}
|
||||
#define RGBA_FROM_8888(Pixel, fmt, r, g, b, a) \
|
||||
{ \
|
||||
r = (Pixel & fmt->Rmask) >> fmt->Rshift; \
|
||||
g = (Pixel & fmt->Gmask) >> fmt->Gshift; \
|
||||
b = (Pixel & fmt->Bmask) >> fmt->Bshift; \
|
||||
a = (Pixel & fmt->Amask) >> fmt->Ashift; \
|
||||
}
|
||||
#define RGBA_FROM_RGBA8888(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
r = (Pixel >> 24); \
|
||||
g = ((Pixel >> 16) & 0xFF); \
|
||||
b = ((Pixel >> 8) & 0xFF); \
|
||||
a = (Pixel & 0xFF); \
|
||||
}
|
||||
#define RGBA_FROM_ARGB8888(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
r = ((Pixel >> 16) & 0xFF); \
|
||||
g = ((Pixel >> 8) & 0xFF); \
|
||||
b = (Pixel & 0xFF); \
|
||||
a = (Pixel >> 24); \
|
||||
}
|
||||
#define RGBA_FROM_ABGR8888(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
r = (Pixel & 0xFF); \
|
||||
g = ((Pixel >> 8) & 0xFF); \
|
||||
b = ((Pixel >> 16) & 0xFF); \
|
||||
a = (Pixel >> 24); \
|
||||
}
|
||||
#define RGBA_FROM_BGRA8888(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
r = ((Pixel >> 8) & 0xFF); \
|
||||
g = ((Pixel >> 16) & 0xFF); \
|
||||
b = (Pixel >> 24); \
|
||||
a = (Pixel & 0xFF); \
|
||||
}
|
||||
#define RGBA_FROM_ARGB2101010(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
r = ((Pixel >> 22) & 0xFF); \
|
||||
g = ((Pixel >> 12) & 0xFF); \
|
||||
b = ((Pixel >> 2) & 0xFF); \
|
||||
a = SDL_expand_byte[6][(Pixel >> 30)]; \
|
||||
}
|
||||
#define DISEMBLE_RGBA(buf, bpp, fmt, Pixel, r, g, b, a) \
|
||||
do { \
|
||||
switch (bpp) { \
|
||||
case 1: \
|
||||
Pixel = *((Uint8 *)(buf)); \
|
||||
RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a); \
|
||||
break; \
|
||||
\
|
||||
case 2: \
|
||||
Pixel = *((Uint16 *)(buf)); \
|
||||
RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a); \
|
||||
break; \
|
||||
\
|
||||
case 3: \
|
||||
{ \
|
||||
Pixel = 0; \
|
||||
if (SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
|
||||
r = *((buf) + fmt->Rshift / 8); \
|
||||
g = *((buf) + fmt->Gshift / 8); \
|
||||
b = *((buf) + fmt->Bshift / 8); \
|
||||
} else { \
|
||||
r = *((buf) + 2 - fmt->Rshift / 8); \
|
||||
g = *((buf) + 2 - fmt->Gshift / 8); \
|
||||
b = *((buf) + 2 - fmt->Bshift / 8); \
|
||||
} \
|
||||
a = 0xFF; \
|
||||
} break; \
|
||||
\
|
||||
case 4: \
|
||||
Pixel = *((Uint32 *)(buf)); \
|
||||
RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a); \
|
||||
break; \
|
||||
\
|
||||
default: \
|
||||
/* stop gcc complaints */ \
|
||||
Pixel = 0; \
|
||||
r = g = b = a = 0; \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* FIXME: this isn't correct, especially for Alpha (maximum != 255) */
|
||||
#define PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a) \
|
||||
{ \
|
||||
Pixel = ((r >> fmt->Rloss) << fmt->Rshift) | \
|
||||
((g >> fmt->Gloss) << fmt->Gshift) | \
|
||||
((b >> fmt->Bloss) << fmt->Bshift) | \
|
||||
((a >> fmt->Aloss) << fmt->Ashift); \
|
||||
}
|
||||
#define ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \
|
||||
{ \
|
||||
switch (bpp) { \
|
||||
case 1: \
|
||||
{ \
|
||||
Uint8 _pixel; \
|
||||
\
|
||||
PIXEL_FROM_RGBA(_pixel, fmt, r, g, b, a); \
|
||||
*((Uint8 *)(buf)) = _pixel; \
|
||||
} break; \
|
||||
\
|
||||
case 2: \
|
||||
{ \
|
||||
Uint16 _pixel; \
|
||||
\
|
||||
PIXEL_FROM_RGBA(_pixel, fmt, r, g, b, a); \
|
||||
*((Uint16 *)(buf)) = _pixel; \
|
||||
} break; \
|
||||
\
|
||||
case 3: \
|
||||
{ \
|
||||
if (SDL_BYTEORDER == SDL_LIL_ENDIAN) { \
|
||||
*((buf) + fmt->Rshift / 8) = r; \
|
||||
*((buf) + fmt->Gshift / 8) = g; \
|
||||
*((buf) + fmt->Bshift / 8) = b; \
|
||||
} else { \
|
||||
*((buf) + 2 - fmt->Rshift / 8) = r; \
|
||||
*((buf) + 2 - fmt->Gshift / 8) = g; \
|
||||
*((buf) + 2 - fmt->Bshift / 8) = b; \
|
||||
} \
|
||||
} break; \
|
||||
\
|
||||
case 4: \
|
||||
{ \
|
||||
Uint32 _pixel; \
|
||||
\
|
||||
PIXEL_FROM_RGBA(_pixel, fmt, r, g, b, a); \
|
||||
*((Uint32 *)(buf)) = _pixel; \
|
||||
} break; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Blend the RGB values of two pixels with an alpha value */
|
||||
#define ALPHA_BLEND_RGB(sR, sG, sB, A, dR, dG, dB) \
|
||||
do { \
|
||||
dR = (Uint8)((((int)(sR - dR) * (int)A) / 255) + dR); \
|
||||
dG = (Uint8)((((int)(sG - dG) * (int)A) / 255) + dG); \
|
||||
dB = (Uint8)((((int)(sB - dB) * (int)A) / 255) + dB); \
|
||||
} while (0)
|
||||
|
||||
/* Blend the RGBA values of two pixels */
|
||||
#define ALPHA_BLEND_RGBA(sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||
do { \
|
||||
dR = (Uint8)((((int)(sR - dR) * (int)sA) / 255) + dR); \
|
||||
dG = (Uint8)((((int)(sG - dG) * (int)sA) / 255) + dG); \
|
||||
dB = (Uint8)((((int)(sB - dB) * (int)sA) / 255) + dB); \
|
||||
dA = (Uint8)((int)sA + dA - ((int)sA * dA) / 255); \
|
||||
} while (0)
|
||||
|
||||
/* This is a very useful loop for optimizing blitters */
|
||||
#if defined(_MSC_VER) && (_MSC_VER == 1300)
|
||||
/* There's a bug in the Visual C++ 7 optimizer when compiling this code */
|
||||
#else
|
||||
#define USE_DUFFS_LOOP
|
||||
#endif
|
||||
#ifdef USE_DUFFS_LOOP
|
||||
|
||||
/* 8-times unrolled loop */
|
||||
#define DUFFS_LOOP8(pixel_copy_increment, width) \
|
||||
{ \
|
||||
int n = (width + 7) / 8; \
|
||||
switch (width & 7) { \
|
||||
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); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* 4-times unrolled loop */
|
||||
#define DUFFS_LOOP4(pixel_copy_increment, width) \
|
||||
{ \
|
||||
int n = (width + 3) / 4; \
|
||||
switch (width & 3) { \
|
||||
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); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Use the 8-times version of the loop by default */
|
||||
#define DUFFS_LOOP(pixel_copy_increment, width) \
|
||||
DUFFS_LOOP8(pixel_copy_increment, width)
|
||||
|
||||
/* Special version of Duff's device for even more optimization */
|
||||
#define DUFFS_LOOP_124(pixel_copy_increment1, \
|
||||
pixel_copy_increment2, \
|
||||
pixel_copy_increment4, width) \
|
||||
{ \
|
||||
int n = width; \
|
||||
if (n & 1) { \
|
||||
pixel_copy_increment1; \
|
||||
n -= 1; \
|
||||
} \
|
||||
if (n & 2) { \
|
||||
pixel_copy_increment2; \
|
||||
n -= 2; \
|
||||
} \
|
||||
if (n & 4) { \
|
||||
pixel_copy_increment4; \
|
||||
n -= 4; \
|
||||
} \
|
||||
if (n) { \
|
||||
n /= 8; \
|
||||
do { \
|
||||
pixel_copy_increment4; \
|
||||
pixel_copy_increment4; \
|
||||
} while (--n > 0); \
|
||||
} \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Don't use Duff's device to unroll loops */
|
||||
#define DUFFS_LOOP(pixel_copy_increment, width) \
|
||||
{ \
|
||||
int n; \
|
||||
for (n = width; n > 0; --n) { \
|
||||
pixel_copy_increment; \
|
||||
} \
|
||||
}
|
||||
#define DUFFS_LOOP8(pixel_copy_increment, width) \
|
||||
DUFFS_LOOP(pixel_copy_increment, width)
|
||||
#define DUFFS_LOOP4(pixel_copy_increment, width) \
|
||||
DUFFS_LOOP(pixel_copy_increment, width)
|
||||
#define DUFFS_LOOP_124(pixel_copy_increment1, \
|
||||
pixel_copy_increment2, \
|
||||
pixel_copy_increment4, width) \
|
||||
DUFFS_LOOP(pixel_copy_increment1, width)
|
||||
|
||||
#endif /* USE_DUFFS_LOOP */
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 600)
|
||||
#pragma warning(disable : 4244) /* '=': conversion from 'X' to 'Y', possible loss of data */
|
||||
#endif
|
||||
|
||||
#endif /* SDL_blit_h_ */
|
793
external/sdl/SDL/src/video/SDL_blit_0.c
vendored
Normal file
793
external/sdl/SDL/src/video/SDL_blit_0.c
vendored
Normal file
@ -0,0 +1,793 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if SDL_HAVE_BLIT_0
|
||||
|
||||
#include "SDL_blit.h"
|
||||
|
||||
/* Functions to blit from bitmaps to other surfaces */
|
||||
|
||||
static void BlitBto1(SDL_BlitInfo *info)
|
||||
{
|
||||
int c;
|
||||
int width, height;
|
||||
Uint8 *src, *map, *dst;
|
||||
int srcskip, dstskip;
|
||||
|
||||
/* Set up some basic variables */
|
||||
width = info->dst_w;
|
||||
height = info->dst_h;
|
||||
src = info->src;
|
||||
srcskip = info->src_skip;
|
||||
dst = info->dst;
|
||||
dstskip = info->dst_skip;
|
||||
map = info->table;
|
||||
srcskip += width - (width + 7) / 8;
|
||||
|
||||
if (map) {
|
||||
if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x01);
|
||||
if (1) {
|
||||
*dst = map[bit];
|
||||
}
|
||||
dst++;
|
||||
byte >>= 1;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x80) >> 7;
|
||||
if (1) {
|
||||
*dst = map[bit];
|
||||
}
|
||||
dst++;
|
||||
byte <<= 1;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x01);
|
||||
if (1) {
|
||||
*dst = bit;
|
||||
}
|
||||
dst++;
|
||||
byte >>= 1;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x80) >> 7;
|
||||
if (1) {
|
||||
*dst = bit;
|
||||
}
|
||||
dst++;
|
||||
byte <<= 1;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BlitBto2(SDL_BlitInfo *info)
|
||||
{
|
||||
int c;
|
||||
int width, height;
|
||||
Uint8 *src;
|
||||
Uint16 *map, *dst;
|
||||
int srcskip, dstskip;
|
||||
|
||||
/* Set up some basic variables */
|
||||
width = info->dst_w;
|
||||
height = info->dst_h;
|
||||
src = info->src;
|
||||
srcskip = info->src_skip;
|
||||
dst = (Uint16 *)info->dst;
|
||||
dstskip = info->dst_skip / 2;
|
||||
map = (Uint16 *)info->table;
|
||||
srcskip += width - (width + 7) / 8;
|
||||
|
||||
if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x01);
|
||||
if (1) {
|
||||
*dst = map[bit];
|
||||
}
|
||||
byte >>= 1;
|
||||
dst++;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x80) >> 7;
|
||||
if (1) {
|
||||
*dst = map[bit];
|
||||
}
|
||||
byte <<= 1;
|
||||
dst++;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BlitBto3(SDL_BlitInfo *info)
|
||||
{
|
||||
int c, o;
|
||||
int width, height;
|
||||
Uint8 *src, *map, *dst;
|
||||
int srcskip, dstskip;
|
||||
|
||||
/* Set up some basic variables */
|
||||
width = info->dst_w;
|
||||
height = info->dst_h;
|
||||
src = info->src;
|
||||
srcskip = info->src_skip;
|
||||
dst = info->dst;
|
||||
dstskip = info->dst_skip;
|
||||
map = info->table;
|
||||
srcskip += width - (width + 7) / 8;
|
||||
|
||||
if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x01);
|
||||
if (1) {
|
||||
o = bit * 4;
|
||||
dst[0] = map[o++];
|
||||
dst[1] = map[o++];
|
||||
dst[2] = map[o++];
|
||||
}
|
||||
byte >>= 1;
|
||||
dst += 3;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x80) >> 7;
|
||||
if (1) {
|
||||
o = bit * 4;
|
||||
dst[0] = map[o++];
|
||||
dst[1] = map[o++];
|
||||
dst[2] = map[o++];
|
||||
}
|
||||
byte <<= 1;
|
||||
dst += 3;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BlitBto4(SDL_BlitInfo *info)
|
||||
{
|
||||
int width, height;
|
||||
Uint8 *src;
|
||||
Uint32 *map, *dst;
|
||||
int srcskip, dstskip;
|
||||
int c;
|
||||
|
||||
/* Set up some basic variables */
|
||||
width = info->dst_w;
|
||||
height = info->dst_h;
|
||||
src = info->src;
|
||||
srcskip = info->src_skip;
|
||||
dst = (Uint32 *)info->dst;
|
||||
dstskip = info->dst_skip / 4;
|
||||
map = (Uint32 *)info->table;
|
||||
srcskip += width - (width + 7) / 8;
|
||||
|
||||
if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x01);
|
||||
if (1) {
|
||||
*dst = map[bit];
|
||||
}
|
||||
byte >>= 1;
|
||||
dst++;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x80) >> 7;
|
||||
if (1) {
|
||||
*dst = map[bit];
|
||||
}
|
||||
byte <<= 1;
|
||||
dst++;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BlitBto1Key(SDL_BlitInfo *info)
|
||||
{
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
Uint8 *dst = info->dst;
|
||||
int srcskip = info->src_skip;
|
||||
int dstskip = info->dst_skip;
|
||||
Uint32 ckey = info->colorkey;
|
||||
Uint8 *palmap = info->table;
|
||||
int c;
|
||||
|
||||
/* Set up some basic variables */
|
||||
srcskip += width - (width + 7) / 8;
|
||||
|
||||
if (palmap) {
|
||||
if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x01);
|
||||
if (bit != ckey) {
|
||||
*dst = palmap[bit];
|
||||
}
|
||||
dst++;
|
||||
byte >>= 1;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x80) >> 7;
|
||||
if (bit != ckey) {
|
||||
*dst = palmap[bit];
|
||||
}
|
||||
dst++;
|
||||
byte <<= 1;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x01);
|
||||
if (bit != ckey) {
|
||||
*dst = bit;
|
||||
}
|
||||
dst++;
|
||||
byte >>= 1;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x80) >> 7;
|
||||
if (bit != ckey) {
|
||||
*dst = bit;
|
||||
}
|
||||
dst++;
|
||||
byte <<= 1;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BlitBto2Key(SDL_BlitInfo *info)
|
||||
{
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
Uint16 *dstp = (Uint16 *)info->dst;
|
||||
int srcskip = info->src_skip;
|
||||
int dstskip = info->dst_skip;
|
||||
Uint32 ckey = info->colorkey;
|
||||
Uint8 *palmap = info->table;
|
||||
int c;
|
||||
|
||||
/* Set up some basic variables */
|
||||
srcskip += width - (width + 7) / 8;
|
||||
dstskip /= 2;
|
||||
|
||||
if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x01);
|
||||
if (bit != ckey) {
|
||||
*dstp = ((Uint16 *)palmap)[bit];
|
||||
}
|
||||
byte >>= 1;
|
||||
dstp++;
|
||||
}
|
||||
src += srcskip;
|
||||
dstp += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x80) >> 7;
|
||||
if (bit != ckey) {
|
||||
*dstp = ((Uint16 *)palmap)[bit];
|
||||
}
|
||||
byte <<= 1;
|
||||
dstp++;
|
||||
}
|
||||
src += srcskip;
|
||||
dstp += dstskip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BlitBto3Key(SDL_BlitInfo *info)
|
||||
{
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
Uint8 *dst = info->dst;
|
||||
int srcskip = info->src_skip;
|
||||
int dstskip = info->dst_skip;
|
||||
Uint32 ckey = info->colorkey;
|
||||
Uint8 *palmap = info->table;
|
||||
int c;
|
||||
|
||||
/* Set up some basic variables */
|
||||
srcskip += width - (width + 7) / 8;
|
||||
|
||||
if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x01);
|
||||
if (bit != ckey) {
|
||||
SDL_memcpy(dst, &palmap[bit * 4], 3);
|
||||
}
|
||||
byte >>= 1;
|
||||
dst += 3;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x80) >> 7;
|
||||
if (bit != ckey) {
|
||||
SDL_memcpy(dst, &palmap[bit * 4], 3);
|
||||
}
|
||||
byte <<= 1;
|
||||
dst += 3;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BlitBto4Key(SDL_BlitInfo *info)
|
||||
{
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
Uint32 *dstp = (Uint32 *)info->dst;
|
||||
int srcskip = info->src_skip;
|
||||
int dstskip = info->dst_skip;
|
||||
Uint32 ckey = info->colorkey;
|
||||
Uint8 *palmap = info->table;
|
||||
int c;
|
||||
|
||||
/* Set up some basic variables */
|
||||
srcskip += width - (width + 7) / 8;
|
||||
dstskip /= 4;
|
||||
|
||||
if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x01);
|
||||
if (bit != ckey) {
|
||||
*dstp = ((Uint32 *)palmap)[bit];
|
||||
}
|
||||
byte >>= 1;
|
||||
dstp++;
|
||||
}
|
||||
src += srcskip;
|
||||
dstp += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x80) >> 7;
|
||||
if (bit != ckey) {
|
||||
*dstp = ((Uint32 *)palmap)[bit];
|
||||
}
|
||||
byte <<= 1;
|
||||
dstp++;
|
||||
}
|
||||
src += srcskip;
|
||||
dstp += dstskip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BlitBtoNAlpha(SDL_BlitInfo *info)
|
||||
{
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
Uint8 *dst = info->dst;
|
||||
int srcskip = info->src_skip;
|
||||
int dstskip = info->dst_skip;
|
||||
const SDL_Color *srcpal = info->src_fmt->palette->colors;
|
||||
SDL_PixelFormat *dstfmt = info->dst_fmt;
|
||||
int dstbpp;
|
||||
int c;
|
||||
Uint32 pixel;
|
||||
unsigned sR, sG, sB;
|
||||
unsigned dR, dG, dB, dA;
|
||||
const unsigned A = info->a;
|
||||
|
||||
/* Set up some basic variables */
|
||||
dstbpp = dstfmt->BytesPerPixel;
|
||||
srcskip += width - (width + 7) / 8;
|
||||
|
||||
if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x01);
|
||||
if (1) {
|
||||
sR = srcpal[bit].r;
|
||||
sG = srcpal[bit].g;
|
||||
sB = srcpal[bit].b;
|
||||
DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
|
||||
ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
|
||||
ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
|
||||
}
|
||||
byte >>= 1;
|
||||
dst += dstbpp;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x80) >> 7;
|
||||
if (1) {
|
||||
sR = srcpal[bit].r;
|
||||
sG = srcpal[bit].g;
|
||||
sB = srcpal[bit].b;
|
||||
DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
|
||||
ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
|
||||
ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
|
||||
}
|
||||
byte <<= 1;
|
||||
dst += dstbpp;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BlitBtoNAlphaKey(SDL_BlitInfo *info)
|
||||
{
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
Uint8 *dst = info->dst;
|
||||
int srcskip = info->src_skip;
|
||||
int dstskip = info->dst_skip;
|
||||
SDL_PixelFormat *srcfmt = info->src_fmt;
|
||||
SDL_PixelFormat *dstfmt = info->dst_fmt;
|
||||
const SDL_Color *srcpal = srcfmt->palette->colors;
|
||||
int dstbpp;
|
||||
int c;
|
||||
Uint32 pixel;
|
||||
unsigned sR, sG, sB;
|
||||
unsigned dR, dG, dB, dA;
|
||||
const unsigned A = info->a;
|
||||
Uint32 ckey = info->colorkey;
|
||||
|
||||
/* Set up some basic variables */
|
||||
dstbpp = dstfmt->BytesPerPixel;
|
||||
srcskip += width - (width + 7) / 8;
|
||||
|
||||
if (info->src_fmt->format == SDL_PIXELFORMAT_INDEX1LSB) {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x01);
|
||||
if (bit != ckey) {
|
||||
sR = srcpal[bit].r;
|
||||
sG = srcpal[bit].g;
|
||||
sB = srcpal[bit].b;
|
||||
DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
|
||||
ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
|
||||
ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
|
||||
}
|
||||
byte >>= 1;
|
||||
dst += dstbpp;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
Uint8 byte = 0, bit;
|
||||
for (c = 0; c < width; ++c) {
|
||||
if (!(c & 7)) {
|
||||
byte = *src++;
|
||||
}
|
||||
bit = (byte & 0x80) >> 7;
|
||||
if (bit != ckey) {
|
||||
sR = srcpal[bit].r;
|
||||
sG = srcpal[bit].g;
|
||||
sB = srcpal[bit].b;
|
||||
DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
|
||||
ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
|
||||
ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
|
||||
}
|
||||
byte <<= 1;
|
||||
dst += dstbpp;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const SDL_BlitFunc bitmap_blit[] = {
|
||||
(SDL_BlitFunc)NULL, BlitBto1, BlitBto2, BlitBto3, BlitBto4
|
||||
};
|
||||
|
||||
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)) {
|
||||
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)) {
|
||||
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->format == SDL_PIXELFORMAT_INDEX4MSB) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (surface->format->format == SDL_PIXELFORMAT_INDEX1MSB) {
|
||||
if (surface->map->dst->format->BitsPerPixel < 8) {
|
||||
which = 0;
|
||||
} else {
|
||||
which = surface->map->dst->format->BytesPerPixel;
|
||||
}
|
||||
switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) {
|
||||
case 0:
|
||||
return bitmap_blit[which];
|
||||
|
||||
case SDL_COPY_COLORKEY:
|
||||
return colorkey_blit[which];
|
||||
|
||||
case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
|
||||
return which >= 2 ? BlitBtoNAlpha : (SDL_BlitFunc)NULL;
|
||||
|
||||
case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
|
||||
return which >= 2 ? BlitBtoNAlphaKey : (SDL_BlitFunc)NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* SDL_HAVE_BLIT_0 */
|
548
external/sdl/SDL/src/video/SDL_blit_1.c
vendored
Normal file
548
external/sdl/SDL/src/video/SDL_blit_1.c
vendored
Normal file
@ -0,0 +1,548 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if SDL_HAVE_BLIT_1
|
||||
|
||||
#include "SDL_blit.h"
|
||||
#include "SDL_sysvideo.h"
|
||||
|
||||
/* Functions to blit from 8-bit surfaces to other surfaces */
|
||||
|
||||
static void Blit1to1(SDL_BlitInfo *info)
|
||||
{
|
||||
#ifndef USE_DUFFS_LOOP
|
||||
int c;
|
||||
#endif
|
||||
int width, height;
|
||||
Uint8 *src, *map, *dst;
|
||||
int srcskip, dstskip;
|
||||
|
||||
/* Set up some basic variables */
|
||||
width = info->dst_w;
|
||||
height = info->dst_h;
|
||||
src = info->src;
|
||||
srcskip = info->src_skip;
|
||||
dst = info->dst;
|
||||
dstskip = info->dst_skip;
|
||||
map = info->table;
|
||||
|
||||
while (height--) {
|
||||
#ifdef USE_DUFFS_LOOP
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
*dst = map[*src];
|
||||
}
|
||||
dst++;
|
||||
src++;
|
||||
, width);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
#else
|
||||
for (c = width; c; --c) {
|
||||
*dst = map[*src];
|
||||
dst++;
|
||||
src++;
|
||||
}
|
||||
#endif
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is now endian dependent */
|
||||
#ifndef USE_DUFFS_LOOP
|
||||
#if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
|
||||
#define HI 1
|
||||
#define LO 0
|
||||
#else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */
|
||||
#define HI 0
|
||||
#define LO 1
|
||||
#endif
|
||||
#endif
|
||||
static void Blit1to2(SDL_BlitInfo *info)
|
||||
{
|
||||
#ifndef USE_DUFFS_LOOP
|
||||
int c;
|
||||
#endif
|
||||
int width, height;
|
||||
Uint8 *src, *dst;
|
||||
Uint16 *map;
|
||||
int srcskip, dstskip;
|
||||
|
||||
/* Set up some basic variables */
|
||||
width = info->dst_w;
|
||||
height = info->dst_h;
|
||||
src = info->src;
|
||||
srcskip = info->src_skip;
|
||||
dst = info->dst;
|
||||
dstskip = info->dst_skip;
|
||||
map = (Uint16 *)info->table;
|
||||
|
||||
#ifdef USE_DUFFS_LOOP
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
*(Uint16 *)dst = map[*src++];
|
||||
dst += 2;
|
||||
},
|
||||
width);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
#else
|
||||
/* Memory align at 4-byte boundary, if necessary */
|
||||
if ((long)dst & 0x03) {
|
||||
/* Don't do anything if width is 0 */
|
||||
if (width == 0) {
|
||||
return;
|
||||
}
|
||||
--width;
|
||||
|
||||
while (height--) {
|
||||
/* Perform copy alignment */
|
||||
*(Uint16 *)dst = map[*src++];
|
||||
dst += 2;
|
||||
|
||||
/* Copy in 4 pixel chunks */
|
||||
for (c = width / 4; c; --c) {
|
||||
*(Uint32 *)dst = (map[src[HI]] << 16) | (map[src[LO]]);
|
||||
src += 2;
|
||||
dst += 4;
|
||||
*(Uint32 *)dst = (map[src[HI]] << 16) | (map[src[LO]]);
|
||||
src += 2;
|
||||
dst += 4;
|
||||
}
|
||||
/* Get any leftovers */
|
||||
switch (width & 3) {
|
||||
case 3:
|
||||
*(Uint16 *)dst = map[*src++];
|
||||
dst += 2;
|
||||
SDL_FALLTHROUGH;
|
||||
case 2:
|
||||
*(Uint32 *)dst = (map[src[HI]] << 16) | (map[src[LO]]);
|
||||
src += 2;
|
||||
dst += 4;
|
||||
break;
|
||||
case 1:
|
||||
*(Uint16 *)dst = map[*src++];
|
||||
dst += 2;
|
||||
break;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
/* Copy in 4 pixel chunks */
|
||||
for (c = width / 4; c; --c) {
|
||||
*(Uint32 *)dst = (map[src[HI]] << 16) | (map[src[LO]]);
|
||||
src += 2;
|
||||
dst += 4;
|
||||
*(Uint32 *)dst = (map[src[HI]] << 16) | (map[src[LO]]);
|
||||
src += 2;
|
||||
dst += 4;
|
||||
}
|
||||
/* Get any leftovers */
|
||||
switch (width & 3) {
|
||||
case 3:
|
||||
*(Uint16 *)dst = map[*src++];
|
||||
dst += 2;
|
||||
SDL_FALLTHROUGH;
|
||||
case 2:
|
||||
*(Uint32 *)dst = (map[src[HI]] << 16) | (map[src[LO]]);
|
||||
src += 2;
|
||||
dst += 4;
|
||||
break;
|
||||
case 1:
|
||||
*(Uint16 *)dst = map[*src++];
|
||||
dst += 2;
|
||||
break;
|
||||
}
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
#endif /* USE_DUFFS_LOOP */
|
||||
}
|
||||
|
||||
static void Blit1to3(SDL_BlitInfo *info)
|
||||
{
|
||||
#ifndef USE_DUFFS_LOOP
|
||||
int c;
|
||||
#endif
|
||||
int o;
|
||||
int width, height;
|
||||
Uint8 *src, *map, *dst;
|
||||
int srcskip, dstskip;
|
||||
|
||||
/* Set up some basic variables */
|
||||
width = info->dst_w;
|
||||
height = info->dst_h;
|
||||
src = info->src;
|
||||
srcskip = info->src_skip;
|
||||
dst = info->dst;
|
||||
dstskip = info->dst_skip;
|
||||
map = info->table;
|
||||
|
||||
while (height--) {
|
||||
#ifdef USE_DUFFS_LOOP
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
o = *src * 4;
|
||||
dst[0] = map[o++];
|
||||
dst[1] = map[o++];
|
||||
dst[2] = map[o++];
|
||||
}
|
||||
src++;
|
||||
dst += 3;
|
||||
, width);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
#else
|
||||
for (c = width; c; --c) {
|
||||
o = *src * 4;
|
||||
dst[0] = map[o++];
|
||||
dst[1] = map[o++];
|
||||
dst[2] = map[o++];
|
||||
src++;
|
||||
dst += 3;
|
||||
}
|
||||
#endif /* USE_DUFFS_LOOP */
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
|
||||
static void Blit1to4(SDL_BlitInfo *info)
|
||||
{
|
||||
#ifndef USE_DUFFS_LOOP
|
||||
int c;
|
||||
#endif
|
||||
int width, height;
|
||||
Uint8 *src;
|
||||
Uint32 *map, *dst;
|
||||
int srcskip, dstskip;
|
||||
|
||||
/* Set up some basic variables */
|
||||
width = info->dst_w;
|
||||
height = info->dst_h;
|
||||
src = info->src;
|
||||
srcskip = info->src_skip;
|
||||
dst = (Uint32 *)info->dst;
|
||||
dstskip = info->dst_skip / 4;
|
||||
map = (Uint32 *)info->table;
|
||||
|
||||
while (height--) {
|
||||
#ifdef USE_DUFFS_LOOP
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
DUFFS_LOOP(
|
||||
*dst++ = map[*src++];
|
||||
, width);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
#else
|
||||
for (c = width / 4; c; --c) {
|
||||
*dst++ = map[*src++];
|
||||
*dst++ = map[*src++];
|
||||
*dst++ = map[*src++];
|
||||
*dst++ = map[*src++];
|
||||
}
|
||||
switch (width & 3) {
|
||||
case 3:
|
||||
*dst++ = map[*src++];
|
||||
SDL_FALLTHROUGH;
|
||||
case 2:
|
||||
*dst++ = map[*src++];
|
||||
SDL_FALLTHROUGH;
|
||||
case 1:
|
||||
*dst++ = map[*src++];
|
||||
}
|
||||
#endif /* USE_DUFFS_LOOP */
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
|
||||
static void Blit1to1Key(SDL_BlitInfo *info)
|
||||
{
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
int srcskip = info->src_skip;
|
||||
Uint8 *dst = info->dst;
|
||||
int dstskip = info->dst_skip;
|
||||
Uint8 *palmap = info->table;
|
||||
Uint32 ckey = info->colorkey;
|
||||
|
||||
if (palmap) {
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
if ( *src != ckey ) {
|
||||
*dst = palmap[*src];
|
||||
}
|
||||
dst++;
|
||||
src++;
|
||||
},
|
||||
width);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
if ( *src != ckey ) {
|
||||
*dst = *src;
|
||||
}
|
||||
dst++;
|
||||
src++;
|
||||
},
|
||||
width);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Blit1to2Key(SDL_BlitInfo *info)
|
||||
{
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
int srcskip = info->src_skip;
|
||||
Uint16 *dstp = (Uint16 *)info->dst;
|
||||
int dstskip = info->dst_skip;
|
||||
Uint16 *palmap = (Uint16 *)info->table;
|
||||
Uint32 ckey = info->colorkey;
|
||||
|
||||
/* Set up some basic variables */
|
||||
dstskip /= 2;
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
if ( *src != ckey ) {
|
||||
*dstp=palmap[*src];
|
||||
}
|
||||
src++;
|
||||
dstp++;
|
||||
},
|
||||
width);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
src += srcskip;
|
||||
dstp += dstskip;
|
||||
}
|
||||
}
|
||||
|
||||
static void Blit1to3Key(SDL_BlitInfo *info)
|
||||
{
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
int srcskip = info->src_skip;
|
||||
Uint8 *dst = info->dst;
|
||||
int dstskip = info->dst_skip;
|
||||
Uint8 *palmap = info->table;
|
||||
Uint32 ckey = info->colorkey;
|
||||
int o;
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
if ( *src != ckey ) {
|
||||
o = *src * 4;
|
||||
dst[0] = palmap[o++];
|
||||
dst[1] = palmap[o++];
|
||||
dst[2] = palmap[o++];
|
||||
}
|
||||
src++;
|
||||
dst += 3;
|
||||
},
|
||||
width);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
|
||||
static void Blit1to4Key(SDL_BlitInfo *info)
|
||||
{
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
int srcskip = info->src_skip;
|
||||
Uint32 *dstp = (Uint32 *)info->dst;
|
||||
int dstskip = info->dst_skip;
|
||||
Uint32 *palmap = (Uint32 *)info->table;
|
||||
Uint32 ckey = info->colorkey;
|
||||
|
||||
/* Set up some basic variables */
|
||||
dstskip /= 4;
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
if ( *src != ckey ) {
|
||||
*dstp = palmap[*src];
|
||||
}
|
||||
src++;
|
||||
dstp++;
|
||||
},
|
||||
width);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
src += srcskip;
|
||||
dstp += dstskip;
|
||||
}
|
||||
}
|
||||
|
||||
static void Blit1toNAlpha(SDL_BlitInfo *info)
|
||||
{
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
int srcskip = info->src_skip;
|
||||
Uint8 *dst = info->dst;
|
||||
int dstskip = info->dst_skip;
|
||||
SDL_PixelFormat *dstfmt = info->dst_fmt;
|
||||
const SDL_Color *srcpal = info->src_fmt->palette->colors;
|
||||
int dstbpp;
|
||||
Uint32 pixel;
|
||||
unsigned sR, sG, sB;
|
||||
unsigned dR, dG, dB, dA;
|
||||
const unsigned A = info->a;
|
||||
|
||||
/* Set up some basic variables */
|
||||
dstbpp = dstfmt->BytesPerPixel;
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
DUFFS_LOOP4(
|
||||
{
|
||||
sR = srcpal[*src].r;
|
||||
sG = srcpal[*src].g;
|
||||
sB = srcpal[*src].b;
|
||||
DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
|
||||
ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
|
||||
ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
|
||||
src++;
|
||||
dst += dstbpp;
|
||||
},
|
||||
width);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
|
||||
static void Blit1toNAlphaKey(SDL_BlitInfo *info)
|
||||
{
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
int srcskip = info->src_skip;
|
||||
Uint8 *dst = info->dst;
|
||||
int dstskip = info->dst_skip;
|
||||
SDL_PixelFormat *dstfmt = info->dst_fmt;
|
||||
const SDL_Color *srcpal = info->src_fmt->palette->colors;
|
||||
Uint32 ckey = info->colorkey;
|
||||
int dstbpp;
|
||||
Uint32 pixel;
|
||||
unsigned sR, sG, sB;
|
||||
unsigned dR, dG, dB, dA;
|
||||
const unsigned A = info->a;
|
||||
|
||||
/* Set up some basic variables */
|
||||
dstbpp = dstfmt->BytesPerPixel;
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
if ( *src != ckey ) {
|
||||
sR = srcpal[*src].r;
|
||||
sG = srcpal[*src].g;
|
||||
sB = srcpal[*src].b;
|
||||
DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
|
||||
ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
|
||||
ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
|
||||
}
|
||||
src++;
|
||||
dst += dstbpp;
|
||||
},
|
||||
width);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
||||
|
||||
static const SDL_BlitFunc one_blit[] = {
|
||||
(SDL_BlitFunc)NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4
|
||||
};
|
||||
|
||||
static const SDL_BlitFunc one_blitkey[] = {
|
||||
(SDL_BlitFunc)NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key
|
||||
};
|
||||
|
||||
SDL_BlitFunc SDL_CalculateBlit1(SDL_Surface *surface)
|
||||
{
|
||||
int which;
|
||||
SDL_PixelFormat *dstfmt;
|
||||
|
||||
dstfmt = surface->map->dst->format;
|
||||
if (dstfmt->BitsPerPixel < 8) {
|
||||
which = 0;
|
||||
} else {
|
||||
which = dstfmt->BytesPerPixel;
|
||||
}
|
||||
switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) {
|
||||
case 0:
|
||||
return one_blit[which];
|
||||
|
||||
case SDL_COPY_COLORKEY:
|
||||
return one_blitkey[which];
|
||||
|
||||
case SDL_COPY_COLORKEY | SDL_COPY_BLEND: /* this is not super-robust but handles a specific case we found sdl12-compat. */
|
||||
return (surface->map->info.a == 255) ? one_blitkey[which] : (SDL_BlitFunc)NULL;
|
||||
|
||||
case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
|
||||
/* Supporting 8bpp->8bpp alpha is doable but requires lots of
|
||||
tables which consume space and takes time to precompute,
|
||||
so is better left to the user */
|
||||
return which >= 2 ? Blit1toNAlpha : (SDL_BlitFunc)NULL;
|
||||
|
||||
case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
|
||||
return which >= 2 ? Blit1toNAlphaKey : (SDL_BlitFunc)NULL;
|
||||
}
|
||||
return (SDL_BlitFunc)NULL;
|
||||
}
|
||||
|
||||
#endif /* SDL_HAVE_BLIT_1 */
|
1471
external/sdl/SDL/src/video/SDL_blit_A.c
vendored
Normal file
1471
external/sdl/SDL/src/video/SDL_blit_A.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3448
external/sdl/SDL/src/video/SDL_blit_N.c
vendored
Normal file
3448
external/sdl/SDL/src/video/SDL_blit_N.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6995
external/sdl/SDL/src/video/SDL_blit_auto.c
vendored
Normal file
6995
external/sdl/SDL/src/video/SDL_blit_auto.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
33
external/sdl/SDL/src/video/SDL_blit_auto.h
vendored
Normal file
33
external/sdl/SDL/src/video/SDL_blit_auto.h
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/* DO NOT EDIT! This file is generated by sdlgenblit.pl */
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if SDL_HAVE_BLIT_AUTO
|
||||
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
|
||||
extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
|
||||
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
|
||||
#endif /* SDL_HAVE_BLIT_AUTO */
|
||||
|
164
external/sdl/SDL/src/video/SDL_blit_copy.c
vendored
Normal file
164
external/sdl/SDL/src/video/SDL_blit_copy.c
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_blit.h"
|
||||
#include "SDL_blit_copy.h"
|
||||
|
||||
#ifdef SDL_SSE_INTRINSICS
|
||||
/* This assumes 16-byte aligned src and dst */
|
||||
static SDL_INLINE void SDL_TARGETING("sse") SDL_memcpySSE(Uint8 *dst, const Uint8 *src, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
__m128 values[4];
|
||||
for (i = len / 64; i--;) {
|
||||
_mm_prefetch((const char *)src, _MM_HINT_NTA);
|
||||
values[0] = *(__m128 *)(src + 0);
|
||||
values[1] = *(__m128 *)(src + 16);
|
||||
values[2] = *(__m128 *)(src + 32);
|
||||
values[3] = *(__m128 *)(src + 48);
|
||||
_mm_stream_ps((float *)(dst + 0), values[0]);
|
||||
_mm_stream_ps((float *)(dst + 16), values[1]);
|
||||
_mm_stream_ps((float *)(dst + 32), values[2]);
|
||||
_mm_stream_ps((float *)(dst + 48), values[3]);
|
||||
src += 64;
|
||||
dst += 64;
|
||||
}
|
||||
|
||||
if (len & 63) {
|
||||
SDL_memcpy(dst, src, len & 63);
|
||||
}
|
||||
}
|
||||
#endif /* SDL_SSE_INTRINSICS */
|
||||
|
||||
#ifdef SDL_MMX_INTRINSICS
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4799)
|
||||
#endif
|
||||
static SDL_INLINE void SDL_TARGETING("mmx") SDL_memcpyMMX(Uint8 *dst, const Uint8 *src, int len)
|
||||
{
|
||||
int remain = len & 63;
|
||||
int i;
|
||||
|
||||
__m64 *d64 = (__m64 *)dst;
|
||||
__m64 *s64 = (__m64 *)src;
|
||||
|
||||
for (i = len / 64; i--;) {
|
||||
d64[0] = s64[0];
|
||||
d64[1] = s64[1];
|
||||
d64[2] = s64[2];
|
||||
d64[3] = s64[3];
|
||||
d64[4] = s64[4];
|
||||
d64[5] = s64[5];
|
||||
d64[6] = s64[6];
|
||||
d64[7] = s64[7];
|
||||
|
||||
d64 += 8;
|
||||
s64 += 8;
|
||||
}
|
||||
|
||||
if (remain) {
|
||||
const int skip = len - remain;
|
||||
dst += skip;
|
||||
src += skip;
|
||||
while (remain--) {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_INLINE void SDL_TARGETING("mmx") SDL_BlitCopyMMX(Uint8 *dst, const Uint8 *src, const int dstskip, const int srcskip, const int w, int h)
|
||||
{
|
||||
while (h--) {
|
||||
SDL_memcpyMMX(dst, src, w);
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
_mm_empty();
|
||||
}
|
||||
#endif /* SDL_MMX_INTRINSICS */
|
||||
|
||||
void SDL_BlitCopy(SDL_BlitInfo *info)
|
||||
{
|
||||
SDL_bool overlap;
|
||||
Uint8 *src, *dst;
|
||||
int w, h;
|
||||
int srcskip, dstskip;
|
||||
|
||||
w = info->dst_w * info->dst_fmt->BytesPerPixel;
|
||||
h = info->dst_h;
|
||||
src = info->src;
|
||||
dst = info->dst;
|
||||
srcskip = info->src_pitch;
|
||||
dstskip = info->dst_pitch;
|
||||
|
||||
/* Properly handle overlapping blits */
|
||||
if (src < dst) {
|
||||
overlap = (dst < (src + h * srcskip));
|
||||
} else {
|
||||
overlap = (src < (dst + h * dstskip));
|
||||
}
|
||||
if (overlap) {
|
||||
if (dst < src) {
|
||||
while (h--) {
|
||||
SDL_memmove(dst, src, w);
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
} else {
|
||||
src += ((h - 1) * srcskip);
|
||||
dst += ((h - 1) * dstskip);
|
||||
while (h--) {
|
||||
SDL_memmove(dst, src, w);
|
||||
src -= srcskip;
|
||||
dst -= dstskip;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SDL_SSE_INTRINSICS
|
||||
if (SDL_HasSSE() &&
|
||||
!((uintptr_t)src & 15) && !(srcskip & 15) &&
|
||||
!((uintptr_t)dst & 15) && !(dstskip & 15)) {
|
||||
while (h--) {
|
||||
SDL_memcpySSE(dst, src, w);
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SDL_MMX_INTRINSICS
|
||||
if (SDL_HasMMX() && !(srcskip & 7) && !(dstskip & 7)) {
|
||||
SDL_BlitCopyMMX(dst, src, dstskip, srcskip, w, h);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (h--) {
|
||||
SDL_memcpy(dst, src, w);
|
||||
src += srcskip;
|
||||
dst += dstskip;
|
||||
}
|
||||
}
|
27
external/sdl/SDL/src/video/SDL_blit_copy.h
vendored
Normal file
27
external/sdl/SDL/src/video/SDL_blit_copy.h
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_blit_copy_h_
|
||||
#define SDL_blit_copy_h_
|
||||
|
||||
void SDL_BlitCopy(SDL_BlitInfo *info);
|
||||
|
||||
#endif /* SDL_blit_copy_h_ */
|
198
external/sdl/SDL/src/video/SDL_blit_slow.c
vendored
Normal file
198
external/sdl/SDL/src/video/SDL_blit_slow.c
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_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 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.
|
||||
*/
|
||||
void SDL_Blit_Slow(SDL_BlitInfo *info)
|
||||
{
|
||||
const int flags = info->flags;
|
||||
const Uint32 modulateR = info->r;
|
||||
const Uint32 modulateG = info->g;
|
||||
const Uint32 modulateB = info->b;
|
||||
const Uint32 modulateA = info->a;
|
||||
Uint32 srcpixel;
|
||||
Uint32 srcR, srcG, srcB, srcA;
|
||||
Uint32 dstpixel;
|
||||
Uint32 dstR, dstG, dstB, dstA;
|
||||
int srcy, srcx;
|
||||
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;
|
||||
|
||||
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;
|
||||
posx = incx / 2; /* start at the middle of pixel */
|
||||
srcy = posy >> 16;
|
||||
while (n--) {
|
||||
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) {
|
||||
srcpixel = (srcR << src_fmt->Rshift) |
|
||||
(srcG << src_fmt->Gshift) | (srcB << src_fmt->Bshift);
|
||||
}
|
||||
if ((srcpixel & rgbmask) == ckey) {
|
||||
posx += incx;
|
||||
dst += dstbpp;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
|
||||
DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB, dstA);
|
||||
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
|
||||
DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB);
|
||||
dstA = 0xFF;
|
||||
} else {
|
||||
/* SDL_PIXELFORMAT_ARGB2101010 */
|
||||
dstpixel = *((Uint32 *)(dst));
|
||||
RGBA_FROM_ARGB2101010(dstpixel, dstR, dstG, dstB, dstA);
|
||||
}
|
||||
|
||||
if (flags & SDL_COPY_MODULATE_COLOR) {
|
||||
srcR = (srcR * modulateR) / 255;
|
||||
srcG = (srcG * modulateG) / 255;
|
||||
srcB = (srcB * modulateB) / 255;
|
||||
}
|
||||
if (flags & SDL_COPY_MODULATE_ALPHA) {
|
||||
srcA = (srcA * modulateA) / 255;
|
||||
}
|
||||
if (flags & (SDL_COPY_BLEND | SDL_COPY_ADD)) {
|
||||
/* This goes away if we ever use premultiplied alpha */
|
||||
if (srcA < 255) {
|
||||
srcR = (srcR * srcA) / 255;
|
||||
srcG = (srcG * srcA) / 255;
|
||||
srcB = (srcB * srcA) / 255;
|
||||
}
|
||||
}
|
||||
switch (flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL)) {
|
||||
case 0:
|
||||
dstR = srcR;
|
||||
dstG = srcG;
|
||||
dstB = srcB;
|
||||
dstA = srcA;
|
||||
break;
|
||||
case SDL_COPY_BLEND:
|
||||
dstR = srcR + ((255 - srcA) * dstR) / 255;
|
||||
dstG = srcG + ((255 - srcA) * dstG) / 255;
|
||||
dstB = srcB + ((255 - srcA) * dstB) / 255;
|
||||
dstA = srcA + ((255 - srcA) * dstA) / 255;
|
||||
break;
|
||||
case SDL_COPY_ADD:
|
||||
dstR = srcR + dstR;
|
||||
if (dstR > 255) {
|
||||
dstR = 255;
|
||||
}
|
||||
dstG = srcG + dstG;
|
||||
if (dstG > 255) {
|
||||
dstG = 255;
|
||||
}
|
||||
dstB = srcB + dstB;
|
||||
if (dstB > 255) {
|
||||
dstB = 255;
|
||||
}
|
||||
break;
|
||||
case SDL_COPY_MOD:
|
||||
dstR = (srcR * dstR) / 255;
|
||||
dstG = (srcG * dstG) / 255;
|
||||
dstB = (srcB * dstB) / 255;
|
||||
break;
|
||||
case SDL_COPY_MUL:
|
||||
dstR = ((srcR * dstR) + (dstR * (255 - srcA))) / 255;
|
||||
if (dstR > 255) {
|
||||
dstR = 255;
|
||||
}
|
||||
dstG = ((srcG * dstG) + (dstG * (255 - srcA))) / 255;
|
||||
if (dstG > 255) {
|
||||
dstG = 255;
|
||||
}
|
||||
dstB = ((srcB * dstB) + (dstB * (255 - srcA))) / 255;
|
||||
if (dstB > 255) {
|
||||
dstB = 255;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
|
||||
ASSEMBLE_RGBA(dst, dstbpp, dst_fmt, dstR, dstG, dstB, dstA);
|
||||
} 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;
|
||||
}
|
||||
posy += incy;
|
||||
info->dst += info->dst_pitch;
|
||||
}
|
||||
}
|
29
external/sdl/SDL/src/video/SDL_blit_slow.h
vendored
Normal file
29
external/sdl/SDL/src/video/SDL_blit_slow.h
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_blit_slow_h_
|
||||
#define SDL_blit_slow_h_
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
extern void SDL_Blit_Slow(SDL_BlitInfo *info);
|
||||
|
||||
#endif /* SDL_blit_slow_h_ */
|
881
external/sdl/SDL/src/video/SDL_bmp.c
vendored
Normal file
881
external/sdl/SDL/src/video/SDL_bmp.c
vendored
Normal file
@ -0,0 +1,881 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
/*
|
||||
Code to load and save surfaces in Windows BMP format.
|
||||
|
||||
Why support BMP format? Well, it's a native format for Windows, and
|
||||
most image processing programs can read and write it. It would be nice
|
||||
to be able to have at least one image format that we can natively load
|
||||
and save, and since PNG is so complex that it would bloat the library,
|
||||
BMP is a good alternative.
|
||||
|
||||
This code currently supports Win32 DIBs in uncompressed 8 and 24 bpp.
|
||||
*/
|
||||
|
||||
#include "SDL_pixels_c.h"
|
||||
|
||||
#define SAVE_32BIT_BMP
|
||||
|
||||
/* Compression encodings for BMP files */
|
||||
#ifndef BI_RGB
|
||||
#define BI_RGB 0
|
||||
#define BI_RLE8 1
|
||||
#define BI_RLE4 2
|
||||
#define BI_BITFIELDS 3
|
||||
#endif
|
||||
|
||||
/* Logical color space values for BMP files */
|
||||
#ifndef LCS_WINDOWS_COLOR_SPACE
|
||||
/* 0x57696E20 == "Win " */
|
||||
#define LCS_WINDOWS_COLOR_SPACE 0x57696E20
|
||||
#endif
|
||||
|
||||
static SDL_bool readRlePixels(SDL_Surface *surface, SDL_RWops *src, int isRle8)
|
||||
{
|
||||
/*
|
||||
| Sets the surface pixels from src. A bmp image is upside down.
|
||||
*/
|
||||
int pitch = surface->pitch;
|
||||
int height = surface->h;
|
||||
Uint8 *start = (Uint8 *)surface->pixels;
|
||||
Uint8 *end = start + (height * pitch);
|
||||
Uint8 *bits = end - pitch, *spot;
|
||||
int ofs = 0;
|
||||
Uint8 ch;
|
||||
Uint8 needsPad;
|
||||
|
||||
#define COPY_PIXEL(x) \
|
||||
spot = &bits[ofs++]; \
|
||||
if (spot >= start && spot < end) \
|
||||
*spot = (x)
|
||||
|
||||
/* !!! FIXME: for all these reads, handle error vs eof? handle -2 if non-blocking? */
|
||||
for (;;) {
|
||||
if (SDL_RWread(src, &ch, 1) <= 0) {
|
||||
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) <= 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
if (isRle8) { /* 256-color bitmap, compressed */
|
||||
do {
|
||||
COPY_PIXEL(pixel);
|
||||
} while (--ch);
|
||||
} else { /* 16-color bitmap, compressed */
|
||||
Uint8 pixel0 = pixel >> 4;
|
||||
Uint8 pixel1 = pixel & 0x0F;
|
||||
for (;;) {
|
||||
COPY_PIXEL(pixel0); /* even count, high nibble */
|
||||
if (!--ch) {
|
||||
break;
|
||||
}
|
||||
COPY_PIXEL(pixel1); /* odd count, low nibble */
|
||||
if (!--ch) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
| A leading zero is an escape; it may signal the end of the bitmap,
|
||||
| a cursor move, or some absolute data.
|
||||
| zero tag may be absolute mode or an escape
|
||||
*/
|
||||
if (SDL_RWread(src, &ch, 1) <= 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
switch (ch) {
|
||||
case 0: /* end of line */
|
||||
ofs = 0;
|
||||
bits -= pitch; /* go to previous */
|
||||
break;
|
||||
case 1: /* end of bitmap */
|
||||
return SDL_FALSE; /* success! */
|
||||
case 2: /* delta */
|
||||
if (SDL_RWread(src, &ch, 1) <= 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
ofs += ch;
|
||||
if (SDL_RWread(src, &ch, 1) <= 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
bits -= (ch * pitch);
|
||||
break;
|
||||
default: /* no compression */
|
||||
if (isRle8) {
|
||||
needsPad = (ch & 1);
|
||||
do {
|
||||
Uint8 pixel;
|
||||
if (SDL_RWread(src, &pixel, 1) <= 0) {
|
||||
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) <= 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
COPY_PIXEL(pixel >> 4);
|
||||
if (!--ch) {
|
||||
break;
|
||||
}
|
||||
COPY_PIXEL(pixel & 0x0F);
|
||||
if (!--ch) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* pad at even boundary */
|
||||
if (needsPad && (SDL_RWread(src, &ch, 1) <= 0)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CorrectAlphaChannel(SDL_Surface *surface)
|
||||
{
|
||||
/* Check to see if there is any alpha channel data */
|
||||
SDL_bool hasAlpha = SDL_FALSE;
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
int alphaChannelOffset = 0;
|
||||
#else
|
||||
int alphaChannelOffset = 3;
|
||||
#endif
|
||||
Uint8 *alpha = ((Uint8 *)surface->pixels) + alphaChannelOffset;
|
||||
Uint8 *end = alpha + surface->h * surface->pitch;
|
||||
|
||||
while (alpha < end) {
|
||||
if (*alpha != 0) {
|
||||
hasAlpha = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
alpha += 4;
|
||||
}
|
||||
|
||||
if (!hasAlpha) {
|
||||
alpha = ((Uint8 *)surface->pixels) + alphaChannelOffset;
|
||||
while (alpha < end) {
|
||||
*alpha = SDL_ALPHA_OPAQUE;
|
||||
alpha += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Surface *SDL_LoadBMP_RW(SDL_RWops *src, SDL_bool freesrc)
|
||||
{
|
||||
SDL_bool was_error;
|
||||
Sint64 fp_offset = 0;
|
||||
int bmpPitch;
|
||||
int i, pad;
|
||||
SDL_Surface *surface;
|
||||
Uint32 Rmask = 0;
|
||||
Uint32 Gmask = 0;
|
||||
Uint32 Bmask = 0;
|
||||
Uint32 Amask = 0;
|
||||
SDL_Palette *palette;
|
||||
Uint8 *bits;
|
||||
Uint8 *top, *end;
|
||||
SDL_bool topDown;
|
||||
int ExpandBMP;
|
||||
SDL_bool haveRGBMasks = SDL_FALSE;
|
||||
SDL_bool haveAlphaMask = SDL_FALSE;
|
||||
SDL_bool correctAlpha = SDL_FALSE;
|
||||
|
||||
/* The Win32 BMP file header (14 bytes) */
|
||||
char magic[2];
|
||||
/* Uint32 bfSize; */
|
||||
/* Uint16 bfReserved1; */
|
||||
/* Uint16 bfReserved2; */
|
||||
Uint32 bfOffBits;
|
||||
|
||||
/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
|
||||
Uint32 biSize;
|
||||
Sint32 biWidth = 0;
|
||||
Sint32 biHeight = 0;
|
||||
/* Uint16 biPlanes; */
|
||||
Uint16 biBitCount = 0;
|
||||
Uint32 biCompression = 0;
|
||||
/* Uint32 biSizeImage; */
|
||||
/* Sint32 biXPelsPerMeter; */
|
||||
/* Sint32 biYPelsPerMeter; */
|
||||
Uint32 biClrUsed = 0;
|
||||
/* Uint32 biClrImportant; */
|
||||
|
||||
/* Make sure we are passed a valid data source */
|
||||
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, 2) != 2) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
if (SDL_strncmp(magic, "BM", 2) != 0) {
|
||||
SDL_SetError("File is not a Windows BMP file");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
/* bfSize = */ SDL_ReadLE32(src);
|
||||
/* bfReserved1 = */ SDL_ReadLE16(src);
|
||||
/* bfReserved2 = */ SDL_ReadLE16(src);
|
||||
bfOffBits = SDL_ReadLE32(src);
|
||||
|
||||
/* Read the Win32 BITMAPINFOHEADER */
|
||||
biSize = SDL_ReadLE32(src);
|
||||
if (biSize == 12) { /* really old BITMAPCOREHEADER */
|
||||
biWidth = (Uint32)SDL_ReadLE16(src);
|
||||
biHeight = (Uint32)SDL_ReadLE16(src);
|
||||
/* biPlanes = */ SDL_ReadLE16(src);
|
||||
biBitCount = SDL_ReadLE16(src);
|
||||
biCompression = BI_RGB;
|
||||
/* biSizeImage = 0; */
|
||||
/* biXPelsPerMeter = 0; */
|
||||
/* biYPelsPerMeter = 0; */
|
||||
biClrUsed = 0;
|
||||
/* biClrImportant = 0; */
|
||||
} else if (biSize >= 40) { /* some version of BITMAPINFOHEADER */
|
||||
Uint32 headerSize;
|
||||
biWidth = SDL_ReadLE32(src);
|
||||
biHeight = SDL_ReadLE32(src);
|
||||
/* biPlanes = */ SDL_ReadLE16(src);
|
||||
biBitCount = SDL_ReadLE16(src);
|
||||
biCompression = SDL_ReadLE32(src);
|
||||
/* biSizeImage = */ SDL_ReadLE32(src);
|
||||
/* biXPelsPerMeter = */ SDL_ReadLE32(src);
|
||||
/* biYPelsPerMeter = */ SDL_ReadLE32(src);
|
||||
biClrUsed = SDL_ReadLE32(src);
|
||||
/* biClrImportant = */ SDL_ReadLE32(src);
|
||||
|
||||
/* 64 == BITMAPCOREHEADER2, an incompatible OS/2 2.x extension. Skip this stuff for now. */
|
||||
if (biSize != 64) {
|
||||
/* This is complicated. If compression is BI_BITFIELDS, then
|
||||
we have 3 DWORDS that specify the RGB masks. This is either
|
||||
stored here in an BITMAPV2INFOHEADER (which only differs in
|
||||
that it adds these RGB masks) and biSize >= 52, or we've got
|
||||
these masks stored in the exact same place, but strictly
|
||||
speaking, this is the bmiColors field in BITMAPINFO immediately
|
||||
following the legacy v1 info header, just past biSize. */
|
||||
if (biCompression == BI_BITFIELDS) {
|
||||
haveRGBMasks = SDL_TRUE;
|
||||
Rmask = SDL_ReadLE32(src);
|
||||
Gmask = SDL_ReadLE32(src);
|
||||
Bmask = SDL_ReadLE32(src);
|
||||
|
||||
/* ...v3 adds an alpha mask. */
|
||||
if (biSize >= 56) { /* BITMAPV3INFOHEADER; adds alpha mask */
|
||||
haveAlphaMask = SDL_TRUE;
|
||||
Amask = SDL_ReadLE32(src);
|
||||
}
|
||||
} else {
|
||||
/* the mask fields are ignored for v2+ headers if not BI_BITFIELD. */
|
||||
if (biSize >= 52) { /* BITMAPV2INFOHEADER; adds RGB masks */
|
||||
/*Rmask = */ SDL_ReadLE32(src);
|
||||
/*Gmask = */ SDL_ReadLE32(src);
|
||||
/*Bmask = */ SDL_ReadLE32(src);
|
||||
}
|
||||
if (biSize >= 56) { /* BITMAPV3INFOHEADER; adds alpha mask */
|
||||
/*Amask = */ SDL_ReadLE32(src);
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert other fields here; Wikipedia and MSDN say we're up to
|
||||
v5 of this header, but we ignore those for now (they add gamma,
|
||||
color spaces, etc). Ignoring the weird OS/2 2.x format, we
|
||||
currently parse up to v3 correctly (hopefully!). */
|
||||
}
|
||||
|
||||
/* skip any header bytes we didn't handle... */
|
||||
headerSize = (Uint32)(SDL_RWtell(src) - (fp_offset + 14));
|
||||
if (biSize > headerSize) {
|
||||
SDL_RWseek(src, (biSize - headerSize), SDL_RW_SEEK_CUR);
|
||||
}
|
||||
}
|
||||
if (biWidth <= 0 || biHeight == 0) {
|
||||
SDL_SetError("BMP file with bad dimensions (%" SDL_PRIs32 "x%" SDL_PRIs32 ")", biWidth, biHeight);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
if (biHeight < 0) {
|
||||
topDown = SDL_TRUE;
|
||||
biHeight = -biHeight;
|
||||
} else {
|
||||
topDown = SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Check for read error */
|
||||
if (SDL_strcmp(SDL_GetError(), "") != 0) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Expand 1, 2 and 4 bit bitmaps to 8 bits per pixel */
|
||||
switch (biBitCount) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
ExpandBMP = biBitCount;
|
||||
biBitCount = 8;
|
||||
break;
|
||||
case 0:
|
||||
case 3:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
SDL_SetError("%d-bpp BMP images are not supported", biBitCount);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
default:
|
||||
ExpandBMP = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* RLE4 and RLE8 BMP compression is supported */
|
||||
switch (biCompression) {
|
||||
case BI_RGB:
|
||||
/* If there are no masks, use the defaults */
|
||||
SDL_assert(!haveRGBMasks);
|
||||
SDL_assert(!haveAlphaMask);
|
||||
/* Default values for the BMP format */
|
||||
switch (biBitCount) {
|
||||
case 15:
|
||||
case 16:
|
||||
/* SDL_PIXELFORMAT_RGB555 or SDL_PIXELFORMAT_ARGB1555 if Amask */
|
||||
Rmask = 0x7C00;
|
||||
Gmask = 0x03E0;
|
||||
Bmask = 0x001F;
|
||||
break;
|
||||
case 24:
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
/* SDL_PIXELFORMAT_RGB24 */
|
||||
Rmask = 0x000000FF;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x00FF0000;
|
||||
#else
|
||||
/* SDL_PIXELFORMAT_BGR24 */
|
||||
Rmask = 0x00FF0000;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x000000FF;
|
||||
#endif
|
||||
break;
|
||||
case 32:
|
||||
/* We don't know if this has alpha channel or not */
|
||||
correctAlpha = SDL_TRUE;
|
||||
/* SDL_PIXELFORMAT_RGBA8888 */
|
||||
Amask = 0xFF000000;
|
||||
Rmask = 0x00FF0000;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x000000FF;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case BI_BITFIELDS:
|
||||
break; /* we handled this in the info header. */
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Create a compatible surface, note that the colors are RGB ordered */
|
||||
{
|
||||
Uint32 format;
|
||||
|
||||
/* Get the pixel format */
|
||||
format = SDL_GetPixelFormatEnumForMasks(biBitCount, Rmask, Gmask, Bmask, Amask);
|
||||
surface = SDL_CreateSurface(biWidth, biHeight, format);
|
||||
|
||||
if (surface == NULL) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load the palette, if any */
|
||||
palette = (surface->format)->palette;
|
||||
if (palette) {
|
||||
if (SDL_RWseek(src, fp_offset + 14 + biSize, SDL_RW_SEEK_SET) < 0) {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (biBitCount >= 32) { /* we shift biClrUsed by this value later. */
|
||||
SDL_SetError("Unsupported or incorrect biBitCount field");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
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) {
|
||||
/* !!! FIXME: this should check for i/o errors! */
|
||||
SDL_RWread(src, &palette->colors[i].b, 1);
|
||||
SDL_RWread(src, &palette->colors[i].g, 1);
|
||||
SDL_RWread(src, &palette->colors[i].r, 1);
|
||||
palette->colors[i].a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < (int)biClrUsed; ++i) {
|
||||
/* !!! FIXME: this should check for i/o errors! */
|
||||
SDL_RWread(src, &palette->colors[i].b, 1);
|
||||
SDL_RWread(src, &palette->colors[i].g, 1);
|
||||
SDL_RWread(src, &palette->colors[i].r, 1);
|
||||
SDL_RWread(src, &palette->colors[i].a, 1);
|
||||
|
||||
/* According to Microsoft documentation, the fourth element
|
||||
is reserved and must be zero, so we shouldn't treat it as
|
||||
alpha.
|
||||
*/
|
||||
palette->colors[i].a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
}
|
||||
palette->ncolors = biClrUsed;
|
||||
}
|
||||
|
||||
/* Read the surface pixels. Note that the bmp image is upside down */
|
||||
if (SDL_RWseek(src, fp_offset + bfOffBits, SDL_RW_SEEK_SET) < 0) {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
if ((biCompression == BI_RLE4) || (biCompression == BI_RLE8)) {
|
||||
was_error = readRlePixels(surface, src, biCompression == BI_RLE8);
|
||||
if (was_error) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
top = (Uint8 *)surface->pixels;
|
||||
end = (Uint8 *)surface->pixels + (surface->h * surface->pitch);
|
||||
switch (ExpandBMP) {
|
||||
case 1:
|
||||
bmpPitch = (biWidth + 7) >> 3;
|
||||
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
|
||||
break;
|
||||
case 2:
|
||||
bmpPitch = (biWidth + 3) >> 2;
|
||||
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
|
||||
break;
|
||||
case 4:
|
||||
bmpPitch = (biWidth + 1) >> 1;
|
||||
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
|
||||
break;
|
||||
default:
|
||||
pad = ((surface->pitch % 4) ? (4 - (surface->pitch % 4)) : 0);
|
||||
break;
|
||||
}
|
||||
if (topDown) {
|
||||
bits = top;
|
||||
} else {
|
||||
bits = end - surface->pitch;
|
||||
}
|
||||
while (bits >= top && bits < end) {
|
||||
switch (ExpandBMP) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
{
|
||||
Uint8 pixel = 0;
|
||||
int shift = (8 - ExpandBMP);
|
||||
for (i = 0; i < surface->w; ++i) {
|
||||
if (i % (8 / ExpandBMP) == 0) {
|
||||
if (SDL_RWread(src, &pixel, 1) != 1) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
bits[i] = (pixel >> shift);
|
||||
if (bits[i] >= biClrUsed) {
|
||||
SDL_SetError("A BMP image contains a pixel with a color out of the palette");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
pixel <<= ExpandBMP;
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
if (SDL_RWread(src, bits, surface->pitch) != surface->pitch) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
if (biBitCount == 8 && palette && biClrUsed < (1u << biBitCount)) {
|
||||
for (i = 0; i < surface->w; ++i) {
|
||||
if (bits[i] >= biClrUsed) {
|
||||
SDL_SetError("A BMP image contains a pixel with a color out of the palette");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
/* Byte-swap the pixels if needed. Note that the 24bpp
|
||||
case has already been taken care of above. */
|
||||
switch (biBitCount) {
|
||||
case 15:
|
||||
case 16:
|
||||
{
|
||||
Uint16 *pix = (Uint16 *)bits;
|
||||
for (i = 0; i < surface->w; i++) {
|
||||
pix[i] = SDL_Swap16(pix[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 32:
|
||||
{
|
||||
Uint32 *pix = (Uint32 *)bits;
|
||||
for (i = 0; i < surface->w; i++) {
|
||||
pix[i] = SDL_Swap32(pix[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
/* Skip padding bytes, ugh */
|
||||
if (pad) {
|
||||
Uint8 padbyte;
|
||||
for (i = 0; i < pad; ++i) {
|
||||
SDL_RWread(src, &padbyte, 1);
|
||||
}
|
||||
}
|
||||
if (topDown) {
|
||||
bits += surface->pitch;
|
||||
} else {
|
||||
bits -= surface->pitch;
|
||||
}
|
||||
}
|
||||
if (correctAlpha) {
|
||||
CorrectAlphaChannel(surface);
|
||||
}
|
||||
done:
|
||||
if (was_error) {
|
||||
if (src) {
|
||||
SDL_RWseek(src, fp_offset, SDL_RW_SEEK_SET);
|
||||
}
|
||||
SDL_DestroySurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
if (freesrc && src) {
|
||||
SDL_RWclose(src);
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
SDL_Surface *SDL_LoadBMP(const char *file)
|
||||
{
|
||||
return SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1);
|
||||
}
|
||||
|
||||
int SDL_SaveBMP_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst)
|
||||
{
|
||||
/* !!! FIXME: this calls SDL_ClearError() and then checks if an error happened during this function to
|
||||
!!! FIXME: decide if there was a problem, but there's risk of innocent things setting an error
|
||||
!!! FIXME: string for innocent unrelated reasons, and also, an app supplying its own RWops
|
||||
!!! FIXME: implementation may not set the error string on failure. We should check for i/o
|
||||
!!! FIXME: failures as we go, and return early if one occurs. */
|
||||
|
||||
Sint64 fp_offset;
|
||||
int i, pad;
|
||||
SDL_Surface *intermediate_surface;
|
||||
Uint8 *bits;
|
||||
SDL_bool save32bit = SDL_FALSE;
|
||||
SDL_bool saveLegacyBMP = SDL_FALSE;
|
||||
|
||||
/* The Win32 BMP file header (14 bytes) */
|
||||
char magic[2] = { 'B', 'M' };
|
||||
Uint32 bfSize;
|
||||
Uint16 bfReserved1;
|
||||
Uint16 bfReserved2;
|
||||
Uint32 bfOffBits;
|
||||
|
||||
/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
|
||||
Uint32 biSize;
|
||||
Sint32 biWidth;
|
||||
Sint32 biHeight;
|
||||
Uint16 biPlanes;
|
||||
Uint16 biBitCount;
|
||||
Uint32 biCompression;
|
||||
Uint32 biSizeImage;
|
||||
Sint32 biXPelsPerMeter;
|
||||
Sint32 biYPelsPerMeter;
|
||||
Uint32 biClrUsed;
|
||||
Uint32 biClrImportant;
|
||||
|
||||
/* The additional header members from the Win32 BITMAPV4HEADER struct (108 bytes in total) */
|
||||
Uint32 bV4RedMask = 0;
|
||||
Uint32 bV4GreenMask = 0;
|
||||
Uint32 bV4BlueMask = 0;
|
||||
Uint32 bV4AlphaMask = 0;
|
||||
Uint32 bV4CSType = 0;
|
||||
Sint32 bV4Endpoints[3 * 3] = { 0 };
|
||||
Uint32 bV4GammaRed = 0;
|
||||
Uint32 bV4GammaGreen = 0;
|
||||
Uint32 bV4GammaBlue = 0;
|
||||
|
||||
/* Make sure we have somewhere to save */
|
||||
intermediate_surface = NULL;
|
||||
if (dst) {
|
||||
#ifdef SAVE_32BIT_BMP
|
||||
/* We can save alpha information in a 32-bit BMP */
|
||||
if (surface->format->BitsPerPixel >= 8 &&
|
||||
(surface->format->Amask != 0 ||
|
||||
surface->map->info.flags & SDL_COPY_COLORKEY)) {
|
||||
save32bit = SDL_TRUE;
|
||||
}
|
||||
#endif /* SAVE_32BIT_BMP */
|
||||
|
||||
if (surface->format->palette != NULL && !save32bit) {
|
||||
if (surface->format->BitsPerPixel == 8) {
|
||||
intermediate_surface = surface;
|
||||
} else {
|
||||
SDL_SetError("%d bpp BMP files not supported",
|
||||
surface->format->BitsPerPixel);
|
||||
}
|
||||
} else if ((surface->format->BitsPerPixel == 24) && !save32bit &&
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
(surface->format->Rmask == 0x00FF0000) &&
|
||||
(surface->format->Gmask == 0x0000FF00) &&
|
||||
(surface->format->Bmask == 0x000000FF)
|
||||
#else
|
||||
(surface->format->Rmask == 0x000000FF) &&
|
||||
(surface->format->Gmask == 0x0000FF00) &&
|
||||
(surface->format->Bmask == 0x00FF0000)
|
||||
#endif
|
||||
) {
|
||||
intermediate_surface = surface;
|
||||
} else {
|
||||
SDL_PixelFormat format;
|
||||
|
||||
/* If the surface has a colorkey or alpha channel we'll save a
|
||||
32-bit BMP with alpha channel, otherwise save a 24-bit BMP. */
|
||||
if (save32bit) {
|
||||
SDL_InitFormat(&format, SDL_PIXELFORMAT_BGRA32);
|
||||
} else {
|
||||
SDL_InitFormat(&format, SDL_PIXELFORMAT_BGR24);
|
||||
}
|
||||
intermediate_surface = SDL_ConvertSurface(surface, &format);
|
||||
if (intermediate_surface == NULL) {
|
||||
SDL_SetError("Couldn't convert image to %d bpp",
|
||||
format.BitsPerPixel);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Set no error here because it may overwrite a more useful message from
|
||||
SDL_RWFromFile() if SDL_SaveBMP_RW() is called from SDL_SaveBMP(). */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (save32bit) {
|
||||
saveLegacyBMP = SDL_GetHintBoolean(SDL_HINT_BMP_SAVE_LEGACY_FORMAT, SDL_FALSE);
|
||||
}
|
||||
|
||||
if (intermediate_surface && (SDL_LockSurface(intermediate_surface) == 0)) {
|
||||
const int bw = intermediate_surface->w * intermediate_surface->format->BytesPerPixel;
|
||||
|
||||
/* Set the BMP file header values */
|
||||
bfSize = 0; /* We'll write this when we're done */
|
||||
bfReserved1 = 0;
|
||||
bfReserved2 = 0;
|
||||
bfOffBits = 0; /* We'll write this when we're done */
|
||||
|
||||
/* Write the BMP file header values */
|
||||
fp_offset = SDL_RWtell(dst);
|
||||
SDL_ClearError();
|
||||
SDL_RWwrite(dst, magic, 2);
|
||||
SDL_WriteLE32(dst, bfSize);
|
||||
SDL_WriteLE16(dst, bfReserved1);
|
||||
SDL_WriteLE16(dst, bfReserved2);
|
||||
SDL_WriteLE32(dst, bfOffBits);
|
||||
|
||||
/* Set the BMP info values */
|
||||
biSize = 40;
|
||||
biWidth = intermediate_surface->w;
|
||||
biHeight = intermediate_surface->h;
|
||||
biPlanes = 1;
|
||||
biBitCount = intermediate_surface->format->BitsPerPixel;
|
||||
biCompression = BI_RGB;
|
||||
biSizeImage = intermediate_surface->h * intermediate_surface->pitch;
|
||||
biXPelsPerMeter = 0;
|
||||
biYPelsPerMeter = 0;
|
||||
if (intermediate_surface->format->palette) {
|
||||
biClrUsed = intermediate_surface->format->palette->ncolors;
|
||||
} else {
|
||||
biClrUsed = 0;
|
||||
}
|
||||
biClrImportant = 0;
|
||||
|
||||
/* Set the BMP info values for the version 4 header */
|
||||
if (save32bit && !saveLegacyBMP) {
|
||||
biSize = 108;
|
||||
biCompression = BI_BITFIELDS;
|
||||
/* The BMP format is always little endian, these masks stay the same */
|
||||
bV4RedMask = 0x00ff0000;
|
||||
bV4GreenMask = 0x0000ff00;
|
||||
bV4BlueMask = 0x000000ff;
|
||||
bV4AlphaMask = 0xff000000;
|
||||
bV4CSType = LCS_WINDOWS_COLOR_SPACE;
|
||||
bV4GammaRed = 0;
|
||||
bV4GammaGreen = 0;
|
||||
bV4GammaBlue = 0;
|
||||
}
|
||||
|
||||
/* Write the BMP info values */
|
||||
SDL_WriteLE32(dst, biSize);
|
||||
SDL_WriteLE32(dst, biWidth);
|
||||
SDL_WriteLE32(dst, biHeight);
|
||||
SDL_WriteLE16(dst, biPlanes);
|
||||
SDL_WriteLE16(dst, biBitCount);
|
||||
SDL_WriteLE32(dst, biCompression);
|
||||
SDL_WriteLE32(dst, biSizeImage);
|
||||
SDL_WriteLE32(dst, biXPelsPerMeter);
|
||||
SDL_WriteLE32(dst, biYPelsPerMeter);
|
||||
SDL_WriteLE32(dst, biClrUsed);
|
||||
SDL_WriteLE32(dst, biClrImportant);
|
||||
|
||||
/* Write the BMP info values for the version 4 header */
|
||||
if (save32bit && !saveLegacyBMP) {
|
||||
SDL_WriteLE32(dst, bV4RedMask);
|
||||
SDL_WriteLE32(dst, bV4GreenMask);
|
||||
SDL_WriteLE32(dst, bV4BlueMask);
|
||||
SDL_WriteLE32(dst, bV4AlphaMask);
|
||||
SDL_WriteLE32(dst, bV4CSType);
|
||||
for (i = 0; i < 3 * 3; i++) {
|
||||
SDL_WriteLE32(dst, bV4Endpoints[i]);
|
||||
}
|
||||
SDL_WriteLE32(dst, bV4GammaRed);
|
||||
SDL_WriteLE32(dst, bV4GammaGreen);
|
||||
SDL_WriteLE32(dst, bV4GammaBlue);
|
||||
}
|
||||
|
||||
/* Write the palette (in BGR color order) */
|
||||
if (intermediate_surface->format->palette) {
|
||||
SDL_Color *colors;
|
||||
int ncolors;
|
||||
|
||||
colors = intermediate_surface->format->palette->colors;
|
||||
ncolors = intermediate_surface->format->palette->ncolors;
|
||||
for (i = 0; i < ncolors; ++i) {
|
||||
SDL_RWwrite(dst, &colors[i].b, 1);
|
||||
SDL_RWwrite(dst, &colors[i].g, 1);
|
||||
SDL_RWwrite(dst, &colors[i].r, 1);
|
||||
SDL_RWwrite(dst, &colors[i].a, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the bitmap offset */
|
||||
bfOffBits = (Uint32)(SDL_RWtell(dst) - fp_offset);
|
||||
if (SDL_RWseek(dst, fp_offset + 10, SDL_RW_SEEK_SET) < 0) {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
}
|
||||
SDL_WriteLE32(dst, bfOffBits);
|
||||
if (SDL_RWseek(dst, fp_offset + bfOffBits, SDL_RW_SEEK_SET) < 0) {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
}
|
||||
|
||||
/* Write the bitmap image upside down */
|
||||
bits = (Uint8 *)intermediate_surface->pixels + (intermediate_surface->h * intermediate_surface->pitch);
|
||||
pad = ((bw % 4) ? (4 - (bw % 4)) : 0);
|
||||
while (bits > (Uint8 *)intermediate_surface->pixels) {
|
||||
bits -= intermediate_surface->pitch;
|
||||
if (SDL_RWwrite(dst, bits, bw) != bw) {
|
||||
SDL_Error(SDL_EFWRITE);
|
||||
break;
|
||||
}
|
||||
if (pad) {
|
||||
const Uint8 padbyte = 0;
|
||||
for (i = 0; i < pad; ++i) {
|
||||
SDL_RWwrite(dst, &padbyte, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the BMP file size */
|
||||
bfSize = (Uint32)(SDL_RWtell(dst) - fp_offset);
|
||||
if (SDL_RWseek(dst, fp_offset + 2, SDL_RW_SEEK_SET) < 0) {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
}
|
||||
SDL_WriteLE32(dst, bfSize);
|
||||
if (SDL_RWseek(dst, fp_offset + bfSize, SDL_RW_SEEK_SET) < 0) {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
}
|
||||
|
||||
/* Close it up.. */
|
||||
SDL_UnlockSurface(intermediate_surface);
|
||||
if (intermediate_surface != surface) {
|
||||
SDL_DestroySurface(intermediate_surface);
|
||||
}
|
||||
}
|
||||
|
||||
if (freedst && dst) {
|
||||
SDL_RWclose(dst);
|
||||
}
|
||||
return (SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1;
|
||||
}
|
||||
|
||||
int SDL_SaveBMP(SDL_Surface *surface, const char *file)
|
||||
{
|
||||
return SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1);
|
||||
}
|
400
external/sdl/SDL/src/video/SDL_clipboard.c
vendored
Normal file
400
external/sdl/SDL/src/video/SDL_clipboard.c
vendored
Normal file
@ -0,0 +1,400 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_clipboard_c.h"
|
||||
#include "SDL_sysvideo.h"
|
||||
#include "../events/SDL_clipboardevents_c.h"
|
||||
|
||||
|
||||
void SDL_CancelClipboardData(Uint32 sequence)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
size_t i;
|
||||
|
||||
if (sequence != _this->clipboard_sequence) {
|
||||
/* This clipboard data was already canceled */
|
||||
return;
|
||||
}
|
||||
|
||||
if (_this->clipboard_cleanup) {
|
||||
_this->clipboard_cleanup(_this->clipboard_userdata);
|
||||
}
|
||||
|
||||
if (_this->clipboard_mime_types) {
|
||||
for (i = 0; i < _this->num_clipboard_mime_types; ++i) {
|
||||
SDL_free(_this->clipboard_mime_types[i]);
|
||||
}
|
||||
SDL_free(_this->clipboard_mime_types);
|
||||
_this->clipboard_mime_types = NULL;
|
||||
_this->num_clipboard_mime_types = 0;
|
||||
}
|
||||
|
||||
_this->clipboard_callback = NULL;
|
||||
_this->clipboard_cleanup = NULL;
|
||||
_this->clipboard_userdata = NULL;
|
||||
}
|
||||
|
||||
int SDL_SetClipboardData(SDL_ClipboardDataCallback callback, SDL_ClipboardCleanupCallback cleanup, void *userdata, const char **mime_types, size_t num_mime_types)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
size_t i;
|
||||
|
||||
if (_this == NULL) {
|
||||
return SDL_SetError("Video subsystem must be initialized to set clipboard text");
|
||||
}
|
||||
|
||||
/* Parameter validation */
|
||||
if (!((callback && mime_types && num_mime_types > 0) ||
|
||||
(!callback && !mime_types && num_mime_types == 0))) {
|
||||
return SDL_SetError("Invalid parameters");
|
||||
}
|
||||
|
||||
if (!callback && !_this->clipboard_callback) {
|
||||
/* Nothing to do, don't modify the system clipboard */
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_CancelClipboardData(_this->clipboard_sequence);
|
||||
|
||||
++_this->clipboard_sequence;
|
||||
if (!_this->clipboard_sequence) {
|
||||
_this->clipboard_sequence = 1;
|
||||
}
|
||||
_this->clipboard_callback = callback;
|
||||
_this->clipboard_cleanup = cleanup;
|
||||
_this->clipboard_userdata = userdata;
|
||||
|
||||
if (mime_types && num_mime_types > 0) {
|
||||
size_t num_allocated = 0;
|
||||
|
||||
_this->clipboard_mime_types = (char **)SDL_malloc(num_mime_types * sizeof(char *));
|
||||
if (_this->clipboard_mime_types) {
|
||||
for (i = 0; i < num_mime_types; ++i) {
|
||||
_this->clipboard_mime_types[i] = SDL_strdup(mime_types[i]);
|
||||
if (_this->clipboard_mime_types[i]) {
|
||||
++num_allocated;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num_allocated < num_mime_types) {
|
||||
SDL_ClearClipboardData();
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
_this->num_clipboard_mime_types = num_mime_types;
|
||||
}
|
||||
|
||||
if (_this->SetClipboardData) {
|
||||
if (_this->SetClipboardData(_this) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else if (_this->SetClipboardText) {
|
||||
char *text = NULL;
|
||||
size_t size;
|
||||
|
||||
for (i = 0; i < num_mime_types; ++i) {
|
||||
const char *mime_type = _this->clipboard_mime_types[i];
|
||||
if (SDL_IsTextMimeType(mime_type)) {
|
||||
const void *data = _this->clipboard_callback(_this->clipboard_userdata, mime_type, &size);
|
||||
if (data) {
|
||||
text = (char *)SDL_malloc(size + 1);
|
||||
SDL_memcpy(text, data, size);
|
||||
text[size] = '\0';
|
||||
if (_this->SetClipboardText(_this, text) < 0) {
|
||||
SDL_free(text);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (text) {
|
||||
SDL_free(text);
|
||||
} else {
|
||||
if (_this->SetClipboardText(_this, "") < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SendClipboardUpdate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_ClearClipboardData(void)
|
||||
{
|
||||
return SDL_SetClipboardData(NULL, NULL, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
void *SDL_GetInternalClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *size)
|
||||
{
|
||||
void *data = NULL;
|
||||
|
||||
if (_this->clipboard_callback) {
|
||||
const void *provided_data = _this->clipboard_callback(_this->clipboard_userdata, mime_type, size);
|
||||
if (provided_data) {
|
||||
/* Make a copy of it for the caller and guarantee null termination */
|
||||
data = SDL_malloc(*size + sizeof(Uint32));
|
||||
if (data) {
|
||||
SDL_memcpy(data, provided_data, *size);
|
||||
SDL_memset((Uint8 *)data + *size, 0, sizeof(Uint32));
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void *SDL_GetClipboardData(const char *mime_type, size_t *size)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
if (_this == NULL) {
|
||||
SDL_SetError("Video subsystem must be initialized to get clipboard data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!mime_type) {
|
||||
SDL_InvalidParamError("mime_type");
|
||||
return NULL;
|
||||
}
|
||||
if (!size) {
|
||||
SDL_InvalidParamError("size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize size to empty, so implementations don't have to worry about it */
|
||||
*size = 0;
|
||||
|
||||
if (_this->GetClipboardData) {
|
||||
return _this->GetClipboardData(_this, mime_type, size);
|
||||
} else if (_this->GetClipboardText && SDL_IsTextMimeType(mime_type)) {
|
||||
void *data = _this->GetClipboardText(_this);
|
||||
if (data && *(char *)data == '\0') {
|
||||
SDL_free(data);
|
||||
data = NULL;
|
||||
}
|
||||
return data;
|
||||
} else {
|
||||
return SDL_GetInternalClipboardData(_this, mime_type, size);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool SDL_HasInternalClipboardData(SDL_VideoDevice *_this, const char *mime_type)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < _this->num_clipboard_mime_types; ++i) {
|
||||
if (SDL_strcmp(mime_type, _this->clipboard_mime_types[i]) == 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool SDL_HasClipboardData(const char *mime_type)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
if (_this == NULL) {
|
||||
SDL_SetError("Video subsystem must be initialized to check clipboard data");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (!mime_type) {
|
||||
SDL_InvalidParamError("mime_type");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (_this->HasClipboardData) {
|
||||
return _this->HasClipboardData(_this, mime_type);
|
||||
} else if (_this->HasClipboardText && SDL_IsTextMimeType(mime_type)) {
|
||||
return _this->HasClipboardText(_this);
|
||||
} else {
|
||||
return SDL_HasInternalClipboardData(_this, mime_type);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clipboard text */
|
||||
|
||||
SDL_bool SDL_IsTextMimeType(const char *mime_type)
|
||||
{
|
||||
return (SDL_strncmp(mime_type, "text", 4) == 0);
|
||||
}
|
||||
|
||||
static const char **SDL_GetTextMimeTypes(SDL_VideoDevice *_this, size_t *num_mime_types)
|
||||
{
|
||||
if (_this->GetTextMimeTypes) {
|
||||
return _this->GetTextMimeTypes(_this, num_mime_types);
|
||||
} else {
|
||||
static const char *text_mime_types[] = {
|
||||
"text/plain;charset=utf-8"
|
||||
};
|
||||
|
||||
*num_mime_types = SDL_arraysize(text_mime_types);
|
||||
return text_mime_types;
|
||||
}
|
||||
}
|
||||
|
||||
const void *SDL_ClipboardTextCallback(void *userdata, const char *mime_type, size_t *size)
|
||||
{
|
||||
char *text = (char *)userdata;
|
||||
if (text) {
|
||||
*size = SDL_strlen(text);
|
||||
} else {
|
||||
*size = 0;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
int SDL_SetClipboardText(const char *text)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
size_t num_mime_types;
|
||||
const char **text_mime_types;
|
||||
|
||||
if (_this == NULL) {
|
||||
return SDL_SetError("Video subsystem must be initialized to set clipboard text");
|
||||
}
|
||||
|
||||
if (text && *text) {
|
||||
text_mime_types = SDL_GetTextMimeTypes(_this, &num_mime_types);
|
||||
|
||||
return SDL_SetClipboardData(SDL_ClipboardTextCallback, SDL_free, SDL_strdup(text), text_mime_types, num_mime_types);
|
||||
} else {
|
||||
return SDL_ClearClipboardData();
|
||||
}
|
||||
}
|
||||
|
||||
char *SDL_GetClipboardText(void)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
size_t i, num_mime_types;
|
||||
const char **text_mime_types;
|
||||
size_t length;
|
||||
char *text = NULL;
|
||||
|
||||
if (_this == NULL) {
|
||||
SDL_SetError("Video subsystem must be initialized to get clipboard text");
|
||||
return SDL_strdup("");
|
||||
}
|
||||
|
||||
text_mime_types = SDL_GetTextMimeTypes(_this, &num_mime_types);
|
||||
for (i = 0; i < num_mime_types; ++i) {
|
||||
text = SDL_GetClipboardData(text_mime_types[i], &length);
|
||||
if (text) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!text) {
|
||||
text = SDL_strdup("");
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
SDL_bool SDL_HasClipboardText(void)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
size_t i, num_mime_types;
|
||||
const char **text_mime_types;
|
||||
|
||||
if (_this == NULL) {
|
||||
SDL_SetError("Video subsystem must be initialized to check clipboard text");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
text_mime_types = SDL_GetTextMimeTypes(_this, &num_mime_types);
|
||||
for (i = 0; i < num_mime_types; ++i) {
|
||||
if (SDL_HasClipboardData(text_mime_types[i])) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Primary selection text */
|
||||
|
||||
int SDL_SetPrimarySelectionText(const char *text)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
if (_this == NULL) {
|
||||
return SDL_SetError("Video subsystem must be initialized to set primary selection text");
|
||||
}
|
||||
|
||||
if (text == NULL) {
|
||||
text = "";
|
||||
}
|
||||
if (_this->SetPrimarySelectionText) {
|
||||
if (_this->SetPrimarySelectionText(_this, text) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
SDL_free(_this->primary_selection_text);
|
||||
_this->primary_selection_text = SDL_strdup(text);
|
||||
}
|
||||
|
||||
SDL_SendClipboardUpdate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *SDL_GetPrimarySelectionText(void)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
if (_this == NULL) {
|
||||
SDL_SetError("Video subsystem must be initialized to get primary selection text");
|
||||
return SDL_strdup("");
|
||||
}
|
||||
|
||||
if (_this->GetPrimarySelectionText) {
|
||||
return _this->GetPrimarySelectionText(_this);
|
||||
} else {
|
||||
const char *text = _this->primary_selection_text;
|
||||
if (text == NULL) {
|
||||
text = "";
|
||||
}
|
||||
return SDL_strdup(text);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool SDL_HasPrimarySelectionText(void)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
if (_this == NULL) {
|
||||
SDL_SetError("Video subsystem must be initialized to check primary selection text");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (_this->HasPrimarySelectionText) {
|
||||
return _this->HasPrimarySelectionText(_this);
|
||||
} else {
|
||||
if (_this->primary_selection_text && _this->primary_selection_text[0] != '\0') {
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
42
external/sdl/SDL/src/video/SDL_clipboard_c.h
vendored
Normal file
42
external/sdl/SDL/src/video/SDL_clipboard_c.h
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_clipboard_c_h_
|
||||
#define SDL_clipboard_c_h_
|
||||
|
||||
#include "SDL_sysvideo.h"
|
||||
|
||||
|
||||
/* Return true if the mime type is valid clipboard text */
|
||||
extern SDL_bool SDL_IsTextMimeType(const char *mime_type);
|
||||
|
||||
/* Cancel the clipboard data callback, called internally for cleanup */
|
||||
extern void SDL_CancelClipboardData(Uint32 sequence);
|
||||
|
||||
/* Call the clipboard callback for application data */
|
||||
extern void *SDL_GetInternalClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *size);
|
||||
extern SDL_bool SDL_HasInternalClipboardData(SDL_VideoDevice *_this, const char *mime_type);
|
||||
|
||||
/* General purpose clipboard text callback */
|
||||
const void *SDL_ClipboardTextCallback(void *userdata, const char *mime_type, size_t *size);
|
||||
|
||||
#endif /* SDL_clipboard_c_h_ */
|
1343
external/sdl/SDL/src/video/SDL_egl.c
vendored
Normal file
1343
external/sdl/SDL/src/video/SDL_egl.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
170
external/sdl/SDL/src/video/SDL_egl_c.h
vendored
Normal file
170
external/sdl/SDL/src/video/SDL_egl_c.h
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_egl_h_
|
||||
#define SDL_egl_h_
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
|
||||
#include <SDL3/SDL_egl.h>
|
||||
|
||||
#include "SDL_sysvideo.h"
|
||||
|
||||
#define SDL_EGL_MAX_DEVICES 8
|
||||
|
||||
/* For systems that don't define these */
|
||||
typedef intptr_t EGLAttrib;
|
||||
typedef void *EGLDeviceEXT;
|
||||
typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETDISPLAYPROC) (EGLNativeDisplayType display_id);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLINITIALIZEPROC) (EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLTERMINATEPROC) (EGLDisplay dpy);
|
||||
typedef __eglMustCastToProperFunctionPointerType (EGLAPIENTRYP PFNEGLGETPROCADDRESSPROC) (const char *procname);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLCHOOSECONFIGPROC) (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef EGLContext (EGLAPIENTRYP PFNEGLCREATECONTEXTPROC) (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYCONTEXTPROC) (EGLDisplay dpy, EGLContext ctx);
|
||||
typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPBUFFERSURFACEPROC) (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEWINDOWSURFACEPROC) (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSURFACEPROC) (EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLMAKECURRENTPROC) (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSPROC) (EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPINTERVALPROC) (EGLDisplay dpy, EGLint interval);
|
||||
typedef const char *(EGLAPIENTRYP PFNEGLQUERYSTRINGPROC) (EGLDisplay dpy, EGLint name);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETCONFIGATTRIBPROC) (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLWAITNATIVEPROC) (EGLint engine);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLWAITGLPROC) (void);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDAPIPROC) (EGLenum api);
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLGETERRORPROC) (void);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
|
||||
typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYPROC) (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
|
||||
typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
|
||||
typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync);
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
|
||||
|
||||
typedef struct SDL_EGL_VideoData
|
||||
{
|
||||
void *opengl_dll_handle, *egl_dll_handle;
|
||||
EGLDisplay egl_display;
|
||||
EGLConfig egl_config;
|
||||
int egl_swapinterval;
|
||||
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 */
|
||||
|
||||
PFNEGLGETDISPLAYPROC eglGetDisplay;
|
||||
PFNEGLINITIALIZEPROC eglInitialize;
|
||||
PFNEGLTERMINATEPROC eglTerminate;
|
||||
PFNEGLGETPROCADDRESSPROC eglGetProcAddress;
|
||||
PFNEGLCHOOSECONFIGPROC eglChooseConfig;
|
||||
PFNEGLCREATECONTEXTPROC eglCreateContext;
|
||||
PFNEGLDESTROYCONTEXTPROC eglDestroyContext;
|
||||
PFNEGLCREATEPBUFFERSURFACEPROC eglCreatePbufferSurface;
|
||||
PFNEGLCREATEWINDOWSURFACEPROC eglCreateWindowSurface;
|
||||
PFNEGLDESTROYSURFACEPROC eglDestroySurface;
|
||||
PFNEGLMAKECURRENTPROC eglMakeCurrent;
|
||||
PFNEGLSWAPBUFFERSPROC eglSwapBuffers;
|
||||
PFNEGLSWAPINTERVALPROC eglSwapInterval;
|
||||
PFNEGLQUERYSTRINGPROC eglQueryString;
|
||||
PFNEGLGETCONFIGATTRIBPROC eglGetConfigAttrib;
|
||||
PFNEGLWAITNATIVEPROC eglWaitNative;
|
||||
PFNEGLWAITGLPROC eglWaitGL;
|
||||
PFNEGLBINDAPIPROC eglBindAPI;
|
||||
PFNEGLGETERRORPROC eglGetError;
|
||||
PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT;
|
||||
PFNEGLGETPLATFORMDISPLAYPROC eglGetPlatformDisplay;
|
||||
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
|
||||
|
||||
/* Atomic functions */
|
||||
PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR;
|
||||
PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR;
|
||||
PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID;
|
||||
PFNEGLWAITSYNCKHRPROC eglWaitSyncKHR;
|
||||
PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR;
|
||||
|
||||
/* Atomic functions end */
|
||||
} SDL_EGL_VideoData;
|
||||
|
||||
/* OpenGLES functions */
|
||||
typedef enum SDL_EGL_ExtensionType
|
||||
{
|
||||
SDL_EGL_DISPLAY_EXTENSION,
|
||||
SDL_EGL_CLIENT_EXTENSION
|
||||
} SDL_EGL_ExtensionType;
|
||||
|
||||
extern SDL_bool SDL_EGL_HasExtension(SDL_VideoDevice *_this, SDL_EGL_ExtensionType type, const char *ext);
|
||||
|
||||
extern int SDL_EGL_GetAttribute(SDL_VideoDevice *_this, SDL_GLattr attrib, int *value);
|
||||
/* SDL_EGL_LoadLibrary can get a display for a specific platform (EGL_PLATFORM_*)
|
||||
* or, if 0 is passed, let the implementation decide.
|
||||
*/
|
||||
extern int SDL_EGL_LoadLibraryOnly(SDL_VideoDevice *_this, const char *path);
|
||||
extern int SDL_EGL_LoadLibrary(SDL_VideoDevice *_this, const char *path, NativeDisplayType native_display, EGLenum platform);
|
||||
extern SDL_FunctionPointer SDL_EGL_GetProcAddressInternal(SDL_VideoDevice *_this, const char *proc);
|
||||
extern void SDL_EGL_UnloadLibrary(SDL_VideoDevice *_this);
|
||||
extern void SDL_EGL_SetRequiredVisualId(SDL_VideoDevice *_this, int visual_id);
|
||||
extern int SDL_EGL_ChooseConfig(SDL_VideoDevice *_this);
|
||||
extern int SDL_EGL_SetSwapInterval(SDL_VideoDevice *_this, int interval);
|
||||
extern int SDL_EGL_GetSwapInterval(SDL_VideoDevice *_this, int *interval);
|
||||
extern int SDL_EGL_DeleteContext(SDL_VideoDevice *_this, SDL_GLContext context);
|
||||
extern EGLSurface *SDL_EGL_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, NativeWindowType nw);
|
||||
extern void SDL_EGL_DestroySurface(SDL_VideoDevice *_this, EGLSurface egl_surface);
|
||||
|
||||
extern EGLSurface SDL_EGL_CreateOffscreenSurface(SDL_VideoDevice *_this, int width, int height);
|
||||
/* Assumes that LoadLibraryOnly() has succeeded */
|
||||
extern int SDL_EGL_InitializeOffscreen(SDL_VideoDevice *_this, int device);
|
||||
|
||||
/* These need to be wrapped to get the surface for the window by the platform GLES implementation */
|
||||
extern SDL_GLContext SDL_EGL_CreateContext(SDL_VideoDevice *_this, EGLSurface egl_surface);
|
||||
extern int SDL_EGL_MakeCurrent(SDL_VideoDevice *_this, EGLSurface egl_surface, SDL_GLContext context);
|
||||
extern int SDL_EGL_SwapBuffers(SDL_VideoDevice *_this, EGLSurface egl_surface);
|
||||
|
||||
/* SDL Error-reporting */
|
||||
extern int SDL_EGL_SetErrorEx(const char *message, const char *eglFunctionName, EGLint eglErrorCode);
|
||||
#define SDL_EGL_SetError(message, eglFunctionName) SDL_EGL_SetErrorEx(message, eglFunctionName, _this->egl_data->eglGetError())
|
||||
|
||||
/* A few of useful macros */
|
||||
|
||||
#define SDL_EGL_SwapWindow_impl(BACKEND) \
|
||||
int BACKEND##_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window) \
|
||||
{ \
|
||||
return SDL_EGL_SwapBuffers(_this, window->driverdata->egl_surface); \
|
||||
}
|
||||
|
||||
#define SDL_EGL_MakeCurrent_impl(BACKEND) \
|
||||
int BACKEND##_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context) \
|
||||
{ \
|
||||
return SDL_EGL_MakeCurrent(_this, window ? window->driverdata->egl_surface : EGL_NO_SURFACE, context); \
|
||||
}
|
||||
|
||||
#define SDL_EGL_CreateContext_impl(BACKEND) \
|
||||
SDL_GLContext BACKEND##_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window) \
|
||||
{ \
|
||||
return SDL_EGL_CreateContext(_this, window->driverdata->egl_surface); \
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_OPENGL_EGL */
|
||||
|
||||
#endif /* SDL_egl_h_ */
|
442
external/sdl/SDL/src/video/SDL_fillrect.c
vendored
Normal file
442
external/sdl/SDL/src/video/SDL_fillrect.c
vendored
Normal file
@ -0,0 +1,442 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_blit.h"
|
||||
|
||||
#ifdef SDL_SSE_INTRINSICS
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#define SSE_BEGIN \
|
||||
__m128 c128; \
|
||||
c128.m128_u32[0] = color; \
|
||||
c128.m128_u32[1] = color; \
|
||||
c128.m128_u32[2] = color; \
|
||||
c128.m128_u32[3] = color;
|
||||
#else
|
||||
#define SSE_BEGIN \
|
||||
__m128 c128; \
|
||||
DECLARE_ALIGNED(Uint32, cccc[4], 16); \
|
||||
cccc[0] = color; \
|
||||
cccc[1] = color; \
|
||||
cccc[2] = color; \
|
||||
cccc[3] = color; \
|
||||
c128 = *(__m128 *)cccc;
|
||||
#endif
|
||||
|
||||
#define SSE_WORK \
|
||||
for (i = n / 64; i--;) { \
|
||||
_mm_stream_ps((float *)(p+0), c128); \
|
||||
_mm_stream_ps((float *)(p+16), c128); \
|
||||
_mm_stream_ps((float *)(p+32), c128); \
|
||||
_mm_stream_ps((float *)(p+48), c128); \
|
||||
p += 64; \
|
||||
}
|
||||
|
||||
#define SSE_END
|
||||
|
||||
#define DEFINE_SSE_FILLRECT(bpp, type) \
|
||||
static void SDL_TARGETING("sse") SDL_FillSurfaceRect##bpp##SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
|
||||
{ \
|
||||
int i, n; \
|
||||
Uint8 *p = NULL; \
|
||||
\
|
||||
SSE_BEGIN; \
|
||||
\
|
||||
while (h--) { \
|
||||
n = (w) * (bpp); \
|
||||
p = pixels; \
|
||||
\
|
||||
if (n > 63) { \
|
||||
int adjust = 16 - ((uintptr_t)p & 15); \
|
||||
if (adjust < 16) { \
|
||||
n -= adjust; \
|
||||
adjust /= (bpp); \
|
||||
while (adjust--) { \
|
||||
*((type *)p) = (type)color; \
|
||||
p += (bpp); \
|
||||
} \
|
||||
} \
|
||||
SSE_WORK; \
|
||||
} \
|
||||
if (n & 63) { \
|
||||
int remainder = (n & 63); \
|
||||
remainder /= (bpp); \
|
||||
while (remainder--) { \
|
||||
*((type *)p) = (type)color; \
|
||||
p += (bpp); \
|
||||
} \
|
||||
} \
|
||||
pixels += pitch; \
|
||||
} \
|
||||
\
|
||||
SSE_END; \
|
||||
}
|
||||
|
||||
static void SDL_TARGETING("sse") SDL_FillSurfaceRect1SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
SSE_BEGIN;
|
||||
while (h--) {
|
||||
Uint8 *p = pixels;
|
||||
n = w;
|
||||
|
||||
if (n > 63) {
|
||||
int adjust = 16 - ((uintptr_t)p & 15);
|
||||
if (adjust) {
|
||||
n -= adjust;
|
||||
SDL_memset(p, color, adjust);
|
||||
p += adjust;
|
||||
}
|
||||
SSE_WORK;
|
||||
}
|
||||
if (n & 63) {
|
||||
int remainder = (n & 63);
|
||||
SDL_memset(p, color, remainder);
|
||||
}
|
||||
pixels += pitch;
|
||||
}
|
||||
|
||||
SSE_END;
|
||||
}
|
||||
/* DEFINE_SSE_FILLRECT(1, Uint8) */
|
||||
DEFINE_SSE_FILLRECT(2, Uint16)
|
||||
DEFINE_SSE_FILLRECT(4, Uint32)
|
||||
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
#endif /* __SSE__ */
|
||||
|
||||
static void SDL_FillSurfaceRect1(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
|
||||
{
|
||||
int n;
|
||||
Uint8 *p = NULL;
|
||||
|
||||
while (h--) {
|
||||
n = w;
|
||||
p = pixels;
|
||||
|
||||
if (n > 3) {
|
||||
switch ((uintptr_t)p & 3) {
|
||||
case 1:
|
||||
*p++ = (Uint8)color;
|
||||
--n;
|
||||
SDL_FALLTHROUGH;
|
||||
case 2:
|
||||
*p++ = (Uint8)color;
|
||||
--n;
|
||||
SDL_FALLTHROUGH;
|
||||
case 3:
|
||||
*p++ = (Uint8)color;
|
||||
--n;
|
||||
}
|
||||
SDL_memset4(p, color, (n >> 2));
|
||||
}
|
||||
if (n & 3) {
|
||||
p += (n & ~3);
|
||||
switch (n & 3) {
|
||||
case 3:
|
||||
*p++ = (Uint8)color;
|
||||
SDL_FALLTHROUGH;
|
||||
case 2:
|
||||
*p++ = (Uint8)color;
|
||||
SDL_FALLTHROUGH;
|
||||
case 1:
|
||||
*p++ = (Uint8)color;
|
||||
}
|
||||
}
|
||||
pixels += pitch;
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL_FillSurfaceRect2(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
|
||||
{
|
||||
int n;
|
||||
Uint16 *p = NULL;
|
||||
|
||||
while (h--) {
|
||||
n = w;
|
||||
p = (Uint16 *)pixels;
|
||||
|
||||
if (n > 1) {
|
||||
if ((uintptr_t)p & 2) {
|
||||
*p++ = (Uint16)color;
|
||||
--n;
|
||||
}
|
||||
SDL_memset4(p, color, (n >> 1));
|
||||
}
|
||||
if (n & 1) {
|
||||
p[n - 1] = (Uint16)color;
|
||||
}
|
||||
pixels += pitch;
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL_FillSurfaceRect3(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
|
||||
{
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
Uint8 b1 = (Uint8)(color & 0xFF);
|
||||
Uint8 b2 = (Uint8)((color >> 8) & 0xFF);
|
||||
Uint8 b3 = (Uint8)((color >> 16) & 0xFF);
|
||||
#elif SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
Uint8 b1 = (Uint8)((color >> 16) & 0xFF);
|
||||
Uint8 b2 = (Uint8)((color >> 8) & 0xFF);
|
||||
Uint8 b3 = (Uint8)(color & 0xFF);
|
||||
#endif
|
||||
int n;
|
||||
Uint8 *p = NULL;
|
||||
|
||||
while (h--) {
|
||||
n = w;
|
||||
p = pixels;
|
||||
|
||||
while (n--) {
|
||||
*p++ = b1;
|
||||
*p++ = b2;
|
||||
*p++ = b3;
|
||||
}
|
||||
pixels += pitch;
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL_FillSurfaceRect4(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
|
||||
{
|
||||
while (h--) {
|
||||
SDL_memset4(pixels, color, w);
|
||||
pixels += pitch;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function performs a fast fill of the given rectangle with 'color'
|
||||
*/
|
||||
int SDL_FillSurfaceRect(SDL_Surface *dst, const SDL_Rect *rect, Uint32 color)
|
||||
{
|
||||
if (dst == NULL) {
|
||||
return SDL_InvalidParamError("SDL_FillSurfaceRect(): dst");
|
||||
}
|
||||
|
||||
/* If 'rect' == NULL, then fill the whole surface */
|
||||
if (rect == NULL) {
|
||||
rect = &dst->clip_rect;
|
||||
/* Don't attempt to fill if the surface's clip_rect is empty */
|
||||
if (SDL_RectEmpty(rect)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_FillSurfaceRects(dst, rect, 1, color);
|
||||
}
|
||||
|
||||
#ifdef SDL_ARM_NEON_BLITTERS
|
||||
void FillSurfaceRect8ARMNEONAsm(int32_t w, int32_t h, uint8_t *dst, int32_t dst_stride, uint8_t src);
|
||||
void FillSurfaceRect16ARMNEONAsm(int32_t w, int32_t h, uint16_t *dst, int32_t dst_stride, uint16_t src);
|
||||
void FillSurfaceRect32ARMNEONAsm(int32_t w, int32_t h, uint32_t *dst, int32_t dst_stride, uint32_t src);
|
||||
|
||||
static void fill_8_neon(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
|
||||
{
|
||||
FillSurfaceRect8ARMNEONAsm(w, h, (uint8_t *)pixels, pitch >> 0, color);
|
||||
return;
|
||||
}
|
||||
|
||||
static void fill_16_neon(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
|
||||
{
|
||||
FillSurfaceRect16ARMNEONAsm(w, h, (uint16_t *)pixels, pitch >> 1, color);
|
||||
return;
|
||||
}
|
||||
|
||||
static void fill_32_neon(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
|
||||
{
|
||||
FillSurfaceRect32ARMNEONAsm(w, h, (uint32_t *)pixels, pitch >> 2, color);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SDL_ARM_SIMD_BLITTERS
|
||||
void FillSurfaceRect8ARMSIMDAsm(int32_t w, int32_t h, uint8_t *dst, int32_t dst_stride, uint8_t src);
|
||||
void FillSurfaceRect16ARMSIMDAsm(int32_t w, int32_t h, uint16_t *dst, int32_t dst_stride, uint16_t src);
|
||||
void FillSurfaceRect32ARMSIMDAsm(int32_t w, int32_t h, uint32_t *dst, int32_t dst_stride, uint32_t src);
|
||||
|
||||
static void fill_8_simd(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
|
||||
{
|
||||
FillSurfaceRect8ARMSIMDAsm(w, h, (uint8_t *)pixels, pitch >> 0, color);
|
||||
return;
|
||||
}
|
||||
|
||||
static void fill_16_simd(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
|
||||
{
|
||||
FillSurfaceRect16ARMSIMDAsm(w, h, (uint16_t *)pixels, pitch >> 1, color);
|
||||
return;
|
||||
}
|
||||
|
||||
static void fill_32_simd(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
|
||||
{
|
||||
FillSurfaceRect32ARMSIMDAsm(w, h, (uint32_t *)pixels, pitch >> 2, color);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
int SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count,
|
||||
Uint32 color)
|
||||
{
|
||||
SDL_Rect clipped;
|
||||
Uint8 *pixels;
|
||||
const SDL_Rect *rect;
|
||||
void (*fill_function)(Uint8 * pixels, int pitch, Uint32 color, int w, int h) = NULL;
|
||||
int i;
|
||||
|
||||
if (dst == NULL) {
|
||||
return SDL_InvalidParamError("SDL_FillSurfaceRects(): dst");
|
||||
}
|
||||
|
||||
/* Nothing to do */
|
||||
if (dst->w == 0 || dst->h == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform software fill */
|
||||
if (!dst->pixels) {
|
||||
return SDL_SetError("SDL_FillSurfaceRects(): You must lock the surface");
|
||||
}
|
||||
|
||||
if (rects == NULL) {
|
||||
return SDL_InvalidParamError("SDL_FillSurfaceRects(): 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->h == dst->h) {
|
||||
if (dst->format->BitsPerPixel == 4) {
|
||||
Uint8 b = (((Uint8)color << 4) | (Uint8)color);
|
||||
SDL_memset(dst->pixels, b, (size_t)dst->h * dst->pitch);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SDL_SetError("SDL_FillSurfaceRects(): Unsupported surface format");
|
||||
}
|
||||
|
||||
#ifdef SDL_ARM_NEON_BLITTERS
|
||||
if (SDL_HasNEON() && dst->format->BytesPerPixel != 3 && fill_function == NULL) {
|
||||
switch (dst->format->BytesPerPixel) {
|
||||
case 1:
|
||||
fill_function = fill_8_neon;
|
||||
break;
|
||||
case 2:
|
||||
fill_function = fill_16_neon;
|
||||
break;
|
||||
case 4:
|
||||
fill_function = fill_32_neon;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef SDL_ARM_SIMD_BLITTERS
|
||||
if (SDL_HasARMSIMD() && dst->format->BytesPerPixel != 3 && fill_function == NULL) {
|
||||
switch (dst->format->BytesPerPixel) {
|
||||
case 1:
|
||||
fill_function = fill_8_simd;
|
||||
break;
|
||||
case 2:
|
||||
fill_function = fill_16_simd;
|
||||
break;
|
||||
case 4:
|
||||
fill_function = fill_32_simd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fill_function == NULL) {
|
||||
switch (dst->format->BytesPerPixel) {
|
||||
case 1:
|
||||
{
|
||||
color |= (color << 8);
|
||||
color |= (color << 16);
|
||||
#ifdef SDL_SSE_INTRINSICS
|
||||
if (SDL_HasSSE()) {
|
||||
fill_function = SDL_FillSurfaceRect1SSE;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
fill_function = SDL_FillSurfaceRect1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
color |= (color << 16);
|
||||
#ifdef SDL_SSE_INTRINSICS
|
||||
if (SDL_HasSSE()) {
|
||||
fill_function = SDL_FillSurfaceRect2SSE;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
fill_function = SDL_FillSurfaceRect2;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
/* 24-bit RGB is a slow path, at least for now. */
|
||||
{
|
||||
fill_function = SDL_FillSurfaceRect3;
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
#ifdef SDL_SSE_INTRINSICS
|
||||
if (SDL_HasSSE()) {
|
||||
fill_function = SDL_FillSurfaceRect4SSE;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
fill_function = SDL_FillSurfaceRect4;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return SDL_SetError("Unsupported pixel format");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
rect = &rects[i];
|
||||
/* Perform clipping */
|
||||
if (!SDL_GetRectIntersection(rect, &dst->clip_rect, &clipped)) {
|
||||
continue;
|
||||
}
|
||||
rect = &clipped;
|
||||
|
||||
pixels = (Uint8 *)dst->pixels + rect->y * dst->pitch +
|
||||
rect->x * dst->format->BytesPerPixel;
|
||||
|
||||
fill_function(pixels, dst->pitch, color, rect->w, rect->h);
|
||||
}
|
||||
|
||||
/* We're done! */
|
||||
return 0;
|
||||
}
|
1141
external/sdl/SDL/src/video/SDL_pixels.c
vendored
Normal file
1141
external/sdl/SDL/src/video/SDL_pixels.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
48
external/sdl/SDL/src/video/SDL_pixels_c.h
vendored
Normal file
48
external/sdl/SDL/src/video/SDL_pixels_c.h
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_pixels_c_h_
|
||||
#define SDL_pixels_c_h_
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
/* Useful functions and variables from SDL_pixel.c */
|
||||
|
||||
#include "SDL_blit.h"
|
||||
|
||||
/* Pixel format functions */
|
||||
extern int SDL_InitFormat(SDL_PixelFormat *format, Uint32 pixel_format);
|
||||
extern int SDL_CalculateSize(Uint32 format, int width, int height, size_t *size, size_t *pitch, SDL_bool minimalPitch);
|
||||
|
||||
/* Blit mapping functions */
|
||||
extern SDL_BlitMap *SDL_AllocBlitMap(void);
|
||||
extern void SDL_InvalidateMap(SDL_BlitMap *map);
|
||||
extern int SDL_MapSurface(SDL_Surface *src, SDL_Surface *dst);
|
||||
extern void SDL_FreeBlitMap(SDL_BlitMap *map);
|
||||
|
||||
extern void SDL_InvalidateAllBlitMap(SDL_Surface *surface);
|
||||
|
||||
/* Miscellaneous functions */
|
||||
extern void SDL_DitherColors(SDL_Color *colors, int bpp);
|
||||
extern Uint8 SDL_FindColor(SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
||||
extern void SDL_DetectPalette(SDL_Palette *pal, SDL_bool *is_opaque, SDL_bool *has_alpha_channel);
|
||||
|
||||
#endif /* SDL_pixels_c_h_ */
|
110
external/sdl/SDL/src/video/SDL_rect.c
vendored
Normal file
110
external/sdl/SDL/src/video/SDL_rect.c
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_rect_c.h"
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int i;
|
||||
int span_y1, span_y2;
|
||||
int rect_y1, rect_y2;
|
||||
|
||||
if (width < 1) {
|
||||
SDL_InvalidParamError("width");
|
||||
return SDL_FALSE;
|
||||
} else if (height < 1) {
|
||||
SDL_InvalidParamError("height");
|
||||
return SDL_FALSE;
|
||||
} else if (rects == NULL) {
|
||||
SDL_InvalidParamError("rects");
|
||||
return SDL_FALSE;
|
||||
} else if (span == NULL) {
|
||||
SDL_InvalidParamError("span");
|
||||
return SDL_FALSE;
|
||||
} else if (numrects < 1) {
|
||||
SDL_InvalidParamError("numrects");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Initialize to empty rect */
|
||||
span_y1 = height;
|
||||
span_y2 = 0;
|
||||
|
||||
for (i = 0; i < numrects; ++i) {
|
||||
rect_y1 = rects[i].y;
|
||||
rect_y2 = rect_y1 + rects[i].h;
|
||||
|
||||
/* Clip out of bounds rectangles, and expand span rect */
|
||||
if (rect_y1 < 0) {
|
||||
span_y1 = 0;
|
||||
} else if (rect_y1 < span_y1) {
|
||||
span_y1 = rect_y1;
|
||||
}
|
||||
if (rect_y2 > height) {
|
||||
span_y2 = height;
|
||||
} else if (rect_y2 > span_y2) {
|
||||
span_y2 = rect_y2;
|
||||
}
|
||||
}
|
||||
if (span_y2 > span_y1) {
|
||||
span->x = 0;
|
||||
span->y = span_y1;
|
||||
span->w = width;
|
||||
span->h = (span_y2 - span_y1);
|
||||
return SDL_TRUE;
|
||||
}
|
||||
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_HasRectIntersection
|
||||
#define SDL_INTERSECTRECT SDL_GetRectIntersection
|
||||
#define SDL_RECTEMPTY SDL_RectEmpty
|
||||
#define SDL_UNIONRECT SDL_GetRectUnion
|
||||
#define SDL_ENCLOSEPOINTS SDL_GetRectEnclosingPoints
|
||||
#define SDL_INTERSECTRECTANDLINE SDL_GetRectAndLineIntersection
|
||||
#include "SDL_rect_impl.h"
|
||||
|
||||
#define RECTTYPE SDL_FRect
|
||||
#define POINTTYPE SDL_FPoint
|
||||
#define SCALARTYPE float
|
||||
#define COMPUTEOUTCODE ComputeOutCodeFloat
|
||||
#define SDL_HASINTERSECTION SDL_HasRectIntersectionFloat
|
||||
#define SDL_INTERSECTRECT SDL_GetRectIntersectionFloat
|
||||
#define SDL_RECTEMPTY SDL_RectEmptyFloat
|
||||
#define SDL_UNIONRECT SDL_GetRectUnionFloat
|
||||
#define SDL_ENCLOSEPOINTS SDL_GetRectEnclosingPointsFloat
|
||||
#define SDL_INTERSECTRECTANDLINE SDL_GetRectAndLineIntersectionFloat
|
||||
#include "SDL_rect_impl.h"
|
29
external/sdl/SDL/src/video/SDL_rect_c.h
vendored
Normal file
29
external/sdl/SDL/src/video/SDL_rect_c.h
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_rect_c_h_
|
||||
#define SDL_rect_c_h_
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
extern SDL_bool SDL_GetSpanEnclosingRect(int width, int height, int numrects, const SDL_Rect *rects, SDL_Rect *span);
|
||||
|
||||
#endif /* SDL_rect_c_h_ */
|
436
external/sdl/SDL/src/video/SDL_rect_impl.h
vendored
Normal file
436
external/sdl/SDL/src/video/SDL_rect_impl.h
vendored
Normal file
@ -0,0 +1,436 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* 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 == NULL) {
|
||||
SDL_InvalidParamError("A");
|
||||
return SDL_FALSE;
|
||||
} else if (B == NULL) {
|
||||
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 == NULL) {
|
||||
SDL_InvalidParamError("A");
|
||||
return SDL_FALSE;
|
||||
} else if (B == NULL) {
|
||||
SDL_InvalidParamError("B");
|
||||
return SDL_FALSE;
|
||||
} else if (result == NULL) {
|
||||
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);
|
||||
}
|
||||
|
||||
int SDL_UNIONRECT(const RECTTYPE *A, const RECTTYPE *B, RECTTYPE *result)
|
||||
{
|
||||
SCALARTYPE Amin, Amax, Bmin, Bmax;
|
||||
|
||||
if (A == NULL) {
|
||||
return SDL_InvalidParamError("A");
|
||||
} else if (B == NULL) {
|
||||
return SDL_InvalidParamError("B");
|
||||
} else if (result == NULL) {
|
||||
return SDL_InvalidParamError("result");
|
||||
} 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 0;
|
||||
} else if (SDL_RECTEMPTY(B)) { /* A not empty, B empty */
|
||||
*result = *A;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 == NULL) {
|
||||
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 == NULL) {
|
||||
SDL_InvalidParamError("rect");
|
||||
return SDL_FALSE;
|
||||
} else if (X1 == NULL) {
|
||||
SDL_InvalidParamError("X1");
|
||||
return SDL_FALSE;
|
||||
} else if (Y1 == NULL) {
|
||||
SDL_InvalidParamError("Y1");
|
||||
return SDL_FALSE;
|
||||
} else if (X2 == NULL) {
|
||||
SDL_InvalidParamError("X2");
|
||||
return SDL_FALSE;
|
||||
} else if (Y2 == NULL) {
|
||||
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) {
|
||||
SDL_assert(y2 != y1); /* if equal: division by zero. */
|
||||
y = recty1;
|
||||
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
|
||||
} else if (outcode2 & CODE_BOTTOM) {
|
||||
SDL_assert(y2 != y1); /* if equal: division by zero. */
|
||||
y = recty2;
|
||||
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
|
||||
} 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
|
304
external/sdl/SDL/src/video/SDL_shape.c
vendored
Normal file
304
external/sdl/SDL/src/video/SDL_shape.c
vendored
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_sysvideo.h"
|
||||
#include "SDL_shape_internals.h"
|
||||
|
||||
SDL_Window *SDL_CreateShapedWindow(const char *title, int w, int h, Uint32 flags)
|
||||
{
|
||||
SDL_Window *result = NULL;
|
||||
result = SDL_CreateWindow(title, w, h, (flags | SDL_WINDOW_BORDERLESS | SDL_WINDOW_HIDDEN) & (~SDL_WINDOW_FULLSCREEN) & (~SDL_WINDOW_RESIZABLE));
|
||||
if (result != NULL) {
|
||||
if (SDL_GetVideoDevice()->shape_driver.CreateShaper == NULL) {
|
||||
SDL_DestroyWindow(result);
|
||||
return NULL;
|
||||
}
|
||||
result->shaper = SDL_GetVideoDevice()->shape_driver.CreateShaper(result);
|
||||
if (result->shaper != NULL) {
|
||||
result->shaper->mode.mode = ShapeModeDefault;
|
||||
result->shaper->mode.parameters.binarizationCutoff = 1;
|
||||
result->shaper->hasshape = SDL_FALSE;
|
||||
return result;
|
||||
} else {
|
||||
SDL_DestroyWindow(result);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_bool SDL_IsShapedWindow(const SDL_Window *window)
|
||||
{
|
||||
if (window == NULL) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return (SDL_bool)(window->shaper != NULL);
|
||||
}
|
||||
|
||||
/* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */
|
||||
void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
Uint8 r = 0, g = 0, b = 0, alpha = 0;
|
||||
Uint8 *pixel = NULL;
|
||||
Uint32 pixel_value = 0, mask_value = 0;
|
||||
size_t bytes_per_scanline = (size_t)(shape->w + (ppb - 1)) / ppb;
|
||||
Uint8 *bitmap_scanline;
|
||||
SDL_Color key;
|
||||
|
||||
if (SDL_MUSTLOCK(shape)) {
|
||||
SDL_LockSurface(shape);
|
||||
}
|
||||
|
||||
SDL_memset(bitmap, 0, shape->h * bytes_per_scanline);
|
||||
|
||||
for (y = 0; y < shape->h; y++) {
|
||||
bitmap_scanline = bitmap + y * bytes_per_scanline;
|
||||
for (x = 0; x < shape->w; x++) {
|
||||
alpha = 0;
|
||||
pixel_value = 0;
|
||||
pixel = (Uint8 *)(shape->pixels) + (y * shape->pitch) + (x * shape->format->BytesPerPixel);
|
||||
switch (shape->format->BytesPerPixel) {
|
||||
case (1):
|
||||
pixel_value = *pixel;
|
||||
break;
|
||||
case (2):
|
||||
pixel_value = *(Uint16 *)pixel;
|
||||
break;
|
||||
case (3):
|
||||
pixel_value = *(Uint32 *)pixel & (~shape->format->Amask);
|
||||
break;
|
||||
case (4):
|
||||
pixel_value = *(Uint32 *)pixel;
|
||||
break;
|
||||
}
|
||||
SDL_GetRGBA(pixel_value, shape->format, &r, &g, &b, &alpha);
|
||||
switch (mode.mode) {
|
||||
case (ShapeModeDefault):
|
||||
mask_value = (alpha >= 1 ? 1 : 0);
|
||||
break;
|
||||
case (ShapeModeBinarizeAlpha):
|
||||
mask_value = (alpha >= mode.parameters.binarizationCutoff ? 1 : 0);
|
||||
break;
|
||||
case (ShapeModeReverseBinarizeAlpha):
|
||||
mask_value = (alpha <= mode.parameters.binarizationCutoff ? 1 : 0);
|
||||
break;
|
||||
case (ShapeModeColorKey):
|
||||
key = mode.parameters.colorKey;
|
||||
mask_value = ((key.r != r || key.g != g || key.b != b) ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
bitmap_scanline[x / ppb] |= mask_value << (x % ppb);
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_MUSTLOCK(shape)) {
|
||||
SDL_UnlockSurface(shape);
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_ShapeTree *RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *mask, SDL_Rect dimensions)
|
||||
{
|
||||
int x = 0, y = 0;
|
||||
Uint8 *pixel = NULL;
|
||||
Uint32 pixel_value = 0;
|
||||
Uint8 r = 0, g = 0, b = 0, a = 0;
|
||||
SDL_bool pixel_opaque = SDL_FALSE;
|
||||
int last_opaque = -1;
|
||||
SDL_Color key;
|
||||
SDL_ShapeTree *result = (SDL_ShapeTree *)SDL_malloc(sizeof(SDL_ShapeTree));
|
||||
SDL_Rect next = { 0, 0, 0, 0 };
|
||||
|
||||
if (result == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (y = dimensions.y; y < dimensions.y + dimensions.h; y++) {
|
||||
for (x = dimensions.x; x < dimensions.x + dimensions.w; x++) {
|
||||
pixel_value = 0;
|
||||
pixel = (Uint8 *)(mask->pixels) + (y * mask->pitch) + (x * mask->format->BytesPerPixel);
|
||||
switch (mask->format->BytesPerPixel) {
|
||||
case (1):
|
||||
pixel_value = *pixel;
|
||||
break;
|
||||
case (2):
|
||||
pixel_value = *(Uint16 *)pixel;
|
||||
break;
|
||||
case (3):
|
||||
pixel_value = *(Uint32 *)pixel & (~mask->format->Amask);
|
||||
break;
|
||||
case (4):
|
||||
pixel_value = *(Uint32 *)pixel;
|
||||
break;
|
||||
}
|
||||
SDL_GetRGBA(pixel_value, mask->format, &r, &g, &b, &a);
|
||||
switch (mode.mode) {
|
||||
case (ShapeModeDefault):
|
||||
pixel_opaque = (a >= 1 ? SDL_TRUE : SDL_FALSE);
|
||||
break;
|
||||
case (ShapeModeBinarizeAlpha):
|
||||
pixel_opaque = (a >= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE);
|
||||
break;
|
||||
case (ShapeModeReverseBinarizeAlpha):
|
||||
pixel_opaque = (a <= mode.parameters.binarizationCutoff ? SDL_TRUE : SDL_FALSE);
|
||||
break;
|
||||
case (ShapeModeColorKey):
|
||||
key = mode.parameters.colorKey;
|
||||
pixel_opaque = ((key.r != r || key.g != g || key.b != b) ? SDL_TRUE : SDL_FALSE);
|
||||
break;
|
||||
}
|
||||
if (last_opaque == -1) {
|
||||
last_opaque = pixel_opaque;
|
||||
}
|
||||
if (last_opaque != pixel_opaque) {
|
||||
const int halfwidth = dimensions.w / 2;
|
||||
const int halfheight = dimensions.h / 2;
|
||||
|
||||
result->kind = QuadShape;
|
||||
|
||||
next.x = dimensions.x;
|
||||
next.y = dimensions.y;
|
||||
next.w = halfwidth;
|
||||
next.h = halfheight;
|
||||
result->data.children.upleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode, mask, next);
|
||||
|
||||
next.x = dimensions.x + halfwidth;
|
||||
next.w = dimensions.w - halfwidth;
|
||||
result->data.children.upright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode, mask, next);
|
||||
|
||||
next.x = dimensions.x;
|
||||
next.w = halfwidth;
|
||||
next.y = dimensions.y + halfheight;
|
||||
next.h = dimensions.h - halfheight;
|
||||
result->data.children.downleft = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode, mask, next);
|
||||
|
||||
next.x = dimensions.x + halfwidth;
|
||||
next.w = dimensions.w - halfwidth;
|
||||
result->data.children.downright = (struct SDL_ShapeTree *)RecursivelyCalculateShapeTree(mode, mask, next);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we never recursed, all the pixels in this quadrant have the same "value". */
|
||||
result->kind = (last_opaque == SDL_TRUE ? OpaqueShape : TransparentShape);
|
||||
result->data.shape = dimensions;
|
||||
return result;
|
||||
}
|
||||
|
||||
SDL_ShapeTree *SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *shape)
|
||||
{
|
||||
SDL_Rect dimensions;
|
||||
SDL_ShapeTree *result = NULL;
|
||||
|
||||
dimensions.x = 0;
|
||||
dimensions.y = 0;
|
||||
dimensions.w = shape->w;
|
||||
dimensions.h = shape->h;
|
||||
|
||||
if (SDL_MUSTLOCK(shape)) {
|
||||
SDL_LockSurface(shape);
|
||||
}
|
||||
result = RecursivelyCalculateShapeTree(mode, shape, dimensions);
|
||||
if (SDL_MUSTLOCK(shape)) {
|
||||
SDL_UnlockSurface(shape);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure)
|
||||
{
|
||||
SDL_assert(tree != NULL);
|
||||
if (tree->kind == QuadShape) {
|
||||
SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upleft, function, closure);
|
||||
SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.upright, function, closure);
|
||||
SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.downleft, function, closure);
|
||||
SDL_TraverseShapeTree((SDL_ShapeTree *)tree->data.children.downright, function, closure);
|
||||
} else {
|
||||
function(tree, closure);
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_FreeShapeTree(SDL_ShapeTree **shape_tree)
|
||||
{
|
||||
if ((*shape_tree)->kind == QuadShape) {
|
||||
SDL_FreeShapeTree((SDL_ShapeTree **)(char *)&(*shape_tree)->data.children.upleft);
|
||||
SDL_FreeShapeTree((SDL_ShapeTree **)(char *)&(*shape_tree)->data.children.upright);
|
||||
SDL_FreeShapeTree((SDL_ShapeTree **)(char *)&(*shape_tree)->data.children.downleft);
|
||||
SDL_FreeShapeTree((SDL_ShapeTree **)(char *)&(*shape_tree)->data.children.downright);
|
||||
}
|
||||
SDL_free(*shape_tree);
|
||||
*shape_tree = NULL;
|
||||
}
|
||||
|
||||
int SDL_SetWindowShape(SDL_Window *window, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
int result;
|
||||
|
||||
if (window == NULL || !SDL_IsShapedWindow(window)) {
|
||||
/* The window given was not a shapeable window. */
|
||||
return SDL_NONSHAPEABLE_WINDOW;
|
||||
}
|
||||
if (shape == NULL) {
|
||||
/* Invalid shape argument. */
|
||||
return SDL_INVALID_SHAPE_ARGUMENT;
|
||||
}
|
||||
|
||||
if (shape_mode != NULL) {
|
||||
window->shaper->mode = *shape_mode;
|
||||
}
|
||||
result = _this->shape_driver.SetWindowShape(window->shaper, shape, shape_mode);
|
||||
if (result == 0) {
|
||||
window->shaper->hasshape = SDL_TRUE;
|
||||
SDL_ShowWindow(window);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static SDL_bool SDL_WindowHasAShape(SDL_Window *window)
|
||||
{
|
||||
if (window == NULL || !SDL_IsShapedWindow(window)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return window->shaper->hasshape;
|
||||
}
|
||||
|
||||
int SDL_GetShapedWindowMode(SDL_Window *window, SDL_WindowShapeMode *shape_mode)
|
||||
{
|
||||
if (window != NULL && SDL_IsShapedWindow(window)) {
|
||||
if (shape_mode == NULL) {
|
||||
if (SDL_WindowHasAShape(window)) {
|
||||
return 0; /* The window given has a shape. */
|
||||
} else {
|
||||
return SDL_WINDOW_LACKS_SHAPE; /* The window given is shapeable but lacks a shape. */
|
||||
}
|
||||
} else {
|
||||
*shape_mode = window->shaper->mode;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return SDL_NONSHAPEABLE_WINDOW; /* The window given is not a valid shapeable window. */
|
||||
}
|
59
external/sdl/SDL/src/video/SDL_shape_internals.h
vendored
Normal file
59
external/sdl/SDL/src/video/SDL_shape_internals.h
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_shape_internals_h_
|
||||
#define SDL_shape_internals_h_
|
||||
|
||||
struct SDL_ShapeTree;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct SDL_ShapeTree *upleft, *upright, *downleft, *downright;
|
||||
} SDL_QuadTreeChildren;
|
||||
|
||||
typedef union
|
||||
{
|
||||
SDL_QuadTreeChildren children;
|
||||
SDL_Rect shape;
|
||||
} SDL_ShapeUnion;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
QuadShape,
|
||||
TransparentShape,
|
||||
OpaqueShape
|
||||
} SDL_ShapeKind;
|
||||
|
||||
typedef struct SDL_ShapeTree
|
||||
{
|
||||
SDL_ShapeKind kind;
|
||||
SDL_ShapeUnion data;
|
||||
} SDL_ShapeTree;
|
||||
|
||||
typedef void (*SDL_TraversalFunction)(SDL_ShapeTree *, void *);
|
||||
|
||||
extern void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb);
|
||||
extern SDL_ShapeTree *SDL_CalculateShapeTree(SDL_WindowShapeMode mode, SDL_Surface *shape);
|
||||
extern void SDL_TraverseShapeTree(SDL_ShapeTree *tree, SDL_TraversalFunction function, void *closure);
|
||||
extern void SDL_FreeShapeTree(SDL_ShapeTree **shape_tree);
|
||||
|
||||
#endif /* SDL_shape_internals_h_ */
|
945
external/sdl/SDL/src/video/SDL_stretch.c
vendored
Normal file
945
external/sdl/SDL/src/video/SDL_stretch.c
vendored
Normal file
@ -0,0 +1,945 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_blit.h"
|
||||
|
||||
static int SDL_LowerSoftStretchNearest(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect);
|
||||
static int SDL_LowerSoftStretchLinear(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect);
|
||||
static int SDL_UpperSoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode);
|
||||
|
||||
int SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect,
|
||||
SDL_Surface *dst, const SDL_Rect *dstrect)
|
||||
{
|
||||
return SDL_UpperSoftStretch(src, srcrect, dst, dstrect, SDL_SCALEMODE_NEAREST);
|
||||
}
|
||||
|
||||
int SDL_SoftStretchLinear(SDL_Surface *src, const SDL_Rect *srcrect,
|
||||
SDL_Surface *dst, const SDL_Rect *dstrect)
|
||||
{
|
||||
return SDL_UpperSoftStretch(src, srcrect, dst, dstrect, SDL_SCALEMODE_LINEAR);
|
||||
}
|
||||
|
||||
static int SDL_UpperSoftStretch(SDL_Surface *src, const SDL_Rect *srcrect,
|
||||
SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode)
|
||||
{
|
||||
int ret;
|
||||
int src_locked;
|
||||
int dst_locked;
|
||||
SDL_Rect full_src;
|
||||
SDL_Rect full_dst;
|
||||
|
||||
if (src->format->format != dst->format->format) {
|
||||
return SDL_SetError("Only works with same format surfaces");
|
||||
}
|
||||
|
||||
if (scaleMode != SDL_SCALEMODE_NEAREST) {
|
||||
if (src->format->BytesPerPixel != 4 || src->format->format == SDL_PIXELFORMAT_ARGB2101010) {
|
||||
return SDL_SetError("Wrong format");
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify the blit rectangles */
|
||||
if (srcrect) {
|
||||
if ((srcrect->x < 0) || (srcrect->y < 0) ||
|
||||
((srcrect->x + srcrect->w) > src->w) ||
|
||||
((srcrect->y + srcrect->h) > src->h)) {
|
||||
return SDL_SetError("Invalid source blit rectangle");
|
||||
}
|
||||
} else {
|
||||
full_src.x = 0;
|
||||
full_src.y = 0;
|
||||
full_src.w = src->w;
|
||||
full_src.h = src->h;
|
||||
srcrect = &full_src;
|
||||
}
|
||||
if (dstrect) {
|
||||
if ((dstrect->x < 0) || (dstrect->y < 0) ||
|
||||
((dstrect->x + dstrect->w) > dst->w) ||
|
||||
((dstrect->y + dstrect->h) > dst->h)) {
|
||||
return SDL_SetError("Invalid destination blit rectangle");
|
||||
}
|
||||
} else {
|
||||
full_dst.x = 0;
|
||||
full_dst.y = 0;
|
||||
full_dst.w = dst->w;
|
||||
full_dst.h = dst->h;
|
||||
dstrect = &full_dst;
|
||||
}
|
||||
|
||||
if (dstrect->w <= 0 || dstrect->h <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
/* Lock the destination if it's in hardware */
|
||||
dst_locked = 0;
|
||||
if (SDL_MUSTLOCK(dst)) {
|
||||
if (SDL_LockSurface(dst) < 0) {
|
||||
return SDL_SetError("Unable to lock destination surface");
|
||||
}
|
||||
dst_locked = 1;
|
||||
}
|
||||
/* Lock the source if it's in hardware */
|
||||
src_locked = 0;
|
||||
if (SDL_MUSTLOCK(src)) {
|
||||
if (SDL_LockSurface(src) < 0) {
|
||||
if (dst_locked) {
|
||||
SDL_UnlockSurface(dst);
|
||||
}
|
||||
return SDL_SetError("Unable to lock source surface");
|
||||
}
|
||||
src_locked = 1;
|
||||
}
|
||||
|
||||
if (scaleMode == SDL_SCALEMODE_NEAREST) {
|
||||
ret = SDL_LowerSoftStretchNearest(src, srcrect, dst, dstrect);
|
||||
} else {
|
||||
ret = SDL_LowerSoftStretchLinear(src, srcrect, dst, dstrect);
|
||||
}
|
||||
|
||||
/* We need to unlock the surfaces if they're locked */
|
||||
if (dst_locked) {
|
||||
SDL_UnlockSurface(dst);
|
||||
}
|
||||
if (src_locked) {
|
||||
SDL_UnlockSurface(src);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* bilinear interpolation precision must be < 8
|
||||
Because with SSE: add-multiply: _mm_madd_epi16 works with signed int
|
||||
so pixels 0xb1...... are negatives and false the result
|
||||
same in NEON probably */
|
||||
#define PRECISION 7
|
||||
|
||||
#define FIXED_POINT(i) ((Uint32)(i) << 16)
|
||||
#define SRC_INDEX(fp) ((Uint32)(fp) >> 16)
|
||||
#define INTEGER(fp) ((Uint32)(fp) >> PRECISION)
|
||||
#define FRAC(fp) ((Uint32)((fp) >> (16 - PRECISION)) & ((1 << PRECISION) - 1))
|
||||
#define FRAC_ZERO 0
|
||||
#define FRAC_ONE (1 << PRECISION)
|
||||
#define FP_ONE FIXED_POINT(1)
|
||||
|
||||
#define BILINEAR___START \
|
||||
int i; \
|
||||
int fp_sum_h, fp_step_h, left_pad_h, right_pad_h; \
|
||||
int fp_sum_w, fp_step_w, left_pad_w, right_pad_w; \
|
||||
int fp_sum_w_init, left_pad_w_init, right_pad_w_init, dst_gap, middle_init; \
|
||||
get_scaler_datas(src_h, dst_h, &fp_sum_h, &fp_step_h, &left_pad_h, &right_pad_h); \
|
||||
get_scaler_datas(src_w, dst_w, &fp_sum_w, &fp_step_w, &left_pad_w, &right_pad_w); \
|
||||
fp_sum_w_init = fp_sum_w + left_pad_w * fp_step_w; \
|
||||
left_pad_w_init = left_pad_w; \
|
||||
right_pad_w_init = right_pad_w; \
|
||||
dst_gap = dst_pitch - 4 * dst_w; \
|
||||
middle_init = dst_w - left_pad_w - right_pad_w;
|
||||
|
||||
#define BILINEAR___HEIGHT \
|
||||
int index_h, frac_h0, frac_h1, middle; \
|
||||
const Uint32 *src_h0, *src_h1; \
|
||||
int no_padding, incr_h0, incr_h1; \
|
||||
\
|
||||
no_padding = !(i < left_pad_h || i > dst_h - 1 - right_pad_h); \
|
||||
index_h = SRC_INDEX(fp_sum_h); \
|
||||
frac_h0 = FRAC(fp_sum_h); \
|
||||
\
|
||||
index_h = no_padding ? index_h : (i < left_pad_h ? 0 : src_h - 1); \
|
||||
frac_h0 = no_padding ? frac_h0 : 0; \
|
||||
incr_h1 = no_padding ? src_pitch : 0; \
|
||||
incr_h0 = index_h * src_pitch; \
|
||||
\
|
||||
src_h0 = (const Uint32 *)((const Uint8 *)src + incr_h0); \
|
||||
src_h1 = (const Uint32 *)((const Uint8 *)src_h0 + incr_h1); \
|
||||
\
|
||||
fp_sum_h += fp_step_h; \
|
||||
\
|
||||
frac_h1 = FRAC_ONE - frac_h0; \
|
||||
fp_sum_w = fp_sum_w_init; \
|
||||
right_pad_w = right_pad_w_init; \
|
||||
left_pad_w = left_pad_w_init; \
|
||||
middle = middle_init;
|
||||
|
||||
#ifdef __clang__
|
||||
// Remove inlining of this function
|
||||
// Compiler crash with clang 9.0.8 / android-ndk-r21d
|
||||
// Compiler crash with clang 11.0.3 / Xcode
|
||||
// OK with clang 11.0.5 / android-ndk-22
|
||||
// OK with clang 12.0.0 / Xcode
|
||||
__attribute__((noinline))
|
||||
#endif
|
||||
static void get_scaler_datas(int src_nb, int dst_nb, int *fp_start, int *fp_step, int *left_pad, int *right_pad)
|
||||
{
|
||||
|
||||
int step = FIXED_POINT(src_nb) / (dst_nb); /* source step in fixed point */
|
||||
int x0 = FP_ONE / 2; /* dst first pixel center at 0.5 in fixed point */
|
||||
int fp_sum;
|
||||
int i;
|
||||
#if 0
|
||||
/* scale to source coordinates */
|
||||
x0 *= src_nb;
|
||||
x0 /= dst_nb; /* x0 == step / 2 */
|
||||
#else
|
||||
/* Use this code for perfect match with pixman */
|
||||
Sint64 tmp[2];
|
||||
tmp[0] = (Sint64)step * (x0 >> 16);
|
||||
tmp[1] = (Sint64)step * (x0 & 0xFFFF);
|
||||
x0 = (int)(tmp[0] + ((tmp[1] + 0x8000) >> 16)); /* x0 == (step + 1) / 2 */
|
||||
#endif
|
||||
/* -= 0.5, get back the pixel origin, in source coordinates */
|
||||
x0 -= FP_ONE / 2;
|
||||
|
||||
*fp_start = x0;
|
||||
*fp_step = step;
|
||||
*left_pad = 0;
|
||||
*right_pad = 0;
|
||||
|
||||
fp_sum = x0;
|
||||
for (i = 0; i < dst_nb; i++) {
|
||||
if (fp_sum < 0) {
|
||||
*left_pad += 1;
|
||||
} else {
|
||||
int index = SRC_INDEX(fp_sum);
|
||||
if (index > src_nb - 2) {
|
||||
*right_pad += 1;
|
||||
}
|
||||
}
|
||||
fp_sum += step;
|
||||
}
|
||||
// SDL_Log("%d -> %d x0=%d step=%d left_pad=%d right_pad=%d", src_nb, dst_nb, *fp_start, *fp_step, *left_pad, *right_pad);
|
||||
}
|
||||
|
||||
typedef struct color_t
|
||||
{
|
||||
Uint8 a;
|
||||
Uint8 b;
|
||||
Uint8 c;
|
||||
Uint8 d;
|
||||
} color_t;
|
||||
|
||||
#if 0
|
||||
static void printf_64(const char *str, void *var)
|
||||
{
|
||||
uint8_t *val = (uint8_t*) var;
|
||||
printf(" * %s: %02x %02x %02x %02x _ %02x %02x %02x %02x\n",
|
||||
str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Interpolated == x0 + frac * (x1 - x0) == x0 * (1 - frac) + x1 * frac */
|
||||
|
||||
static SDL_INLINE void INTERPOL(const Uint32 *src_x0, const Uint32 *src_x1, int frac0, int frac1, Uint32 *dst)
|
||||
{
|
||||
const color_t *c0 = (const color_t *)src_x0;
|
||||
const color_t *c1 = (const color_t *)src_x1;
|
||||
color_t *cx = (color_t *)dst;
|
||||
#if 0
|
||||
cx->a = c0->a + INTEGER(frac0 * (c1->a - c0->a));
|
||||
cx->b = c0->b + INTEGER(frac0 * (c1->b - c0->b));
|
||||
cx->c = c0->c + INTEGER(frac0 * (c1->c - c0->c));
|
||||
cx->d = c0->d + INTEGER(frac0 * (c1->d - c0->d));
|
||||
#else
|
||||
cx->a = (Uint8)INTEGER(frac1 * c0->a + frac0 * c1->a);
|
||||
cx->b = (Uint8)INTEGER(frac1 * c0->b + frac0 * c1->b);
|
||||
cx->c = (Uint8)INTEGER(frac1 * c0->c + frac0 * c1->c);
|
||||
cx->d = (Uint8)INTEGER(frac1 * c0->d + frac0 * c1->d);
|
||||
#endif
|
||||
}
|
||||
|
||||
static SDL_INLINE void INTERPOL_BILINEAR(const Uint32 *s0, const Uint32 *s1, int frac_w0, int frac_h0, int frac_h1, Uint32 *dst)
|
||||
{
|
||||
Uint32 tmp[2];
|
||||
unsigned int frac_w1 = FRAC_ONE - frac_w0;
|
||||
|
||||
/* Vertical first, store to 'tmp' */
|
||||
INTERPOL(s0, s1, frac_h0, frac_h1, tmp);
|
||||
INTERPOL(s0 + 1, s1 + 1, frac_h0, frac_h1, tmp + 1);
|
||||
|
||||
/* Horizontal, store to 'dst' */
|
||||
INTERPOL(tmp, tmp + 1, frac_w0, frac_w1, dst);
|
||||
}
|
||||
|
||||
static int scale_mat(const Uint32 *src, int src_w, int src_h, int src_pitch,
|
||||
Uint32 *dst, int dst_w, int dst_h, int dst_pitch)
|
||||
{
|
||||
BILINEAR___START
|
||||
|
||||
for (i = 0; i < dst_h; i++) {
|
||||
|
||||
BILINEAR___HEIGHT
|
||||
|
||||
while (left_pad_w--) {
|
||||
INTERPOL_BILINEAR(src_h0, src_h1, FRAC_ZERO, frac_h0, frac_h1, dst);
|
||||
dst += 1;
|
||||
}
|
||||
|
||||
while (middle--) {
|
||||
const Uint32 *s_00_01;
|
||||
const Uint32 *s_10_11;
|
||||
int index_w = 4 * SRC_INDEX(fp_sum_w);
|
||||
int frac_w = FRAC(fp_sum_w);
|
||||
fp_sum_w += fp_step_w;
|
||||
|
||||
/*
|
||||
x00 ... x0_ ..... x01
|
||||
. . .
|
||||
. x .
|
||||
. . .
|
||||
. . .
|
||||
x10 ... x1_ ..... x11
|
||||
*/
|
||||
s_00_01 = (const Uint32 *)((const Uint8 *)src_h0 + index_w);
|
||||
s_10_11 = (const Uint32 *)((const Uint8 *)src_h1 + index_w);
|
||||
|
||||
INTERPOL_BILINEAR(s_00_01, s_10_11, frac_w, frac_h0, frac_h1, dst);
|
||||
|
||||
dst += 1;
|
||||
}
|
||||
|
||||
while (right_pad_w--) {
|
||||
int index_w = 4 * (src_w - 2);
|
||||
const Uint32 *s_00_01 = (const Uint32 *)((const Uint8 *)src_h0 + index_w);
|
||||
const Uint32 *s_10_11 = (const Uint32 *)((const Uint8 *)src_h1 + index_w);
|
||||
INTERPOL_BILINEAR(s_00_01, s_10_11, FRAC_ONE, frac_h0, frac_h1, dst);
|
||||
dst += 1;
|
||||
}
|
||||
dst = (Uint32 *)((Uint8 *)dst + dst_gap);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SDL_NEON_INTRINSICS
|
||||
#define CAST_uint8x8_t (uint8x8_t)
|
||||
#define CAST_uint32x2_t (uint32x2_t)
|
||||
#endif
|
||||
|
||||
#if defined(__WINRT__) || defined(_MSC_VER)
|
||||
#ifdef SDL_NEON_INTRINSICS
|
||||
#undef CAST_uint8x8_t
|
||||
#undef CAST_uint32x2_t
|
||||
#define CAST_uint8x8_t
|
||||
#define CAST_uint32x2_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SDL_SSE2_INTRINSICS
|
||||
|
||||
#if 0
|
||||
static void SDL_TARGETING("sse2") printf_128(const char *str, __m128i var)
|
||||
{
|
||||
uint16_t *val = (uint16_t*) &var;
|
||||
printf(" * %s: %04x %04x %04x %04x _ %04x %04x %04x %04x\n",
|
||||
str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static SDL_INLINE int hasSSE2(void)
|
||||
{
|
||||
static int val = -1;
|
||||
if (val != -1) {
|
||||
return val;
|
||||
}
|
||||
val = SDL_HasSSE2();
|
||||
return val;
|
||||
}
|
||||
|
||||
static SDL_INLINE void SDL_TARGETING("sse2") INTERPOL_BILINEAR_SSE(const Uint32 *s0, const Uint32 *s1, int frac_w, __m128i v_frac_h0, __m128i v_frac_h1, Uint32 *dst, __m128i zero)
|
||||
{
|
||||
__m128i x_00_01, x_10_11; /* Pixels in 4*uint8 in row */
|
||||
__m128i v_frac_w0, k0, l0, d0, e0;
|
||||
|
||||
int f, f2;
|
||||
f = frac_w;
|
||||
f2 = FRAC_ONE - frac_w;
|
||||
v_frac_w0 = _mm_set_epi16((short)f, (short)f2, (short)f, (short)f2, (short)f, (short)f2, (short)f, (short)f2);
|
||||
|
||||
x_00_01 = _mm_loadl_epi64((const __m128i *)s0); /* Load x00 and x01 */
|
||||
x_10_11 = _mm_loadl_epi64((const __m128i *)s1);
|
||||
|
||||
/* Interpolated == x0 + frac * (x1 - x0) == x0 * (1 - frac) + x1 * frac */
|
||||
|
||||
/* Interpolation vertical */
|
||||
k0 = _mm_mullo_epi16(_mm_unpacklo_epi8(x_00_01, zero), v_frac_h1);
|
||||
l0 = _mm_mullo_epi16(_mm_unpacklo_epi8(x_10_11, zero), v_frac_h0);
|
||||
k0 = _mm_add_epi16(k0, l0);
|
||||
|
||||
/* For perfect match, clear the factionnal part eventually. */
|
||||
/*
|
||||
k0 = _mm_srli_epi16(k0, PRECISION);
|
||||
k0 = _mm_slli_epi16(k0, PRECISION);
|
||||
*/
|
||||
|
||||
/* Interpolation horizontal */
|
||||
l0 = _mm_unpacklo_epi64(/* unused */ l0, k0);
|
||||
k0 = _mm_madd_epi16(_mm_unpackhi_epi16(l0, k0), v_frac_w0);
|
||||
|
||||
/* Store 1 pixel */
|
||||
d0 = _mm_srli_epi32(k0, PRECISION * 2);
|
||||
e0 = _mm_packs_epi32(d0, d0);
|
||||
e0 = _mm_packus_epi16(e0, e0);
|
||||
*dst = _mm_cvtsi128_si32(e0);
|
||||
}
|
||||
|
||||
static int SDL_TARGETING("sse2") scale_mat_SSE(const Uint32 *src, int src_w, int src_h, int src_pitch, Uint32 *dst, int dst_w, int dst_h, int dst_pitch)
|
||||
{
|
||||
BILINEAR___START
|
||||
|
||||
for (i = 0; i < dst_h; i++) {
|
||||
int nb_block2;
|
||||
__m128i v_frac_h0;
|
||||
__m128i v_frac_h1;
|
||||
__m128i zero;
|
||||
|
||||
BILINEAR___HEIGHT
|
||||
|
||||
nb_block2 = middle / 2;
|
||||
|
||||
v_frac_h0 = _mm_set_epi16((short)frac_h0, (short)frac_h0, (short)frac_h0, (short)frac_h0, (short)frac_h0, (short)frac_h0, (short)frac_h0, (short)frac_h0);
|
||||
v_frac_h1 = _mm_set_epi16((short)frac_h1, (short)frac_h1, (short)frac_h1, (short)frac_h1, (short)frac_h1, (short)frac_h1, (short)frac_h1, (short)frac_h1);
|
||||
zero = _mm_setzero_si128();
|
||||
|
||||
while (left_pad_w--) {
|
||||
INTERPOL_BILINEAR_SSE(src_h0, src_h1, FRAC_ZERO, v_frac_h0, v_frac_h1, dst, zero);
|
||||
dst += 1;
|
||||
}
|
||||
|
||||
while (nb_block2--) {
|
||||
int index_w_0, frac_w_0;
|
||||
int index_w_1, frac_w_1;
|
||||
|
||||
const Uint32 *s_00_01, *s_02_03, *s_10_11, *s_12_13;
|
||||
|
||||
__m128i x_00_01, x_10_11, x_02_03, x_12_13; /* Pixels in 4*uint8 in row */
|
||||
__m128i v_frac_w0, k0, l0, d0, e0;
|
||||
__m128i v_frac_w1, k1, l1, d1, e1;
|
||||
|
||||
int f, f2;
|
||||
index_w_0 = 4 * SRC_INDEX(fp_sum_w);
|
||||
frac_w_0 = FRAC(fp_sum_w);
|
||||
fp_sum_w += fp_step_w;
|
||||
index_w_1 = 4 * SRC_INDEX(fp_sum_w);
|
||||
frac_w_1 = FRAC(fp_sum_w);
|
||||
fp_sum_w += fp_step_w;
|
||||
/*
|
||||
x00............ x01 x02...........x03
|
||||
. . . . . .
|
||||
j0 f0 j1 j2 f1 j3
|
||||
. . . . . .
|
||||
. . . . . .
|
||||
. . . . . .
|
||||
x10............ x11 x12...........x13
|
||||
*/
|
||||
s_00_01 = (const Uint32 *)((const Uint8 *)src_h0 + index_w_0);
|
||||
s_02_03 = (const Uint32 *)((const Uint8 *)src_h0 + index_w_1);
|
||||
s_10_11 = (const Uint32 *)((const Uint8 *)src_h1 + index_w_0);
|
||||
s_12_13 = (const Uint32 *)((const Uint8 *)src_h1 + index_w_1);
|
||||
|
||||
f = frac_w_0;
|
||||
f2 = FRAC_ONE - frac_w_0;
|
||||
v_frac_w0 = _mm_set_epi16((short)f, (short)f2, (short)f, (short)f2, (short)f, (short)f2, (short)f, (short)f2);
|
||||
|
||||
f = frac_w_1;
|
||||
f2 = FRAC_ONE - frac_w_1;
|
||||
v_frac_w1 = _mm_set_epi16((short)f, (short)f2, (short)f, (short)f2, (short)f, (short)f2, (short)f, (short)f2);
|
||||
|
||||
x_00_01 = _mm_loadl_epi64((const __m128i *)s_00_01); /* Load x00 and x01 */
|
||||
x_02_03 = _mm_loadl_epi64((const __m128i *)s_02_03);
|
||||
x_10_11 = _mm_loadl_epi64((const __m128i *)s_10_11);
|
||||
x_12_13 = _mm_loadl_epi64((const __m128i *)s_12_13);
|
||||
|
||||
/* Interpolation vertical */
|
||||
k0 = _mm_mullo_epi16(_mm_unpacklo_epi8(x_00_01, zero), v_frac_h1);
|
||||
l0 = _mm_mullo_epi16(_mm_unpacklo_epi8(x_10_11, zero), v_frac_h0);
|
||||
k0 = _mm_add_epi16(k0, l0);
|
||||
k1 = _mm_mullo_epi16(_mm_unpacklo_epi8(x_02_03, zero), v_frac_h1);
|
||||
l1 = _mm_mullo_epi16(_mm_unpacklo_epi8(x_12_13, zero), v_frac_h0);
|
||||
k1 = _mm_add_epi16(k1, l1);
|
||||
|
||||
/* Interpolation horizontal */
|
||||
l0 = _mm_unpacklo_epi64(/* unused */ l0, k0);
|
||||
k0 = _mm_madd_epi16(_mm_unpackhi_epi16(l0, k0), v_frac_w0);
|
||||
l1 = _mm_unpacklo_epi64(/* unused */ l1, k1);
|
||||
k1 = _mm_madd_epi16(_mm_unpackhi_epi16(l1, k1), v_frac_w1);
|
||||
|
||||
/* Store 1 pixel */
|
||||
d0 = _mm_srli_epi32(k0, PRECISION * 2);
|
||||
e0 = _mm_packs_epi32(d0, d0);
|
||||
e0 = _mm_packus_epi16(e0, e0);
|
||||
*dst++ = _mm_cvtsi128_si32(e0);
|
||||
|
||||
/* Store 1 pixel */
|
||||
d1 = _mm_srli_epi32(k1, PRECISION * 2);
|
||||
e1 = _mm_packs_epi32(d1, d1);
|
||||
e1 = _mm_packus_epi16(e1, e1);
|
||||
*dst++ = _mm_cvtsi128_si32(e1);
|
||||
}
|
||||
|
||||
/* Last point */
|
||||
if (middle & 0x1) {
|
||||
const Uint32 *s_00_01;
|
||||
const Uint32 *s_10_11;
|
||||
int index_w = 4 * SRC_INDEX(fp_sum_w);
|
||||
int frac_w = FRAC(fp_sum_w);
|
||||
fp_sum_w += fp_step_w;
|
||||
s_00_01 = (const Uint32 *)((const Uint8 *)src_h0 + index_w);
|
||||
s_10_11 = (const Uint32 *)((const Uint8 *)src_h1 + index_w);
|
||||
INTERPOL_BILINEAR_SSE(s_00_01, s_10_11, frac_w, v_frac_h0, v_frac_h1, dst, zero);
|
||||
dst += 1;
|
||||
}
|
||||
|
||||
while (right_pad_w--) {
|
||||
int index_w = 4 * (src_w - 2);
|
||||
const Uint32 *s_00_01 = (const Uint32 *)((const Uint8 *)src_h0 + index_w);
|
||||
const Uint32 *s_10_11 = (const Uint32 *)((const Uint8 *)src_h1 + index_w);
|
||||
INTERPOL_BILINEAR_SSE(s_00_01, s_10_11, FRAC_ONE, v_frac_h0, v_frac_h1, dst, zero);
|
||||
dst += 1;
|
||||
}
|
||||
dst = (Uint32 *)((Uint8 *)dst + dst_gap);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SDL_NEON_INTRINSICS
|
||||
|
||||
static SDL_INLINE int hasNEON(void)
|
||||
{
|
||||
static int val = -1;
|
||||
if (val != -1) {
|
||||
return val;
|
||||
}
|
||||
val = SDL_HasNEON();
|
||||
return val;
|
||||
}
|
||||
|
||||
static SDL_INLINE void INTERPOL_BILINEAR_NEON(const Uint32 *s0, const Uint32 *s1, int frac_w, uint8x8_t v_frac_h0, uint8x8_t v_frac_h1, Uint32 *dst)
|
||||
{
|
||||
uint8x8_t x_00_01, x_10_11; /* Pixels in 4*uint8 in row */
|
||||
uint16x8_t k0;
|
||||
uint32x4_t l0;
|
||||
uint16x8_t d0;
|
||||
uint8x8_t e0;
|
||||
|
||||
x_00_01 = CAST_uint8x8_t vld1_u32(s0); /* Load 2 pixels */
|
||||
x_10_11 = CAST_uint8x8_t vld1_u32(s1);
|
||||
|
||||
/* Interpolated == x0 + frac * (x1 - x0) == x0 * (1 - frac) + x1 * frac */
|
||||
k0 = vmull_u8(x_00_01, v_frac_h1); /* k0 := x0 * (1 - frac) */
|
||||
k0 = vmlal_u8(k0, x_10_11, v_frac_h0); /* k0 += x1 * frac */
|
||||
|
||||
/* k0 now contains 2 interpolated pixels { j0, j1 } */
|
||||
l0 = vshll_n_u16(vget_low_u16(k0), PRECISION);
|
||||
l0 = vmlsl_n_u16(l0, vget_low_u16(k0), frac_w);
|
||||
l0 = vmlal_n_u16(l0, vget_high_u16(k0), frac_w);
|
||||
|
||||
/* Shift and narrow */
|
||||
d0 = vcombine_u16(
|
||||
/* uint16x4_t */ vshrn_n_u32(l0, 2 * PRECISION),
|
||||
/* uint16x4_t */ vshrn_n_u32(l0, 2 * PRECISION));
|
||||
|
||||
/* Narrow again */
|
||||
e0 = vmovn_u16(d0);
|
||||
|
||||
/* Store 1 pixel */
|
||||
*dst = vget_lane_u32(CAST_uint32x2_t e0, 0);
|
||||
}
|
||||
|
||||
static int scale_mat_NEON(const Uint32 *src, int src_w, int src_h, int src_pitch, Uint32 *dst, int dst_w, int dst_h, int dst_pitch)
|
||||
{
|
||||
BILINEAR___START
|
||||
|
||||
for (i = 0; i < dst_h; i++) {
|
||||
int nb_block4;
|
||||
uint8x8_t v_frac_h0, v_frac_h1;
|
||||
|
||||
BILINEAR___HEIGHT
|
||||
|
||||
nb_block4 = middle / 4;
|
||||
|
||||
v_frac_h0 = vmov_n_u8(frac_h0);
|
||||
v_frac_h1 = vmov_n_u8(frac_h1);
|
||||
|
||||
while (left_pad_w--) {
|
||||
INTERPOL_BILINEAR_NEON(src_h0, src_h1, FRAC_ZERO, v_frac_h0, v_frac_h1, dst);
|
||||
dst += 1;
|
||||
}
|
||||
|
||||
while (nb_block4--) {
|
||||
int index_w_0, frac_w_0;
|
||||
int index_w_1, frac_w_1;
|
||||
int index_w_2, frac_w_2;
|
||||
int index_w_3, frac_w_3;
|
||||
|
||||
const Uint32 *s_00_01, *s_02_03, *s_04_05, *s_06_07;
|
||||
const Uint32 *s_10_11, *s_12_13, *s_14_15, *s_16_17;
|
||||
|
||||
uint8x8_t x_00_01, x_10_11, x_02_03, x_12_13; /* Pixels in 4*uint8 in row */
|
||||
uint8x8_t x_04_05, x_14_15, x_06_07, x_16_17;
|
||||
|
||||
uint16x8_t k0, k1, k2, k3;
|
||||
uint32x4_t l0, l1, l2, l3;
|
||||
uint16x8_t d0, d1;
|
||||
uint8x8_t e0, e1;
|
||||
uint32x4_t f0;
|
||||
|
||||
index_w_0 = 4 * SRC_INDEX(fp_sum_w);
|
||||
frac_w_0 = FRAC(fp_sum_w);
|
||||
fp_sum_w += fp_step_w;
|
||||
index_w_1 = 4 * SRC_INDEX(fp_sum_w);
|
||||
frac_w_1 = FRAC(fp_sum_w);
|
||||
fp_sum_w += fp_step_w;
|
||||
index_w_2 = 4 * SRC_INDEX(fp_sum_w);
|
||||
frac_w_2 = FRAC(fp_sum_w);
|
||||
fp_sum_w += fp_step_w;
|
||||
index_w_3 = 4 * SRC_INDEX(fp_sum_w);
|
||||
frac_w_3 = FRAC(fp_sum_w);
|
||||
fp_sum_w += fp_step_w;
|
||||
|
||||
s_00_01 = (const Uint32 *)((const Uint8 *)src_h0 + index_w_0);
|
||||
s_02_03 = (const Uint32 *)((const Uint8 *)src_h0 + index_w_1);
|
||||
s_04_05 = (const Uint32 *)((const Uint8 *)src_h0 + index_w_2);
|
||||
s_06_07 = (const Uint32 *)((const Uint8 *)src_h0 + index_w_3);
|
||||
s_10_11 = (const Uint32 *)((const Uint8 *)src_h1 + index_w_0);
|
||||
s_12_13 = (const Uint32 *)((const Uint8 *)src_h1 + index_w_1);
|
||||
s_14_15 = (const Uint32 *)((const Uint8 *)src_h1 + index_w_2);
|
||||
s_16_17 = (const Uint32 *)((const Uint8 *)src_h1 + index_w_3);
|
||||
|
||||
/* Interpolation vertical */
|
||||
x_00_01 = CAST_uint8x8_t vld1_u32(s_00_01); /* Load 2 pixels */
|
||||
x_02_03 = CAST_uint8x8_t vld1_u32(s_02_03);
|
||||
x_04_05 = CAST_uint8x8_t vld1_u32(s_04_05);
|
||||
x_06_07 = CAST_uint8x8_t vld1_u32(s_06_07);
|
||||
x_10_11 = CAST_uint8x8_t vld1_u32(s_10_11);
|
||||
x_12_13 = CAST_uint8x8_t vld1_u32(s_12_13);
|
||||
x_14_15 = CAST_uint8x8_t vld1_u32(s_14_15);
|
||||
x_16_17 = CAST_uint8x8_t vld1_u32(s_16_17);
|
||||
|
||||
/* Interpolated == x0 + frac * (x1 - x0) == x0 * (1 - frac) + x1 * frac */
|
||||
k0 = vmull_u8(x_00_01, v_frac_h1); /* k0 := x0 * (1 - frac) */
|
||||
k0 = vmlal_u8(k0, x_10_11, v_frac_h0); /* k0 += x1 * frac */
|
||||
|
||||
k1 = vmull_u8(x_02_03, v_frac_h1);
|
||||
k1 = vmlal_u8(k1, x_12_13, v_frac_h0);
|
||||
|
||||
k2 = vmull_u8(x_04_05, v_frac_h1);
|
||||
k2 = vmlal_u8(k2, x_14_15, v_frac_h0);
|
||||
|
||||
k3 = vmull_u8(x_06_07, v_frac_h1);
|
||||
k3 = vmlal_u8(k3, x_16_17, v_frac_h0);
|
||||
|
||||
/* k0 now contains 2 interpolated pixels { j0, j1 } */
|
||||
/* k1 now contains 2 interpolated pixels { j2, j3 } */
|
||||
/* k2 now contains 2 interpolated pixels { j4, j5 } */
|
||||
/* k3 now contains 2 interpolated pixels { j6, j7 } */
|
||||
|
||||
l0 = vshll_n_u16(vget_low_u16(k0), PRECISION);
|
||||
l0 = vmlsl_n_u16(l0, vget_low_u16(k0), frac_w_0);
|
||||
l0 = vmlal_n_u16(l0, vget_high_u16(k0), frac_w_0);
|
||||
|
||||
l1 = vshll_n_u16(vget_low_u16(k1), PRECISION);
|
||||
l1 = vmlsl_n_u16(l1, vget_low_u16(k1), frac_w_1);
|
||||
l1 = vmlal_n_u16(l1, vget_high_u16(k1), frac_w_1);
|
||||
|
||||
l2 = vshll_n_u16(vget_low_u16(k2), PRECISION);
|
||||
l2 = vmlsl_n_u16(l2, vget_low_u16(k2), frac_w_2);
|
||||
l2 = vmlal_n_u16(l2, vget_high_u16(k2), frac_w_2);
|
||||
|
||||
l3 = vshll_n_u16(vget_low_u16(k3), PRECISION);
|
||||
l3 = vmlsl_n_u16(l3, vget_low_u16(k3), frac_w_3);
|
||||
l3 = vmlal_n_u16(l3, vget_high_u16(k3), frac_w_3);
|
||||
|
||||
/* shift and narrow */
|
||||
d0 = vcombine_u16(
|
||||
/* uint16x4_t */ vshrn_n_u32(l0, 2 * PRECISION),
|
||||
/* uint16x4_t */ vshrn_n_u32(l1, 2 * PRECISION));
|
||||
/* narrow again */
|
||||
e0 = vmovn_u16(d0);
|
||||
|
||||
/* Shift and narrow */
|
||||
d1 = vcombine_u16(
|
||||
/* uint16x4_t */ vshrn_n_u32(l2, 2 * PRECISION),
|
||||
/* uint16x4_t */ vshrn_n_u32(l3, 2 * PRECISION));
|
||||
/* Narrow again */
|
||||
e1 = vmovn_u16(d1);
|
||||
|
||||
f0 = vcombine_u32(CAST_uint32x2_t e0, CAST_uint32x2_t e1);
|
||||
/* Store 4 pixels */
|
||||
vst1q_u32(dst, f0);
|
||||
|
||||
dst += 4;
|
||||
}
|
||||
|
||||
if (middle & 0x2) {
|
||||
int index_w_0, frac_w_0;
|
||||
int index_w_1, frac_w_1;
|
||||
const Uint32 *s_00_01, *s_02_03;
|
||||
const Uint32 *s_10_11, *s_12_13;
|
||||
uint8x8_t x_00_01, x_10_11, x_02_03, x_12_13; /* Pixels in 4*uint8 in row */
|
||||
uint16x8_t k0, k1;
|
||||
uint32x4_t l0, l1;
|
||||
uint16x8_t d0;
|
||||
uint8x8_t e0;
|
||||
|
||||
index_w_0 = 4 * SRC_INDEX(fp_sum_w);
|
||||
frac_w_0 = FRAC(fp_sum_w);
|
||||
fp_sum_w += fp_step_w;
|
||||
index_w_1 = 4 * SRC_INDEX(fp_sum_w);
|
||||
frac_w_1 = FRAC(fp_sum_w);
|
||||
fp_sum_w += fp_step_w;
|
||||
/*
|
||||
x00............ x01 x02...........x03
|
||||
. . . . . .
|
||||
j0 dest0 j1 j2 dest1 j3
|
||||
. . . . . .
|
||||
. . . . . .
|
||||
. . . . . .
|
||||
x10............ x11 x12...........x13
|
||||
*/
|
||||
s_00_01 = (const Uint32 *)((const Uint8 *)src_h0 + index_w_0);
|
||||
s_02_03 = (const Uint32 *)((const Uint8 *)src_h0 + index_w_1);
|
||||
s_10_11 = (const Uint32 *)((const Uint8 *)src_h1 + index_w_0);
|
||||
s_12_13 = (const Uint32 *)((const Uint8 *)src_h1 + index_w_1);
|
||||
|
||||
/* Interpolation vertical */
|
||||
x_00_01 = CAST_uint8x8_t vld1_u32(s_00_01); /* Load 2 pixels */
|
||||
x_02_03 = CAST_uint8x8_t vld1_u32(s_02_03);
|
||||
x_10_11 = CAST_uint8x8_t vld1_u32(s_10_11);
|
||||
x_12_13 = CAST_uint8x8_t vld1_u32(s_12_13);
|
||||
|
||||
/* Interpolated == x0 + frac * (x1 - x0) == x0 * (1 - frac) + x1 * frac */
|
||||
k0 = vmull_u8(x_00_01, v_frac_h1); /* k0 := x0 * (1 - frac) */
|
||||
k0 = vmlal_u8(k0, x_10_11, v_frac_h0); /* k0 += x1 * frac */
|
||||
|
||||
k1 = vmull_u8(x_02_03, v_frac_h1);
|
||||
k1 = vmlal_u8(k1, x_12_13, v_frac_h0);
|
||||
|
||||
/* k0 now contains 2 interpolated pixels { j0, j1 } */
|
||||
/* k1 now contains 2 interpolated pixels { j2, j3 } */
|
||||
|
||||
l0 = vshll_n_u16(vget_low_u16(k0), PRECISION);
|
||||
l0 = vmlsl_n_u16(l0, vget_low_u16(k0), frac_w_0);
|
||||
l0 = vmlal_n_u16(l0, vget_high_u16(k0), frac_w_0);
|
||||
|
||||
l1 = vshll_n_u16(vget_low_u16(k1), PRECISION);
|
||||
l1 = vmlsl_n_u16(l1, vget_low_u16(k1), frac_w_1);
|
||||
l1 = vmlal_n_u16(l1, vget_high_u16(k1), frac_w_1);
|
||||
|
||||
/* Shift and narrow */
|
||||
|
||||
d0 = vcombine_u16(
|
||||
/* uint16x4_t */ vshrn_n_u32(l0, 2 * PRECISION),
|
||||
/* uint16x4_t */ vshrn_n_u32(l1, 2 * PRECISION));
|
||||
|
||||
/* Narrow again */
|
||||
e0 = vmovn_u16(d0);
|
||||
|
||||
/* Store 2 pixels */
|
||||
vst1_u32(dst, CAST_uint32x2_t e0);
|
||||
dst += 2;
|
||||
}
|
||||
|
||||
/* Last point */
|
||||
if (middle & 0x1) {
|
||||
int index_w = 4 * SRC_INDEX(fp_sum_w);
|
||||
int frac_w = FRAC(fp_sum_w);
|
||||
const Uint32 *s_00_01 = (const Uint32 *)((const Uint8 *)src_h0 + index_w);
|
||||
const Uint32 *s_10_11 = (const Uint32 *)((const Uint8 *)src_h1 + index_w);
|
||||
INTERPOL_BILINEAR_NEON(s_00_01, s_10_11, frac_w, v_frac_h0, v_frac_h1, dst);
|
||||
dst += 1;
|
||||
}
|
||||
|
||||
while (right_pad_w--) {
|
||||
int index_w = 4 * (src_w - 2);
|
||||
const Uint32 *s_00_01 = (const Uint32 *)((const Uint8 *)src_h0 + index_w);
|
||||
const Uint32 *s_10_11 = (const Uint32 *)((const Uint8 *)src_h1 + index_w);
|
||||
INTERPOL_BILINEAR_NEON(s_00_01, s_10_11, FRAC_ONE, v_frac_h0, v_frac_h1, dst);
|
||||
dst += 1;
|
||||
}
|
||||
|
||||
dst = (Uint32 *)((Uint8 *)dst + dst_gap);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int SDL_LowerSoftStretchLinear(SDL_Surface *s, const SDL_Rect *srcrect,
|
||||
SDL_Surface *d, const SDL_Rect *dstrect)
|
||||
{
|
||||
int ret = -1;
|
||||
int src_w = srcrect->w;
|
||||
int src_h = srcrect->h;
|
||||
int dst_w = dstrect->w;
|
||||
int dst_h = dstrect->h;
|
||||
int src_pitch = s->pitch;
|
||||
int dst_pitch = d->pitch;
|
||||
Uint32 *src = (Uint32 *)((Uint8 *)s->pixels + srcrect->x * 4 + srcrect->y * src_pitch);
|
||||
Uint32 *dst = (Uint32 *)((Uint8 *)d->pixels + dstrect->x * 4 + dstrect->y * dst_pitch);
|
||||
|
||||
#ifdef SDL_NEON_INTRINSICS
|
||||
if (ret == -1 && hasNEON()) {
|
||||
ret = scale_mat_NEON(src, src_w, src_h, src_pitch, dst, dst_w, dst_h, dst_pitch);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SDL_SSE2_INTRINSICS
|
||||
if (ret == -1 && hasSSE2()) {
|
||||
ret = scale_mat_SSE(src, src_w, src_h, src_pitch, dst, dst_w, dst_h, dst_pitch);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret == -1) {
|
||||
ret = scale_mat(src, src_w, src_h, src_pitch, dst, dst_w, dst_h, dst_pitch);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define SDL_SCALE_NEAREST__START \
|
||||
int i; \
|
||||
Uint32 posy, incy; \
|
||||
Uint32 posx, incx; \
|
||||
int dst_gap; \
|
||||
int srcy, n; \
|
||||
const Uint32 *src_h0; \
|
||||
incy = (src_h << 16) / dst_h; \
|
||||
incx = (src_w << 16) / dst_w; \
|
||||
dst_gap = dst_pitch - bpp * dst_w; \
|
||||
posy = incy / 2;
|
||||
|
||||
#define SDL_SCALE_NEAREST__HEIGHT \
|
||||
srcy = (posy >> 16); \
|
||||
src_h0 = (const Uint32 *)((const Uint8 *)src_ptr + srcy * src_pitch); \
|
||||
posy += incy; \
|
||||
posx = incx / 2; \
|
||||
n = dst_w;
|
||||
|
||||
static int scale_mat_nearest_1(const Uint32 *src_ptr, int src_w, int src_h, int src_pitch,
|
||||
Uint32 *dst, int dst_w, int dst_h, int dst_pitch)
|
||||
{
|
||||
Uint32 bpp = 1;
|
||||
SDL_SCALE_NEAREST__START
|
||||
for (i = 0; i < dst_h; i++) {
|
||||
SDL_SCALE_NEAREST__HEIGHT
|
||||
while (n--) {
|
||||
const Uint8 *src;
|
||||
int srcx = bpp * (posx >> 16);
|
||||
posx += incx;
|
||||
src = (const Uint8 *)src_h0 + srcx;
|
||||
*(Uint8 *)dst = *src;
|
||||
dst = (Uint32 *)((Uint8 *)dst + bpp);
|
||||
}
|
||||
dst = (Uint32 *)((Uint8 *)dst + dst_gap);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scale_mat_nearest_2(const Uint32 *src_ptr, int src_w, int src_h, int src_pitch,
|
||||
Uint32 *dst, int dst_w, int dst_h, int dst_pitch)
|
||||
{
|
||||
Uint32 bpp = 2;
|
||||
SDL_SCALE_NEAREST__START
|
||||
for (i = 0; i < dst_h; i++) {
|
||||
SDL_SCALE_NEAREST__HEIGHT
|
||||
while (n--) {
|
||||
const Uint16 *src;
|
||||
int srcx = bpp * (posx >> 16);
|
||||
posx += incx;
|
||||
src = (const Uint16 *)((const Uint8 *)src_h0 + srcx);
|
||||
*(Uint16 *)dst = *src;
|
||||
dst = (Uint32 *)((Uint8 *)dst + bpp);
|
||||
}
|
||||
dst = (Uint32 *)((Uint8 *)dst + dst_gap);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scale_mat_nearest_3(const Uint32 *src_ptr, int src_w, int src_h, int src_pitch,
|
||||
Uint32 *dst, int dst_w, int dst_h, int dst_pitch)
|
||||
{
|
||||
Uint32 bpp = 3;
|
||||
SDL_SCALE_NEAREST__START
|
||||
for (i = 0; i < dst_h; i++) {
|
||||
SDL_SCALE_NEAREST__HEIGHT
|
||||
while (n--) {
|
||||
const Uint8 *src;
|
||||
int srcx = bpp * (posx >> 16);
|
||||
posx += incx;
|
||||
src = (const Uint8 *)src_h0 + srcx;
|
||||
((Uint8 *)dst)[0] = src[0];
|
||||
((Uint8 *)dst)[1] = src[1];
|
||||
((Uint8 *)dst)[2] = src[2];
|
||||
dst = (Uint32 *)((Uint8 *)dst + bpp);
|
||||
}
|
||||
dst = (Uint32 *)((Uint8 *)dst + dst_gap);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scale_mat_nearest_4(const Uint32 *src_ptr, int src_w, int src_h, int src_pitch,
|
||||
Uint32 *dst, int dst_w, int dst_h, int dst_pitch)
|
||||
{
|
||||
Uint32 bpp = 4;
|
||||
SDL_SCALE_NEAREST__START
|
||||
for (i = 0; i < dst_h; i++) {
|
||||
SDL_SCALE_NEAREST__HEIGHT
|
||||
while (n--) {
|
||||
const Uint32 *src;
|
||||
int srcx = bpp * (posx >> 16);
|
||||
posx += incx;
|
||||
src = (const Uint32 *)((const Uint8 *)src_h0 + srcx);
|
||||
*dst = *src;
|
||||
dst = (Uint32 *)((Uint8 *)dst + bpp);
|
||||
}
|
||||
dst = (Uint32 *)((Uint8 *)dst + dst_gap);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_LowerSoftStretchNearest(SDL_Surface *s, const SDL_Rect *srcrect,
|
||||
SDL_Surface *d, const SDL_Rect *dstrect)
|
||||
{
|
||||
int src_w = srcrect->w;
|
||||
int src_h = srcrect->h;
|
||||
int dst_w = dstrect->w;
|
||||
int dst_h = dstrect->h;
|
||||
int src_pitch = s->pitch;
|
||||
int dst_pitch = d->pitch;
|
||||
|
||||
const int bpp = d->format->BytesPerPixel;
|
||||
|
||||
Uint32 *src = (Uint32 *)((Uint8 *)s->pixels + srcrect->x * bpp + srcrect->y * src_pitch);
|
||||
Uint32 *dst = (Uint32 *)((Uint8 *)d->pixels + dstrect->x * bpp + dstrect->y * dst_pitch);
|
||||
|
||||
if (bpp == 4) {
|
||||
return scale_mat_nearest_4(src, src_w, src_h, src_pitch, dst, dst_w, dst_h, dst_pitch);
|
||||
} else if (bpp == 3) {
|
||||
return scale_mat_nearest_3(src, src_w, src_h, src_pitch, dst, dst_w, dst_h, dst_pitch);
|
||||
} else if (bpp == 2) {
|
||||
return scale_mat_nearest_2(src, src_w, src_h, src_pitch, dst, dst_w, dst_h, dst_pitch);
|
||||
} else {
|
||||
return scale_mat_nearest_1(src, src_w, src_h, src_pitch, dst, dst_w, dst_h, dst_pitch);
|
||||
}
|
||||
}
|
1579
external/sdl/SDL/src/video/SDL_surface.c
vendored
Normal file
1579
external/sdl/SDL/src/video/SDL_surface.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
549
external/sdl/SDL/src/video/SDL_sysvideo.h
vendored
Normal file
549
external/sdl/SDL/src/video/SDL_sysvideo.h
vendored
Normal file
@ -0,0 +1,549 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_sysvideo_h_
|
||||
#define SDL_sysvideo_h_
|
||||
|
||||
#include "SDL_vulkan_internal.h"
|
||||
|
||||
/* The SDL video driver */
|
||||
|
||||
typedef struct SDL_WindowShaper SDL_WindowShaper;
|
||||
typedef struct SDL_ShapeDriver SDL_ShapeDriver;
|
||||
typedef struct SDL_VideoDisplay SDL_VideoDisplay;
|
||||
typedef struct SDL_VideoDevice SDL_VideoDevice;
|
||||
typedef struct SDL_VideoData SDL_VideoData;
|
||||
typedef struct SDL_DisplayData SDL_DisplayData;
|
||||
typedef struct SDL_DisplayModeData SDL_DisplayModeData;
|
||||
typedef struct SDL_WindowData SDL_WindowData;
|
||||
|
||||
/* Define the SDL window-shaper structure */
|
||||
struct SDL_WindowShaper
|
||||
{
|
||||
/* The window associated with the shaper */
|
||||
SDL_Window *window;
|
||||
|
||||
/* The parameters for shape calculation. */
|
||||
SDL_WindowShapeMode mode;
|
||||
|
||||
/* Has this window been assigned a shape? */
|
||||
SDL_bool hasshape;
|
||||
|
||||
void *driverdata;
|
||||
};
|
||||
|
||||
/* Define the SDL shape driver structure */
|
||||
struct SDL_ShapeDriver
|
||||
{
|
||||
SDL_WindowShaper *(*CreateShaper)(SDL_Window *window);
|
||||
int (*SetWindowShape)(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode);
|
||||
};
|
||||
|
||||
typedef struct SDL_WindowUserData
|
||||
{
|
||||
char *name;
|
||||
void *data;
|
||||
struct SDL_WindowUserData *next;
|
||||
} SDL_WindowUserData;
|
||||
|
||||
/* Define the SDL window structure, corresponding to toplevel windows */
|
||||
struct SDL_Window
|
||||
{
|
||||
const void *magic;
|
||||
SDL_WindowID id;
|
||||
char *title;
|
||||
SDL_Surface *icon;
|
||||
int x, y;
|
||||
int w, h;
|
||||
int min_w, min_h;
|
||||
int max_w, max_h;
|
||||
int last_pixel_w, last_pixel_h;
|
||||
Uint32 flags;
|
||||
Uint32 pending_flags;
|
||||
float display_scale;
|
||||
SDL_bool fullscreen_exclusive; /* The window is currently fullscreen exclusive */
|
||||
SDL_DisplayID last_fullscreen_exclusive_display; /* The last fullscreen_exclusive display */
|
||||
SDL_DisplayID last_displayID;
|
||||
|
||||
/* Stored position and size for windowed mode */
|
||||
SDL_Rect windowed;
|
||||
|
||||
/* Whether or not the initial position was defined */
|
||||
SDL_bool undefined_x;
|
||||
SDL_bool undefined_y;
|
||||
|
||||
SDL_DisplayMode requested_fullscreen_mode;
|
||||
SDL_DisplayMode current_fullscreen_mode;
|
||||
|
||||
float opacity;
|
||||
|
||||
SDL_Surface *surface;
|
||||
SDL_bool surface_valid;
|
||||
|
||||
SDL_bool is_hiding;
|
||||
SDL_bool restore_on_show; /* Child was hidden recursively by the parent, restore when shown. */
|
||||
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;
|
||||
void *hit_test_data;
|
||||
|
||||
SDL_WindowUserData *data;
|
||||
|
||||
SDL_WindowData *driverdata;
|
||||
|
||||
SDL_Window *prev;
|
||||
SDL_Window *next;
|
||||
|
||||
SDL_Window *parent;
|
||||
SDL_Window *first_child;
|
||||
SDL_Window *prev_sibling;
|
||||
SDL_Window *next_sibling;
|
||||
};
|
||||
#define SDL_WINDOW_FULLSCREEN_VISIBLE(W) \
|
||||
((((W)->flags & SDL_WINDOW_FULLSCREEN) != 0) && \
|
||||
(((W)->flags & SDL_WINDOW_HIDDEN) == 0) && \
|
||||
(((W)->flags & SDL_WINDOW_MINIMIZED) == 0))
|
||||
|
||||
#define SDL_WINDOW_IS_POPUP(W) \
|
||||
((((W)->flags & SDL_WINDOW_TOOLTIP) != 0) || \
|
||||
(((W)->flags & SDL_WINDOW_POPUP_MENU) != 0)) \
|
||||
\
|
||||
/*
|
||||
* Define the SDL display structure.
|
||||
* This corresponds to physical monitors attached to the system.
|
||||
*/
|
||||
struct SDL_VideoDisplay
|
||||
{
|
||||
SDL_DisplayID id;
|
||||
char *name;
|
||||
int max_fullscreen_modes;
|
||||
int num_fullscreen_modes;
|
||||
SDL_DisplayMode *fullscreen_modes;
|
||||
SDL_DisplayMode desktop_mode;
|
||||
const SDL_DisplayMode *current_mode;
|
||||
SDL_DisplayOrientation natural_orientation;
|
||||
SDL_DisplayOrientation current_orientation;
|
||||
float content_scale;
|
||||
|
||||
SDL_Window *fullscreen_window;
|
||||
|
||||
SDL_VideoDevice *device;
|
||||
|
||||
SDL_DisplayData *driverdata;
|
||||
};
|
||||
|
||||
/* Forward declaration */
|
||||
struct SDL_SysWMinfo;
|
||||
|
||||
/* Video device flags */
|
||||
typedef enum
|
||||
{
|
||||
VIDEO_DEVICE_QUIRK_MODE_SWITCHING_EMULATED = 0x01,
|
||||
VIDEO_DEVICE_QUIRK_DISABLE_UNSET_FULLSCREEN_ON_MINIMIZE = 0x02,
|
||||
VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT = 0x04,
|
||||
} DeviceQuirkFlags;
|
||||
|
||||
struct SDL_VideoDevice
|
||||
{
|
||||
/* * * */
|
||||
/* The name of this video driver */
|
||||
const char *name;
|
||||
|
||||
/* * * */
|
||||
/* Initialization/Query functions */
|
||||
|
||||
/*
|
||||
* Initialize the native video subsystem, filling in the list of
|
||||
* displays for this driver, returning 0 or -1 if there's an error.
|
||||
*/
|
||||
int (*VideoInit)(SDL_VideoDevice *_this);
|
||||
|
||||
/*
|
||||
* Reverse the effects VideoInit() -- called if VideoInit() fails or
|
||||
* if the application is shutting down the video subsystem.
|
||||
*/
|
||||
void (*VideoQuit)(SDL_VideoDevice *_this);
|
||||
|
||||
/*
|
||||
* Reinitialize the touch devices -- called if an unknown touch ID occurs.
|
||||
*/
|
||||
void (*ResetTouch)(SDL_VideoDevice *_this);
|
||||
|
||||
/* * * */
|
||||
/*
|
||||
* Display functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Refresh the display list
|
||||
*/
|
||||
void (*RefreshDisplays)(SDL_VideoDevice *_this);
|
||||
|
||||
/*
|
||||
* Get the bounds of a display
|
||||
*/
|
||||
int (*GetDisplayBounds)(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect);
|
||||
|
||||
/*
|
||||
* Get the usable bounds of a display (bounds minus menubar or whatever)
|
||||
*/
|
||||
int (*GetDisplayUsableBounds)(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect);
|
||||
|
||||
/*
|
||||
* Get a list of the available display modes for a display.
|
||||
*/
|
||||
int (*GetDisplayModes)(SDL_VideoDevice *_this, SDL_VideoDisplay *display);
|
||||
|
||||
/*
|
||||
* Setting the display mode is independent of creating windows, so
|
||||
* when the display mode is changed, all existing windows should have
|
||||
* their data updated accordingly, including the display surfaces
|
||||
* associated with them.
|
||||
*/
|
||||
int (*SetDisplayMode)(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
|
||||
|
||||
/* * * */
|
||||
/*
|
||||
* Window functions
|
||||
*/
|
||||
int (*CreateSDLWindow)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
int (*CreateSDLWindowFrom)(SDL_VideoDevice *_this, SDL_Window *window, const void *data);
|
||||
void (*SetWindowTitle)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
int (*SetWindowIcon)(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon);
|
||||
int (*SetWindowPosition)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*SetWindowSize)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*SetWindowMinimumSize)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*SetWindowMaximumSize)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
int (*GetWindowBordersSize)(SDL_VideoDevice *_this, SDL_Window *window, int *top, int *left, int *bottom, int *right);
|
||||
void (*GetWindowSizeInPixels)(SDL_VideoDevice *_this, SDL_Window *window, int *w, int *h);
|
||||
int (*SetWindowOpacity)(SDL_VideoDevice *_this, SDL_Window *window, float opacity);
|
||||
int (*SetWindowModalFor)(SDL_VideoDevice *_this, SDL_Window *modal_window, SDL_Window *parent_window);
|
||||
int (*SetWindowInputFocus)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*ShowWindow)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*HideWindow)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*RaiseWindow)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*MaximizeWindow)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*MinimizeWindow)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*RestoreWindow)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*SetWindowBordered)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered);
|
||||
void (*SetWindowResizable)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable);
|
||||
void (*SetWindowAlwaysOnTop)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top);
|
||||
void (*SetWindowFullscreen)(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
|
||||
void *(*GetWindowICCProfile)(SDL_VideoDevice *_this, SDL_Window *window, size_t *size);
|
||||
SDL_DisplayID (*GetDisplayForWindow)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*SetWindowMouseRect)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*SetWindowMouseGrab)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
|
||||
void (*SetWindowKeyboardGrab)(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
|
||||
void (*DestroyWindow)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
int (*CreateWindowFramebuffer)(SDL_VideoDevice *_this, SDL_Window *window, Uint32 *format, void **pixels, int *pitch);
|
||||
int (*UpdateWindowFramebuffer)(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, int numrects);
|
||||
void (*DestroyWindowFramebuffer)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*OnWindowEnter)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
int (*FlashWindow)(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);
|
||||
|
||||
/* * * */
|
||||
/*
|
||||
* Shaped-window functions
|
||||
*/
|
||||
SDL_ShapeDriver shape_driver;
|
||||
|
||||
/* Get some platform dependent window information */
|
||||
int (*GetWindowWMInfo)(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info);
|
||||
|
||||
/* * * */
|
||||
/*
|
||||
* OpenGL support
|
||||
*/
|
||||
int (*GL_LoadLibrary)(SDL_VideoDevice *_this, const char *path);
|
||||
SDL_FunctionPointer (*GL_GetProcAddress)(SDL_VideoDevice *_this, const char *proc);
|
||||
void (*GL_UnloadLibrary)(SDL_VideoDevice *_this);
|
||||
SDL_GLContext (*GL_CreateContext)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
int (*GL_MakeCurrent)(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context);
|
||||
SDL_EGLSurface (*GL_GetEGLSurface)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
int (*GL_SetSwapInterval)(SDL_VideoDevice *_this, int interval);
|
||||
int (*GL_GetSwapInterval)(SDL_VideoDevice *_this, int *interval);
|
||||
int (*GL_SwapWindow)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
int (*GL_DeleteContext)(SDL_VideoDevice *_this, SDL_GLContext context);
|
||||
void (*GL_DefaultProfileConfig)(SDL_VideoDevice *_this, int *mask, int *major, int *minor);
|
||||
|
||||
/* * * */
|
||||
/*
|
||||
* Vulkan support
|
||||
*/
|
||||
int (*Vulkan_LoadLibrary)(SDL_VideoDevice *_this, const char *path);
|
||||
void (*Vulkan_UnloadLibrary)(SDL_VideoDevice *_this);
|
||||
SDL_bool (*Vulkan_GetInstanceExtensions)(SDL_VideoDevice *_this, unsigned *count, const char **names);
|
||||
SDL_bool (*Vulkan_CreateSurface)(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, VkSurfaceKHR *surface);
|
||||
|
||||
/* * * */
|
||||
/*
|
||||
* Metal support
|
||||
*/
|
||||
SDL_MetalView (*Metal_CreateView)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*Metal_DestroyView)(SDL_VideoDevice *_this, SDL_MetalView view);
|
||||
void *(*Metal_GetLayer)(SDL_VideoDevice *_this, SDL_MetalView view);
|
||||
|
||||
/* * * */
|
||||
/*
|
||||
* Event manager functions
|
||||
*/
|
||||
int (*WaitEventTimeout)(SDL_VideoDevice *_this, Sint64 timeoutNS);
|
||||
void (*SendWakeupEvent)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*PumpEvents)(SDL_VideoDevice *_this);
|
||||
|
||||
/* Suspend the screensaver */
|
||||
int (*SuspendScreenSaver)(SDL_VideoDevice *_this);
|
||||
|
||||
/* Text input */
|
||||
void (*StartTextInput)(SDL_VideoDevice *_this);
|
||||
void (*StopTextInput)(SDL_VideoDevice *_this);
|
||||
int (*SetTextInputRect)(SDL_VideoDevice *_this, const SDL_Rect *rect);
|
||||
void (*ClearComposition)(SDL_VideoDevice *_this);
|
||||
SDL_bool (*IsTextInputShown)(SDL_VideoDevice *_this);
|
||||
|
||||
/* Screen keyboard */
|
||||
SDL_bool (*HasScreenKeyboardSupport)(SDL_VideoDevice *_this);
|
||||
void (*ShowScreenKeyboard)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void (*HideScreenKeyboard)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
SDL_bool (*IsScreenKeyboardShown)(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
|
||||
/* Clipboard */
|
||||
const char **(*GetTextMimeTypes)(SDL_VideoDevice *_this, size_t *num_mime_types);
|
||||
int (*SetClipboardData)(SDL_VideoDevice *_this);
|
||||
void *(*GetClipboardData)(SDL_VideoDevice *_this, const char *mime_type, size_t *size);
|
||||
SDL_bool (*HasClipboardData)(SDL_VideoDevice *_this, const char *mime_type);
|
||||
/* If you implement *ClipboardData, you don't need to implement *ClipboardText */
|
||||
int (*SetClipboardText)(SDL_VideoDevice *_this, const char *text);
|
||||
char *(*GetClipboardText)(SDL_VideoDevice *_this);
|
||||
SDL_bool (*HasClipboardText)(SDL_VideoDevice *_this);
|
||||
/* These functions are only needed if the platform has a separate primary selection buffer */
|
||||
int (*SetPrimarySelectionText)(SDL_VideoDevice *_this, const char *text);
|
||||
char *(*GetPrimarySelectionText)(SDL_VideoDevice *_this);
|
||||
SDL_bool (*HasPrimarySelectionText)(SDL_VideoDevice *_this);
|
||||
|
||||
/* MessageBox */
|
||||
int (*ShowMessageBox)(SDL_VideoDevice *_this, const SDL_MessageBoxData *messageboxdata, int *buttonid);
|
||||
|
||||
/* Hit-testing */
|
||||
int (*SetWindowHitTest)(SDL_Window *window, SDL_bool enabled);
|
||||
|
||||
/* Tell window that app enabled drag'n'drop events */
|
||||
void (*AcceptDragAndDrop)(SDL_Window *window, SDL_bool accept);
|
||||
|
||||
/* * * */
|
||||
/* Data common to all drivers */
|
||||
SDL_threadID thread;
|
||||
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;
|
||||
SDL_Window *grabbed_window;
|
||||
Uint8 window_magic;
|
||||
SDL_WindowID next_object_id;
|
||||
Uint32 clipboard_sequence;
|
||||
SDL_ClipboardDataCallback clipboard_callback;
|
||||
SDL_ClipboardCleanupCallback clipboard_cleanup;
|
||||
void *clipboard_userdata;
|
||||
char **clipboard_mime_types;
|
||||
size_t num_clipboard_mime_types;
|
||||
char *primary_selection_text;
|
||||
SDL_bool setting_display_mode;
|
||||
Uint32 quirk_flags;
|
||||
SDL_SystemTheme system_theme;
|
||||
|
||||
/* * * */
|
||||
/* Data used by the GL drivers */
|
||||
struct
|
||||
{
|
||||
int red_size;
|
||||
int green_size;
|
||||
int blue_size;
|
||||
int alpha_size;
|
||||
int depth_size;
|
||||
int buffer_size;
|
||||
int stencil_size;
|
||||
int double_buffer;
|
||||
int accum_red_size;
|
||||
int accum_green_size;
|
||||
int accum_blue_size;
|
||||
int accum_alpha_size;
|
||||
int stereo;
|
||||
int multisamplebuffers;
|
||||
int multisamplesamples;
|
||||
int floatbuffers;
|
||||
int accelerated;
|
||||
int major_version;
|
||||
int minor_version;
|
||||
int flags;
|
||||
int profile_mask;
|
||||
int share_with_current_context;
|
||||
int release_behavior;
|
||||
int reset_notification;
|
||||
int framebuffer_srgb_capable;
|
||||
int no_error;
|
||||
int retained_backing;
|
||||
int egl_platform;
|
||||
int driver_loaded;
|
||||
char driver_path[256];
|
||||
void *dll_handle;
|
||||
} gl_config;
|
||||
|
||||
SDL_EGLAttribArrayCallback egl_platformattrib_callback;
|
||||
SDL_EGLIntArrayCallback egl_surfaceattrib_callback;
|
||||
SDL_EGLIntArrayCallback egl_contextattrib_callback;
|
||||
|
||||
/* * * */
|
||||
/* Cache current GL context; don't call the OS when it hasn't changed. */
|
||||
/* We have the global pointers here so Cocoa continues to work the way
|
||||
it always has, and the thread-local storage for the general case.
|
||||
*/
|
||||
SDL_Window *current_glwin;
|
||||
SDL_GLContext current_glctx;
|
||||
SDL_TLSID current_glwin_tls;
|
||||
SDL_TLSID current_glctx_tls;
|
||||
|
||||
/* Flag that stores whether it's allowed to call SDL_GL_MakeCurrent()
|
||||
* with a NULL window, but a non-NULL context. (Not allowed in most cases,
|
||||
* except on EGL under some circumstances.) */
|
||||
SDL_bool gl_allow_no_surface;
|
||||
|
||||
/* * * */
|
||||
/* Data used by the Vulkan drivers */
|
||||
struct
|
||||
{
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
|
||||
PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
|
||||
int loader_loaded;
|
||||
char loader_path[256];
|
||||
void *loader_handle;
|
||||
} vulkan_config;
|
||||
|
||||
/* * * */
|
||||
/* Data private to this driver */
|
||||
SDL_VideoData *driverdata;
|
||||
struct SDL_GLDriverData *gl_data;
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
struct SDL_EGL_VideoData *egl_data;
|
||||
#endif
|
||||
|
||||
#if defined(SDL_VIDEO_OPENGL_ES) || defined(SDL_VIDEO_OPENGL_ES2)
|
||||
struct SDL_PrivateGLESData *gles_data;
|
||||
#endif
|
||||
|
||||
/* * * */
|
||||
/* The function used to dispose of this structure */
|
||||
void (*free)(SDL_VideoDevice *_this);
|
||||
};
|
||||
|
||||
typedef struct VideoBootStrap
|
||||
{
|
||||
const char *name;
|
||||
const char *desc;
|
||||
SDL_VideoDevice *(*create)(void);
|
||||
} VideoBootStrap;
|
||||
|
||||
/* Not all of these are available in a given build. Use #ifdefs, etc. */
|
||||
extern VideoBootStrap COCOA_bootstrap;
|
||||
extern VideoBootStrap X11_bootstrap;
|
||||
extern VideoBootStrap WINDOWS_bootstrap;
|
||||
extern VideoBootStrap WINRT_bootstrap;
|
||||
extern VideoBootStrap HAIKU_bootstrap;
|
||||
extern VideoBootStrap PND_bootstrap;
|
||||
extern VideoBootStrap UIKIT_bootstrap;
|
||||
extern VideoBootStrap Android_bootstrap;
|
||||
extern VideoBootStrap PS2_bootstrap;
|
||||
extern VideoBootStrap PSP_bootstrap;
|
||||
extern VideoBootStrap VITA_bootstrap;
|
||||
extern VideoBootStrap RISCOS_bootstrap;
|
||||
extern VideoBootStrap N3DS_bootstrap;
|
||||
extern VideoBootStrap RPI_bootstrap;
|
||||
extern VideoBootStrap KMSDRM_bootstrap;
|
||||
extern VideoBootStrap KMSDRM_LEGACY_bootstrap;
|
||||
extern VideoBootStrap DUMMY_bootstrap;
|
||||
extern VideoBootStrap DUMMY_evdev_bootstrap;
|
||||
extern VideoBootStrap Wayland_bootstrap;
|
||||
extern VideoBootStrap VIVANTE_bootstrap;
|
||||
extern VideoBootStrap Emscripten_bootstrap;
|
||||
extern VideoBootStrap OFFSCREEN_bootstrap;
|
||||
extern VideoBootStrap NGAGE_bootstrap;
|
||||
extern VideoBootStrap QNX_bootstrap;
|
||||
|
||||
/* Use SDL_OnVideoThread() sparingly, to avoid regressions in use cases that currently happen to work */
|
||||
extern SDL_bool SDL_OnVideoThread(void);
|
||||
extern SDL_VideoDevice *SDL_GetVideoDevice(void);
|
||||
extern SDL_bool SDL_IsVideoContextExternal(void);
|
||||
extern void SDL_SetSystemTheme(SDL_SystemTheme theme);
|
||||
extern SDL_DisplayID SDL_AddBasicVideoDisplay(const SDL_DisplayMode *desktop_mode);
|
||||
extern SDL_DisplayID SDL_AddVideoDisplay(const SDL_VideoDisplay *display, SDL_bool send_event);
|
||||
extern void SDL_DelVideoDisplay(SDL_DisplayID display, SDL_bool send_event);
|
||||
extern SDL_bool SDL_AddFullscreenDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode);
|
||||
extern void SDL_ResetFullscreenDisplayModes(SDL_VideoDisplay *display);
|
||||
extern void SDL_SetDesktopDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode);
|
||||
extern void SDL_SetCurrentDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode);
|
||||
extern void SDL_SetDisplayContentScale(SDL_VideoDisplay *display, float scale);
|
||||
extern SDL_VideoDisplay *SDL_GetVideoDisplay(SDL_DisplayID display);
|
||||
extern SDL_VideoDisplay *SDL_GetVideoDisplayForWindow(SDL_Window *window);
|
||||
extern int SDL_GetDisplayIndex(SDL_DisplayID displayID);
|
||||
extern SDL_DisplayData *SDL_GetDisplayDriverData(SDL_DisplayID display);
|
||||
extern SDL_DisplayData *SDL_GetDisplayDriverDataForWindow(SDL_Window *window);
|
||||
extern int SDL_GetMessageBoxCount(void);
|
||||
|
||||
extern void SDL_GL_DeduceMaxSupportedESProfile(int *major, int *minor);
|
||||
|
||||
extern int SDL_RecreateWindow(SDL_Window *window, Uint32 flags);
|
||||
extern SDL_bool SDL_HasWindows(void);
|
||||
extern void SDL_RelativeToGlobalForWindow(SDL_Window *window, int rel_x, int rel_y, int *abs_x, int *abs_y);
|
||||
extern void SDL_GlobalToRelativeForWindow(SDL_Window *window, int abs_x, int abs_y, int *rel_x, int *rel_y);
|
||||
|
||||
extern void SDL_OnDisplayConnected(SDL_VideoDisplay *display);
|
||||
extern void SDL_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_CheckWindowPixelSizeChanged(SDL_Window *window);
|
||||
extern void SDL_OnWindowPixelSizeChanged(SDL_Window *window);
|
||||
extern void SDL_OnWindowMinimized(SDL_Window *window);
|
||||
extern void SDL_OnWindowMaximized(SDL_Window *window);
|
||||
extern void SDL_OnWindowRestored(SDL_Window *window);
|
||||
extern void SDL_OnWindowEnter(SDL_Window *window);
|
||||
extern void SDL_OnWindowLeave(SDL_Window *window);
|
||||
extern void SDL_OnWindowFocusGained(SDL_Window *window);
|
||||
extern void SDL_OnWindowFocusLost(SDL_Window *window);
|
||||
extern void SDL_OnWindowDisplayChanged(SDL_Window *window);
|
||||
extern void SDL_UpdateWindowGrab(SDL_Window *window);
|
||||
extern SDL_Window *SDL_GetFocusWindow(void);
|
||||
|
||||
extern SDL_bool SDL_ShouldAllowTopmost(void);
|
||||
|
||||
extern void SDL_ToggleDragAndDropSupport(void);
|
||||
|
||||
#endif /* SDL_sysvideo_h_ */
|
5252
external/sdl/SDL/src/video/SDL_video.c
vendored
Normal file
5252
external/sdl/SDL/src/video/SDL_video.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
60
external/sdl/SDL/src/video/SDL_video_c.h
vendored
Normal file
60
external/sdl/SDL/src/video/SDL_video_c.h
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_video_c_h_
|
||||
#define SDL_video_c_h_
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
/**
|
||||
* Initialize the video subsystem, optionally specifying a video driver.
|
||||
*
|
||||
* This function initializes the video subsystem, setting up a connection to
|
||||
* the window manager, etc, and determines the available display modes and
|
||||
* pixel formats, but does not initialize a window or graphics mode.
|
||||
*
|
||||
* If you use this function and you haven't used the SDL_INIT_VIDEO flag with
|
||||
* either SDL_Init() or SDL_InitSubSystem(), you should call SDL_VideoQuit()
|
||||
* before calling SDL_Quit().
|
||||
*
|
||||
* It is safe to call this function multiple times. SDL_VideoInit() will call
|
||||
* SDL_VideoQuit() itself if the video subsystem has already been initialized.
|
||||
*
|
||||
* You can use SDL_GetNumVideoDrivers() and SDL_GetVideoDriver() to find a
|
||||
* specific `driver_name`.
|
||||
*
|
||||
* \param driver_name the name of a video driver to initialize, or NULL for
|
||||
* the default driver
|
||||
* \returns 0 on success or a negative error code on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
*/
|
||||
extern int SDL_VideoInit(const char *driver_name);
|
||||
|
||||
/**
|
||||
* Shut down the video subsystem, if initialized with SDL_VideoInit().
|
||||
*
|
||||
* This function closes all windows, and restores the original video mode.
|
||||
*/
|
||||
extern void SDL_VideoQuit(void);
|
||||
|
||||
extern int SDL_SetWindowTextureVSync(SDL_Window *window, int vsync);
|
||||
|
||||
#endif /* SDL_video_c_h_ */
|
90
external/sdl/SDL/src/video/SDL_vulkan_internal.h
vendored
Normal file
90
external/sdl/SDL/src/video/SDL_vulkan_internal.h
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#ifndef SDL_vulkan_internal_h_
|
||||
#define SDL_vulkan_internal_h_
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_VULKAN
|
||||
#if defined(SDL_LOADSO_DISABLED) || defined(SDL_LOADSO_DUMMY)
|
||||
#error You should not be here.
|
||||
#endif
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_ANDROID
|
||||
#define VK_USE_PLATFORM_ANDROID_KHR
|
||||
#endif
|
||||
#ifdef SDL_VIDEO_DRIVER_COCOA
|
||||
#define VK_USE_PLATFORM_METAL_EXT
|
||||
#define VK_USE_PLATFORM_MACOS_MVK
|
||||
#endif
|
||||
#ifdef SDL_VIDEO_DRIVER_UIKIT
|
||||
#define VK_USE_PLATFORM_METAL_EXT
|
||||
#define VK_USE_PLATFORM_IOS_MVK
|
||||
#endif
|
||||
#ifdef SDL_VIDEO_DRIVER_WAYLAND
|
||||
#define VK_USE_PLATFORM_WAYLAND_KHR
|
||||
#include "wayland/SDL_waylanddyn.h"
|
||||
#endif
|
||||
#ifdef SDL_VIDEO_DRIVER_WINDOWS
|
||||
#define VK_USE_PLATFORM_WIN32_KHR
|
||||
#include "../core/windows/SDL_windows.h"
|
||||
#endif
|
||||
#ifdef SDL_VIDEO_DRIVER_X11
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#define VK_USE_PLATFORM_XCB_KHR
|
||||
#endif
|
||||
|
||||
#define VK_NO_PROTOTYPES
|
||||
#include "./khronos/vulkan/vulkan.h"
|
||||
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
|
||||
extern const char *SDL_Vulkan_GetResultString(VkResult result);
|
||||
|
||||
extern VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties,
|
||||
Uint32 *extensionCount); /* free returned list with SDL_free */
|
||||
|
||||
/* Implements functionality of SDL_Vulkan_GetInstanceExtensions for a list of
|
||||
* names passed in nameCount and names. */
|
||||
extern SDL_bool SDL_Vulkan_GetInstanceExtensions_Helper(unsigned *userCount,
|
||||
const char **userNames,
|
||||
unsigned nameCount,
|
||||
const char *const *names);
|
||||
|
||||
/* Create a surface directly from a display connected to a physical device
|
||||
* using the DisplayKHR extension.
|
||||
* This needs to be passed an instance that was created with the VK_KHR_DISPLAY_EXTENSION_NAME
|
||||
* extension. */
|
||||
extern SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface);
|
||||
#else
|
||||
|
||||
/* No SDL Vulkan support, just include the header for typedefs */
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
|
||||
typedef void (*PFN_vkGetInstanceProcAddr)(void);
|
||||
typedef int (*PFN_vkEnumerateInstanceExtensionProperties)(void);
|
||||
|
||||
#endif /* SDL_VIDEO_VULKAN */
|
||||
|
||||
#endif /* SDL_vulkan_internal_h_ */
|
496
external/sdl/SDL/src/video/SDL_vulkan_utils.c
vendored
Normal file
496
external/sdl/SDL/src/video/SDL_vulkan_utils.c
vendored
Normal file
@ -0,0 +1,496 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_vulkan_internal.h"
|
||||
|
||||
#ifdef 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";
|
||||
#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) {
|
||||
return "VK_ERROR_<Unknown>";
|
||||
}
|
||||
return "VK_<Unknown>";
|
||||
}
|
||||
|
||||
VkExtensionProperties *SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties,
|
||||
Uint32 *extensionCount)
|
||||
{
|
||||
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. */
|
||||
SDL_SetError(
|
||||
"You probably don't have a working Vulkan driver installed. %s %s %s(%d)",
|
||||
"Getting Vulkan extensions failed:",
|
||||
"vkEnumerateInstanceExtensionProperties returned",
|
||||
SDL_Vulkan_GetResultString(result),
|
||||
(int)result);
|
||||
return NULL;
|
||||
} else if (result != VK_SUCCESS) {
|
||||
SDL_SetError(
|
||||
"Getting Vulkan extensions failed: vkEnumerateInstanceExtensionProperties returned "
|
||||
"%s(%d)",
|
||||
SDL_Vulkan_GetResultString(result),
|
||||
(int)result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
retval = SDL_calloc(1, sizeof(VkExtensionProperties)); // so we can return non-null
|
||||
} else {
|
||||
retval = SDL_calloc(count, sizeof(VkExtensionProperties));
|
||||
}
|
||||
|
||||
if (retval == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = vkEnumerateInstanceExtensionProperties(NULL, &count, retval);
|
||||
if (result != VK_SUCCESS) {
|
||||
SDL_SetError(
|
||||
"Getting Vulkan extensions failed: vkEnumerateInstanceExtensionProperties returned "
|
||||
"%s(%d)",
|
||||
SDL_Vulkan_GetResultString(result),
|
||||
(int)result);
|
||||
SDL_free(retval);
|
||||
return NULL;
|
||||
}
|
||||
*extensionCount = count;
|
||||
return retval;
|
||||
}
|
||||
|
||||
SDL_bool SDL_Vulkan_GetInstanceExtensions_Helper(unsigned *userCount,
|
||||
const char **userNames,
|
||||
unsigned nameCount,
|
||||
const char *const *names)
|
||||
{
|
||||
if (userNames) {
|
||||
unsigned i;
|
||||
|
||||
if (*userCount < nameCount) {
|
||||
SDL_SetError("Output array for SDL_Vulkan_GetInstanceExtensions needs to be at least %d big", nameCount);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < nameCount; i++) {
|
||||
userNames[i] = names[i];
|
||||
}
|
||||
}
|
||||
*userCount = nameCount;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Alpha modes, in order of preference */
|
||||
static const VkDisplayPlaneAlphaFlagBitsKHR alphaModes[4] = {
|
||||
VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR,
|
||||
VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR,
|
||||
VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR,
|
||||
VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR,
|
||||
};
|
||||
|
||||
SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)vkGetInstanceProcAddr_;
|
||||
#define VULKAN_INSTANCE_FUNCTION(name) \
|
||||
PFN_##name name = (PFN_##name)vkGetInstanceProcAddr((VkInstance)instance, #name)
|
||||
VULKAN_INSTANCE_FUNCTION(vkEnumeratePhysicalDevices);
|
||||
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceDisplayPropertiesKHR);
|
||||
VULKAN_INSTANCE_FUNCTION(vkGetDisplayModePropertiesKHR);
|
||||
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceDisplayPlanePropertiesKHR);
|
||||
VULKAN_INSTANCE_FUNCTION(vkGetDisplayPlaneCapabilitiesKHR);
|
||||
VULKAN_INSTANCE_FUNCTION(vkGetDisplayPlaneSupportedDisplaysKHR);
|
||||
VULKAN_INSTANCE_FUNCTION(vkCreateDisplayPlaneSurfaceKHR);
|
||||
#undef VULKAN_INSTANCE_FUNCTION
|
||||
VkDisplaySurfaceCreateInfoKHR createInfo;
|
||||
VkResult result;
|
||||
uint32_t physicalDeviceCount = 0;
|
||||
VkPhysicalDevice *physicalDevices = NULL;
|
||||
uint32_t physicalDeviceIndex;
|
||||
const char *chosenDisplayId;
|
||||
int displayId = 0; /* Counting from physical device 0, display 0 */
|
||||
|
||||
if (!vkEnumeratePhysicalDevices ||
|
||||
!vkGetPhysicalDeviceDisplayPropertiesKHR ||
|
||||
!vkGetDisplayModePropertiesKHR ||
|
||||
!vkGetPhysicalDeviceDisplayPlanePropertiesKHR ||
|
||||
!vkGetDisplayPlaneCapabilitiesKHR ||
|
||||
!vkGetDisplayPlaneSupportedDisplaysKHR ||
|
||||
!vkCreateDisplayPlaneSurfaceKHR) {
|
||||
SDL_SetError(VK_KHR_DISPLAY_EXTENSION_NAME " extension is not enabled in the Vulkan instance.");
|
||||
goto error;
|
||||
}
|
||||
chosenDisplayId = SDL_getenv("SDL_VULKAN_DISPLAY");
|
||||
if (chosenDisplayId != NULL) {
|
||||
displayId = SDL_atoi(chosenDisplayId);
|
||||
}
|
||||
|
||||
/* Enumerate physical devices */
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, NULL);
|
||||
if (result != VK_SUCCESS) {
|
||||
SDL_SetError("Could not enumerate Vulkan physical devices");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (physicalDeviceCount == 0) {
|
||||
SDL_SetError("No Vulkan physical devices");
|
||||
goto error;
|
||||
}
|
||||
|
||||
physicalDevices = SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
|
||||
if (physicalDevices == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
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];
|
||||
uint32_t displayPropertiesCount = 0;
|
||||
VkDisplayPropertiesKHR *displayProperties = NULL;
|
||||
uint32_t displayModePropertiesCount = 0;
|
||||
VkDisplayModePropertiesKHR *displayModeProperties = NULL;
|
||||
int bestMatchIndex = -1;
|
||||
uint32_t refreshRate = 0;
|
||||
uint32_t i;
|
||||
uint32_t displayPlanePropertiesCount = 0;
|
||||
int planeIndex = -1;
|
||||
VkDisplayKHR display;
|
||||
VkDisplayPlanePropertiesKHR *displayPlaneProperties = NULL;
|
||||
VkExtent2D extent;
|
||||
VkDisplayPlaneCapabilitiesKHR planeCaps = { 0 };
|
||||
|
||||
/* Get information about the physical displays */
|
||||
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) {
|
||||
/* 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 == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = vkGetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, &displayPropertiesCount, displayProperties);
|
||||
if (result != VK_SUCCESS || displayPropertiesCount == 0) {
|
||||
SDL_free(displayProperties);
|
||||
SDL_SetError("Error enumerating physical device displays");
|
||||
goto error;
|
||||
}
|
||||
|
||||
display = displayProperties[displayId].display;
|
||||
extent = displayProperties[displayId].physicalResolution;
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Display: %s Native resolution: %ux%u",
|
||||
displayProperties[displayId].displayName, extent.width, extent.height);
|
||||
|
||||
SDL_free(displayProperties);
|
||||
displayProperties = NULL;
|
||||
|
||||
/* Get display mode properties for the chosen display */
|
||||
result = vkGetDisplayModePropertiesKHR(physicalDevice, display, &displayModePropertiesCount, NULL);
|
||||
if (result != VK_SUCCESS || displayModePropertiesCount == 0) {
|
||||
SDL_SetError("Error enumerating display modes");
|
||||
goto error;
|
||||
}
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of display modes: %u", displayModePropertiesCount);
|
||||
|
||||
displayModeProperties = SDL_malloc(sizeof(VkDisplayModePropertiesKHR) * displayModePropertiesCount);
|
||||
if (displayModeProperties == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = vkGetDisplayModePropertiesKHR(physicalDevice, display, &displayModePropertiesCount, displayModeProperties);
|
||||
if (result != VK_SUCCESS || displayModePropertiesCount == 0) {
|
||||
SDL_SetError("Error enumerating display modes");
|
||||
SDL_free(displayModeProperties);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Try to find a display mode that matches the native resolution */
|
||||
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) {
|
||||
bestMatchIndex = i;
|
||||
refreshRate = displayModeProperties[i].parameters.refreshRate;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestMatchIndex < 0) {
|
||||
SDL_SetError("Found no matching display mode");
|
||||
SDL_free(displayModeProperties);
|
||||
goto error;
|
||||
}
|
||||
|
||||
SDL_zero(createInfo);
|
||||
createInfo.displayMode = displayModeProperties[bestMatchIndex].displayMode;
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Matching mode %ux%u with refresh rate %u",
|
||||
displayModeProperties[bestMatchIndex].parameters.visibleRegion.width,
|
||||
displayModeProperties[bestMatchIndex].parameters.visibleRegion.height,
|
||||
refreshRate);
|
||||
|
||||
SDL_free(displayModeProperties);
|
||||
displayModeProperties = NULL;
|
||||
|
||||
/* Try to find a plane index that supports our display */
|
||||
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 == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check supported displays for this plane. */
|
||||
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 == NULL) {
|
||||
SDL_free(displayPlaneProperties);
|
||||
SDL_OutOfMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
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);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (j = 0; j < planeSupportedDisplaysCount && planeSupportedDisplays[j] != display; ++j) {
|
||||
}
|
||||
|
||||
SDL_free(planeSupportedDisplays);
|
||||
planeSupportedDisplays = NULL;
|
||||
|
||||
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) {
|
||||
SDL_SetError("Error getting display plane capabilities");
|
||||
SDL_free(displayPlaneProperties);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
/* 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,
|
||||
planeCaps.maxDstExtent.width, planeCaps.maxDstExtent.height);
|
||||
planeIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (planeIndex < 0) {
|
||||
SDL_SetError("No plane supports the selected resolution");
|
||||
SDL_free(displayPlaneProperties);
|
||||
goto error;
|
||||
}
|
||||
|
||||
createInfo.planeIndex = planeIndex;
|
||||
createInfo.planeStackIndex = displayPlaneProperties[planeIndex].currentStackIndex;
|
||||
SDL_free(displayPlaneProperties);
|
||||
displayPlaneProperties = NULL;
|
||||
|
||||
/* Find a supported alpha mode. Not all planes support OPAQUE */
|
||||
createInfo.alphaMode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR;
|
||||
for (i = 0; i < SDL_arraysize(alphaModes); i++) {
|
||||
if (planeCaps.supportedAlpha & alphaModes[i]) {
|
||||
createInfo.alphaMode = alphaModes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Chose alpha mode 0x%x", createInfo.alphaMode);
|
||||
|
||||
/* Found a match, finally! Fill in extent, and break from loop */
|
||||
createInfo.imageExtent = extent;
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_free(physicalDevices);
|
||||
physicalDevices = NULL;
|
||||
|
||||
if (physicalDeviceIndex == physicalDeviceCount) {
|
||||
SDL_SetError("No usable displays found or requested display out of range");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR;
|
||||
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));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Created surface");
|
||||
return SDL_TRUE;
|
||||
|
||||
error:
|
||||
SDL_free(physicalDevices);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
#endif
|
2375
external/sdl/SDL/src/video/SDL_yuv.c
vendored
Normal file
2375
external/sdl/SDL/src/video/SDL_yuv.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
36
external/sdl/SDL/src/video/SDL_yuv_c.h
vendored
Normal file
36
external/sdl/SDL/src/video/SDL_yuv_c.h
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_yuv_c_h_
|
||||
#define SDL_yuv_c_h_
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
/* YUV conversion functions */
|
||||
|
||||
extern int SDL_ConvertPixels_YUV_to_RGB(int width, int height, Uint32 src_format, const void *src, int src_pitch, Uint32 dst_format, void *dst, int dst_pitch);
|
||||
extern int SDL_ConvertPixels_RGB_to_YUV(int width, int height, Uint32 src_format, const void *src, int src_pitch, Uint32 dst_format, void *dst, int dst_pitch);
|
||||
extern int SDL_ConvertPixels_YUV_to_YUV(int width, int height, Uint32 src_format, const void *src, int src_pitch, Uint32 dst_format, void *dst, int dst_pitch);
|
||||
|
||||
|
||||
extern int SDL_CalculateYUVSize(Uint32 format, int w, int h, size_t *size, size_t *pitch);
|
||||
|
||||
#endif /* SDL_yuv_c_h_ */
|
44
external/sdl/SDL/src/video/android/SDL_androidclipboard.c
vendored
Normal file
44
external/sdl/SDL/src/video/android/SDL_androidclipboard.c
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_ANDROID
|
||||
|
||||
#include "SDL_androidvideo.h"
|
||||
#include "SDL_androidclipboard.h"
|
||||
#include "../../core/android/SDL_android.h"
|
||||
|
||||
int Android_SetClipboardText(SDL_VideoDevice *_this, const char *text)
|
||||
{
|
||||
return Android_JNI_SetClipboardText(text);
|
||||
}
|
||||
|
||||
char *Android_GetClipboardText(SDL_VideoDevice *_this)
|
||||
{
|
||||
return Android_JNI_GetClipboardText();
|
||||
}
|
||||
|
||||
SDL_bool Android_HasClipboardText(SDL_VideoDevice *_this)
|
||||
{
|
||||
return Android_JNI_HasClipboardText();
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_ANDROID */
|
30
external/sdl/SDL/src/video/android/SDL_androidclipboard.h
vendored
Normal file
30
external/sdl/SDL/src/video/android/SDL_androidclipboard.h
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_androidclipboard_h_
|
||||
#define SDL_androidclipboard_h_
|
||||
|
||||
extern int Android_SetClipboardText(SDL_VideoDevice *_this, const char *text);
|
||||
extern char *Android_GetClipboardText(SDL_VideoDevice *_this);
|
||||
extern SDL_bool Android_HasClipboardText(SDL_VideoDevice *_this);
|
||||
|
||||
#endif /* SDL_androidclipboard_h_ */
|
255
external/sdl/SDL/src/video/android/SDL_androidevents.c
vendored
Normal file
255
external/sdl/SDL/src/video/android/SDL_androidevents.c
vendored
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_ANDROID
|
||||
|
||||
#include "SDL_androidevents.h"
|
||||
#include "SDL_androidkeyboard.h"
|
||||
#include "SDL_androidwindow.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
|
||||
#include "../../audio/android/SDL_androidaudio.h"
|
||||
#include "../../audio/aaudio/SDL_aaudio.h"
|
||||
#include "../../audio/openslES/SDL_openslES.h"
|
||||
|
||||
/* Number of 'type' events in the event queue */
|
||||
static int SDL_NumberOfEvents(Uint32 type)
|
||||
{
|
||||
return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type);
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
static void android_egl_context_restore(SDL_Window *window)
|
||||
{
|
||||
if (window) {
|
||||
SDL_Event event;
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
if (SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context) < 0) {
|
||||
/* The context is no longer valid, create a new one */
|
||||
data->egl_context = (EGLContext)SDL_GL_CreateContext(window);
|
||||
SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context);
|
||||
event.type = SDL_EVENT_RENDER_DEVICE_RESET;
|
||||
event.common.timestamp = 0;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
data->backup_done = 0;
|
||||
|
||||
if (data->has_swap_interval) {
|
||||
SDL_GL_SetSwapInterval(data->swap_interval);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void android_egl_context_backup(SDL_Window *window)
|
||||
{
|
||||
if (window) {
|
||||
int interval = 0;
|
||||
/* Keep a copy of the EGL Context so we can try to restore it when we resume */
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
data->egl_context = SDL_GL_GetCurrentContext();
|
||||
|
||||
/* Save/Restore the swap interval / vsync */
|
||||
if (SDL_GL_GetSwapInterval(&interval) == 0) {
|
||||
data->has_swap_interval = 1;
|
||||
data->swap_interval = interval;
|
||||
}
|
||||
|
||||
/* We need to do this so the EGLSurface can be freed */
|
||||
SDL_GL_MakeCurrent(window, NULL);
|
||||
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
|
||||
* When the pause semaphore is signaled, if Android_PumpEvents_Blocking is used, the event loop will block until the resume signal is emitted.
|
||||
*
|
||||
* No polling necessary
|
||||
*/
|
||||
|
||||
void Android_PumpEvents_Blocking(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *videodata = _this->driverdata;
|
||||
|
||||
if (videodata->isPaused) {
|
||||
SDL_bool isContextExternal = SDL_IsVideoContextExternal();
|
||||
|
||||
#ifdef 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_WaitSemaphore(Android_ResumeSem) == 0) {
|
||||
|
||||
videodata->isPaused = 0;
|
||||
|
||||
/* Android_ResumeSem was signaled */
|
||||
SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND);
|
||||
|
||||
ANDROIDAUDIO_ResumeDevices();
|
||||
openslES_ResumeDevices();
|
||||
aaudio_ResumeDevices();
|
||||
|
||||
/* Restore the GL Context from here, as this operation is thread dependent */
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
if (!isContextExternal && !SDL_HasEvent(SDL_EVENT_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_TextInputActive()) {
|
||||
Android_StartTextInput(_this); /* Only showTextInput */
|
||||
}
|
||||
|
||||
SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND);
|
||||
SDL_SendWindowEvent(Android_Window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
|
||||
}
|
||||
} else {
|
||||
if (videodata->isPausing || SDL_TryWaitSemaphore(Android_PauseSem) == 0) {
|
||||
|
||||
/* Android_PauseSem was signaled */
|
||||
if (videodata->isPausing == 0) {
|
||||
SDL_SendWindowEvent(Android_Window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
|
||||
SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_BACKGROUND);
|
||||
SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND);
|
||||
}
|
||||
|
||||
/* We've been signaled to pause (potentially several times), but before we block ourselves,
|
||||
* we need to make sure that the very last event (of the first pause sequence, if several)
|
||||
* has reached the app */
|
||||
if (SDL_NumberOfEvents(SDL_EVENT_DID_ENTER_BACKGROUND) > SDL_GetSemaphoreValue(Android_PauseSem)) {
|
||||
videodata->isPausing = 1;
|
||||
} else {
|
||||
videodata->isPausing = 0;
|
||||
videodata->isPaused = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aaudio_DetectBrokenPlayState()) {
|
||||
aaudio_PauseDevices();
|
||||
aaudio_ResumeDevices();
|
||||
}
|
||||
}
|
||||
|
||||
void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *videodata = _this->driverdata;
|
||||
static int backup_context = 0;
|
||||
|
||||
if (videodata->isPaused) {
|
||||
|
||||
SDL_bool isContextExternal = SDL_IsVideoContextExternal();
|
||||
if (backup_context) {
|
||||
|
||||
#ifdef 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;
|
||||
}
|
||||
|
||||
if (SDL_TryWaitSemaphore(Android_ResumeSem) == 0) {
|
||||
|
||||
videodata->isPaused = 0;
|
||||
|
||||
/* Android_ResumeSem was signaled */
|
||||
SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND);
|
||||
|
||||
if (videodata->pauseAudio) {
|
||||
ANDROIDAUDIO_ResumeDevices();
|
||||
openslES_ResumeDevices();
|
||||
aaudio_ResumeDevices();
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
/* Restore the GL Context from here, as this operation is thread dependent */
|
||||
if (!isContextExternal && !SDL_HasEvent(SDL_EVENT_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_TextInputActive()) {
|
||||
Android_StartTextInput(_this); /* Only showTextInput */
|
||||
}
|
||||
|
||||
SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND);
|
||||
SDL_SendWindowEvent(Android_Window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
|
||||
}
|
||||
} else {
|
||||
if (videodata->isPausing || SDL_TryWaitSemaphore(Android_PauseSem) == 0) {
|
||||
|
||||
/* Android_PauseSem was signaled */
|
||||
if (videodata->isPausing == 0) {
|
||||
SDL_SendWindowEvent(Android_Window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
|
||||
SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_BACKGROUND);
|
||||
SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND);
|
||||
}
|
||||
|
||||
/* We've been signaled to pause (potentially several times), but before we block ourselves,
|
||||
* we need to make sure that the very last event (of the first pause sequence, if several)
|
||||
* has reached the app */
|
||||
if (SDL_NumberOfEvents(SDL_EVENT_DID_ENTER_BACKGROUND) > SDL_GetSemaphoreValue(Android_PauseSem)) {
|
||||
videodata->isPausing = 1;
|
||||
} else {
|
||||
videodata->isPausing = 0;
|
||||
videodata->isPaused = 1;
|
||||
backup_context = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aaudio_DetectBrokenPlayState()) {
|
||||
aaudio_PauseDevices();
|
||||
aaudio_ResumeDevices();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_ANDROID */
|
26
external/sdl/SDL/src/video/android/SDL_androidevents.h
vendored
Normal file
26
external/sdl/SDL/src/video/android/SDL_androidevents.h
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_androidvideo.h"
|
||||
|
||||
extern void Android_PumpEvents_Blocking(SDL_VideoDevice *_this);
|
||||
extern void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this);
|
85
external/sdl/SDL/src/video/android/SDL_androidgl.c
vendored
Normal file
85
external/sdl/SDL/src/video/android/SDL_androidgl.c
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if defined(SDL_VIDEO_DRIVER_ANDROID) && defined(SDL_VIDEO_OPENGL_EGL)
|
||||
|
||||
/* Android SDL video driver implementation */
|
||||
|
||||
#include "../SDL_egl_c.h"
|
||||
#include "SDL_androidwindow.h"
|
||||
|
||||
#include "SDL_androidvideo.h"
|
||||
#include "SDL_androidgl.h"
|
||||
#include "../../core/android/SDL_android.h"
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
int Android_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context)
|
||||
{
|
||||
if (window && context) {
|
||||
return SDL_EGL_MakeCurrent(_this, window->driverdata->egl_surface, context);
|
||||
} else {
|
||||
return SDL_EGL_MakeCurrent(_this, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_GLContext Android_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
SDL_GLContext ret;
|
||||
|
||||
Android_ActivityMutex_Lock_Running();
|
||||
|
||||
ret = SDL_EGL_CreateContext(_this, window->driverdata->egl_surface);
|
||||
|
||||
SDL_UnlockMutex(Android_ActivityMutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Android_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
int retval;
|
||||
|
||||
SDL_LockMutex(Android_ActivityMutex);
|
||||
|
||||
/* 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 our bug tracker. -- Gabriel
|
||||
*/
|
||||
|
||||
/*_this->egl_data->eglWaitNative(EGL_CORE_NATIVE_ENGINE);
|
||||
_this->egl_data->eglWaitGL();*/
|
||||
retval = SDL_EGL_SwapBuffers(_this, window->driverdata->egl_surface);
|
||||
|
||||
SDL_UnlockMutex(Android_ActivityMutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int Android_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
||||
{
|
||||
return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType)0, 0);
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_ANDROID */
|
31
external/sdl/SDL/src/video/android/SDL_androidgl.h
vendored
Normal file
31
external/sdl/SDL/src/video/android/SDL_androidgl.h
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_androidgl_h_
|
||||
#define SDL_androidgl_h_
|
||||
|
||||
SDL_GLContext Android_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
int Android_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context);
|
||||
int Android_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
int Android_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path);
|
||||
|
||||
#endif /* SDL_androidgl_h_ */
|
367
external/sdl/SDL/src/video/android/SDL_androidkeyboard.c
vendored
Normal file
367
external/sdl/SDL/src/video/android/SDL_androidkeyboard.c
vendored
Normal file
@ -0,0 +1,367 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_ANDROID
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#include "SDL_androidkeyboard.h"
|
||||
|
||||
#include "../../core/android/SDL_android.h"
|
||||
|
||||
static SDL_Scancode Android_Keycodes[] = {
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_UNKNOWN */
|
||||
SDL_SCANCODE_SOFTLEFT, /* AKEYCODE_SOFT_LEFT */
|
||||
SDL_SCANCODE_SOFTRIGHT, /* AKEYCODE_SOFT_RIGHT */
|
||||
SDL_SCANCODE_AC_HOME, /* AKEYCODE_HOME */
|
||||
SDL_SCANCODE_AC_BACK, /* AKEYCODE_BACK */
|
||||
SDL_SCANCODE_CALL, /* AKEYCODE_CALL */
|
||||
SDL_SCANCODE_ENDCALL, /* AKEYCODE_ENDCALL */
|
||||
SDL_SCANCODE_0, /* AKEYCODE_0 */
|
||||
SDL_SCANCODE_1, /* AKEYCODE_1 */
|
||||
SDL_SCANCODE_2, /* AKEYCODE_2 */
|
||||
SDL_SCANCODE_3, /* AKEYCODE_3 */
|
||||
SDL_SCANCODE_4, /* AKEYCODE_4 */
|
||||
SDL_SCANCODE_5, /* AKEYCODE_5 */
|
||||
SDL_SCANCODE_6, /* AKEYCODE_6 */
|
||||
SDL_SCANCODE_7, /* AKEYCODE_7 */
|
||||
SDL_SCANCODE_8, /* AKEYCODE_8 */
|
||||
SDL_SCANCODE_9, /* AKEYCODE_9 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_STAR */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_POUND */
|
||||
SDL_SCANCODE_UP, /* AKEYCODE_DPAD_UP */
|
||||
SDL_SCANCODE_DOWN, /* AKEYCODE_DPAD_DOWN */
|
||||
SDL_SCANCODE_LEFT, /* AKEYCODE_DPAD_LEFT */
|
||||
SDL_SCANCODE_RIGHT, /* AKEYCODE_DPAD_RIGHT */
|
||||
SDL_SCANCODE_SELECT, /* AKEYCODE_DPAD_CENTER */
|
||||
SDL_SCANCODE_VOLUMEUP, /* AKEYCODE_VOLUME_UP */
|
||||
SDL_SCANCODE_VOLUMEDOWN, /* AKEYCODE_VOLUME_DOWN */
|
||||
SDL_SCANCODE_POWER, /* AKEYCODE_POWER */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_CAMERA */
|
||||
SDL_SCANCODE_CLEAR, /* AKEYCODE_CLEAR */
|
||||
SDL_SCANCODE_A, /* AKEYCODE_A */
|
||||
SDL_SCANCODE_B, /* AKEYCODE_B */
|
||||
SDL_SCANCODE_C, /* AKEYCODE_C */
|
||||
SDL_SCANCODE_D, /* AKEYCODE_D */
|
||||
SDL_SCANCODE_E, /* AKEYCODE_E */
|
||||
SDL_SCANCODE_F, /* AKEYCODE_F */
|
||||
SDL_SCANCODE_G, /* AKEYCODE_G */
|
||||
SDL_SCANCODE_H, /* AKEYCODE_H */
|
||||
SDL_SCANCODE_I, /* AKEYCODE_I */
|
||||
SDL_SCANCODE_J, /* AKEYCODE_J */
|
||||
SDL_SCANCODE_K, /* AKEYCODE_K */
|
||||
SDL_SCANCODE_L, /* AKEYCODE_L */
|
||||
SDL_SCANCODE_M, /* AKEYCODE_M */
|
||||
SDL_SCANCODE_N, /* AKEYCODE_N */
|
||||
SDL_SCANCODE_O, /* AKEYCODE_O */
|
||||
SDL_SCANCODE_P, /* AKEYCODE_P */
|
||||
SDL_SCANCODE_Q, /* AKEYCODE_Q */
|
||||
SDL_SCANCODE_R, /* AKEYCODE_R */
|
||||
SDL_SCANCODE_S, /* AKEYCODE_S */
|
||||
SDL_SCANCODE_T, /* AKEYCODE_T */
|
||||
SDL_SCANCODE_U, /* AKEYCODE_U */
|
||||
SDL_SCANCODE_V, /* AKEYCODE_V */
|
||||
SDL_SCANCODE_W, /* AKEYCODE_W */
|
||||
SDL_SCANCODE_X, /* AKEYCODE_X */
|
||||
SDL_SCANCODE_Y, /* AKEYCODE_Y */
|
||||
SDL_SCANCODE_Z, /* AKEYCODE_Z */
|
||||
SDL_SCANCODE_COMMA, /* AKEYCODE_COMMA */
|
||||
SDL_SCANCODE_PERIOD, /* AKEYCODE_PERIOD */
|
||||
SDL_SCANCODE_LALT, /* AKEYCODE_ALT_LEFT */
|
||||
SDL_SCANCODE_RALT, /* AKEYCODE_ALT_RIGHT */
|
||||
SDL_SCANCODE_LSHIFT, /* AKEYCODE_SHIFT_LEFT */
|
||||
SDL_SCANCODE_RSHIFT, /* AKEYCODE_SHIFT_RIGHT */
|
||||
SDL_SCANCODE_TAB, /* AKEYCODE_TAB */
|
||||
SDL_SCANCODE_SPACE, /* AKEYCODE_SPACE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_SYM */
|
||||
SDL_SCANCODE_WWW, /* AKEYCODE_EXPLORER */
|
||||
SDL_SCANCODE_MAIL, /* AKEYCODE_ENVELOPE */
|
||||
SDL_SCANCODE_RETURN, /* AKEYCODE_ENTER */
|
||||
SDL_SCANCODE_BACKSPACE, /* AKEYCODE_DEL */
|
||||
SDL_SCANCODE_GRAVE, /* AKEYCODE_GRAVE */
|
||||
SDL_SCANCODE_MINUS, /* AKEYCODE_MINUS */
|
||||
SDL_SCANCODE_EQUALS, /* AKEYCODE_EQUALS */
|
||||
SDL_SCANCODE_LEFTBRACKET, /* AKEYCODE_LEFT_BRACKET */
|
||||
SDL_SCANCODE_RIGHTBRACKET, /* AKEYCODE_RIGHT_BRACKET */
|
||||
SDL_SCANCODE_BACKSLASH, /* AKEYCODE_BACKSLASH */
|
||||
SDL_SCANCODE_SEMICOLON, /* AKEYCODE_SEMICOLON */
|
||||
SDL_SCANCODE_APOSTROPHE, /* AKEYCODE_APOSTROPHE */
|
||||
SDL_SCANCODE_SLASH, /* AKEYCODE_SLASH */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_AT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NUM */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_HEADSETHOOK */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_FOCUS */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_PLUS */
|
||||
SDL_SCANCODE_MENU, /* AKEYCODE_MENU */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NOTIFICATION */
|
||||
SDL_SCANCODE_AC_SEARCH, /* AKEYCODE_SEARCH */
|
||||
SDL_SCANCODE_AUDIOPLAY, /* AKEYCODE_MEDIA_PLAY_PAUSE */
|
||||
SDL_SCANCODE_AUDIOSTOP, /* AKEYCODE_MEDIA_STOP */
|
||||
SDL_SCANCODE_AUDIONEXT, /* AKEYCODE_MEDIA_NEXT */
|
||||
SDL_SCANCODE_AUDIOPREV, /* AKEYCODE_MEDIA_PREVIOUS */
|
||||
SDL_SCANCODE_AUDIOREWIND, /* AKEYCODE_MEDIA_REWIND */
|
||||
SDL_SCANCODE_AUDIOFASTFORWARD, /* AKEYCODE_MEDIA_FAST_FORWARD */
|
||||
SDL_SCANCODE_MUTE, /* AKEYCODE_MUTE */
|
||||
SDL_SCANCODE_PAGEUP, /* AKEYCODE_PAGE_UP */
|
||||
SDL_SCANCODE_PAGEDOWN, /* AKEYCODE_PAGE_DOWN */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_PICTSYMBOLS */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_SWITCH_CHARSET */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_A */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_B */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_C */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_X */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_Y */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_Z */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_L1 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_R1 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_L2 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_R2 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_THUMBL */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_THUMBR */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_START */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_SELECT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_MODE */
|
||||
SDL_SCANCODE_ESCAPE, /* AKEYCODE_ESCAPE */
|
||||
SDL_SCANCODE_DELETE, /* AKEYCODE_FORWARD_DEL */
|
||||
SDL_SCANCODE_LCTRL, /* AKEYCODE_CTRL_LEFT */
|
||||
SDL_SCANCODE_RCTRL, /* AKEYCODE_CTRL_RIGHT */
|
||||
SDL_SCANCODE_CAPSLOCK, /* AKEYCODE_CAPS_LOCK */
|
||||
SDL_SCANCODE_SCROLLLOCK, /* AKEYCODE_SCROLL_LOCK */
|
||||
SDL_SCANCODE_LGUI, /* AKEYCODE_META_LEFT */
|
||||
SDL_SCANCODE_RGUI, /* AKEYCODE_META_RIGHT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_FUNCTION */
|
||||
SDL_SCANCODE_PRINTSCREEN, /* AKEYCODE_SYSRQ */
|
||||
SDL_SCANCODE_PAUSE, /* AKEYCODE_BREAK */
|
||||
SDL_SCANCODE_HOME, /* AKEYCODE_MOVE_HOME */
|
||||
SDL_SCANCODE_END, /* AKEYCODE_MOVE_END */
|
||||
SDL_SCANCODE_INSERT, /* AKEYCODE_INSERT */
|
||||
SDL_SCANCODE_AC_FORWARD, /* AKEYCODE_FORWARD */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_PLAY */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_PAUSE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_CLOSE */
|
||||
SDL_SCANCODE_EJECT, /* AKEYCODE_MEDIA_EJECT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_RECORD */
|
||||
SDL_SCANCODE_F1, /* AKEYCODE_F1 */
|
||||
SDL_SCANCODE_F2, /* AKEYCODE_F2 */
|
||||
SDL_SCANCODE_F3, /* AKEYCODE_F3 */
|
||||
SDL_SCANCODE_F4, /* AKEYCODE_F4 */
|
||||
SDL_SCANCODE_F5, /* AKEYCODE_F5 */
|
||||
SDL_SCANCODE_F6, /* AKEYCODE_F6 */
|
||||
SDL_SCANCODE_F7, /* AKEYCODE_F7 */
|
||||
SDL_SCANCODE_F8, /* AKEYCODE_F8 */
|
||||
SDL_SCANCODE_F9, /* AKEYCODE_F9 */
|
||||
SDL_SCANCODE_F10, /* AKEYCODE_F10 */
|
||||
SDL_SCANCODE_F11, /* AKEYCODE_F11 */
|
||||
SDL_SCANCODE_F12, /* AKEYCODE_F12 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NUM_LOCK */
|
||||
SDL_SCANCODE_KP_0, /* AKEYCODE_NUMPAD_0 */
|
||||
SDL_SCANCODE_KP_1, /* AKEYCODE_NUMPAD_1 */
|
||||
SDL_SCANCODE_KP_2, /* AKEYCODE_NUMPAD_2 */
|
||||
SDL_SCANCODE_KP_3, /* AKEYCODE_NUMPAD_3 */
|
||||
SDL_SCANCODE_KP_4, /* AKEYCODE_NUMPAD_4 */
|
||||
SDL_SCANCODE_KP_5, /* AKEYCODE_NUMPAD_5 */
|
||||
SDL_SCANCODE_KP_6, /* AKEYCODE_NUMPAD_6 */
|
||||
SDL_SCANCODE_KP_7, /* AKEYCODE_NUMPAD_7 */
|
||||
SDL_SCANCODE_KP_8, /* AKEYCODE_NUMPAD_8 */
|
||||
SDL_SCANCODE_KP_9, /* AKEYCODE_NUMPAD_9 */
|
||||
SDL_SCANCODE_KP_DIVIDE, /* AKEYCODE_NUMPAD_DIVIDE */
|
||||
SDL_SCANCODE_KP_MULTIPLY, /* AKEYCODE_NUMPAD_MULTIPLY */
|
||||
SDL_SCANCODE_KP_MINUS, /* AKEYCODE_NUMPAD_SUBTRACT */
|
||||
SDL_SCANCODE_KP_PLUS, /* AKEYCODE_NUMPAD_ADD */
|
||||
SDL_SCANCODE_KP_PERIOD, /* AKEYCODE_NUMPAD_DOT */
|
||||
SDL_SCANCODE_KP_COMMA, /* AKEYCODE_NUMPAD_COMMA */
|
||||
SDL_SCANCODE_KP_ENTER, /* AKEYCODE_NUMPAD_ENTER */
|
||||
SDL_SCANCODE_KP_EQUALS, /* AKEYCODE_NUMPAD_EQUALS */
|
||||
SDL_SCANCODE_KP_LEFTPAREN, /* AKEYCODE_NUMPAD_LEFT_PAREN */
|
||||
SDL_SCANCODE_KP_RIGHTPAREN, /* AKEYCODE_NUMPAD_RIGHT_PAREN */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_VOLUME_MUTE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_INFO */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_CHANNEL_UP */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_CHANNEL_DOWN */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_ZOOM_IN */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_ZOOM_OUT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_WINDOW */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_GUIDE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_DVR */
|
||||
SDL_SCANCODE_AC_BOOKMARKS, /* AKEYCODE_BOOKMARK */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_CAPTIONS */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_SETTINGS */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_POWER */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_INPUT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_STB_POWER */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_STB_INPUT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_AVR_POWER */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_AVR_INPUT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_PROG_RED */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_PROG_GREEN */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_PROG_YELLOW */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_PROG_BLUE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_APP_SWITCH */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_1 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_2 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_3 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_4 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_5 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_6 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_7 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_8 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_9 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_10 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_11 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_12 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_13 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_14 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_15 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_BUTTON_16 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_LANGUAGE_SWITCH */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MANNER_MODE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_3D_MODE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_CONTACTS */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_CALENDAR */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MUSIC */
|
||||
SDL_SCANCODE_CALCULATOR, /* AKEYCODE_CALCULATOR */
|
||||
SDL_SCANCODE_LANG5, /* AKEYCODE_ZENKAKU_HANKAKU */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_EISU */
|
||||
SDL_SCANCODE_INTERNATIONAL5, /* AKEYCODE_MUHENKAN */
|
||||
SDL_SCANCODE_INTERNATIONAL4, /* AKEYCODE_HENKAN */
|
||||
SDL_SCANCODE_LANG3, /* AKEYCODE_KATAKANA_HIRAGANA */
|
||||
SDL_SCANCODE_INTERNATIONAL3, /* AKEYCODE_YEN */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_RO */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_KANA */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_ASSIST */
|
||||
SDL_SCANCODE_BRIGHTNESSDOWN, /* AKEYCODE_BRIGHTNESS_DOWN */
|
||||
SDL_SCANCODE_BRIGHTNESSUP, /* AKEYCODE_BRIGHTNESS_UP */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_AUDIO_TRACK */
|
||||
SDL_SCANCODE_SLEEP, /* AKEYCODE_SLEEP */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_WAKEUP */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_PAIRING */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_TOP_MENU */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_11 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_12 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_LAST_CHANNEL */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_DATA_SERVICE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_VOICE_ASSIST */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_RADIO_SERVICE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_TELETEXT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_NUMBER_ENTRY */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_TERRESTRIAL_ANALOG */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_TERRESTRIAL_DIGITAL */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_SATELLITE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_SATELLITE_BS */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_SATELLITE_CS */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_SATELLITE_SERVICE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_NETWORK */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_ANTENNA_CABLE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_INPUT_HDMI_1 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_INPUT_HDMI_2 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_INPUT_HDMI_3 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_INPUT_HDMI_4 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_INPUT_COMPOSITE_1 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_INPUT_COMPOSITE_2 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_INPUT_COMPONENT_1 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_INPUT_COMPONENT_2 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_INPUT_VGA_1 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_AUDIO_DESCRIPTION */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_ZOOM_MODE */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_CONTENTS_MENU */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_MEDIA_CONTEXT_MENU */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_TV_TIMER_PROGRAMMING */
|
||||
SDL_SCANCODE_HELP, /* AKEYCODE_HELP */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NAVIGATE_PREVIOUS */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NAVIGATE_NEXT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NAVIGATE_IN */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NAVIGATE_OUT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_STEM_PRIMARY */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_STEM_1 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_STEM_2 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_STEM_3 */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_DPAD_UP_LEFT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_DPAD_DOWN_LEFT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_DPAD_UP_RIGHT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_DPAD_DOWN_RIGHT */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_SKIP_FORWARD */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_SKIP_BACKWARD */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_STEP_FORWARD */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_STEP_BACKWARD */
|
||||
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_SOFT_SLEEP */
|
||||
SDL_SCANCODE_CUT, /* AKEYCODE_CUT */
|
||||
SDL_SCANCODE_COPY, /* AKEYCODE_COPY */
|
||||
SDL_SCANCODE_PASTE, /* AKEYCODE_PASTE */
|
||||
};
|
||||
|
||||
static SDL_Scancode TranslateKeycode(int keycode)
|
||||
{
|
||||
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
|
||||
|
||||
if (keycode < SDL_arraysize(Android_Keycodes)) {
|
||||
scancode = Android_Keycodes[keycode];
|
||||
}
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "SDL", "Unknown keycode %d", keycode);
|
||||
}
|
||||
return scancode;
|
||||
}
|
||||
|
||||
int Android_OnKeyDown(int keycode)
|
||||
{
|
||||
return SDL_SendKeyboardKey(0, SDL_PRESSED, TranslateKeycode(keycode));
|
||||
}
|
||||
|
||||
int Android_OnKeyUp(int keycode)
|
||||
{
|
||||
return SDL_SendKeyboardKey(0, SDL_RELEASED, TranslateKeycode(keycode));
|
||||
}
|
||||
|
||||
SDL_bool Android_HasScreenKeyboardSupport(SDL_VideoDevice *_this)
|
||||
{
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
return Android_JNI_IsScreenKeyboardShown();
|
||||
}
|
||||
|
||||
void Android_StartTextInput(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *videodata = _this->driverdata;
|
||||
Android_JNI_ShowTextInput(&videodata->textRect);
|
||||
}
|
||||
|
||||
void Android_StopTextInput(SDL_VideoDevice *_this)
|
||||
{
|
||||
Android_JNI_HideTextInput();
|
||||
}
|
||||
|
||||
int Android_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect)
|
||||
{
|
||||
SDL_VideoData *videodata = _this->driverdata;
|
||||
videodata->textRect = *rect;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_ANDROID */
|
33
external/sdl/SDL/src/video/android/SDL_androidkeyboard.h
vendored
Normal file
33
external/sdl/SDL/src/video/android/SDL_androidkeyboard.h
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_androidvideo.h"
|
||||
|
||||
extern int Android_OnKeyDown(int keycode);
|
||||
extern int Android_OnKeyUp(int keycode);
|
||||
|
||||
extern SDL_bool Android_HasScreenKeyboardSupport(SDL_VideoDevice *_this);
|
||||
extern SDL_bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
|
||||
extern void Android_StartTextInput(SDL_VideoDevice *_this);
|
||||
extern void Android_StopTextInput(SDL_VideoDevice *_this);
|
||||
extern int Android_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect);
|
33
external/sdl/SDL/src/video/android/SDL_androidmessagebox.c
vendored
Normal file
33
external/sdl/SDL/src/video/android/SDL_androidmessagebox.c
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_ANDROID
|
||||
|
||||
#include "SDL_androidmessagebox.h"
|
||||
#include "../../core/android/SDL_android.h"
|
||||
|
||||
int Android_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{
|
||||
return Android_JNI_ShowMessageBox(messageboxdata, buttonid);
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_ANDROID */
|
27
external/sdl/SDL/src/video/android/SDL_androidmessagebox.h
vendored
Normal file
27
external/sdl/SDL/src/video/android/SDL_androidmessagebox.h
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_ANDROID
|
||||
|
||||
extern int Android_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_ANDROID */
|
253
external/sdl/SDL/src/video/android/SDL_androidmouse.c
vendored
Normal file
253
external/sdl/SDL/src/video/android/SDL_androidmouse.c
vendored
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_ANDROID
|
||||
|
||||
#include "SDL_androidmouse.h"
|
||||
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
|
||||
#include "../../core/android/SDL_android.h"
|
||||
|
||||
/* See Android's MotionEvent class for constants */
|
||||
#define ACTION_DOWN 0
|
||||
#define ACTION_UP 1
|
||||
#define ACTION_MOVE 2
|
||||
#define ACTION_HOVER_MOVE 7
|
||||
#define ACTION_SCROLL 8
|
||||
#define BUTTON_PRIMARY 1
|
||||
#define BUTTON_SECONDARY 2
|
||||
#define BUTTON_TERTIARY 4
|
||||
#define BUTTON_BACK 8
|
||||
#define BUTTON_FORWARD 16
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int custom_cursor;
|
||||
int system_cursor;
|
||||
|
||||
} SDL_AndroidCursorData;
|
||||
|
||||
/* Last known Android mouse button state (includes all buttons) */
|
||||
static int last_state;
|
||||
|
||||
/* Blank cursor */
|
||||
static SDL_Cursor *empty_cursor;
|
||||
|
||||
static SDL_Cursor *Android_WrapCursor(int custom_cursor, int system_cursor)
|
||||
{
|
||||
SDL_Cursor *cursor;
|
||||
|
||||
cursor = SDL_calloc(1, sizeof(*cursor));
|
||||
if (cursor) {
|
||||
SDL_AndroidCursorData *data = (SDL_AndroidCursorData *)SDL_calloc(1, sizeof(*data));
|
||||
if (data) {
|
||||
data->custom_cursor = custom_cursor;
|
||||
data->system_cursor = system_cursor;
|
||||
cursor->driverdata = data;
|
||||
} else {
|
||||
SDL_free(cursor);
|
||||
cursor = NULL;
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static SDL_Cursor *Android_CreateDefaultCursor()
|
||||
{
|
||||
return Android_WrapCursor(0, SDL_SYSTEM_CURSOR_ARROW);
|
||||
}
|
||||
|
||||
static SDL_Cursor *Android_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
|
||||
{
|
||||
int custom_cursor;
|
||||
SDL_Surface *converted;
|
||||
|
||||
converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888);
|
||||
if (converted == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
custom_cursor = Android_JNI_CreateCustomCursor(converted, hot_x, hot_y);
|
||||
SDL_DestroySurface(converted);
|
||||
if (!custom_cursor) {
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
return Android_WrapCursor(custom_cursor, 0);
|
||||
}
|
||||
|
||||
static SDL_Cursor *Android_CreateSystemCursor(SDL_SystemCursor id)
|
||||
{
|
||||
return Android_WrapCursor(0, 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);
|
||||
}
|
||||
|
||||
static SDL_Cursor *Android_CreateEmptyCursor()
|
||||
{
|
||||
if (empty_cursor == NULL) {
|
||||
SDL_Surface *empty_surface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ARGB8888);
|
||||
if (empty_surface) {
|
||||
SDL_memset(empty_surface->pixels, 0, (size_t)empty_surface->h * empty_surface->pitch);
|
||||
empty_cursor = Android_CreateCursor(empty_surface, 0, 0);
|
||||
SDL_DestroySurface(empty_surface);
|
||||
}
|
||||
}
|
||||
return empty_cursor;
|
||||
}
|
||||
|
||||
static void Android_DestroyEmptyCursor()
|
||||
{
|
||||
if (empty_cursor) {
|
||||
Android_FreeCursor(empty_cursor);
|
||||
empty_cursor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int Android_ShowCursor(SDL_Cursor *cursor)
|
||||
{
|
||||
if (cursor == NULL) {
|
||||
cursor = Android_CreateEmptyCursor();
|
||||
}
|
||||
if (cursor) {
|
||||
SDL_AndroidCursorData *data = (SDL_AndroidCursorData *)cursor->driverdata;
|
||||
if (data->custom_cursor) {
|
||||
if (!Android_JNI_SetCustomCursor(data->custom_cursor)) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
} else {
|
||||
if (!Android_JNI_SetSystemCursor(data->system_cursor)) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
/* SDL error set inside Android_CreateEmptyCursor() */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int Android_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
if (!Android_JNI_SupportsRelativeMouse()) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
if (!Android_JNI_SetRelativeMouseEnabled(enabled)) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Android_InitMouse(void)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
mouse->CreateCursor = Android_CreateCursor;
|
||||
mouse->CreateSystemCursor = Android_CreateSystemCursor;
|
||||
mouse->ShowCursor = Android_ShowCursor;
|
||||
mouse->FreeCursor = Android_FreeCursor;
|
||||
mouse->SetRelativeMouseMode = Android_SetRelativeMouseMode;
|
||||
|
||||
SDL_SetDefaultCursor(Android_CreateDefaultCursor());
|
||||
|
||||
last_state = 0;
|
||||
}
|
||||
|
||||
void Android_QuitMouse(void)
|
||||
{
|
||||
Android_DestroyEmptyCursor();
|
||||
}
|
||||
|
||||
/* Translate Android mouse button state to SDL mouse button */
|
||||
static Uint8 TranslateButton(int state)
|
||||
{
|
||||
if (state & BUTTON_PRIMARY) {
|
||||
return SDL_BUTTON_LEFT;
|
||||
} else if (state & BUTTON_SECONDARY) {
|
||||
return SDL_BUTTON_RIGHT;
|
||||
} else if (state & BUTTON_TERTIARY) {
|
||||
return SDL_BUTTON_MIDDLE;
|
||||
} else if (state & BUTTON_FORWARD) {
|
||||
return SDL_BUTTON_X1;
|
||||
} else if (state & BUTTON_BACK) {
|
||||
return SDL_BUTTON_X2;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Android_OnMouse(SDL_Window *window, int state, int action, float x, float y, SDL_bool relative)
|
||||
{
|
||||
int changes;
|
||||
Uint8 button;
|
||||
|
||||
if (window == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case ACTION_DOWN:
|
||||
changes = state & ~last_state;
|
||||
button = TranslateButton(changes);
|
||||
last_state = state;
|
||||
SDL_SendMouseMotion(0, window, 0, relative, x, y);
|
||||
SDL_SendMouseButton(0, window, 0, SDL_PRESSED, button);
|
||||
break;
|
||||
|
||||
case ACTION_UP:
|
||||
changes = last_state & ~state;
|
||||
button = TranslateButton(changes);
|
||||
last_state = state;
|
||||
SDL_SendMouseMotion(0, window, 0, relative, x, y);
|
||||
SDL_SendMouseButton(0, window, 0, SDL_RELEASED, button);
|
||||
break;
|
||||
|
||||
case ACTION_MOVE:
|
||||
case ACTION_HOVER_MOVE:
|
||||
SDL_SendMouseMotion(0, window, 0, relative, x, y);
|
||||
break;
|
||||
|
||||
case ACTION_SCROLL:
|
||||
SDL_SendMouseWheel(0, window, 0, x, y, SDL_MOUSEWHEEL_NORMAL);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_ANDROID */
|
31
external/sdl/SDL/src/video/android/SDL_androidmouse.h
vendored
Normal file
31
external/sdl/SDL/src/video/android/SDL_androidmouse.h
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_androidmouse_h_
|
||||
#define SDL_androidmouse_h_
|
||||
|
||||
#include "SDL_androidvideo.h"
|
||||
|
||||
extern void Android_InitMouse(void);
|
||||
extern void Android_OnMouse(SDL_Window *window, int button, int action, float x, float y, SDL_bool relative);
|
||||
extern void Android_QuitMouse(void);
|
||||
|
||||
#endif /* SDL_androidmouse_h_ */
|
85
external/sdl/SDL/src/video/android/SDL_androidtouch.c
vendored
Normal file
85
external/sdl/SDL/src/video/android/SDL_androidtouch.c
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_ANDROID
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#include "SDL_androidtouch.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
#include "../../core/android/SDL_android.h"
|
||||
|
||||
#define ACTION_DOWN 0
|
||||
#define ACTION_UP 1
|
||||
#define ACTION_MOVE 2
|
||||
/* #define ACTION_CANCEL 3 */
|
||||
/* #define ACTION_OUTSIDE 4 */
|
||||
#define ACTION_POINTER_DOWN 5
|
||||
#define ACTION_POINTER_UP 6
|
||||
|
||||
void Android_InitTouch(void)
|
||||
{
|
||||
/* Add all touch devices */
|
||||
Android_JNI_InitTouch();
|
||||
}
|
||||
|
||||
void Android_QuitTouch(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Android_OnTouch(SDL_Window *window, int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p)
|
||||
{
|
||||
SDL_TouchID touchDeviceId = 0;
|
||||
SDL_FingerID fingerId = 0;
|
||||
|
||||
if (window == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
touchDeviceId = (SDL_TouchID)touch_device_id_in;
|
||||
if (SDL_AddTouch(touchDeviceId, SDL_TOUCH_DEVICE_DIRECT, "") < 0) {
|
||||
SDL_Log("error: can't add touch %s, %d", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
fingerId = (SDL_FingerID)pointer_finger_id_in;
|
||||
switch (action) {
|
||||
case ACTION_DOWN:
|
||||
case ACTION_POINTER_DOWN:
|
||||
SDL_SendTouch(0, touchDeviceId, fingerId, window, SDL_TRUE, x, y, p);
|
||||
break;
|
||||
|
||||
case ACTION_MOVE:
|
||||
SDL_SendTouchMotion(0, touchDeviceId, fingerId, window, x, y, p);
|
||||
break;
|
||||
|
||||
case ACTION_UP:
|
||||
case ACTION_POINTER_UP:
|
||||
SDL_SendTouch(0, touchDeviceId, fingerId, window, SDL_FALSE, x, y, p);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_ANDROID */
|
27
external/sdl/SDL/src/video/android/SDL_androidtouch.h
vendored
Normal file
27
external/sdl/SDL/src/video/android/SDL_androidtouch.h
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_androidvideo.h"
|
||||
|
||||
extern void Android_InitTouch(void);
|
||||
extern void Android_QuitTouch(void);
|
||||
extern void Android_OnTouch(SDL_Window *window, int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p);
|
302
external/sdl/SDL/src/video/android/SDL_androidvideo.c
vendored
Normal file
302
external/sdl/SDL/src/video/android/SDL_androidvideo.c
vendored
Normal file
@ -0,0 +1,302 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_ANDROID
|
||||
|
||||
/* Android SDL video driver implementation */
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_pixels_c.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../events/SDL_windowevents_c.h"
|
||||
|
||||
#include "SDL_androidvideo.h"
|
||||
#include "SDL_androidgl.h"
|
||||
#include "SDL_androidclipboard.h"
|
||||
#include "SDL_androidevents.h"
|
||||
#include "SDL_androidkeyboard.h"
|
||||
#include "SDL_androidmouse.h"
|
||||
#include "SDL_androidtouch.h"
|
||||
#include "SDL_androidwindow.h"
|
||||
#include "SDL_androidvulkan.h"
|
||||
|
||||
#define ANDROID_VID_DRIVER_NAME "Android"
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int Android_VideoInit(SDL_VideoDevice *_this);
|
||||
static void Android_VideoQuit(SDL_VideoDevice *_this);
|
||||
|
||||
#include "../SDL_egl_c.h"
|
||||
#define Android_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal
|
||||
#define Android_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
|
||||
#define Android_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
|
||||
#define Android_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
|
||||
#define Android_GLES_DeleteContext SDL_EGL_DeleteContext
|
||||
|
||||
/* Android driver bootstrap functions */
|
||||
|
||||
/* These are filled in with real values in Android_SetScreenResolution on init (before SDL_main()) */
|
||||
int Android_SurfaceWidth = 0;
|
||||
int Android_SurfaceHeight = 0;
|
||||
static int Android_DeviceWidth = 0;
|
||||
static int Android_DeviceHeight = 0;
|
||||
static Uint32 Android_ScreenFormat = SDL_PIXELFORMAT_RGB565; /* Default SurfaceView format, in case this is queried before being filled */
|
||||
float Android_ScreenDensity = 1.0f;
|
||||
static float Android_ScreenRate = 0.0f;
|
||||
SDL_Semaphore *Android_PauseSem = NULL;
|
||||
SDL_Semaphore *Android_ResumeSem = NULL;
|
||||
SDL_Mutex *Android_ActivityMutex = NULL;
|
||||
static SDL_SystemTheme Android_SystemTheme;
|
||||
|
||||
static int Android_SuspendScreenSaver(SDL_VideoDevice *_this)
|
||||
{
|
||||
return Android_JNI_SuspendScreenSaver(_this->suspend_screensaver);
|
||||
}
|
||||
|
||||
static void Android_DeleteDevice(SDL_VideoDevice *device)
|
||||
{
|
||||
SDL_free(device->driverdata);
|
||||
SDL_free(device);
|
||||
}
|
||||
|
||||
static SDL_VideoDevice *Android_CreateDevice(void)
|
||||
{
|
||||
SDL_VideoDevice *device;
|
||||
SDL_VideoData *data;
|
||||
SDL_bool block_on_pause;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
|
||||
if (device == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData));
|
||||
if (data == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
SDL_free(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
device->driverdata = data;
|
||||
device->system_theme = Android_SystemTheme;
|
||||
|
||||
/* Set the function pointers */
|
||||
device->VideoInit = Android_VideoInit;
|
||||
device->VideoQuit = Android_VideoQuit;
|
||||
block_on_pause = SDL_GetHintBoolean(SDL_HINT_ANDROID_BLOCK_ON_PAUSE, SDL_TRUE);
|
||||
if (block_on_pause) {
|
||||
device->PumpEvents = Android_PumpEvents_Blocking;
|
||||
} else {
|
||||
device->PumpEvents = Android_PumpEvents_NonBlocking;
|
||||
}
|
||||
|
||||
device->CreateSDLWindow = Android_CreateWindow;
|
||||
device->SetWindowTitle = Android_SetWindowTitle;
|
||||
device->SetWindowFullscreen = Android_SetWindowFullscreen;
|
||||
device->MinimizeWindow = Android_MinimizeWindow;
|
||||
device->SetWindowResizable = Android_SetWindowResizable;
|
||||
device->DestroyWindow = Android_DestroyWindow;
|
||||
device->GetWindowWMInfo = Android_GetWindowWMInfo;
|
||||
|
||||
device->free = Android_DeleteDevice;
|
||||
|
||||
/* GL pointers */
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
device->GL_LoadLibrary = Android_GLES_LoadLibrary;
|
||||
device->GL_GetProcAddress = Android_GLES_GetProcAddress;
|
||||
device->GL_UnloadLibrary = Android_GLES_UnloadLibrary;
|
||||
device->GL_CreateContext = Android_GLES_CreateContext;
|
||||
device->GL_MakeCurrent = Android_GLES_MakeCurrent;
|
||||
device->GL_SetSwapInterval = Android_GLES_SetSwapInterval;
|
||||
device->GL_GetSwapInterval = Android_GLES_GetSwapInterval;
|
||||
device->GL_SwapWindow = Android_GLES_SwapWindow;
|
||||
device->GL_DeleteContext = Android_GLES_DeleteContext;
|
||||
#endif
|
||||
|
||||
#ifdef SDL_VIDEO_VULKAN
|
||||
device->Vulkan_LoadLibrary = Android_Vulkan_LoadLibrary;
|
||||
device->Vulkan_UnloadLibrary = Android_Vulkan_UnloadLibrary;
|
||||
device->Vulkan_GetInstanceExtensions = Android_Vulkan_GetInstanceExtensions;
|
||||
device->Vulkan_CreateSurface = Android_Vulkan_CreateSurface;
|
||||
#endif
|
||||
|
||||
/* Screensaver */
|
||||
device->SuspendScreenSaver = Android_SuspendScreenSaver;
|
||||
|
||||
/* Text input */
|
||||
device->StartTextInput = Android_StartTextInput;
|
||||
device->StopTextInput = Android_StopTextInput;
|
||||
device->SetTextInputRect = Android_SetTextInputRect;
|
||||
|
||||
/* Screen keyboard */
|
||||
device->HasScreenKeyboardSupport = Android_HasScreenKeyboardSupport;
|
||||
device->IsScreenKeyboardShown = Android_IsScreenKeyboardShown;
|
||||
|
||||
/* Clipboard */
|
||||
device->SetClipboardText = Android_SetClipboardText;
|
||||
device->GetClipboardText = Android_GetClipboardText;
|
||||
device->HasClipboardText = Android_HasClipboardText;
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
VideoBootStrap Android_bootstrap = {
|
||||
ANDROID_VID_DRIVER_NAME, "SDL Android video driver",
|
||||
Android_CreateDevice
|
||||
};
|
||||
|
||||
int Android_VideoInit(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *videodata = _this->driverdata;
|
||||
SDL_DisplayID displayID;
|
||||
SDL_VideoDisplay *display;
|
||||
SDL_DisplayMode mode;
|
||||
|
||||
videodata->isPaused = SDL_FALSE;
|
||||
videodata->isPausing = SDL_FALSE;
|
||||
videodata->pauseAudio = SDL_GetHintBoolean(SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO, SDL_TRUE);
|
||||
|
||||
SDL_zero(mode);
|
||||
mode.format = Android_ScreenFormat;
|
||||
mode.w = Android_DeviceWidth;
|
||||
mode.h = Android_DeviceHeight;
|
||||
mode.refresh_rate = Android_ScreenRate;
|
||||
mode.driverdata = NULL;
|
||||
|
||||
displayID = SDL_AddBasicVideoDisplay(&mode);
|
||||
if (displayID == 0) {
|
||||
return -1;
|
||||
}
|
||||
display = SDL_GetVideoDisplay(displayID);
|
||||
display->natural_orientation = Android_JNI_GetDisplayNaturalOrientation();
|
||||
display->current_orientation = Android_JNI_GetDisplayCurrentOrientation();
|
||||
display->content_scale = Android_ScreenDensity;
|
||||
|
||||
Android_InitTouch();
|
||||
|
||||
Android_InitMouse();
|
||||
|
||||
/* We're done! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Android_VideoQuit(SDL_VideoDevice *_this)
|
||||
{
|
||||
Android_QuitMouse();
|
||||
Android_QuitTouch();
|
||||
}
|
||||
|
||||
void Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, float density, float rate)
|
||||
{
|
||||
Android_SurfaceWidth = surfaceWidth;
|
||||
Android_SurfaceHeight = surfaceHeight;
|
||||
Android_DeviceWidth = deviceWidth;
|
||||
Android_DeviceHeight = deviceHeight;
|
||||
Android_ScreenDensity = (density > 0.0f) ? density : 1.0f;
|
||||
Android_ScreenRate = 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 if (format == 0x115) {
|
||||
/* HAL_PIXEL_FORMAT_BGR_565 */
|
||||
pf = SDL_PIXELFORMAT_RGB565;
|
||||
} 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)
|
||||
{
|
||||
/*
|
||||
Update the resolution of the desktop mode, so that the window
|
||||
can be properly resized. The screen resolution change can for
|
||||
example happen when the Activity enters or exits immersive mode,
|
||||
which can happen after VideoInit().
|
||||
*/
|
||||
SDL_VideoDevice *device = SDL_GetVideoDevice();
|
||||
if (device && device->num_displays > 0) {
|
||||
SDL_VideoDisplay *display = &device->displays[0];
|
||||
SDL_DisplayMode desktop_mode;
|
||||
|
||||
SDL_zero(desktop_mode);
|
||||
desktop_mode.format = Android_ScreenFormat;
|
||||
desktop_mode.w = Android_DeviceWidth;
|
||||
desktop_mode.h = Android_DeviceHeight;
|
||||
desktop_mode.refresh_rate = Android_ScreenRate;
|
||||
SDL_SetDesktopDisplayMode(display, &desktop_mode);
|
||||
}
|
||||
|
||||
if (window) {
|
||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, Android_SurfaceWidth, Android_SurfaceHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void Android_SetDarkMode(SDL_bool enabled)
|
||||
{
|
||||
SDL_VideoDevice *device = SDL_GetVideoDevice();
|
||||
|
||||
if (enabled) {
|
||||
Android_SystemTheme = SDL_SYSTEM_THEME_DARK;
|
||||
} else {
|
||||
Android_SystemTheme = SDL_SYSTEM_THEME_LIGHT;
|
||||
}
|
||||
|
||||
if (device) {
|
||||
SDL_SetSystemTheme(Android_SystemTheme);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_ANDROID */
|
50
external/sdl/SDL/src/video/android/SDL_androidvideo.h
vendored
Normal file
50
external/sdl/SDL/src/video/android/SDL_androidvideo.h
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_androidvideo_h_
|
||||
#define SDL_androidvideo_h_
|
||||
|
||||
#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, float density, float rate);
|
||||
extern void Android_SetFormat(int format_wanted, int format_got);
|
||||
extern void Android_SendResize(SDL_Window *window);
|
||||
extern void Android_SetDarkMode(SDL_bool enabled);
|
||||
|
||||
/* Private display data */
|
||||
|
||||
struct SDL_VideoData
|
||||
{
|
||||
SDL_Rect textRect;
|
||||
int isPaused;
|
||||
int isPausing;
|
||||
int pauseAudio;
|
||||
};
|
||||
|
||||
extern int Android_SurfaceWidth;
|
||||
extern int Android_SurfaceHeight;
|
||||
extern float Android_ScreenDensity;
|
||||
extern SDL_Semaphore *Android_PauseSem, *Android_ResumeSem;
|
||||
extern SDL_Mutex *Android_ActivityMutex;
|
||||
|
||||
#endif /* SDL_androidvideo_h_ */
|
168
external/sdl/SDL/src/video/android/SDL_androidvulkan.c
vendored
Normal file
168
external/sdl/SDL/src/video/android/SDL_androidvulkan.c
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.c.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_ANDROID)
|
||||
|
||||
#include "SDL_androidvideo.h"
|
||||
#include "SDL_androidwindow.h"
|
||||
|
||||
#include "SDL_androidvulkan.h"
|
||||
|
||||
#include <SDL3/SDL_syswm.h>
|
||||
|
||||
int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
||||
{
|
||||
VkExtensionProperties *extensions = NULL;
|
||||
Uint32 i, extensionCount = 0;
|
||||
SDL_bool hasSurfaceExtension = SDL_FALSE;
|
||||
SDL_bool hasAndroidSurfaceExtension = SDL_FALSE;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
|
||||
if (_this->vulkan_config.loader_handle) {
|
||||
return SDL_SetError("Vulkan already loaded");
|
||||
}
|
||||
|
||||
/* Load the Vulkan loader library */
|
||||
if (path == NULL) {
|
||||
path = SDL_getenv("SDL_VULKAN_LIBRARY");
|
||||
}
|
||||
if (path == NULL) {
|
||||
path = "libvulkan.so";
|
||||
}
|
||||
_this->vulkan_config.loader_handle = SDL_LoadObject(path);
|
||||
if (!_this->vulkan_config.loader_handle) {
|
||||
return -1;
|
||||
}
|
||||
SDL_strlcpy(_this->vulkan_config.loader_path, path,
|
||||
SDL_arraysize(_this->vulkan_config.loader_path));
|
||||
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
|
||||
_this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
|
||||
if (!vkGetInstanceProcAddr) {
|
||||
goto fail;
|
||||
}
|
||||
_this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties =
|
||||
(void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
|
||||
VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
|
||||
if (!_this->vulkan_config.vkEnumerateInstanceExtensionProperties) {
|
||||
goto fail;
|
||||
}
|
||||
extensions = SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
(PFN_vkEnumerateInstanceExtensionProperties)
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties,
|
||||
&extensionCount);
|
||||
if (extensions == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i < extensionCount; i++) {
|
||||
if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
|
||||
hasSurfaceExtension = SDL_TRUE;
|
||||
} else if (SDL_strcmp(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
|
||||
hasAndroidSurfaceExtension = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
SDL_free(extensions);
|
||||
if (!hasSurfaceExtension) {
|
||||
SDL_SetError("Installed Vulkan doesn't implement the " VK_KHR_SURFACE_EXTENSION_NAME " extension");
|
||||
goto fail;
|
||||
} else if (!hasAndroidSurfaceExtension) {
|
||||
SDL_SetError("Installed Vulkan doesn't implement the " VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "extension");
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Android_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
|
||||
{
|
||||
if (_this->vulkan_config.loader_handle) {
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
|
||||
unsigned *count,
|
||||
const char **names)
|
||||
{
|
||||
static const char *const extensionsForAndroid[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
|
||||
};
|
||||
if (!_this->vulkan_config.loader_handle) {
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_Vulkan_GetInstanceExtensions_Helper(
|
||||
count, names, SDL_arraysize(extensionsForAndroid),
|
||||
extensionsForAndroid);
|
||||
}
|
||||
|
||||
SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
SDL_WindowData *windowData = window->driverdata;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
|
||||
PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR =
|
||||
(PFN_vkCreateAndroidSurfaceKHR)vkGetInstanceProcAddr(
|
||||
instance,
|
||||
"vkCreateAndroidSurfaceKHR");
|
||||
VkAndroidSurfaceCreateInfoKHR createInfo;
|
||||
VkResult result;
|
||||
|
||||
if (!_this->vulkan_config.loader_handle) {
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (!vkCreateAndroidSurfaceKHR) {
|
||||
SDL_SetError(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
|
||||
" extension is not enabled in the Vulkan instance.");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
SDL_zero(createInfo);
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = 0;
|
||||
createInfo.window = windowData->native_window;
|
||||
result = vkCreateAndroidSurfaceKHR(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if (result != VK_SUCCESS) {
|
||||
SDL_SetError("vkCreateAndroidSurfaceKHR failed: %s",
|
||||
SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
#endif
|
49
external/sdl/SDL/src/video/android/SDL_androidvulkan.h
vendored
Normal file
49
external/sdl/SDL/src/video/android/SDL_androidvulkan.h
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.h.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_androidvulkan_h_
|
||||
#define SDL_androidvulkan_h_
|
||||
|
||||
#include "../SDL_vulkan_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_ANDROID)
|
||||
|
||||
int Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path);
|
||||
void Android_Vulkan_UnloadLibrary(SDL_VideoDevice *_this);
|
||||
SDL_bool Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
|
||||
unsigned *count,
|
||||
const char **names);
|
||||
SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SDL_androidvulkan_h_ */
|
211
external/sdl/SDL/src/video/android/SDL_androidwindow.c
vendored
Normal file
211
external/sdl/SDL/src/video/android/SDL_androidwindow.c
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_ANDROID
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_windowevents_c.h"
|
||||
#include "../../core/android/SDL_android.h"
|
||||
|
||||
#include "SDL_androidvideo.h"
|
||||
#include "SDL_androidwindow.h"
|
||||
|
||||
#include <SDL3/SDL_syswm.h>
|
||||
|
||||
/* Currently only one window */
|
||||
SDL_Window *Android_Window = NULL;
|
||||
|
||||
int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data;
|
||||
int retval = 0;
|
||||
|
||||
Android_ActivityMutex_Lock_Running();
|
||||
|
||||
if (Android_Window) {
|
||||
retval = SDL_SetError("Android only supports one window");
|
||||
goto endfunction;
|
||||
}
|
||||
|
||||
/* Set orientation */
|
||||
Android_JNI_SetOrientation(window->w, window->h, window->flags & SDL_WINDOW_RESIZABLE, SDL_GetHint(SDL_HINT_ORIENTATIONS));
|
||||
|
||||
/* Adjust the window data to match the screen */
|
||||
window->x = 0;
|
||||
window->y = 0;
|
||||
window->w = Android_SurfaceWidth;
|
||||
window->h = Android_SurfaceHeight;
|
||||
|
||||
/* One window, it always has focus */
|
||||
SDL_SetMouseFocus(window);
|
||||
SDL_SetKeyboardFocus(window);
|
||||
|
||||
data = (SDL_WindowData *)SDL_calloc(1, sizeof(*data));
|
||||
if (data == NULL) {
|
||||
retval = SDL_OutOfMemory();
|
||||
goto endfunction;
|
||||
}
|
||||
|
||||
data->native_window = Android_JNI_GetNativeWindow();
|
||||
|
||||
if (!data->native_window) {
|
||||
SDL_free(data);
|
||||
retval = SDL_SetError("Could not fetch native window");
|
||||
goto endfunction;
|
||||
}
|
||||
|
||||
/* Do not create EGLSurface for Vulkan window since it will then make the window
|
||||
incompatible with vkCreateAndroidSurfaceKHR */
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
if (window->flags & SDL_WINDOW_OPENGL) {
|
||||
data->egl_surface = SDL_EGL_CreateSurface(_this, window, (NativeWindowType)data->native_window);
|
||||
|
||||
if (data->egl_surface == EGL_NO_SURFACE) {
|
||||
ANativeWindow_release(data->native_window);
|
||||
SDL_free(data);
|
||||
retval = -1;
|
||||
goto endfunction;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
window->driverdata = data;
|
||||
Android_Window = window;
|
||||
|
||||
endfunction:
|
||||
|
||||
SDL_UnlockMutex(Android_ActivityMutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
Android_JNI_SetActivityTitle(window->title);
|
||||
}
|
||||
|
||||
void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
|
||||
{
|
||||
SDL_LockMutex(Android_ActivityMutex);
|
||||
|
||||
if (window == Android_Window) {
|
||||
SDL_WindowData *data;
|
||||
int old_w, old_h, new_w, new_h;
|
||||
|
||||
/* If the window is being destroyed don't change visible state */
|
||||
if (!window->is_destroying) {
|
||||
Android_JNI_SetWindowStyle(fullscreen);
|
||||
}
|
||||
|
||||
/* Ensure our size matches reality after we've executed the window style change.
|
||||
*
|
||||
* It is possible that we've set width and height to the full-size display, but on
|
||||
* Samsung DeX or Chromebooks or other windowed Android environemtns, our window may
|
||||
* still not be the full display size.
|
||||
*/
|
||||
if (!SDL_IsDeXMode() && !SDL_IsChromebook()) {
|
||||
goto endfunction;
|
||||
}
|
||||
|
||||
data = window->driverdata;
|
||||
if (data == NULL || !data->native_window) {
|
||||
if (data && !data->native_window) {
|
||||
SDL_SetError("Missing native window");
|
||||
}
|
||||
goto endfunction;
|
||||
}
|
||||
|
||||
old_w = window->w;
|
||||
old_h = window->h;
|
||||
|
||||
new_w = ANativeWindow_getWidth(data->native_window);
|
||||
new_h = ANativeWindow_getHeight(data->native_window);
|
||||
|
||||
if (new_w < 0 || new_h < 0) {
|
||||
SDL_SetError("ANativeWindow_getWidth/Height() fails");
|
||||
}
|
||||
|
||||
if (old_w != new_w || old_h != new_h) {
|
||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, new_w, new_h);
|
||||
}
|
||||
}
|
||||
|
||||
endfunction:
|
||||
|
||||
SDL_UnlockMutex(Android_ActivityMutex);
|
||||
}
|
||||
|
||||
void Android_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
Android_JNI_MinizeWindow();
|
||||
}
|
||||
|
||||
void Android_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable)
|
||||
{
|
||||
/* Set orientation */
|
||||
Android_JNI_SetOrientation(window->w, window->h, window->flags & SDL_WINDOW_RESIZABLE, SDL_GetHint(SDL_HINT_ORIENTATIONS));
|
||||
}
|
||||
|
||||
void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
SDL_LockMutex(Android_ActivityMutex);
|
||||
|
||||
if (window == Android_Window) {
|
||||
Android_Window = NULL;
|
||||
|
||||
if (window->driverdata) {
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
|
||||
#ifdef 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);
|
||||
}
|
||||
SDL_free(window->driverdata);
|
||||
window->driverdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(Android_ActivityMutex);
|
||||
}
|
||||
|
||||
int Android_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, SDL_SysWMinfo *info)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
|
||||
info->subsystem = SDL_SYSWM_ANDROID;
|
||||
info->info.android.window = data->native_window;
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
info->info.android.surface = data->egl_surface;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_ANDROID */
|
52
external/sdl/SDL/src/video/android/SDL_androidwindow.h
vendored
Normal file
52
external/sdl/SDL/src/video/android/SDL_androidwindow.h
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_androidwindow_h_
|
||||
#define SDL_androidwindow_h_
|
||||
|
||||
#include "../../core/android/SDL_android.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
|
||||
extern int Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
|
||||
extern void Android_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Android_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable);
|
||||
|
||||
extern void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int Android_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info);
|
||||
extern SDL_Window *Android_Window;
|
||||
|
||||
struct SDL_WindowData
|
||||
{
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
EGLSurface egl_surface;
|
||||
EGLContext egl_context; /* We use this to preserve the context when losing focus */
|
||||
int has_swap_interval; /* Save/Restore the swap interval / vsync */
|
||||
int swap_interval;
|
||||
#endif
|
||||
SDL_bool backup_done;
|
||||
ANativeWindow *native_window;
|
||||
|
||||
};
|
||||
|
||||
#endif /* SDL_androidwindow_h_ */
|
36
external/sdl/SDL/src/video/arm/pixman-arm-asm.h
vendored
Normal file
36
external/sdl/SDL/src/video/arm/pixman-arm-asm.h
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright © 2010 Nokia Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Mozilla Corporation not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Mozilla Corporation makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Siarhei Siamashka (siarhei.siamashka@nokia.com)
|
||||
*
|
||||
*/
|
||||
|
||||
/* Supplementary macro for setting function attributes */
|
||||
.macro pixman_asm_function fname
|
||||
.func fname
|
||||
.global fname
|
||||
#ifdef __ELF__
|
||||
.hidden fname
|
||||
.type fname, %function
|
||||
#endif
|
||||
fname:
|
||||
.endm
|
375
external/sdl/SDL/src/video/arm/pixman-arm-neon-asm.S
vendored
Normal file
375
external/sdl/SDL/src/video/arm/pixman-arm-neon-asm.S
vendored
Normal file
@ -0,0 +1,375 @@
|
||||
/*
|
||||
* Copyright © 2009 Nokia Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Siarhei Siamashka (siarhei.siamashka@nokia.com)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 RISC OS Open Ltd
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* Prevent the stack from becoming executable for no reason... */
|
||||
#if defined(__linux__) && defined(__ELF__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
||||
.text
|
||||
.fpu neon
|
||||
.arch armv7a
|
||||
.object_arch armv4
|
||||
.eabi_attribute 10, 0 /* suppress Tag_FP_arch */
|
||||
.eabi_attribute 12, 0 /* suppress Tag_Advanced_SIMD_arch */
|
||||
.arm
|
||||
.altmacro
|
||||
.p2align 2
|
||||
|
||||
#include "pixman-arm-asm.h"
|
||||
#include "pixman-arm-neon-asm.h"
|
||||
|
||||
/* Global configuration options and preferences */
|
||||
|
||||
/*
|
||||
* The code can optionally make use of unaligned memory accesses to improve
|
||||
* performance of handling leading/trailing pixels for each scanline.
|
||||
* Configuration variable RESPECT_STRICT_ALIGNMENT can be set to 0 for
|
||||
* example in linux if unaligned memory accesses are not configured to
|
||||
* generate.exceptions.
|
||||
*/
|
||||
.set RESPECT_STRICT_ALIGNMENT, 1
|
||||
|
||||
/*
|
||||
* Set default prefetch type. There is a choice between the following options:
|
||||
*
|
||||
* PREFETCH_TYPE_NONE (may be useful for the ARM cores where PLD is set to work
|
||||
* as NOP to workaround some HW bugs or for whatever other reason)
|
||||
*
|
||||
* PREFETCH_TYPE_SIMPLE (may be useful for simple single-issue ARM cores where
|
||||
* advanced prefetch introduces heavy overhead)
|
||||
*
|
||||
* PREFETCH_TYPE_ADVANCED (useful for superscalar cores such as ARM Cortex-A8
|
||||
* which can run ARM and NEON instructions simultaneously so that extra ARM
|
||||
* instructions do not add (many) extra cycles, but improve prefetch efficiency)
|
||||
*
|
||||
* Note: some types of function can't support advanced prefetch and fallback
|
||||
* to simple one (those which handle 24bpp pixels)
|
||||
*/
|
||||
.set PREFETCH_TYPE_DEFAULT, PREFETCH_TYPE_ADVANCED
|
||||
|
||||
/* Prefetch distance in pixels for simple prefetch */
|
||||
.set PREFETCH_DISTANCE_SIMPLE, 64
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* We can actually do significantly better than the Pixman macros, at least for
|
||||
* the case of fills, by using a carefully scheduled inner loop. Cortex-A53
|
||||
* shows an improvement of up to 78% in ideal cases (large fills to L1 cache).
|
||||
*/
|
||||
|
||||
.macro generate_fillrect_function name, bpp, log2Bpp
|
||||
/*
|
||||
* void name(int32_t w, int32_t h, uint8_t *dst, int32_t dst_stride, uint8_t src);
|
||||
* On entry:
|
||||
* a1 = width, pixels
|
||||
* a2 = height, rows
|
||||
* a3 = pointer to top-left destination pixel
|
||||
* a4 = stride, pixels
|
||||
* [sp] = pixel value to fill with
|
||||
* Within the function:
|
||||
* v1 = width remaining
|
||||
* v2 = vst offset
|
||||
* v3 = alternate pointer
|
||||
* ip = data ARM register
|
||||
*/
|
||||
pixman_asm_function name
|
||||
vld1.\bpp {d0[],d1[]}, [sp]
|
||||
sub a4, a1
|
||||
vld1.\bpp {d2[],d3[]}, [sp]
|
||||
cmp a1, #(15+64) >> \log2Bpp
|
||||
push {v1-v3,lr}
|
||||
vmov ip, s0
|
||||
blo 51f
|
||||
|
||||
/* Long-row case */
|
||||
mov v2, #64
|
||||
1: mov v1, a1
|
||||
ands v3, a3, #15
|
||||
beq 2f
|
||||
/* Leading pixels */
|
||||
rsb v3, v3, #16 /* number of leading bytes until 16-byte aligned */
|
||||
sub v1, v1, v3, lsr #\log2Bpp
|
||||
rbit v3, v3
|
||||
.if bpp <= 16
|
||||
.if bpp == 8
|
||||
tst a3, #1 /* bit 0 unaffected by rsb so can avoid register interlock */
|
||||
strneb ip, [a3], #1
|
||||
tst v3, #1<<30
|
||||
.else
|
||||
tst a3, #2 /* bit 1 unaffected by rsb (assuming halfword alignment) so can avoid register interlock */
|
||||
.endif
|
||||
strneh ip, [a3], #2
|
||||
.endif
|
||||
movs v3, v3, lsl #3
|
||||
vstmcs a3!, {s0}
|
||||
vstmmi a3!, {d0}
|
||||
2: sub v1, v1, #64 >> \log2Bpp /* simplifies inner loop termination */
|
||||
add v3, a3, #32
|
||||
/* Inner loop */
|
||||
3: vst1.\bpp {q0-q1}, [a3 :128], v2
|
||||
subs v1, v1, #64 >> \log2Bpp
|
||||
vst1.\bpp {q0-q1}, [v3 :128], v2
|
||||
bhs 3b
|
||||
/* Trailing pixels */
|
||||
4: movs v1, v1, lsl #27 + \log2Bpp
|
||||
bcc 5f
|
||||
vst1.\bpp {q0-q1}, [a3 :128]!
|
||||
5: bpl 6f
|
||||
vst1.\bpp {q0}, [a3 :128]!
|
||||
6: movs v1, v1, lsl #2
|
||||
vstmcs a3!, {d0}
|
||||
vstmmi a3!, {s0}
|
||||
.if bpp <= 16
|
||||
movs v1, v1, lsl #2
|
||||
strcsh ip, [a3], #2
|
||||
.if bpp == 8
|
||||
strmib ip, [a3], #1
|
||||
.endif
|
||||
.endif
|
||||
subs a2, a2, #1
|
||||
add a3, a3, a4, lsl #\log2Bpp
|
||||
bhi 1b
|
||||
pop {v1-v3,pc}
|
||||
|
||||
/* Short-row case */
|
||||
51: movs v1, a1
|
||||
.if bpp == 8
|
||||
tst a3, #3
|
||||
beq 53f
|
||||
52: subs v1, v1, #1
|
||||
blo 57f
|
||||
strb ip, [a3], #1
|
||||
tst a3, #3
|
||||
bne 52b
|
||||
.elseif bpp == 16
|
||||
tstne a3, #2
|
||||
subne v1, v1, #1
|
||||
strneh ip, [a3], #2
|
||||
.endif
|
||||
53: cmp v1, #32 >> \log2Bpp
|
||||
bcc 54f
|
||||
vst1.\bpp {q0-q1}, [a3]!
|
||||
sub v1, v1, #32 >> \log2Bpp
|
||||
/* Trailing pixels */
|
||||
54: movs v1, v1, lsl #27 + \log2Bpp
|
||||
bcc 55f
|
||||
vst1.\bpp {q0-q1}, [a3]!
|
||||
55: bpl 56f
|
||||
vst1.\bpp {q0}, [a3]!
|
||||
56: movs v1, v1, lsl #2
|
||||
vstmcs a3!, {d0}
|
||||
vstmmi a3!, {s0}
|
||||
.if bpp <= 16
|
||||
movs v1, v1, lsl #2
|
||||
strcsh ip, [a3], #2
|
||||
.if bpp == 8
|
||||
strmib ip, [a3], #1
|
||||
.endif
|
||||
.endif
|
||||
subs a2, a2, #1
|
||||
add a3, a3, a4, lsl #\log2Bpp
|
||||
bhi 51b
|
||||
57: pop {v1-v3,pc}
|
||||
|
||||
.endfunc
|
||||
.endm
|
||||
|
||||
generate_fillrect_function FillSurfaceRect32ARMNEONAsm, 32, 2
|
||||
generate_fillrect_function FillSurfaceRect16ARMNEONAsm, 16, 1
|
||||
generate_fillrect_function FillSurfaceRect8ARMNEONAsm, 8, 0
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro RGBtoRGBPixelAlpha_process_pixblock_head
|
||||
vmvn d30, d3 /* get inverted source alpha */
|
||||
vmov d31, d7 /* dest alpha is always unchanged */
|
||||
vmull.u8 q14, d0, d3
|
||||
vmlal.u8 q14, d4, d30
|
||||
vmull.u8 q0, d1, d3
|
||||
vmlal.u8 q0, d5, d30
|
||||
vmull.u8 q1, d2, d3
|
||||
vmlal.u8 q1, d6, d30
|
||||
vrshr.u16 q2, q14, #8
|
||||
vrshr.u16 q3, q0, #8
|
||||
vraddhn.u16 d28, q14, q2
|
||||
vrshr.u16 q2, q1, #8
|
||||
vraddhn.u16 d29, q0, q3
|
||||
vraddhn.u16 d30, q1, q2
|
||||
.endm
|
||||
|
||||
.macro RGBtoRGBPixelAlpha_process_pixblock_tail
|
||||
/* nothing */
|
||||
.endm
|
||||
|
||||
.macro RGBtoRGBPixelAlpha_process_pixblock_tail_head
|
||||
vld4.8 {d0-d3}, [SRC]!
|
||||
PF add PF_X, PF_X, #8
|
||||
vst4.8 {d28-d31}, [DST_W :128]!
|
||||
PF tst PF_CTL, #0xF
|
||||
vld4.8 {d4-d7}, [DST_R :128]!
|
||||
PF addne PF_X, PF_X, #8
|
||||
vmvn d30, d3 /* get inverted source alpha */
|
||||
vmov d31, d7 /* dest alpha is always unchanged */
|
||||
vmull.u8 q14, d0, d3
|
||||
PF subne PF_CTL, PF_CTL, #1
|
||||
vmlal.u8 q14, d4, d30
|
||||
PF cmp PF_X, ORIG_W
|
||||
vmull.u8 q0, d1, d3
|
||||
PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift]
|
||||
vmlal.u8 q0, d5, d30
|
||||
PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift]
|
||||
vmull.u8 q1, d2, d3
|
||||
PF subge PF_X, PF_X, ORIG_W
|
||||
vmlal.u8 q1, d6, d30
|
||||
PF subges PF_CTL, PF_CTL, #0x10
|
||||
vrshr.u16 q2, q14, #8
|
||||
PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]!
|
||||
vrshr.u16 q3, q0, #8
|
||||
PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]!
|
||||
vraddhn.u16 d28, q14, q2
|
||||
vrshr.u16 q2, q1, #8
|
||||
vraddhn.u16 d29, q0, q3
|
||||
vraddhn.u16 d30, q1, q2
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
BlitRGBtoRGBPixelAlphaARMNEONAsm, 32, 0, 32, \
|
||||
FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \
|
||||
8, /* number of pixels, processed in a single block */ \
|
||||
5, /* prefetch distance */ \
|
||||
default_init, \
|
||||
default_cleanup, \
|
||||
RGBtoRGBPixelAlpha_process_pixblock_head, \
|
||||
RGBtoRGBPixelAlpha_process_pixblock_tail, \
|
||||
RGBtoRGBPixelAlpha_process_pixblock_tail_head
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro ARGBto565PixelAlpha_process_pixblock_head
|
||||
vmvn d6, d3
|
||||
vshr.u8 d1, #2
|
||||
vshr.u8 d3, #3
|
||||
vshr.u8 d0, #3
|
||||
vshrn.u16 d7, q2, #3
|
||||
vshrn.u16 d25, q2, #8
|
||||
vbic.i16 q2, #0xe0
|
||||
vshr.u8 d6, #3
|
||||
vshr.u8 d7, #2
|
||||
vshr.u8 d2, #3
|
||||
vmovn.u16 d24, q2
|
||||
vshr.u8 d25, #3
|
||||
vmull.u8 q13, d1, d3
|
||||
vmlal.u8 q13, d7, d6
|
||||
vmull.u8 q14, d0, d3
|
||||
vmlal.u8 q14, d24, d6
|
||||
vmull.u8 q15, d2, d3
|
||||
vmlal.u8 q15, d25, d6
|
||||
.endm
|
||||
|
||||
.macro ARGBto565PixelAlpha_process_pixblock_tail
|
||||
vsra.u16 q13, #5
|
||||
vsra.u16 q14, #5
|
||||
vsra.u16 q15, #5
|
||||
vrshr.u16 q13, #5
|
||||
vrshr.u16 q14, #5
|
||||
vrshr.u16 q15, #5
|
||||
vsli.u16 q14, q13, #5
|
||||
vsli.u16 q14, q15, #11
|
||||
.endm
|
||||
|
||||
.macro ARGBto565PixelAlpha_process_pixblock_tail_head
|
||||
vld4.8 {d0-d3}, [SRC]!
|
||||
PF add PF_X, PF_X, #8
|
||||
vsra.u16 q13, #5
|
||||
PF tst PF_CTL, #0xF
|
||||
vsra.u16 q14, #5
|
||||
PF addne PF_X, PF_X, #8
|
||||
vsra.u16 q15, #5
|
||||
PF subne PF_CTL, PF_CTL, #1
|
||||
vrshr.u16 q13, #5
|
||||
PF cmp PF_X, ORIG_W
|
||||
vrshr.u16 q14, #5
|
||||
PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift]
|
||||
vrshr.u16 q15, #5
|
||||
PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift]
|
||||
vld1.8 {d4-d5}, [DST_R]!
|
||||
PF subge PF_X, PF_X, ORIG_W
|
||||
vsli.u16 q14, q13, #5
|
||||
PF subges PF_CTL, PF_CTL, #0x10
|
||||
vsli.u16 q14, q15, #11
|
||||
PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]!
|
||||
vst1.8 {q14}, [DST_W :128]!
|
||||
vmvn d6, d3
|
||||
vshr.u8 d1, #2
|
||||
vshr.u8 d3, #3
|
||||
vshr.u8 d0, #3
|
||||
vshrn.u16 d7, q2, #3
|
||||
vshrn.u16 d25, q2, #8
|
||||
vbic.i16 q2, #0xe0
|
||||
PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]!
|
||||
vshr.u8 d6, #3
|
||||
vshr.u8 d7, #2
|
||||
vshr.u8 d2, #3
|
||||
vmovn.u16 d24, q2
|
||||
vshr.u8 d25, #3
|
||||
vmull.u8 q13, d1, d3
|
||||
vmlal.u8 q13, d7, d6
|
||||
vmull.u8 q14, d0, d3
|
||||
vmlal.u8 q14, d24, d6
|
||||
vmull.u8 q15, d2, d3
|
||||
vmlal.u8 q15, d25, d6
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
BlitARGBto565PixelAlphaARMNEONAsm, 32, 0, 16, \
|
||||
FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \
|
||||
8, /* number of pixels, processed in a single block */ \
|
||||
6, /* prefetch distance */ \
|
||||
default_init, \
|
||||
default_cleanup, \
|
||||
ARGBto565PixelAlpha_process_pixblock_head, \
|
||||
ARGBto565PixelAlpha_process_pixblock_tail, \
|
||||
ARGBto565PixelAlpha_process_pixblock_tail_head
|
1184
external/sdl/SDL/src/video/arm/pixman-arm-neon-asm.h
vendored
Normal file
1184
external/sdl/SDL/src/video/arm/pixman-arm-neon-asm.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
532
external/sdl/SDL/src/video/arm/pixman-arm-simd-asm.S
vendored
Normal file
532
external/sdl/SDL/src/video/arm/pixman-arm-simd-asm.S
vendored
Normal file
@ -0,0 +1,532 @@
|
||||
/*
|
||||
* Copyright (c) 2016 RISC OS Open Ltd
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* Prevent the stack from becoming executable */
|
||||
#if defined(__linux__) && defined(__ELF__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
||||
.text
|
||||
.arch armv6
|
||||
.object_arch armv4
|
||||
.arm
|
||||
.altmacro
|
||||
.p2align 2
|
||||
|
||||
#include "pixman-arm-asm.h"
|
||||
#include "pixman-arm-simd-asm.h"
|
||||
|
||||
/* A head macro should do all processing which results in an output of up to
|
||||
* 16 bytes, as far as the final load instruction. The corresponding tail macro
|
||||
* should complete the processing of the up-to-16 bytes. The calling macro will
|
||||
* sometimes choose to insert a preload or a decrement of X between them.
|
||||
* cond ARM condition code for code block
|
||||
* numbytes Number of output bytes that should be generated this time
|
||||
* firstreg First WK register in which to place output
|
||||
* unaligned_src Whether to use non-wordaligned loads of source image
|
||||
* unaligned_mask Whether to use non-wordaligned loads of mask image
|
||||
* preload If outputting 16 bytes causes 64 bytes to be read, whether an extra preload should be output
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro FillRect32_init
|
||||
ldr SRC, [sp, #ARGS_STACK_OFFSET]
|
||||
mov STRIDE_S, SRC
|
||||
mov MASK, SRC
|
||||
mov STRIDE_M, SRC
|
||||
.endm
|
||||
|
||||
.macro FillRect16_init
|
||||
ldrh SRC, [sp, #ARGS_STACK_OFFSET]
|
||||
orr SRC, SRC, lsl #16
|
||||
mov STRIDE_S, SRC
|
||||
mov MASK, SRC
|
||||
mov STRIDE_M, SRC
|
||||
.endm
|
||||
|
||||
.macro FillRect8_init
|
||||
ldrb SRC, [sp, #ARGS_STACK_OFFSET]
|
||||
orr SRC, SRC, lsl #8
|
||||
orr SRC, SRC, lsl #16
|
||||
mov STRIDE_S, SRC
|
||||
mov MASK, SRC
|
||||
mov STRIDE_M, SRC
|
||||
.endm
|
||||
|
||||
.macro FillRect_process_tail cond, numbytes, firstreg
|
||||
WK4 .req SRC
|
||||
WK5 .req STRIDE_S
|
||||
WK6 .req MASK
|
||||
WK7 .req STRIDE_M
|
||||
pixst cond, numbytes, 4, DST
|
||||
.unreq WK4
|
||||
.unreq WK5
|
||||
.unreq WK6
|
||||
.unreq WK7
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
FillSurfaceRect32ARMSIMDAsm, 0, 0, 32, \
|
||||
FLAG_DST_WRITEONLY | FLAG_COND_EXEC | FLAG_PROCESS_PRESERVES_PSR | FLAG_PROCESS_DOES_STORE | FLAG_PROCESS_PRESERVES_SCRATCH \
|
||||
0, /* prefetch distance doesn't apply */ \
|
||||
FillRect32_init \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro /* cleanup */ \
|
||||
nop_macro /* process head */ \
|
||||
FillRect_process_tail
|
||||
|
||||
generate_composite_function \
|
||||
FillSurfaceRect16ARMSIMDAsm, 0, 0, 16, \
|
||||
FLAG_DST_WRITEONLY | FLAG_COND_EXEC | FLAG_PROCESS_PRESERVES_PSR | FLAG_PROCESS_DOES_STORE | FLAG_PROCESS_PRESERVES_SCRATCH \
|
||||
0, /* prefetch distance doesn't apply */ \
|
||||
FillRect16_init \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro /* cleanup */ \
|
||||
nop_macro /* process head */ \
|
||||
FillRect_process_tail
|
||||
|
||||
generate_composite_function \
|
||||
FillSurfaceRect8ARMSIMDAsm, 0, 0, 8, \
|
||||
FLAG_DST_WRITEONLY | FLAG_COND_EXEC | FLAG_PROCESS_PRESERVES_PSR | FLAG_PROCESS_DOES_STORE | FLAG_PROCESS_PRESERVES_SCRATCH \
|
||||
0, /* prefetch distance doesn't apply */ \
|
||||
FillRect8_init \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro /* cleanup */ \
|
||||
nop_macro /* process head */ \
|
||||
FillRect_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* This differs from the over_8888_8888 routine in Pixman in that the destination
|
||||
* alpha component is always left unchanged, and RGB components are not
|
||||
* premultiplied by alpha. It differs from BlitRGBtoRGBPixelAlpha in that
|
||||
* renormalisation is done by multiplying by 257/256 (with rounding) rather than
|
||||
* simply shifting right by 8 bits - removing the need to special-case alpha=0xff.
|
||||
*/
|
||||
|
||||
.macro RGBtoRGBPixelAlpha_init
|
||||
line_saved_regs STRIDE_S, ORIG_W
|
||||
mov MASK, #0x80
|
||||
.endm
|
||||
|
||||
.macro RGBtoRGBPixelAlpha_1pixel_translucent s, d, tmp0, tmp1, tmp2, tmp3, half
|
||||
uxtb tmp3, s
|
||||
uxtb tmp0, d
|
||||
sub tmp0, tmp3, tmp0
|
||||
uxtb tmp3, s, ror #16
|
||||
uxtb tmp1, d, ror #16
|
||||
sub tmp1, tmp3, tmp1
|
||||
uxtb tmp3, s, ror #8
|
||||
mov s, s, lsr #24
|
||||
uxtb tmp2, d, ror #8
|
||||
sub tmp2, tmp3, tmp2
|
||||
smlabb tmp0, tmp0, s, half
|
||||
smlabb tmp1, tmp1, s, half
|
||||
smlabb tmp2, tmp2, s, half
|
||||
add tmp0, tmp0, asr #8
|
||||
add tmp1, tmp1, asr #8
|
||||
add tmp2, tmp2, asr #8
|
||||
pkhbt tmp0, tmp0, tmp1, lsl #16
|
||||
and tmp2, tmp2, #0xff00
|
||||
uxtb16 tmp0, tmp0, ror #8
|
||||
orr tmp0, tmp0, tmp2
|
||||
uadd8 d, d, tmp0
|
||||
.endm
|
||||
|
||||
.macro RGBtoRGBPixelAlpha_1pixel_opaque s, d
|
||||
and d, d, #0xff000000
|
||||
bic s, s, #0xff000000
|
||||
orr d, d, s
|
||||
.endm
|
||||
|
||||
.macro RGBtoRGBPixelAlpha_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
.if numbytes == 16
|
||||
ldm SRC!, {WK0, WK1}
|
||||
ldm SRC!, {STRIDE_S, STRIDE_M}
|
||||
ldrd WK2, WK3, [DST], #16
|
||||
orr SCRATCH, WK0, WK1
|
||||
and ORIG_W, WK0, WK1
|
||||
orr SCRATCH, SCRATCH, STRIDE_S
|
||||
and ORIG_W, ORIG_W, STRIDE_S
|
||||
orr SCRATCH, SCRATCH, STRIDE_M
|
||||
and ORIG_W, ORIG_W, STRIDE_M
|
||||
tst SCRATCH, #0xff000000
|
||||
.elseif numbytes == 8
|
||||
ldm SRC!, {WK0, WK1}
|
||||
ldm DST!, {WK2, WK3}
|
||||
orr SCRATCH, WK0, WK1
|
||||
and ORIG_W, WK0, WK1
|
||||
tst SCRATCH, #0xff000000
|
||||
.else // numbytes == 4
|
||||
ldr WK0, [SRC], #4
|
||||
ldr WK2, [DST], #4
|
||||
tst WK0, #0xff000000
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro RGBtoRGBPixelAlpha_process_tail cond, numbytes, firstreg
|
||||
beq 20f @ all transparent
|
||||
.if numbytes == 16
|
||||
cmp ORIG_W, #0xff000000
|
||||
bhs 10f @ all opaque
|
||||
RGBtoRGBPixelAlpha_1pixel_translucent WK0, WK2, STRIDE_S, STRIDE_M, SCRATCH, ORIG_W, MASK
|
||||
RGBtoRGBPixelAlpha_1pixel_translucent WK1, WK3, STRIDE_S, STRIDE_M, SCRATCH, ORIG_W, MASK
|
||||
strd WK2, WK3, [DST, #-16]
|
||||
ldrd WK0, WK1, [SRC, #-8]
|
||||
ldrd WK2, WK3, [DST, #-8]
|
||||
RGBtoRGBPixelAlpha_1pixel_translucent WK0, WK2, STRIDE_S, STRIDE_M, SCRATCH, ORIG_W, MASK
|
||||
RGBtoRGBPixelAlpha_1pixel_translucent WK1, WK3, STRIDE_S, STRIDE_M, SCRATCH, ORIG_W, MASK
|
||||
b 19f
|
||||
10: RGBtoRGBPixelAlpha_1pixel_opaque WK0, WK2
|
||||
RGBtoRGBPixelAlpha_1pixel_opaque WK1, WK3
|
||||
strd WK2, WK3, [DST, #-16]
|
||||
ldrd WK0, WK1, [SRC, #-8]
|
||||
ldrd WK2, WK3, [DST, #-8]
|
||||
RGBtoRGBPixelAlpha_1pixel_opaque WK0, WK2
|
||||
RGBtoRGBPixelAlpha_1pixel_opaque WK1, WK3
|
||||
19: strd WK2, WK3, [DST, #-8]
|
||||
.elseif numbytes == 8
|
||||
cmp ORIG_W, #0xff000000
|
||||
bhs 10f @ all opaque
|
||||
RGBtoRGBPixelAlpha_1pixel_translucent WK0, WK2, STRIDE_S, STRIDE_M, SCRATCH, ORIG_W, MASK
|
||||
RGBtoRGBPixelAlpha_1pixel_translucent WK1, WK3, STRIDE_S, STRIDE_M, SCRATCH, ORIG_W, MASK
|
||||
b 19f
|
||||
10: RGBtoRGBPixelAlpha_1pixel_opaque WK0, WK2
|
||||
RGBtoRGBPixelAlpha_1pixel_opaque WK1, WK3
|
||||
19: strd WK2, WK3, [DST, #-8]
|
||||
.else // numbytes == 4
|
||||
cmp WK0, #0xff000000
|
||||
bhs 10f @ opaque
|
||||
RGBtoRGBPixelAlpha_1pixel_translucent WK0, WK2, STRIDE_S, STRIDE_M, SCRATCH, ORIG_W, MASK
|
||||
b 19f
|
||||
10: RGBtoRGBPixelAlpha_1pixel_opaque WK0, WK2
|
||||
19: str WK2, [DST, #-4]
|
||||
.endif
|
||||
20:
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
BlitRGBtoRGBPixelAlphaARMSIMDAsm, 32, 0, 32, \
|
||||
FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS | FLAG_PROCESS_CORRUPTS_WK0, \
|
||||
2, /* prefetch distance */ \
|
||||
RGBtoRGBPixelAlpha_init, \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
RGBtoRGBPixelAlpha_process_head, \
|
||||
RGBtoRGBPixelAlpha_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro ARGBto565PixelAlpha_init
|
||||
line_saved_regs STRIDE_D, STRIDE_S, ORIG_W
|
||||
mov MASK, #0x001f
|
||||
mov STRIDE_M, #0x0010
|
||||
orr MASK, MASK, MASK, lsl #16
|
||||
orr STRIDE_M, STRIDE_M, STRIDE_M, lsl #16
|
||||
.endm
|
||||
|
||||
.macro ARGBto565PixelAlpha_newline
|
||||
mov STRIDE_S, #0x0200
|
||||
.endm
|
||||
|
||||
/* On entry:
|
||||
* s1 holds 1 32bpp source pixel
|
||||
* d holds 1 16bpp destination pixel
|
||||
* rbmask, rbhalf, ghalf hold 0x001f001f, 0x00100010, 0x00000200 respectively
|
||||
* other registers are temporaries
|
||||
* On exit:
|
||||
* Constant registers preserved
|
||||
*/
|
||||
|
||||
.macro ARGBto565PixelAlpha_1pixel_translucent s, d, rbmask, rbhalf, ghalf, alpha, rb, g, misc
|
||||
mov alpha, s, lsr #27
|
||||
and misc, s, #0xfc00
|
||||
and g, d, #0x07e0
|
||||
pkhbt rb, d, d, lsl #5
|
||||
rsb misc, g, misc, lsr #5
|
||||
and s, rbmask, s, lsr #3
|
||||
and rb, rbmask, rb
|
||||
sub s, s, rb
|
||||
smlabb misc, misc, alpha, ghalf
|
||||
mla s, s, alpha, rbhalf
|
||||
add misc, misc, misc, lsl #5
|
||||
add g, g, misc, asr #10
|
||||
add s, s, s, lsl #5
|
||||
and g, g, #0x07e0
|
||||
add rb, rb, s, asr #10
|
||||
and rb, rb, rbmask
|
||||
pkhbt rb, rb, rb, lsl #11
|
||||
orr d, rb, g
|
||||
orr d, d, rb, lsr #16
|
||||
.endm
|
||||
|
||||
/* On entry:
|
||||
* s1 holds 1 32bpp source pixel
|
||||
* d holds 1 16bpp destination pixel
|
||||
* rbmask holds 0x001f001f
|
||||
* On exit:
|
||||
* Constant registers preserved
|
||||
*/
|
||||
|
||||
.macro ARGBto565PixelAlpha_1pixel_opaque s, d, rbmask
|
||||
and d, rbmask, s, lsr #3
|
||||
and s, s, #0xfc00
|
||||
orr d, d, d, lsr #5
|
||||
orr d, d, s, lsr #5
|
||||
.endm
|
||||
|
||||
/* On entry:
|
||||
* s1, s2 hold 2 32bpp source pixels
|
||||
* d holds 2 16bpp destination pixels
|
||||
* rbmask, rbhalf, ghalf hold 0x001f001f, 0x00100010, 0x00000200 respectively
|
||||
* other registers are temporaries
|
||||
* On exit:
|
||||
* Constant registers preserved
|
||||
* Blended results have been written through destination pointer
|
||||
*/
|
||||
|
||||
.macro ARGBto565PixelAlpha_2pixels_translucent s1, s2, d, rbmask, rbhalf, ghalf, alpha, rb, g, misc
|
||||
mov alpha, s1, lsr #27
|
||||
and misc, s1, #0xfc00
|
||||
and g, d, #0x07e0
|
||||
pkhbt rb, d, d, lsl #5
|
||||
rsb misc, g, misc, lsr #5
|
||||
and s1, rbmask, s1, lsr #3
|
||||
and rb, rbmask, rb
|
||||
sub s1, s1, rb
|
||||
smlabb misc, misc, alpha, ghalf
|
||||
mla s1, s1, alpha, rbhalf
|
||||
uxth d, d, ror #16
|
||||
add misc, misc, misc, lsl #5
|
||||
mov alpha, s2, lsr #27
|
||||
add g, g, misc, asr #10
|
||||
add s1, s1, s1, lsl #5
|
||||
and g, g, #0x07e0
|
||||
add rb, rb, s1, asr #10
|
||||
and rb, rb, rbmask
|
||||
and misc, s2, #0xfc00
|
||||
pkhbt rb, rb, rb, lsl #11
|
||||
and s1, d, #0x07e0
|
||||
pkhbt d, d, d, lsl #5
|
||||
rsb misc, s1, misc, lsr #5
|
||||
and s2, rbmask, s2, lsr #3
|
||||
and d, rbmask, d
|
||||
sub s2, s2, d
|
||||
smlabb misc, misc, alpha, ghalf
|
||||
mla s2, s2, alpha, rbhalf
|
||||
orr alpha, rb, g
|
||||
add misc, misc, misc, lsl #5
|
||||
orr alpha, alpha, rb, lsr #16
|
||||
add s1, s1, misc, asr #10
|
||||
add s2, s2, s2, lsl #5
|
||||
and s1, s1, #0x07e0
|
||||
add d, d, s2, asr #10
|
||||
and d, d, rbmask
|
||||
strh alpha, [DST, #-4]
|
||||
pkhbt d, d, d, lsl #11
|
||||
orr alpha, d, s1
|
||||
orr alpha, alpha, d, lsr #16
|
||||
strh alpha, [DST, #-2]
|
||||
.endm
|
||||
|
||||
/* On entry:
|
||||
* s1, s2 hold 2 32bpp source pixels
|
||||
* rbmask holds 0x001f001f
|
||||
* other registers are temporaries
|
||||
* On exit:
|
||||
* Constant registers preserved
|
||||
* Blended results have been written through destination pointer
|
||||
*/
|
||||
|
||||
.macro ARGBto565PixelAlpha_2pixels_opaque s1, s2, d, rbmask, g
|
||||
and g, s1, #0xfc00
|
||||
and d, rbmask, s1, lsr #3
|
||||
and s1, rbmask, s2, lsr #3
|
||||
orr d, d, d, lsr #5
|
||||
orr d, d, g, lsr #5
|
||||
and g, s2, #0xfc00
|
||||
strh d, [DST, #-4]
|
||||
orr s1, s1, s1, lsr #5
|
||||
orr s1, s1, g, lsr #5
|
||||
strh s1, [DST, #-2]
|
||||
.endm
|
||||
|
||||
.macro ARGBto565PixelAlpha_2pixels_head
|
||||
ldrd WK0, WK1, [SRC], #8
|
||||
ldr WK2, [DST], #4
|
||||
orr SCRATCH, WK0, WK1
|
||||
and ORIG_W, WK0, WK1
|
||||
tst SCRATCH, #0xff000000
|
||||
.endm
|
||||
|
||||
.macro ARGBto565PixelAlpha_2pixels_tail
|
||||
beq 20f @ all transparent
|
||||
cmp ORIG_W, #0xff000000
|
||||
bhs 10f @ all opaque
|
||||
ARGBto565PixelAlpha_2pixels_translucent WK0, WK1, WK2, MASK, STRIDE_M, STRIDE_S, STRIDE_D, WK3, SCRATCH, ORIG_W
|
||||
b 20f
|
||||
10: ARGBto565PixelAlpha_2pixels_opaque WK0, WK1, WK2, MASK, SCRATCH
|
||||
20:
|
||||
.endm
|
||||
|
||||
.macro ARGBto565PixelAlpha_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
.if numbytes == 16
|
||||
ARGBto565PixelAlpha_2pixels_head
|
||||
ARGBto565PixelAlpha_2pixels_tail
|
||||
ARGBto565PixelAlpha_2pixels_head
|
||||
ARGBto565PixelAlpha_2pixels_tail
|
||||
.endif
|
||||
.if numbytes >= 8
|
||||
ARGBto565PixelAlpha_2pixels_head
|
||||
ARGBto565PixelAlpha_2pixels_tail
|
||||
.endif
|
||||
.if numbytes >= 4
|
||||
ARGBto565PixelAlpha_2pixels_head
|
||||
.else // numbytes == 2
|
||||
ldr WK0, [SRC], #4
|
||||
ldrh WK2, [DST], #2
|
||||
tst WK0, #0xff000000
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro ARGBto565PixelAlpha_process_tail cond, numbytes, firstreg
|
||||
.if numbytes >= 4
|
||||
ARGBto565PixelAlpha_2pixels_tail
|
||||
.else // numbytes == 2
|
||||
beq 20f @ all transparent
|
||||
cmp WK0, #0xff000000
|
||||
bhs 10f @ opaque
|
||||
ARGBto565PixelAlpha_1pixel_translucent WK0, WK2, MASK, STRIDE_M, STRIDE_S, STRIDE_D, WK3, SCRATCH, ORIG_W
|
||||
b 19f
|
||||
10: ARGBto565PixelAlpha_1pixel_opaque WK0, WK2, MASK
|
||||
19: strh WK2, [DST, #-2]
|
||||
20:
|
||||
.endif
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
BlitARGBto565PixelAlphaARMSIMDAsm, 32, 0, 16, \
|
||||
FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS | FLAG_PROCESS_CORRUPTS_WK0, \
|
||||
2, /* prefetch distance */ \
|
||||
ARGBto565PixelAlpha_init, \
|
||||
ARGBto565PixelAlpha_newline, \
|
||||
nop_macro, /* cleanup */ \
|
||||
ARGBto565PixelAlpha_process_head, \
|
||||
ARGBto565PixelAlpha_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro BGR888toRGB888_1pixel cond, reg, tmp
|
||||
uxtb16&cond tmp, WK®, ror #8
|
||||
uxtb16&cond WK®, WK®, ror #16
|
||||
orr&cond WK®, WK®, tmp, lsl #8
|
||||
.endm
|
||||
|
||||
.macro BGR888toRGB888_2pixels cond, reg1, reg2, tmp1, tmp2
|
||||
uxtb16&cond tmp1, WK®1, ror #8
|
||||
uxtb16&cond WK®1, WK®1, ror #16
|
||||
uxtb16&cond tmp2, WK®2, ror #8
|
||||
uxtb16&cond WK®2, WK®2, ror #16
|
||||
orr&cond WK®1, WK®1, tmp1, lsl #8
|
||||
orr&cond WK®2, WK®2, tmp2, lsl #8
|
||||
.endm
|
||||
|
||||
.macro BGR888toRGB888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
pixld cond, numbytes, firstreg, SRC, unaligned_src
|
||||
.endm
|
||||
|
||||
.macro BGR888toRGB888_process_tail cond, numbytes, firstreg
|
||||
.if numbytes >= 8
|
||||
BGR888toRGB888_2pixels cond, %(firstreg+0), %(firstreg+1), MASK, STRIDE_M
|
||||
.if numbytes == 16
|
||||
BGR888toRGB888_2pixels cond, %(firstreg+2), %(firstreg+3), MASK, STRIDE_M
|
||||
.endif
|
||||
.else @ numbytes == 4
|
||||
BGR888toRGB888_1pixel cond, %(firstreg+0), MASK
|
||||
.endif
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
Blit_XBGR8888_XRGB8888ARMSIMDAsm, 32, 0, 32, \
|
||||
FLAG_DST_WRITEONLY | FLAG_COND_EXEC | FLAG_PROCESS_PRESERVES_SCRATCH, \
|
||||
2, /* prefetch distance */ \
|
||||
nop_macro, /* init */ \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
BGR888toRGB888_process_head, \
|
||||
BGR888toRGB888_process_tail
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.macro RGB444toRGB888_init
|
||||
ldr MASK, =0x0f0f0f0f
|
||||
/* Set GE[3:0] to 0101 so SEL instructions do what we want */
|
||||
msr CPSR_s, #0x50000
|
||||
.endm
|
||||
|
||||
.macro RGB444toRGB888_1pixel reg, mask, tmp
|
||||
pkhbt WK®, WK®, WK®, lsl #12 @ 0000aaaarrrrggggaaaarrrrggggbbbb
|
||||
and WK®, mask, WK® @ 0000aaaa0000gggg0000rrrr0000bbbb
|
||||
orr WK®, WK®, WK®, lsl #4 @ aaaaaaaaggggggggrrrrrrrrbbbbbbbb
|
||||
pkhtb tmp, WK®, WK®, asr #8 @ aaaaaaaaggggggggggggggggrrrrrrrr
|
||||
pkhbt WK®, WK®, WK®, lsl #8 @ ggggggggrrrrrrrrrrrrrrrrbbbbbbbb
|
||||
sel WK®, WK®, tmp @ aaaaaaaarrrrrrrrggggggggbbbbbbbb
|
||||
.endm
|
||||
|
||||
.macro RGB444toRGB888_2pixels in, out1, out2, mask, tmp1, tmp2
|
||||
and tmp1, mask, WK&in @ 0000RRRR0000BBBB0000rrrr0000bbbb
|
||||
and tmp2, mask, WK&in, lsr #4 @ 0000AAAA0000GGGG0000aaaa0000gggg
|
||||
orr tmp1, tmp1, tmp1, lsl #4 @ RRRRRRRRBBBBBBBBrrrrrrrrbbbbbbbb
|
||||
orr tmp2, tmp2, tmp2, lsl #4 @ AAAAAAAAGGGGGGGGaaaaaaaagggggggg
|
||||
pkhtb WK&out2, tmp2, tmp1, asr #16 @ AAAAAAAAGGGGGGGGRRRRRRRRBBBBBBBB
|
||||
pkhbt WK&out1, tmp1, tmp2, lsl #16 @ aaaaaaaaggggggggrrrrrrrrbbbbbbbb
|
||||
pkhtb tmp2, WK&out2, WK&out2, asr #8 @ AAAAAAAAGGGGGGGGGGGGGGGGRRRRRRRR
|
||||
pkhtb tmp1, WK&out1, WK&out1, asr #8 @ aaaaaaaaggggggggggggggggrrrrrrrr
|
||||
pkhbt WK&out1, WK&out1, WK&out1, lsl #8 @ ggggggggrrrrrrrrrrrrrrrrbbbbbbbb
|
||||
pkhbt WK&out2, WK&out2, WK&out2, lsl #8 @ GGGGGGGGRRRRRRRRRRRRRRRRBBBBBBBB
|
||||
sel WK&out1, WK&out1, tmp1 @ aaaaaaaarrrrrrrrggggggggbbbbbbbb
|
||||
sel WK&out2, WK&out2, tmp2 @ AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB
|
||||
.endm
|
||||
|
||||
.macro RGB444toRGB888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload
|
||||
pixld cond, numbytes/2, firstreg, SRC, unaligned_src
|
||||
.endm
|
||||
|
||||
.macro RGB444toRGB888_process_tail cond, numbytes, firstreg
|
||||
.if numbytes >= 8
|
||||
.if numbytes == 16
|
||||
RGB444toRGB888_2pixels %(firstreg+1), %(firstreg+2), %(firstreg+3), MASK, STRIDE_M, SCRATCH
|
||||
.endif
|
||||
RGB444toRGB888_2pixels %(firstreg+0), %(firstreg+0), %(firstreg+1), MASK, STRIDE_M, SCRATCH
|
||||
.else @ numbytes == 4
|
||||
RGB444toRGB888_1pixel %(firstreg+0), MASK, SCRATCH
|
||||
.endif
|
||||
.endm
|
||||
|
||||
generate_composite_function \
|
||||
Blit_RGB444_XRGB8888ARMSIMDAsm, 16, 0, 32, \
|
||||
FLAG_DST_WRITEONLY | FLAG_BRANCH_OVER, \
|
||||
2, /* prefetch distance */ \
|
||||
RGB444toRGB888_init, \
|
||||
nop_macro, /* newline */ \
|
||||
nop_macro, /* cleanup */ \
|
||||
RGB444toRGB888_process_head, \
|
||||
RGB444toRGB888_process_tail
|
1034
external/sdl/SDL/src/video/arm/pixman-arm-simd-asm.h
vendored
Normal file
1034
external/sdl/SDL/src/video/arm/pixman-arm-simd-asm.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
37
external/sdl/SDL/src/video/cocoa/SDL_cocoaclipboard.h
vendored
Normal file
37
external/sdl/SDL/src/video/cocoa/SDL_cocoaclipboard.h
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoaclipboard_h_
|
||||
#define SDL_cocoaclipboard_h_
|
||||
|
||||
/* Forward declaration */
|
||||
@class SDL_CocoaVideoData;
|
||||
|
||||
extern int Cocoa_SetClipboardText(SDL_VideoDevice *_this, const char *text);
|
||||
extern char *Cocoa_GetClipboardText(SDL_VideoDevice *_this);
|
||||
extern SDL_bool Cocoa_HasClipboardText(SDL_VideoDevice *_this);
|
||||
extern void Cocoa_CheckClipboardUpdate(SDL_CocoaVideoData *data);
|
||||
extern int Cocoa_SetClipboardData(SDL_VideoDevice *_this);
|
||||
extern void *Cocoa_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *size);
|
||||
extern SDL_bool Cocoa_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type);
|
||||
|
||||
#endif /* SDL_cocoaclipboard_h_ */
|
178
external/sdl/SDL/src/video/cocoa/SDL_cocoaclipboard.m
vendored
Normal file
178
external/sdl/SDL/src/video/cocoa/SDL_cocoaclipboard.m
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_COCOA
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "../../events/SDL_clipboardevents_c.h"
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101300
|
||||
typedef NSString *NSPasteboardType; /* Defined in macOS 10.13+ */
|
||||
#endif
|
||||
|
||||
@interface Cocoa_PasteboardDataProvider : NSObject<NSPasteboardItemDataProvider>
|
||||
{
|
||||
SDL_ClipboardDataCallback m_callback;
|
||||
void *m_userdata;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation Cocoa_PasteboardDataProvider
|
||||
|
||||
- (nullable instancetype)initWith:(SDL_ClipboardDataCallback)callback
|
||||
userData:(void *)userdata
|
||||
{
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
m_callback = callback;
|
||||
m_userdata = userdata;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)pasteboard:(NSPasteboard *)pasteboard
|
||||
item:(NSPasteboardItem *)item
|
||||
provideDataForType:(NSPasteboardType)type
|
||||
{
|
||||
@autoreleasepool {
|
||||
size_t size = 0;
|
||||
CFStringRef mimeType;
|
||||
const void *callbackData;
|
||||
NSData *data;
|
||||
mimeType = UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)type, kUTTagClassMIMEType);
|
||||
callbackData = m_callback(m_userdata, [(__bridge NSString *)mimeType UTF8String], &size);
|
||||
CFRelease(mimeType);
|
||||
if (callbackData == NULL || size == 0) {
|
||||
return;
|
||||
}
|
||||
data = [NSData dataWithBytes: callbackData length: size];
|
||||
[item setData: data forType: type];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
void Cocoa_CheckClipboardUpdate(SDL_CocoaVideoData *data)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSPasteboard *pasteboard;
|
||||
NSInteger count;
|
||||
|
||||
pasteboard = [NSPasteboard generalPasteboard];
|
||||
count = [pasteboard changeCount];
|
||||
if (count != data.clipboard_count) {
|
||||
if (data.clipboard_count) {
|
||||
SDL_SendClipboardUpdate();
|
||||
}
|
||||
data.clipboard_count = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_SetClipboardData(SDL_VideoDevice *_this)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata;
|
||||
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
||||
NSPasteboardItem *newItem = [NSPasteboardItem new];
|
||||
NSMutableArray *utiTypes = [NSMutableArray new];
|
||||
Cocoa_PasteboardDataProvider *provider = [[Cocoa_PasteboardDataProvider alloc] initWith: _this->clipboard_callback userData: _this->clipboard_userdata];
|
||||
BOOL itemResult = FALSE;
|
||||
BOOL writeResult = FALSE;
|
||||
|
||||
if (_this->clipboard_callback) {
|
||||
for (int i = 0; i < _this->num_clipboard_mime_types; i++) {
|
||||
CFStringRef mimeType = CFStringCreateWithCString(NULL, _this->clipboard_mime_types[i], kCFStringEncodingUTF8);
|
||||
CFStringRef utiType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
|
||||
CFRelease(mimeType);
|
||||
|
||||
[utiTypes addObject: (__bridge NSString *)utiType];
|
||||
CFRelease(utiType);
|
||||
}
|
||||
itemResult = [newItem setDataProvider: provider forTypes: utiTypes];
|
||||
if (itemResult == FALSE) {
|
||||
return SDL_SetError("Unable to set clipboard item data");
|
||||
}
|
||||
|
||||
[pasteboard clearContents];
|
||||
writeResult = [pasteboard writeObjects: @[newItem]];
|
||||
if (writeResult == FALSE) {
|
||||
return SDL_SetError("Unable to set clipboard data");
|
||||
}
|
||||
} else {
|
||||
[pasteboard clearContents];
|
||||
}
|
||||
data.clipboard_count = [pasteboard changeCount];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *Cocoa_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *size)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
||||
void *data = NULL;
|
||||
*size = 0;
|
||||
for (NSPasteboardItem *item in [pasteboard pasteboardItems]) {
|
||||
NSData *itemData;
|
||||
CFStringRef mimeType = CFStringCreateWithCString(NULL, mime_type, kCFStringEncodingUTF8);
|
||||
CFStringRef utiType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
|
||||
CFRelease(mimeType);
|
||||
itemData = [item dataForType: (__bridge NSString *)utiType];
|
||||
CFRelease(utiType);
|
||||
if (itemData != nil) {
|
||||
NSUInteger length = [itemData length];
|
||||
*size = (size_t)length;
|
||||
data = SDL_malloc(*size + sizeof(Uint32));
|
||||
if (data) {
|
||||
[itemData getBytes: data length: length];
|
||||
SDL_memset((Uint8 *)data + length, 0, sizeof(Uint32));
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool Cocoa_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type)
|
||||
{
|
||||
SDL_bool result = SDL_FALSE;
|
||||
@autoreleasepool {
|
||||
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
||||
CFStringRef mimeType = CFStringCreateWithCString(NULL, mime_type, kCFStringEncodingUTF8);
|
||||
CFStringRef utiType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
|
||||
CFRelease(mimeType);
|
||||
if ([pasteboard canReadItemWithDataConformingToTypes: @[(__bridge NSString *)utiType]]) {
|
||||
result = SDL_TRUE;
|
||||
}
|
||||
CFRelease(utiType);
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
33
external/sdl/SDL/src/video/cocoa/SDL_cocoaevents.h
vendored
Normal file
33
external/sdl/SDL/src/video/cocoa/SDL_cocoaevents.h
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoaevents_h_
|
||||
#define SDL_cocoaevents_h_
|
||||
|
||||
extern void Cocoa_RegisterApp(void);
|
||||
extern Uint64 Cocoa_GetEventTimestamp(NSTimeInterval nsTimestamp);
|
||||
extern void Cocoa_PumpEvents(SDL_VideoDevice *_this);
|
||||
extern int Cocoa_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS);
|
||||
extern void Cocoa_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int Cocoa_SuspendScreenSaver(SDL_VideoDevice *_this);
|
||||
|
||||
#endif /* SDL_cocoaevents_h_ */
|
616
external/sdl/SDL/src/video/cocoa/SDL_cocoaevents.m
vendored
Normal file
616
external/sdl/SDL/src/video/cocoa/SDL_cocoaevents.m
vendored
Normal file
@ -0,0 +1,616 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_COCOA
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#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 = ((__bridge SDL_CocoaWindowData *)sdlwindow->driverdata).nswindow;
|
||||
if (win == nswindow) {
|
||||
return sdlwindow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sdlwindow;
|
||||
}
|
||||
|
||||
@interface SDLApplication : NSApplication
|
||||
|
||||
- (void)terminate:(id)sender;
|
||||
- (void)sendEvent:(NSEvent *)theEvent;
|
||||
|
||||
+ (void)registerUserDefaults;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDLApplication
|
||||
|
||||
// Override terminate to handle Quit and System Shutdown smoothly.
|
||||
- (void)terminate:(id)sender
|
||||
{
|
||||
SDL_SendQuit();
|
||||
}
|
||||
|
||||
static SDL_bool s_bShouldHandleEventsInSDLApplication = SDL_FALSE;
|
||||
|
||||
static void Cocoa_DispatchEvent(NSEvent *theEvent)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
switch ([theEvent type]) {
|
||||
case NSEventTypeLeftMouseDown:
|
||||
case NSEventTypeOtherMouseDown:
|
||||
case NSEventTypeRightMouseDown:
|
||||
case NSEventTypeLeftMouseUp:
|
||||
case NSEventTypeOtherMouseUp:
|
||||
case NSEventTypeRightMouseUp:
|
||||
case NSEventTypeLeftMouseDragged:
|
||||
case NSEventTypeRightMouseDragged:
|
||||
case NSEventTypeOtherMouseDragged: /* usually middle mouse dragged */
|
||||
case NSEventTypeMouseMoved:
|
||||
case NSEventTypeScrollWheel:
|
||||
Cocoa_HandleMouseEvent(_this, theEvent);
|
||||
break;
|
||||
case NSEventTypeKeyDown:
|
||||
case NSEventTypeKeyUp:
|
||||
case NSEventTypeFlagsChanged:
|
||||
Cocoa_HandleKeyEvent(_this, theEvent);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch events here so that we can handle events caught by
|
||||
// nextEventMatchingMask in SDL, as well as events caught by other
|
||||
// processes (such as CEF) that are passed down to NSApp.
|
||||
- (void)sendEvent:(NSEvent *)theEvent
|
||||
{
|
||||
if (s_bShouldHandleEventsInSDLApplication) {
|
||||
Cocoa_DispatchEvent(theEvent);
|
||||
}
|
||||
|
||||
[super sendEvent:theEvent];
|
||||
}
|
||||
|
||||
+ (void)registerUserDefaults
|
||||
{
|
||||
NSDictionary *appDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:
|
||||
[NSNumber numberWithBool:NO], @"AppleMomentumScrollSupported",
|
||||
[NSNumber numberWithBool:NO], @"ApplePressAndHoldEnabled",
|
||||
[NSNumber numberWithBool:YES], @"ApplePersistenceIgnoreState",
|
||||
nil];
|
||||
[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
|
||||
}
|
||||
|
||||
@end // SDLApplication
|
||||
|
||||
/* setAppleMenu disappeared from the headers in 10.4 */
|
||||
@interface NSApplication (NSAppleMenu)
|
||||
- (void)setAppleMenu:(NSMenu *)menu;
|
||||
@end
|
||||
|
||||
@interface SDLAppDelegate : NSObject <NSApplicationDelegate>
|
||||
{
|
||||
@public
|
||||
BOOL seenFirstActivate;
|
||||
}
|
||||
|
||||
- (id)init;
|
||||
- (void)localeDidChange:(NSNotification *)notification;
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||
ofObject:(id)object
|
||||
change:(NSDictionary *)change
|
||||
context:(void *)context;
|
||||
@end
|
||||
|
||||
@implementation SDLAppDelegate : NSObject
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||
|
||||
seenFirstActivate = NO;
|
||||
|
||||
[center addObserver:self
|
||||
selector:@selector(windowWillClose:)
|
||||
name:NSWindowWillCloseNotification
|
||||
object:nil];
|
||||
|
||||
[center addObserver:self
|
||||
selector:@selector(focusSomeWindow:)
|
||||
name:NSApplicationDidBecomeActiveNotification
|
||||
object:nil];
|
||||
|
||||
[center addObserver:self
|
||||
selector:@selector(localeDidChange:)
|
||||
name:NSCurrentLocaleDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
[NSApp addObserver:self
|
||||
forKeyPath:@"effectiveAppearance"
|
||||
options:NSKeyValueObservingOptionInitial
|
||||
context:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
||||
|
||||
[center removeObserver:self name:NSWindowWillCloseNotification object:nil];
|
||||
[center removeObserver:self name:NSApplicationDidBecomeActiveNotification object:nil];
|
||||
[center removeObserver:self name:NSCurrentLocaleDidChangeNotification object:nil];
|
||||
[NSApp removeObserver:self forKeyPath:@"effectiveAppearance"];
|
||||
|
||||
/* Remove our URL event handler only if we set it */
|
||||
if ([NSApp delegate] == self) {
|
||||
[[NSAppleEventManager sharedAppleEventManager]
|
||||
removeEventHandlerForEventClass:kInternetEventClass
|
||||
andEventID:kAEGetURL];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)windowWillClose:(NSNotification *)notification;
|
||||
{
|
||||
NSWindow *win = (NSWindow *)[notification object];
|
||||
|
||||
if (![win isKeyWindow]) {
|
||||
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
|
||||
*/
|
||||
|
||||
/* +[NSApp orderedWindows] never includes the 'About' window, but we still
|
||||
* want to try its list first since the behavior in other apps is to only
|
||||
* make the 'About' window key if no other windows are on-screen.
|
||||
*/
|
||||
for (NSWindow *window in [NSApp orderedWindows]) {
|
||||
if (window != win && [window canBecomeKeyWindow]) {
|
||||
if (![window isOnActiveSpace]) {
|
||||
continue;
|
||||
}
|
||||
[window makeKeyAndOrderFront:self];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If a window wasn't found above, iterate through all visible windows in
|
||||
* the active Space in z-order (including the 'About' window, if it's shown)
|
||||
* and make the first one key.
|
||||
*/
|
||||
for (NSNumber *num in [NSWindow windowNumbersWithOptions:0]) {
|
||||
NSWindow *window = [NSApp windowWithWindowNumber:[num integerValue]];
|
||||
if (window && window != win && [window canBecomeKeyWindow]) {
|
||||
[window makeKeyAndOrderFront:self];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)focusSomeWindow:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_VideoDevice *device;
|
||||
/* HACK: Ignore the first call. The application gets a
|
||||
* applicationDidBecomeActive: a little bit after the first window is
|
||||
* created, and if we don't ignore it, a window that has been created with
|
||||
* SDL_WINDOW_MINIMIZED will ~immediately be restored.
|
||||
*/
|
||||
if (!seenFirstActivate) {
|
||||
seenFirstActivate = YES;
|
||||
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;
|
||||
}
|
||||
|
||||
device = SDL_GetVideoDevice();
|
||||
if (device && device->windows) {
|
||||
SDL_Window *window = device->windows;
|
||||
int i;
|
||||
for (i = 0; i < device->num_displays; ++i) {
|
||||
SDL_Window *fullscreen_window = device->displays[i].fullscreen_window;
|
||||
if (fullscreen_window) {
|
||||
if (fullscreen_window->flags & SDL_WINDOW_MINIMIZED) {
|
||||
SDL_RestoreWindow(fullscreen_window);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (window->flags & SDL_WINDOW_MINIMIZED) {
|
||||
SDL_RestoreWindow(window);
|
||||
} else {
|
||||
SDL_RaiseWindow(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)localeDidChange:(NSNotification *)notification
|
||||
{
|
||||
SDL_SendLocaleChangedEvent();
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||
ofObject:(id)object
|
||||
change:(NSDictionary *)change
|
||||
context:(void *)context
|
||||
{
|
||||
SDL_SetSystemTheme(Cocoa_GetSystemTheme());
|
||||
}
|
||||
|
||||
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
|
||||
{
|
||||
return (BOOL)SDL_SendDropFile(NULL, [filename UTF8String]) && SDL_SendDropComplete(NULL);
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
||||
{
|
||||
/* The menu bar of SDL apps which don't have the typical .app bundle
|
||||
* structure fails to work the first time a window is created (until it's
|
||||
* de-focused and re-focused), if this call is in Cocoa_RegisterApp instead
|
||||
* of here. https://bugzilla.libsdl.org/show_bug.cgi?id=3051
|
||||
*/
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_MAC_BACKGROUND_APP, SDL_FALSE)) {
|
||||
/* Get more aggressive for Catalina: activate the Dock first so we definitely reset all activation state. */
|
||||
for (NSRunningApplication *i in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) {
|
||||
[i activateWithOptions:NSApplicationActivateIgnoringOtherApps];
|
||||
break;
|
||||
}
|
||||
SDL_Delay(300); /* !!! FIXME: this isn't right. */
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
}
|
||||
|
||||
/* If we call this before NSApp activation, macOS might print a complaint
|
||||
* about ApplePersistenceIgnoreState. */
|
||||
[SDLApplication registerUserDefaults];
|
||||
}
|
||||
|
||||
- (void)handleURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
|
||||
{
|
||||
NSString *path = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
|
||||
SDL_SendDropFile(NULL, [path UTF8String]);
|
||||
SDL_SendDropComplete(NULL);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static SDLAppDelegate *appDelegate = nil;
|
||||
|
||||
static NSString *GetApplicationName(void)
|
||||
{
|
||||
NSString *appName;
|
||||
|
||||
/* Determine the application name */
|
||||
appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
|
||||
if (!appName) {
|
||||
appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
|
||||
}
|
||||
|
||||
if (![appName length]) {
|
||||
appName = [[NSProcessInfo processInfo] processName];
|
||||
}
|
||||
|
||||
return appName;
|
||||
}
|
||||
|
||||
static bool LoadMainMenuNibIfAvailable(void)
|
||||
{
|
||||
NSDictionary *infoDict;
|
||||
NSString *mainNibFileName;
|
||||
bool success = false;
|
||||
|
||||
infoDict = [[NSBundle mainBundle] infoDictionary];
|
||||
if (infoDict) {
|
||||
mainNibFileName = [infoDict valueForKey:@"NSMainNibFile"];
|
||||
|
||||
if (mainNibFileName) {
|
||||
success = [[NSBundle mainBundle] loadNibNamed:mainNibFileName owner:[NSApplication sharedApplication] topLevelObjects:nil];
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void CreateApplicationMenus(void)
|
||||
{
|
||||
NSString *appName;
|
||||
NSString *title;
|
||||
NSMenu *appleMenu;
|
||||
NSMenu *serviceMenu;
|
||||
NSMenu *windowMenu;
|
||||
NSMenuItem *menuItem;
|
||||
NSMenu *mainMenu;
|
||||
|
||||
if (NSApp == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
mainMenu = [[NSMenu alloc] init];
|
||||
|
||||
/* Create the main menu bar */
|
||||
[NSApp setMainMenu:mainMenu];
|
||||
|
||||
/* Create the application menu */
|
||||
appName = GetApplicationName();
|
||||
appleMenu = [[NSMenu alloc] initWithTitle:@""];
|
||||
|
||||
/* Add menu items */
|
||||
title = [@"About " stringByAppendingString:appName];
|
||||
[appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
|
||||
|
||||
[appleMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
[appleMenu addItemWithTitle:@"Preferences…" action:nil keyEquivalent:@","];
|
||||
|
||||
[appleMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
serviceMenu = [[NSMenu alloc] initWithTitle:@""];
|
||||
menuItem = [appleMenu addItemWithTitle:@"Services" action:nil keyEquivalent:@""];
|
||||
[menuItem setSubmenu:serviceMenu];
|
||||
|
||||
[NSApp setServicesMenu:serviceMenu];
|
||||
|
||||
[appleMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
title = [@"Hide " stringByAppendingString:appName];
|
||||
[appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
|
||||
|
||||
menuItem = [appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
|
||||
[menuItem setKeyEquivalentModifierMask:(NSEventModifierFlagOption | NSEventModifierFlagCommand)];
|
||||
|
||||
[appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
|
||||
|
||||
[appleMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
title = [@"Quit " stringByAppendingString:appName];
|
||||
[appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
|
||||
|
||||
/* Put menu into the menubar */
|
||||
menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
|
||||
[menuItem setSubmenu:appleMenu];
|
||||
[[NSApp mainMenu] addItem:menuItem];
|
||||
|
||||
/* Tell the application object that this is now the application menu */
|
||||
[NSApp setAppleMenu:appleMenu];
|
||||
|
||||
/* Create the window menu */
|
||||
windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
|
||||
|
||||
/* Add menu items */
|
||||
[windowMenu addItemWithTitle:@"Close" action:@selector(performClose:) keyEquivalent:@"w"];
|
||||
|
||||
[windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
|
||||
|
||||
[windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
|
||||
|
||||
/* Add the fullscreen toggle menu option. */
|
||||
/* Cocoa should update the title to Enter or Exit Full Screen automatically.
|
||||
* But if not, then just fallback to Toggle Full Screen.
|
||||
*/
|
||||
menuItem = [[NSMenuItem alloc] initWithTitle:@"Toggle Full Screen" action:@selector(toggleFullScreen:) keyEquivalent:@"f"];
|
||||
[menuItem setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
|
||||
[windowMenu addItem:menuItem];
|
||||
|
||||
/* Put menu into the menubar */
|
||||
menuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
|
||||
[menuItem setSubmenu:windowMenu];
|
||||
[[NSApp mainMenu] addItem:menuItem];
|
||||
|
||||
/* Tell the application object that this is now the window menu */
|
||||
[NSApp setWindowsMenu:windowMenu];
|
||||
}
|
||||
|
||||
void Cocoa_RegisterApp(void)
|
||||
{
|
||||
@autoreleasepool {
|
||||
/* This can get called more than once! Be careful what you initialize! */
|
||||
|
||||
if (NSApp == nil) {
|
||||
[SDLApplication sharedApplication];
|
||||
SDL_assert(NSApp != nil);
|
||||
|
||||
s_bShouldHandleEventsInSDLApplication = SDL_TRUE;
|
||||
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_MAC_BACKGROUND_APP, SDL_FALSE)) {
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
}
|
||||
|
||||
/* If there aren't already menus in place, look to see if there's
|
||||
* a nib we should use. If not, then manually create the basic
|
||||
* menus we meed.
|
||||
*/
|
||||
if ([NSApp mainMenu] == nil) {
|
||||
bool nibLoaded;
|
||||
|
||||
nibLoaded = LoadMainMenuNibIfAvailable();
|
||||
if (!nibLoaded) {
|
||||
CreateApplicationMenus();
|
||||
}
|
||||
}
|
||||
[NSApp finishLaunching];
|
||||
if ([NSApp delegate]) {
|
||||
/* The SDL app delegate calls this in didFinishLaunching if it's
|
||||
* attached to the NSApp, otherwise we need to call it manually.
|
||||
*/
|
||||
[SDLApplication registerUserDefaults];
|
||||
}
|
||||
}
|
||||
if (NSApp && !appDelegate) {
|
||||
appDelegate = [[SDLAppDelegate alloc] init];
|
||||
|
||||
/* If someone else has an app delegate, it means we can't turn a
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Uint64 Cocoa_GetEventTimestamp(NSTimeInterval nsTimestamp)
|
||||
{
|
||||
static Uint64 timestamp_offset;
|
||||
Uint64 timestamp = (Uint64)(nsTimestamp * SDL_NS_PER_SECOND);
|
||||
Uint64 now = SDL_GetTicksNS();
|
||||
|
||||
if (!timestamp_offset) {
|
||||
timestamp_offset = (now - timestamp);
|
||||
}
|
||||
timestamp += timestamp_offset;
|
||||
|
||||
if (timestamp > now) {
|
||||
timestamp_offset -= (timestamp - now);
|
||||
timestamp = now;
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
int Cocoa_PumpEventsUntilDate(SDL_VideoDevice *_this, NSDate *expiration, bool accumulate)
|
||||
{
|
||||
for (;;) {
|
||||
NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:expiration inMode:NSDefaultRunLoopMode dequeue:YES];
|
||||
if (event == nil) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s_bShouldHandleEventsInSDLApplication) {
|
||||
Cocoa_DispatchEvent(event);
|
||||
}
|
||||
|
||||
// Pass events down to SDLApplication to be handled in sendEvent:
|
||||
[NSApp sendEvent:event];
|
||||
if (!accumulate) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Cocoa_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS)
|
||||
{
|
||||
@autoreleasepool {
|
||||
if (timeoutNS > 0) {
|
||||
NSDate *limitDate = [NSDate dateWithTimeIntervalSinceNow:(double)timeoutNS / SDL_NS_PER_SECOND];
|
||||
return Cocoa_PumpEventsUntilDate(_this, limitDate, false);
|
||||
} else if (timeoutNS == 0) {
|
||||
return Cocoa_PumpEventsUntilDate(_this, [NSDate distantPast], false);
|
||||
} else {
|
||||
while (Cocoa_PumpEventsUntilDate(_this, [NSDate distantFuture], false) == 0) {
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Cocoa_PumpEvents(SDL_VideoDevice *_this)
|
||||
{
|
||||
@autoreleasepool {
|
||||
Cocoa_PumpEventsUntilDate(_this, [NSDate distantPast], true);
|
||||
}
|
||||
}
|
||||
|
||||
void Cocoa_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSEvent *event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
|
||||
location:NSMakePoint(0, 0)
|
||||
modifierFlags:0
|
||||
timestamp:0.0
|
||||
windowNumber:((__bridge SDL_CocoaWindowData *)window->driverdata).window_number
|
||||
context:nil
|
||||
subtype:0
|
||||
data1:0
|
||||
data2:0];
|
||||
|
||||
[NSApp postEvent:event atStart:YES];
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_SuspendScreenSaver(SDL_VideoDevice *_this)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata;
|
||||
|
||||
if (data.screensaver_assertion) {
|
||||
IOPMAssertionRelease(data.screensaver_assertion);
|
||||
data.screensaver_assertion = kIOPMNullAssertionID;
|
||||
}
|
||||
|
||||
if (_this->suspend_screensaver) {
|
||||
/* FIXME: this should ideally describe the real reason why the game
|
||||
* called SDL_DisableScreenSaver. Note that the name is only meant to be
|
||||
* seen by macOS power users. there's an additional optional human-readable
|
||||
* (localized) reason parameter which we don't set.
|
||||
*/
|
||||
IOPMAssertionID assertion = kIOPMNullAssertionID;
|
||||
NSString *name = [GetApplicationName() stringByAppendingString:@" using SDL_DisableScreenSaver"];
|
||||
IOPMAssertionCreateWithDescription(kIOPMAssertPreventUserIdleDisplaySleep,
|
||||
(__bridge CFStringRef)name,
|
||||
NULL, NULL, NULL, 0, NULL,
|
||||
&assertion);
|
||||
data.screensaver_assertion = assertion;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
36
external/sdl/SDL/src/video/cocoa/SDL_cocoakeyboard.h
vendored
Normal file
36
external/sdl/SDL/src/video/cocoa/SDL_cocoakeyboard.h
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoakeyboard_h_
|
||||
#define SDL_cocoakeyboard_h_
|
||||
|
||||
extern void Cocoa_InitKeyboard(SDL_VideoDevice *_this);
|
||||
extern void Cocoa_HandleKeyEvent(SDL_VideoDevice *_this, NSEvent *event);
|
||||
extern void Cocoa_QuitKeyboard(SDL_VideoDevice *_this);
|
||||
|
||||
extern void Cocoa_StartTextInput(SDL_VideoDevice *_this);
|
||||
extern void Cocoa_StopTextInput(SDL_VideoDevice *_this);
|
||||
extern int Cocoa_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect);
|
||||
|
||||
extern void Cocoa_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
|
||||
|
||||
#endif /* SDL_cocoakeyboard_h_ */
|
467
external/sdl/SDL/src/video/cocoa/SDL_cocoakeyboard.m
vendored
Normal file
467
external/sdl/SDL/src/video/cocoa/SDL_cocoakeyboard.m
vendored
Normal file
@ -0,0 +1,467 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_COCOA
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/scancodes_darwin.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
/*#define DEBUG_IME NSLog */
|
||||
#define DEBUG_IME(...)
|
||||
|
||||
@interface SDLTranslatorResponder : NSView <NSTextInputClient>
|
||||
{
|
||||
NSString *_markedText;
|
||||
NSRange _markedRange;
|
||||
NSRange _selectedRange;
|
||||
SDL_Rect _inputRect;
|
||||
}
|
||||
- (void)doCommandBySelector:(SEL)myselector;
|
||||
- (void)setInputRect:(const SDL_Rect *)rect;
|
||||
@end
|
||||
|
||||
@implementation SDLTranslatorResponder
|
||||
|
||||
- (void)setInputRect:(const SDL_Rect *)rect
|
||||
{
|
||||
_inputRect = *rect;
|
||||
}
|
||||
|
||||
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
|
||||
{
|
||||
/* TODO: Make use of replacementRange? */
|
||||
|
||||
const char *str;
|
||||
|
||||
DEBUG_IME(@"insertText: %@", aString);
|
||||
|
||||
/* Could be NSString or NSAttributedString, so we have
|
||||
* to test and convert it before return as SDL event */
|
||||
if ([aString isKindOfClass:[NSAttributedString class]]) {
|
||||
str = [[aString string] UTF8String];
|
||||
} else {
|
||||
str = [aString UTF8String];
|
||||
}
|
||||
|
||||
/* We're likely sending the composed text, so we reset the IME status. */
|
||||
if ([self hasMarkedText]) {
|
||||
[self unmarkText];
|
||||
}
|
||||
|
||||
SDL_SendKeyboardText(str);
|
||||
}
|
||||
|
||||
- (void)doCommandBySelector:(SEL)myselector
|
||||
{
|
||||
/* No need to do anything since we are not using Cocoa
|
||||
selectors to handle special keys, instead we use SDL
|
||||
key events to do the same job.
|
||||
*/
|
||||
}
|
||||
|
||||
- (BOOL)hasMarkedText
|
||||
{
|
||||
return _markedText != nil;
|
||||
}
|
||||
|
||||
- (NSRange)markedRange
|
||||
{
|
||||
return _markedRange;
|
||||
}
|
||||
|
||||
- (NSRange)selectedRange
|
||||
{
|
||||
return _selectedRange;
|
||||
}
|
||||
|
||||
- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
|
||||
{
|
||||
if ([aString isKindOfClass:[NSAttributedString class]]) {
|
||||
aString = [aString string];
|
||||
}
|
||||
|
||||
if ([aString length] == 0) {
|
||||
[self unmarkText];
|
||||
return;
|
||||
}
|
||||
|
||||
if (_markedText != aString) {
|
||||
_markedText = aString;
|
||||
}
|
||||
|
||||
_selectedRange = selectedRange;
|
||||
_markedRange = NSMakeRange(0, [aString length]);
|
||||
|
||||
SDL_SendEditingText([aString UTF8String],
|
||||
(int)selectedRange.location, (int)selectedRange.length);
|
||||
|
||||
DEBUG_IME(@"setMarkedText: %@, (%d, %d)", _markedText,
|
||||
selectedRange.location, selectedRange.length);
|
||||
}
|
||||
|
||||
- (void)unmarkText
|
||||
{
|
||||
_markedText = nil;
|
||||
|
||||
SDL_SendEditingText("", 0, 0);
|
||||
}
|
||||
|
||||
- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
|
||||
{
|
||||
NSWindow *window = [self window];
|
||||
NSRect contentRect = [window contentRectForFrameRect:[window frame]];
|
||||
float windowHeight = contentRect.size.height;
|
||||
NSRect rect = NSMakeRect(_inputRect.x, windowHeight - _inputRect.y - _inputRect.h,
|
||||
_inputRect.w, _inputRect.h);
|
||||
|
||||
if (actualRange) {
|
||||
*actualRange = aRange;
|
||||
}
|
||||
|
||||
DEBUG_IME(@"firstRectForCharacterRange: (%d, %d): windowHeight = %g, rect = %@",
|
||||
aRange.location, aRange.length, windowHeight,
|
||||
NSStringFromRect(rect));
|
||||
|
||||
rect = [window convertRectToScreen:rect];
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
|
||||
{
|
||||
DEBUG_IME(@"attributedSubstringFromRange: (%d, %d)", aRange.location, aRange.length);
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSInteger)conversationIdentifier
|
||||
{
|
||||
return (NSInteger)self;
|
||||
}
|
||||
|
||||
/* This method returns the index for character that is
|
||||
* nearest to thePoint. thPoint is in screen coordinate system.
|
||||
*/
|
||||
- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
|
||||
{
|
||||
DEBUG_IME(@"characterIndexForPoint: (%g, %g)", thePoint.x, thePoint.y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This method is the key to attribute extension.
|
||||
* We could add new attributes through this method.
|
||||
* NSInputServer examines the return value of this
|
||||
* method & constructs appropriate attributed string.
|
||||
*/
|
||||
- (NSArray *)validAttributesForMarkedText
|
||||
{
|
||||
return [NSArray array];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static bool IsModifierKeyPressed(unsigned int flags,
|
||||
unsigned int target_mask,
|
||||
unsigned int other_mask,
|
||||
unsigned int either_mask)
|
||||
{
|
||||
bool target_pressed = (flags & target_mask) != 0;
|
||||
bool other_pressed = (flags & other_mask) != 0;
|
||||
bool either_pressed = (flags & either_mask) != 0;
|
||||
|
||||
if (either_pressed != (target_pressed || other_pressed))
|
||||
return either_pressed;
|
||||
|
||||
return target_pressed;
|
||||
}
|
||||
|
||||
static void HandleModifiers(SDL_VideoDevice *_this, SDL_Scancode code, unsigned int modifierFlags)
|
||||
{
|
||||
bool pressed = false;
|
||||
|
||||
if (code == SDL_SCANCODE_LSHIFT) {
|
||||
pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICELSHIFTKEYMASK,
|
||||
NX_DEVICERSHIFTKEYMASK, NX_SHIFTMASK);
|
||||
} else if (code == SDL_SCANCODE_LCTRL) {
|
||||
pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICELCTLKEYMASK,
|
||||
NX_DEVICERCTLKEYMASK, NX_CONTROLMASK);
|
||||
} else if (code == SDL_SCANCODE_LALT) {
|
||||
pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICELALTKEYMASK,
|
||||
NX_DEVICERALTKEYMASK, NX_ALTERNATEMASK);
|
||||
} else if (code == SDL_SCANCODE_LGUI) {
|
||||
pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICELCMDKEYMASK,
|
||||
NX_DEVICERCMDKEYMASK, NX_COMMANDMASK);
|
||||
} else if (code == SDL_SCANCODE_RSHIFT) {
|
||||
pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICERSHIFTKEYMASK,
|
||||
NX_DEVICELSHIFTKEYMASK, NX_SHIFTMASK);
|
||||
} else if (code == SDL_SCANCODE_RCTRL) {
|
||||
pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICERCTLKEYMASK,
|
||||
NX_DEVICELCTLKEYMASK, NX_CONTROLMASK);
|
||||
} else if (code == SDL_SCANCODE_RALT) {
|
||||
pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICERALTKEYMASK,
|
||||
NX_DEVICELALTKEYMASK, NX_ALTERNATEMASK);
|
||||
} else if (code == SDL_SCANCODE_RGUI) {
|
||||
pressed = IsModifierKeyPressed(modifierFlags, NX_DEVICERCMDKEYMASK,
|
||||
NX_DEVICELCMDKEYMASK, NX_COMMANDMASK);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pressed) {
|
||||
SDL_SendKeyboardKey(0, SDL_PRESSED, code);
|
||||
} else {
|
||||
SDL_SendKeyboardKey(0, SDL_RELEASED, code);
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateKeymap(SDL_CocoaVideoData *data, SDL_bool send_event)
|
||||
{
|
||||
TISInputSourceRef key_layout;
|
||||
const void *chr_data;
|
||||
int i;
|
||||
SDL_Scancode scancode;
|
||||
SDL_Keycode keymap[SDL_NUM_SCANCODES];
|
||||
CFDataRef uchrDataRef;
|
||||
|
||||
/* See if the keymap needs to be updated */
|
||||
key_layout = TISCopyCurrentKeyboardLayoutInputSource();
|
||||
if (key_layout == data.key_layout) {
|
||||
return;
|
||||
}
|
||||
data.key_layout = key_layout;
|
||||
|
||||
SDL_GetDefaultKeymap(keymap);
|
||||
|
||||
/* Try Unicode data first */
|
||||
uchrDataRef = TISGetInputSourceProperty(key_layout, kTISPropertyUnicodeKeyLayoutData);
|
||||
if (uchrDataRef) {
|
||||
chr_data = CFDataGetBytePtr(uchrDataRef);
|
||||
} else {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (chr_data) {
|
||||
UInt32 keyboard_type = LMGetKbdType();
|
||||
OSStatus err;
|
||||
|
||||
for (i = 0; i < SDL_arraysize(darwin_scancode_table); i++) {
|
||||
UniChar s[8];
|
||||
UniCharCount len;
|
||||
UInt32 dead_key_state;
|
||||
|
||||
/* Make sure this scancode is a valid character scancode */
|
||||
scancode = darwin_scancode_table[i];
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN ||
|
||||
(keymap[scancode] & SDLK_SCANCODE_MASK)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Swap the scancode for these two wrongly translated keys
|
||||
* UCKeyTranslate() function does not do its job properly for ISO layout keyboards, where the key '@',
|
||||
* which is located in the top left corner of the keyboard right under the Escape key, and the additional
|
||||
* key '<', which is on the right of the Shift key, are inverted
|
||||
*/
|
||||
if ((scancode == SDL_SCANCODE_NONUSBACKSLASH || scancode == SDL_SCANCODE_GRAVE) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) {
|
||||
/* see comments in scancodes_darwin.h */
|
||||
scancode = (SDL_Scancode)((SDL_SCANCODE_NONUSBACKSLASH + SDL_SCANCODE_GRAVE) - scancode);
|
||||
}
|
||||
|
||||
dead_key_state = 0;
|
||||
err = UCKeyTranslate((UCKeyboardLayout *)chr_data,
|
||||
i, kUCKeyActionDown,
|
||||
0, keyboard_type,
|
||||
kUCKeyTranslateNoDeadKeysMask,
|
||||
&dead_key_state, 8, &len, s);
|
||||
if (err != noErr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len > 0 && s[0] != 0x10) {
|
||||
keymap[scancode] = s[0];
|
||||
}
|
||||
}
|
||||
SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES, send_event);
|
||||
return;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
CFRelease(key_layout);
|
||||
}
|
||||
|
||||
void Cocoa_InitKeyboard(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata;
|
||||
|
||||
UpdateKeymap(data, SDL_FALSE);
|
||||
|
||||
/* Set our own names for the platform-dependent but layout-independent keys */
|
||||
/* This key is NumLock on the MacBook keyboard. :) */
|
||||
/*SDL_SetScancodeName(SDL_SCANCODE_NUMLOCKCLEAR, "Clear");*/
|
||||
SDL_SetScancodeName(SDL_SCANCODE_LALT, "Left Option");
|
||||
SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Command");
|
||||
SDL_SetScancodeName(SDL_SCANCODE_RALT, "Right Option");
|
||||
SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Command");
|
||||
|
||||
data.modifierFlags = (unsigned int)[NSEvent modifierFlags];
|
||||
SDL_ToggleModState(SDL_KMOD_CAPS, (data.modifierFlags & NSEventModifierFlagCapsLock) ? SDL_TRUE : SDL_FALSE);
|
||||
}
|
||||
|
||||
void Cocoa_StartTextInput(SDL_VideoDevice *_this)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSView *parentView;
|
||||
SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata;
|
||||
SDL_Window *window = SDL_GetKeyboardFocus();
|
||||
NSWindow *nswindow = nil;
|
||||
if (window) {
|
||||
nswindow = ((__bridge SDL_CocoaWindowData *)window->driverdata).nswindow;
|
||||
}
|
||||
|
||||
parentView = [nswindow contentView];
|
||||
|
||||
/* We only keep one field editor per process, since only the front most
|
||||
* window can receive text input events, so it make no sense to keep more
|
||||
* than one copy. When we switched to another window and requesting for
|
||||
* text input, simply remove the field editor from its superview then add
|
||||
* it to the front most window's content view */
|
||||
if (!data.fieldEdit) {
|
||||
data.fieldEdit =
|
||||
[[SDLTranslatorResponder alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)];
|
||||
}
|
||||
|
||||
if (![[data.fieldEdit superview] isEqual:parentView]) {
|
||||
/* DEBUG_IME(@"add fieldEdit to window contentView"); */
|
||||
[data.fieldEdit removeFromSuperview];
|
||||
[parentView addSubview:data.fieldEdit];
|
||||
[nswindow makeFirstResponder:data.fieldEdit];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cocoa_StopTextInput(SDL_VideoDevice *_this)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata;
|
||||
|
||||
if (data && data.fieldEdit) {
|
||||
[data.fieldEdit removeFromSuperview];
|
||||
data.fieldEdit = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect)
|
||||
{
|
||||
SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata;
|
||||
[data.fieldEdit setInputRect:rect];
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Cocoa_HandleKeyEvent(SDL_VideoDevice *_this, NSEvent *event)
|
||||
{
|
||||
unsigned short scancode;
|
||||
SDL_Scancode code;
|
||||
SDL_CocoaVideoData *data = _this ? ((__bridge SDL_CocoaVideoData *)_this->driverdata) : nil;
|
||||
if (!data) {
|
||||
return; /* can happen when returning from fullscreen Space on shutdown */
|
||||
}
|
||||
|
||||
scancode = [event keyCode];
|
||||
#if 0
|
||||
const char *text;
|
||||
#endif
|
||||
|
||||
if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) {
|
||||
/* see comments in scancodes_darwin.h */
|
||||
scancode = 60 - scancode;
|
||||
}
|
||||
|
||||
if (scancode < SDL_arraysize(darwin_scancode_table)) {
|
||||
code = darwin_scancode_table[scancode];
|
||||
} else {
|
||||
/* Hmm, does this ever happen? If so, need to extend the keymap... */
|
||||
code = SDL_SCANCODE_UNKNOWN;
|
||||
}
|
||||
|
||||
switch ([event type]) {
|
||||
case NSEventTypeKeyDown:
|
||||
if (![event isARepeat]) {
|
||||
/* See if we need to rebuild the keyboard layout */
|
||||
UpdateKeymap(data, SDL_TRUE);
|
||||
}
|
||||
|
||||
SDL_SendKeyboardKey(Cocoa_GetEventTimestamp([event timestamp]), SDL_PRESSED, code);
|
||||
#ifdef DEBUG_SCANCODES
|
||||
if (code == SDL_SCANCODE_UNKNOWN) {
|
||||
SDL_Log("The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL forums/mailing list <https://discourse.libsdl.org/> or to Christian Walther <cwalther@gmx.ch>. Mac virtual key code is %d.\n", scancode);
|
||||
}
|
||||
#endif
|
||||
if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) {
|
||||
/* FIXME CW 2007-08-16: only send those events to the field editor for which we actually want text events, not e.g. esc or function keys. Arrow keys in particular seem to produce crashes sometimes. */
|
||||
[data.fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
|
||||
#if 0
|
||||
text = [[event characters] UTF8String];
|
||||
if(text && *text) {
|
||||
SDL_SendKeyboardText(text);
|
||||
[data->fieldEdit setString:@""];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case NSEventTypeKeyUp:
|
||||
SDL_SendKeyboardKey(Cocoa_GetEventTimestamp([event timestamp]), SDL_RELEASED, code);
|
||||
break;
|
||||
case NSEventTypeFlagsChanged:
|
||||
HandleModifiers(_this, code, (unsigned int)[event modifierFlags]);
|
||||
break;
|
||||
default: /* just to avoid compiler warnings */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Cocoa_QuitKeyboard(SDL_VideoDevice *_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(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed)
|
||||
{
|
||||
#ifdef SDL_MAC_NO_SANDBOX
|
||||
CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), grabbed ? CGSGlobalHotKeyDisable : CGSGlobalHotKeyEnable);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
27
external/sdl/SDL/src/video/cocoa/SDL_cocoamessagebox.h
vendored
Normal file
27
external/sdl/SDL/src/video/cocoa/SDL_cocoamessagebox.h
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_COCOA
|
||||
|
||||
extern int Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
145
external/sdl/SDL/src/video/cocoa/SDL_cocoamessagebox.m
vendored
Normal file
145
external/sdl/SDL/src/video/cocoa/SDL_cocoamessagebox.m
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_COCOA
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
|
||||
@interface SDLMessageBoxPresenter : NSObject
|
||||
{
|
||||
@public
|
||||
NSInteger clicked;
|
||||
NSWindow *nswindow;
|
||||
}
|
||||
- (id)initWithParentWindow:(SDL_Window *)window;
|
||||
@end
|
||||
|
||||
@implementation SDLMessageBoxPresenter
|
||||
- (id)initWithParentWindow:(SDL_Window *)window
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
clicked = -1;
|
||||
|
||||
/* Retain the NSWindow because we'll show the alert later on the main thread */
|
||||
if (window) {
|
||||
nswindow = ((__bridge SDL_CocoaWindowData *)window->driverdata).nswindow;
|
||||
} else {
|
||||
nswindow = nil;
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)showAlert:(NSAlert *)alert
|
||||
{
|
||||
if (nswindow) {
|
||||
[alert beginSheetModalForWindow:nswindow
|
||||
completionHandler:^(NSModalResponse returnCode) {
|
||||
[NSApp stopModalWithCode:returnCode];
|
||||
}];
|
||||
clicked = [NSApp runModalForWindow:nswindow];
|
||||
nswindow = nil;
|
||||
} else {
|
||||
clicked = [alert runModal];
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
static void Cocoa_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid, int *returnValue)
|
||||
{
|
||||
NSAlert *alert;
|
||||
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
|
||||
SDLMessageBoxPresenter *presenter;
|
||||
NSInteger clicked;
|
||||
int i;
|
||||
Cocoa_RegisterApp();
|
||||
|
||||
alert = [[NSAlert alloc] init];
|
||||
|
||||
if (messageboxdata->flags & SDL_MESSAGEBOX_ERROR) {
|
||||
[alert setAlertStyle:NSAlertStyleCritical];
|
||||
} else if (messageboxdata->flags & SDL_MESSAGEBOX_WARNING) {
|
||||
[alert setAlertStyle:NSAlertStyleWarning];
|
||||
} else {
|
||||
[alert setAlertStyle:NSAlertStyleInformational];
|
||||
}
|
||||
|
||||
[alert setMessageText:[NSString stringWithUTF8String:messageboxdata->title]];
|
||||
[alert setInformativeText:[NSString stringWithUTF8String:messageboxdata->message]];
|
||||
|
||||
for (i = 0; i < messageboxdata->numbuttons; ++i) {
|
||||
const SDL_MessageBoxButtonData *sdlButton;
|
||||
NSButton *button;
|
||||
|
||||
if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
|
||||
sdlButton = &messageboxdata->buttons[messageboxdata->numbuttons - 1 - i];
|
||||
} else {
|
||||
sdlButton = &messageboxdata->buttons[i];
|
||||
}
|
||||
|
||||
button = [alert addButtonWithTitle:[NSString stringWithUTF8String:sdlButton->text]];
|
||||
if (sdlButton->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
|
||||
[button setKeyEquivalent:@"\r"];
|
||||
} else if (sdlButton->flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
|
||||
[button setKeyEquivalent:@"\033"];
|
||||
} else {
|
||||
[button setKeyEquivalent:@""];
|
||||
}
|
||||
}
|
||||
|
||||
presenter = [[SDLMessageBoxPresenter alloc] initWithParentWindow:messageboxdata->window];
|
||||
|
||||
[presenter showAlert:alert];
|
||||
|
||||
clicked = presenter->clicked;
|
||||
if (clicked >= NSAlertFirstButtonReturn) {
|
||||
clicked -= NSAlertFirstButtonReturn;
|
||||
if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
66
external/sdl/SDL/src/video/cocoa/SDL_cocoametalview.h
vendored
Normal file
66
external/sdl/SDL/src/video/cocoa/SDL_cocoametalview.h
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com.
|
||||
*
|
||||
* Thanks to @slime73 on GitHub for their gist showing how to add a CAMetalLayer
|
||||
* backed view.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoametalview_h_
|
||||
#define SDL_cocoametalview_h_
|
||||
|
||||
#if defined(SDL_VIDEO_DRIVER_COCOA) && (defined(SDL_VIDEO_VULKAN) || defined(SDL_VIDEO_METAL))
|
||||
|
||||
#import "../SDL_sysvideo.h"
|
||||
|
||||
#import "SDL_cocoawindow.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
|
||||
@interface SDL_cocoametalview : NSView
|
||||
|
||||
- (instancetype)initWithFrame:(NSRect)frame
|
||||
highDPI:(BOOL)highDPI
|
||||
windowID:(Uint32)windowID
|
||||
opaque:(BOOL)opaque;
|
||||
|
||||
- (void)updateDrawableSize;
|
||||
- (NSView *)hitTest:(NSPoint)point;
|
||||
|
||||
/* Override superclass tag so this class can set it. */
|
||||
@property(assign, readonly) NSInteger tag;
|
||||
|
||||
@property(nonatomic) BOOL highDPI;
|
||||
@property(nonatomic) Uint32 sdlWindowID;
|
||||
|
||||
@end
|
||||
|
||||
SDL_MetalView Cocoa_Metal_CreateView(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
void Cocoa_Metal_DestroyView(SDL_VideoDevice *_this, SDL_MetalView view);
|
||||
void *Cocoa_Metal_GetLayer(SDL_VideoDevice *_this, SDL_MetalView view);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
|
||||
|
||||
#endif /* SDL_cocoametalview_h_ */
|
182
external/sdl/SDL/src/video/cocoa/SDL_cocoametalview.m
vendored
Normal file
182
external/sdl/SDL/src/video/cocoa/SDL_cocoametalview.m
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com.
|
||||
*
|
||||
* Thanks to @slime73 on GitHub for their gist showing how to add a CAMetalLayer
|
||||
* backed view.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#import "SDL_cocoametalview.h"
|
||||
|
||||
#if defined(SDL_VIDEO_DRIVER_COCOA) && (defined(SDL_VIDEO_VULKAN) || defined(SDL_VIDEO_METAL))
|
||||
|
||||
#include <SDL3/SDL_syswm.h>
|
||||
|
||||
static int SDLCALL SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
|
||||
{
|
||||
/* Update the drawable size when SDL receives a size changed event for
|
||||
* the window that contains the metal view. It would be nice to use
|
||||
* - (void)resizeWithOldSuperviewSize:(NSSize)oldSize and
|
||||
* - (void)viewDidChangeBackingProperties instead, but SDL's size change
|
||||
* events don't always happen in the same frame (for example when a
|
||||
* resizable window exits a fullscreen Space via the user pressing the OS
|
||||
* exit-space button). */
|
||||
if (event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) {
|
||||
@autoreleasepool {
|
||||
SDL_cocoametalview *view = (__bridge SDL_cocoametalview *)userdata;
|
||||
if (view.sdlWindowID == event->window.windowID) {
|
||||
[view updateDrawableSize];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@implementation SDL_cocoametalview
|
||||
|
||||
/* Return a Metal-compatible layer. */
|
||||
+ (Class)layerClass
|
||||
{
|
||||
return NSClassFromString(@"CAMetalLayer");
|
||||
}
|
||||
|
||||
/* Indicate the view wants to draw using a backing layer instead of drawRect. */
|
||||
- (BOOL)wantsUpdateLayer
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
/* When the wantsLayer property is set to YES, this method will be invoked to
|
||||
* return a layer instance.
|
||||
*/
|
||||
- (CALayer *)makeBackingLayer
|
||||
{
|
||||
return [self.class.layerClass layer];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(NSRect)frame
|
||||
highDPI:(BOOL)highDPI
|
||||
windowID:(Uint32)windowID
|
||||
opaque:(BOOL)opaque
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self != nil) {
|
||||
self.highDPI = highDPI;
|
||||
self.sdlWindowID = windowID;
|
||||
self.wantsLayer = YES;
|
||||
|
||||
/* Allow resize. */
|
||||
self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
|
||||
self.layer.opaque = opaque;
|
||||
|
||||
SDL_AddEventWatch(SDL_MetalViewEventWatch, (__bridge void *)(self));
|
||||
|
||||
[self updateDrawableSize];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
SDL_DelEventWatch(SDL_MetalViewEventWatch, (__bridge void *)(self));
|
||||
}
|
||||
|
||||
- (NSInteger)tag
|
||||
{
|
||||
return SDL_METALVIEW_TAG;
|
||||
}
|
||||
|
||||
- (void)updateDrawableSize
|
||||
{
|
||||
CAMetalLayer *metalLayer = (CAMetalLayer *)self.layer;
|
||||
NSSize size = self.bounds.size;
|
||||
NSSize backingSize = size;
|
||||
|
||||
if (self.highDPI) {
|
||||
/* Note: NSHighResolutionCapable must be set to true in the app's
|
||||
* Info.plist in order for the backing size to be high res.
|
||||
*/
|
||||
backingSize = [self convertSizeToBacking:size];
|
||||
}
|
||||
|
||||
metalLayer.contentsScale = backingSize.height / size.height;
|
||||
metalLayer.drawableSize = NSSizeToCGSize(backingSize);
|
||||
}
|
||||
|
||||
- (NSView *)hitTest:(NSPoint)point
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
SDL_MetalView Cocoa_Metal_CreateView(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata;
|
||||
NSView *view = data.nswindow.contentView;
|
||||
BOOL highDPI = (window->flags & SDL_WINDOW_HIGH_PIXEL_DENSITY) != 0;
|
||||
BOOL opaque = (window->flags & SDL_WINDOW_TRANSPARENT) == 0;
|
||||
Uint32 windowID = SDL_GetWindowID(window);
|
||||
SDL_cocoametalview *newview;
|
||||
SDL_MetalView metalview;
|
||||
|
||||
newview = [[SDL_cocoametalview alloc] initWithFrame:view.frame
|
||||
highDPI:highDPI
|
||||
windowID:windowID
|
||||
opaque:opaque];
|
||||
if (newview == nil) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
[view addSubview:newview];
|
||||
|
||||
/* Make sure the drawable size is up to date after attaching the view. */
|
||||
[newview updateDrawableSize];
|
||||
|
||||
metalview = (SDL_MetalView)CFBridgingRetain(newview);
|
||||
|
||||
return metalview;
|
||||
}
|
||||
}
|
||||
|
||||
void Cocoa_Metal_DestroyView(SDL_VideoDevice *_this, SDL_MetalView view)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_cocoametalview *metalview = CFBridgingRelease(view);
|
||||
[metalview removeFromSuperview];
|
||||
}
|
||||
}
|
||||
|
||||
void *Cocoa_Metal_GetLayer(SDL_VideoDevice *_this, SDL_MetalView view)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_cocoametalview *cocoaview = (__bridge SDL_cocoametalview *)view;
|
||||
return (__bridge void *)cocoaview.layer;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
|
43
external/sdl/SDL/src/video/cocoa/SDL_cocoamodes.h
vendored
Normal file
43
external/sdl/SDL/src/video/cocoa/SDL_cocoamodes.h
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoamodes_h_
|
||||
#define SDL_cocoamodes_h_
|
||||
|
||||
struct SDL_DisplayData
|
||||
{
|
||||
CGDirectDisplayID display;
|
||||
};
|
||||
|
||||
struct SDL_DisplayModeData
|
||||
{
|
||||
CFMutableArrayRef modes;
|
||||
};
|
||||
|
||||
extern void Cocoa_InitModes(SDL_VideoDevice *_this);
|
||||
extern int Cocoa_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect);
|
||||
extern int Cocoa_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect);
|
||||
extern int Cocoa_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display);
|
||||
extern int Cocoa_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
|
||||
extern void Cocoa_QuitModes(SDL_VideoDevice *_this);
|
||||
|
||||
#endif /* SDL_cocoamodes_h_ */
|
540
external/sdl/SDL/src/video/cocoa/SDL_cocoamodes.m
vendored
Normal file
540
external/sdl/SDL/src/video/cocoa/SDL_cocoamodes.m
vendored
Normal file
@ -0,0 +1,540 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_COCOA
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
|
||||
/* We need this for IODisplayCreateInfoDictionary and kIODisplayOnlyPreferredName */
|
||||
#include <IOKit/graphics/IOGraphicsLib.h>
|
||||
|
||||
/* We need this for CVDisplayLinkGetNominalOutputVideoRefreshPeriod */
|
||||
#include <CoreVideo/CVBase.h>
|
||||
#include <CoreVideo/CVDisplayLink.h>
|
||||
|
||||
/* This gets us MAC_OS_X_VERSION_MIN_REQUIRED... */
|
||||
#include <AvailabilityMacros.h>
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_13
|
||||
#define NSAppKitVersionNumber10_12 1504
|
||||
#endif
|
||||
#if (IOGRAPHICSTYPES_REV < 40)
|
||||
#define kDisplayModeNativeFlag 0x02000000
|
||||
#endif
|
||||
|
||||
static int CG_SetError(const char *prefix, CGDisplayErr result)
|
||||
{
|
||||
const char *error;
|
||||
|
||||
switch (result) {
|
||||
case kCGErrorFailure:
|
||||
error = "kCGErrorFailure";
|
||||
break;
|
||||
case kCGErrorIllegalArgument:
|
||||
error = "kCGErrorIllegalArgument";
|
||||
break;
|
||||
case kCGErrorInvalidConnection:
|
||||
error = "kCGErrorInvalidConnection";
|
||||
break;
|
||||
case kCGErrorInvalidContext:
|
||||
error = "kCGErrorInvalidContext";
|
||||
break;
|
||||
case kCGErrorCannotComplete:
|
||||
error = "kCGErrorCannotComplete";
|
||||
break;
|
||||
case kCGErrorNotImplemented:
|
||||
error = "kCGErrorNotImplemented";
|
||||
break;
|
||||
case kCGErrorRangeCheck:
|
||||
error = "kCGErrorRangeCheck";
|
||||
break;
|
||||
case kCGErrorTypeCheck:
|
||||
error = "kCGErrorTypeCheck";
|
||||
break;
|
||||
case kCGErrorInvalidOperation:
|
||||
error = "kCGErrorInvalidOperation";
|
||||
break;
|
||||
case kCGErrorNoneAvailable:
|
||||
error = "kCGErrorNoneAvailable";
|
||||
break;
|
||||
default:
|
||||
error = "Unknown Error";
|
||||
break;
|
||||
}
|
||||
return SDL_SetError("%s: %s", prefix, error);
|
||||
}
|
||||
|
||||
static float GetDisplayModeRefreshRate(CGDisplayModeRef vidmode, CVDisplayLinkRef link)
|
||||
{
|
||||
double refreshRate = CGDisplayModeGetRefreshRate(vidmode);
|
||||
|
||||
/* CGDisplayModeGetRefreshRate can return 0 (eg for built-in displays). */
|
||||
if (refreshRate == 0 && link != NULL) {
|
||||
CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
|
||||
if ((time.flags & kCVTimeIsIndefinite) == 0 && time.timeValue != 0) {
|
||||
refreshRate = (double)time.timeScale / time.timeValue;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)(refreshRate * 100) / 100.0f;
|
||||
}
|
||||
|
||||
static SDL_bool HasValidDisplayModeFlags(CGDisplayModeRef vidmode)
|
||||
{
|
||||
uint32_t ioflags = CGDisplayModeGetIOFlags(vidmode);
|
||||
|
||||
/* Filter out modes which have flags that we don't want. */
|
||||
if (ioflags & (kDisplayModeNeverShowFlag | kDisplayModeNotGraphicsQualityFlag)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Filter out modes which don't have flags that we want. */
|
||||
if (!(ioflags & kDisplayModeValidFlag) || !(ioflags & kDisplayModeSafeFlag)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static Uint32 GetDisplayModePixelFormat(CGDisplayModeRef vidmode)
|
||||
{
|
||||
/* This API is deprecated in 10.11 with no good replacement (as of 10.15). */
|
||||
CFStringRef fmt = CGDisplayModeCopyPixelEncoding(vidmode);
|
||||
Uint32 pixelformat = SDL_PIXELFORMAT_UNKNOWN;
|
||||
|
||||
if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
|
||||
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
|
||||
pixelformat = SDL_PIXELFORMAT_ARGB8888;
|
||||
} else if (CFStringCompare(fmt, CFSTR(IO16BitDirectPixels),
|
||||
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
|
||||
pixelformat = SDL_PIXELFORMAT_ARGB1555;
|
||||
} else if (CFStringCompare(fmt, CFSTR(kIO30BitDirectPixels),
|
||||
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
|
||||
pixelformat = SDL_PIXELFORMAT_ARGB2101010;
|
||||
} else {
|
||||
/* ignore 8-bit and such for now. */
|
||||
}
|
||||
|
||||
CFRelease(fmt);
|
||||
|
||||
return pixelformat;
|
||||
}
|
||||
|
||||
static SDL_bool GetDisplayMode(SDL_VideoDevice *_this, CGDisplayModeRef vidmode, SDL_bool vidmodeCurrent, CFArrayRef modelist, CVDisplayLinkRef link, SDL_DisplayMode *mode)
|
||||
{
|
||||
SDL_DisplayModeData *data;
|
||||
bool usableForGUI = CGDisplayModeIsUsableForDesktopGUI(vidmode);
|
||||
size_t width = CGDisplayModeGetWidth(vidmode);
|
||||
size_t height = CGDisplayModeGetHeight(vidmode);
|
||||
size_t pixelW = width;
|
||||
size_t pixelH = height;
|
||||
uint32_t ioflags = CGDisplayModeGetIOFlags(vidmode);
|
||||
float refreshrate = GetDisplayModeRefreshRate(vidmode, link);
|
||||
Uint32 format = GetDisplayModePixelFormat(vidmode);
|
||||
bool interlaced = (ioflags & kDisplayModeInterlacedFlag) != 0;
|
||||
CFMutableArrayRef modes;
|
||||
|
||||
if (format == SDL_PIXELFORMAT_UNKNOWN) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
modes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
||||
CFArrayAppendValue(modes, vidmode);
|
||||
|
||||
/* If a list of possible display modes is passed in, use it to filter out
|
||||
* modes that have duplicate sizes. We don't just rely on SDL's higher level
|
||||
* duplicate filtering because this code can choose what properties are
|
||||
* preferred, and it can add CGDisplayModes to the DisplayModeData's list of
|
||||
* modes to try (see comment below for why that's necessary). */
|
||||
pixelW = CGDisplayModeGetPixelWidth(vidmode);
|
||||
pixelH = CGDisplayModeGetPixelHeight(vidmode);
|
||||
|
||||
if (modelist != NULL) {
|
||||
CFIndex modescount = CFArrayGetCount(modelist);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < modescount; i++) {
|
||||
size_t otherW, otherH, otherpixelW, otherpixelH;
|
||||
float otherrefresh;
|
||||
Uint32 otherformat;
|
||||
bool otherGUI;
|
||||
CGDisplayModeRef othermode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modelist, i);
|
||||
uint32_t otherioflags = CGDisplayModeGetIOFlags(othermode);
|
||||
|
||||
if (CFEqual(vidmode, othermode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!HasValidDisplayModeFlags(othermode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
otherW = CGDisplayModeGetWidth(othermode);
|
||||
otherH = CGDisplayModeGetHeight(othermode);
|
||||
otherpixelW = CGDisplayModeGetPixelWidth(othermode);
|
||||
otherpixelH = CGDisplayModeGetPixelHeight(othermode);
|
||||
otherrefresh = GetDisplayModeRefreshRate(othermode, link);
|
||||
otherformat = GetDisplayModePixelFormat(othermode);
|
||||
otherGUI = CGDisplayModeIsUsableForDesktopGUI(othermode);
|
||||
|
||||
/* Ignore this mode if it's interlaced and there's a non-interlaced
|
||||
* mode in the list with the same properties.
|
||||
*/
|
||||
if (interlaced && ((otherioflags & kDisplayModeInterlacedFlag) == 0) && width == otherW && height == otherH && pixelW == otherpixelW && pixelH == otherpixelH && refreshrate == otherrefresh && format == otherformat && usableForGUI == otherGUI) {
|
||||
CFRelease(modes);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Ignore this mode if it's not usable for desktop UI and its
|
||||
* properties are equal to another GUI-capable mode in the list.
|
||||
*/
|
||||
if (width == otherW && height == otherH && pixelW == otherpixelW && pixelH == otherpixelH && !usableForGUI && otherGUI && refreshrate == otherrefresh && format == otherformat) {
|
||||
CFRelease(modes);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* If multiple modes have the exact same properties, they'll all
|
||||
* go in the list of modes to try when SetDisplayMode is called.
|
||||
* This is needed because kCGDisplayShowDuplicateLowResolutionModes
|
||||
* (which is used to expose highdpi display modes) can make the
|
||||
* list of modes contain duplicates (according to their properties
|
||||
* obtained via public APIs) which don't work with SetDisplayMode.
|
||||
* Those duplicate non-functional modes *do* have different pixel
|
||||
* formats according to their internal data structure viewed with
|
||||
* NSLog, but currently no public API can detect that.
|
||||
* https://bugzilla.libsdl.org/show_bug.cgi?id=4822
|
||||
*
|
||||
* As of macOS 10.15.0, those duplicates have the exact same
|
||||
* properties via public APIs in every way (even their IO flags and
|
||||
* CGDisplayModeGetIODisplayModeID is the same), so we could test
|
||||
* those for equality here too, but I'm intentionally not doing that
|
||||
* in case there are duplicate modes with different IO flags or IO
|
||||
* display mode IDs in the future. In that case I think it's better
|
||||
* to try them all in SetDisplayMode than to risk one of them being
|
||||
* correct but it being filtered out by SDL_AddFullscreenDisplayMode
|
||||
* as being a duplicate.
|
||||
*/
|
||||
if (width == otherW && height == otherH && pixelW == otherpixelW && pixelH == otherpixelH && usableForGUI == otherGUI && refreshrate == otherrefresh && format == otherformat) {
|
||||
CFArrayAppendValue(modes, othermode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_zerop(mode);
|
||||
data = (SDL_DisplayModeData *)SDL_malloc(sizeof(*data));
|
||||
if (!data) {
|
||||
CFRelease(modes);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
data->modes = modes;
|
||||
mode->format = format;
|
||||
mode->w = (int)width;
|
||||
mode->h = (int)height;
|
||||
mode->pixel_density = (float)pixelW / width;
|
||||
mode->refresh_rate = refreshrate;
|
||||
mode->driverdata = data;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static const char *Cocoa_GetDisplayName(CGDirectDisplayID displayID)
|
||||
{
|
||||
/* This API is deprecated in 10.9 with no good replacement (as of 10.15). */
|
||||
io_service_t servicePort = CGDisplayIOServicePort(displayID);
|
||||
CFDictionaryRef deviceInfo = IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName);
|
||||
NSDictionary *localizedNames = [(__bridge NSDictionary *)deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
|
||||
const char *displayName = NULL;
|
||||
|
||||
if ([localizedNames count] > 0) {
|
||||
displayName = SDL_strdup([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]);
|
||||
}
|
||||
CFRelease(deviceInfo);
|
||||
return displayName;
|
||||
}
|
||||
|
||||
void Cocoa_InitModes(SDL_VideoDevice *_this)
|
||||
{
|
||||
@autoreleasepool {
|
||||
CGDisplayErr result;
|
||||
CGDirectDisplayID *displays;
|
||||
CGDisplayCount numDisplays;
|
||||
SDL_bool isstack;
|
||||
int pass, i;
|
||||
|
||||
result = CGGetOnlineDisplayList(0, NULL, &numDisplays);
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGGetOnlineDisplayList()", result);
|
||||
return;
|
||||
}
|
||||
displays = SDL_small_alloc(CGDirectDisplayID, numDisplays, &isstack);
|
||||
result = CGGetOnlineDisplayList(numDisplays, displays, &numDisplays);
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGGetOnlineDisplayList()", result);
|
||||
SDL_small_free(displays, isstack);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Pick up the primary display in the first pass, then get the rest */
|
||||
for (pass = 0; pass < 2; ++pass) {
|
||||
for (i = 0; i < numDisplays; ++i) {
|
||||
SDL_VideoDisplay display;
|
||||
SDL_DisplayData *displaydata;
|
||||
SDL_DisplayMode mode;
|
||||
CGDisplayModeRef moderef = NULL;
|
||||
CVDisplayLinkRef link = NULL;
|
||||
|
||||
if (pass == 0) {
|
||||
if (!CGDisplayIsMain(displays[i])) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (CGDisplayIsMain(displays[i])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay) {
|
||||
continue;
|
||||
}
|
||||
|
||||
moderef = CGDisplayCopyDisplayMode(displays[i]);
|
||||
|
||||
if (!moderef) {
|
||||
continue;
|
||||
}
|
||||
|
||||
displaydata = (SDL_DisplayData *)SDL_malloc(sizeof(*displaydata));
|
||||
if (!displaydata) {
|
||||
CGDisplayModeRelease(moderef);
|
||||
continue;
|
||||
}
|
||||
displaydata->display = displays[i];
|
||||
|
||||
CVDisplayLinkCreateWithCGDisplay(displays[i], &link);
|
||||
|
||||
SDL_zero(display);
|
||||
/* this returns a stddup'ed string */
|
||||
display.name = (char *)Cocoa_GetDisplayName(displays[i]);
|
||||
if (!GetDisplayMode(_this, moderef, SDL_TRUE, NULL, link, &mode)) {
|
||||
CVDisplayLinkRelease(link);
|
||||
CGDisplayModeRelease(moderef);
|
||||
SDL_free(display.name);
|
||||
SDL_free(displaydata);
|
||||
continue;
|
||||
}
|
||||
|
||||
CVDisplayLinkRelease(link);
|
||||
CGDisplayModeRelease(moderef);
|
||||
|
||||
display.desktop_mode = mode;
|
||||
display.driverdata = displaydata;
|
||||
SDL_AddVideoDisplay(&display, SDL_FALSE);
|
||||
SDL_free(display.name);
|
||||
}
|
||||
}
|
||||
SDL_small_free(displays, isstack);
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
|
||||
{
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
|
||||
CGRect cgrect;
|
||||
|
||||
cgrect = CGDisplayBounds(displaydata->display);
|
||||
rect->x = (int)cgrect.origin.x;
|
||||
rect->y = (int)cgrect.origin.y;
|
||||
rect->w = (int)cgrect.size.width;
|
||||
rect->h = (int)cgrect.size.height;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Cocoa_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
|
||||
{
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
|
||||
const CGDirectDisplayID cgdisplay = displaydata->display;
|
||||
NSArray *screens = [NSScreen screens];
|
||||
NSScreen *screen = nil;
|
||||
|
||||
/* !!! FIXME: maybe track the NSScreen in SDL_DisplayData? */
|
||||
for (NSScreen *i in screens) {
|
||||
const CGDirectDisplayID thisDisplay = (CGDirectDisplayID)[[[i deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
|
||||
if (thisDisplay == cgdisplay) {
|
||||
screen = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(screen != nil); /* didn't find it?! */
|
||||
if (screen == nil) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
const NSRect frame = [screen visibleFrame];
|
||||
rect->x = (int)frame.origin.x;
|
||||
rect->y = (int)(CGDisplayPixelsHigh(kCGDirectMainDisplay) - frame.origin.y - frame.size.height);
|
||||
rect->w = (int)frame.size.width;
|
||||
rect->h = (int)frame.size.height;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Cocoa_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display)
|
||||
{
|
||||
SDL_DisplayData *data = (SDL_DisplayData *)display->driverdata;
|
||||
CVDisplayLinkRef link = NULL;
|
||||
CFArrayRef modes;
|
||||
CFDictionaryRef dict = NULL;
|
||||
const CFStringRef dictkeys[] = { kCGDisplayShowDuplicateLowResolutionModes };
|
||||
const CFBooleanRef dictvalues[] = { kCFBooleanTrue };
|
||||
|
||||
CVDisplayLinkCreateWithCGDisplay(data->display, &link);
|
||||
|
||||
/* By default, CGDisplayCopyAllDisplayModes will only get a subset of the
|
||||
* system's available modes. For example on a 15" 2016 MBP, users can
|
||||
* choose 1920x1080@2x in System Preferences but it won't show up here,
|
||||
* unless we specify the option below.
|
||||
* The display modes returned by CGDisplayCopyAllDisplayModes are also not
|
||||
* high dpi-capable unless this option is set.
|
||||
* macOS 10.15 also seems to have a bug where entering, exiting, and
|
||||
* re-entering exclusive fullscreen with a low dpi display mode can cause
|
||||
* the content of the screen to move up, which this setting avoids:
|
||||
* https://bugzilla.libsdl.org/show_bug.cgi?id=4822
|
||||
*/
|
||||
|
||||
dict = CFDictionaryCreate(NULL,
|
||||
(const void **)dictkeys,
|
||||
(const void **)dictvalues,
|
||||
1,
|
||||
&kCFCopyStringDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
modes = CGDisplayCopyAllDisplayModes(data->display, dict);
|
||||
|
||||
if (dict) {
|
||||
CFRelease(dict);
|
||||
}
|
||||
|
||||
if (modes) {
|
||||
CFIndex i;
|
||||
const CFIndex count = CFArrayGetCount(modes);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
CGDisplayModeRef moderef = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i);
|
||||
SDL_DisplayMode mode;
|
||||
|
||||
if (GetDisplayMode(_this, moderef, SDL_FALSE, modes, link, &mode)) {
|
||||
if (!SDL_AddFullscreenDisplayMode(display, &mode)) {
|
||||
CFRelease(((SDL_DisplayModeData *)mode.driverdata)->modes);
|
||||
SDL_free(mode.driverdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(modes);
|
||||
}
|
||||
|
||||
CVDisplayLinkRelease(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CGError SetDisplayModeForDisplay(CGDirectDisplayID display, SDL_DisplayModeData *data)
|
||||
{
|
||||
/* SDL_DisplayModeData can contain multiple CGDisplayModes to try (with
|
||||
* identical properties), some of which might not work. See GetDisplayMode.
|
||||
*/
|
||||
CGError result = kCGErrorFailure;
|
||||
for (CFIndex i = 0; i < CFArrayGetCount(data->modes); i++) {
|
||||
CGDisplayModeRef moderef = (CGDisplayModeRef)CFArrayGetValueAtIndex(data->modes, i);
|
||||
result = CGDisplaySetDisplayMode(display, moderef, NULL);
|
||||
if (result == kCGErrorSuccess) {
|
||||
/* If this mode works, try it first next time. */
|
||||
CFArrayExchangeValuesAtIndices(data->modes, i, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int Cocoa_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
|
||||
{
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
|
||||
SDL_DisplayModeData *data = (SDL_DisplayModeData *)mode->driverdata;
|
||||
CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
|
||||
CGError result = kCGErrorSuccess;
|
||||
|
||||
/* Fade to black to hide resolution-switching flicker */
|
||||
if (CGAcquireDisplayFadeReservation(5, &fade_token) == kCGErrorSuccess) {
|
||||
CGDisplayFade(fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
|
||||
}
|
||||
|
||||
if (data == display->desktop_mode.driverdata) {
|
||||
/* Restoring desktop mode */
|
||||
SetDisplayModeForDisplay(displaydata->display, data);
|
||||
} else {
|
||||
/* Do the physical switch */
|
||||
result = SetDisplayModeForDisplay(displaydata->display, data);
|
||||
}
|
||||
|
||||
/* Fade in again (asynchronously) */
|
||||
if (fade_token != kCGDisplayFadeReservationInvalidToken) {
|
||||
CGDisplayFade(fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
|
||||
CGReleaseDisplayFadeReservation(fade_token);
|
||||
}
|
||||
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGDisplaySwitchToMode()", result);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Cocoa_QuitModes(SDL_VideoDevice *_this)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < _this->num_displays; ++i) {
|
||||
SDL_VideoDisplay *display = &_this->displays[i];
|
||||
SDL_DisplayModeData *mode;
|
||||
|
||||
if (display->current_mode->driverdata != display->desktop_mode.driverdata) {
|
||||
Cocoa_SetDisplayMode(_this, display, &display->desktop_mode);
|
||||
}
|
||||
|
||||
mode = (SDL_DisplayModeData *)display->desktop_mode.driverdata;
|
||||
CFRelease(mode->modes);
|
||||
|
||||
for (j = 0; j < display->num_fullscreen_modes; j++) {
|
||||
mode = (SDL_DisplayModeData *)display->fullscreen_modes[j].driverdata;
|
||||
CFRelease(mode->modes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
50
external/sdl/SDL/src/video/cocoa/SDL_cocoamouse.h
vendored
Normal file
50
external/sdl/SDL/src/video/cocoa/SDL_cocoamouse.h
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoamouse_h_
|
||||
#define SDL_cocoamouse_h_
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
|
||||
extern int Cocoa_InitMouse(SDL_VideoDevice *_this);
|
||||
extern void Cocoa_HandleMouseEvent(SDL_VideoDevice *_this, NSEvent *event);
|
||||
extern void Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event);
|
||||
extern void Cocoa_HandleMouseWarp(CGFloat x, CGFloat y);
|
||||
extern void Cocoa_QuitMouse(SDL_VideoDevice *_this);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Whether we've seen a cursor warp since the last move event. */
|
||||
SDL_bool seenWarp;
|
||||
/* What location our last cursor warp was to. */
|
||||
CGFloat lastWarpX;
|
||||
CGFloat lastWarpY;
|
||||
/* What location we last saw the cursor move to. */
|
||||
CGFloat lastMoveX;
|
||||
CGFloat lastMoveY;
|
||||
} SDL_MouseData;
|
||||
|
||||
@interface NSCursor (InvisibleCursor)
|
||||
+ (NSCursor *)invisibleCursor;
|
||||
@end
|
||||
|
||||
#endif /* SDL_cocoamouse_h_ */
|
571
external/sdl/SDL/src/video/cocoa/SDL_cocoamouse.m
vendored
Normal file
571
external/sdl/SDL/src/video/cocoa/SDL_cocoamouse.m
vendored
Normal file
@ -0,0 +1,571 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_COCOA
|
||||
|
||||
#include "SDL_cocoamouse.h"
|
||||
#include "SDL_cocoavideo.h"
|
||||
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
|
||||
/* #define DEBUG_COCOAMOUSE */
|
||||
|
||||
#ifdef DEBUG_COCOAMOUSE
|
||||
#define DLog(fmt, ...) printf("%s: " fmt "\n", __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DLog(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
@implementation NSCursor (InvisibleCursor)
|
||||
+ (NSCursor *)invisibleCursor
|
||||
{
|
||||
static NSCursor *invisibleCursor = NULL;
|
||||
if (!invisibleCursor) {
|
||||
/* RAW 16x16 transparent GIF */
|
||||
static unsigned char cursorBytes[] = {
|
||||
0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x10, 0x00, 0x10, 0x00, 0x80,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xF9, 0x04,
|
||||
0x01, 0x00, 0x00, 0x01, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x10,
|
||||
0x00, 0x10, 0x00, 0x00, 0x02, 0x0E, 0x8C, 0x8F, 0xA9, 0xCB, 0xED,
|
||||
0x0F, 0xA3, 0x9C, 0xB4, 0xDA, 0x8B, 0xB3, 0x3E, 0x05, 0x00, 0x3B
|
||||
};
|
||||
|
||||
NSData *cursorData = [NSData dataWithBytesNoCopy:&cursorBytes[0]
|
||||
length:sizeof(cursorBytes)
|
||||
freeWhenDone:NO];
|
||||
NSImage *cursorImage = [[NSImage alloc] initWithData:cursorData];
|
||||
invisibleCursor = [[NSCursor alloc] initWithImage:cursorImage
|
||||
hotSpot:NSZeroPoint];
|
||||
}
|
||||
|
||||
return invisibleCursor;
|
||||
}
|
||||
@end
|
||||
|
||||
static SDL_Cursor *Cocoa_CreateDefaultCursor(void)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSCursor *nscursor;
|
||||
SDL_Cursor *cursor = NULL;
|
||||
|
||||
nscursor = [NSCursor arrowCursor];
|
||||
|
||||
if (nscursor) {
|
||||
cursor = SDL_calloc(1, sizeof(*cursor));
|
||||
if (cursor) {
|
||||
cursor->driverdata = (void *)CFBridgingRetain(nscursor);
|
||||
}
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_Cursor *Cocoa_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSImage *nsimage;
|
||||
NSCursor *nscursor = NULL;
|
||||
SDL_Cursor *cursor = NULL;
|
||||
|
||||
nsimage = Cocoa_CreateImage(surface);
|
||||
if (nsimage) {
|
||||
nscursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSMakePoint(hot_x, hot_y)];
|
||||
}
|
||||
|
||||
if (nscursor) {
|
||||
cursor = SDL_calloc(1, sizeof(*cursor));
|
||||
if (cursor) {
|
||||
cursor->driverdata = (void *)CFBridgingRetain(nscursor);
|
||||
}
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/* there are .pdf files of some of the cursors we need, installed by default on macOS, but not available through NSCursor.
|
||||
If we can load them ourselves, use them, otherwise fallback to something standard but not super-great.
|
||||
Since these are under /System, they should be available even to sandboxed apps. */
|
||||
static NSCursor *LoadHiddenSystemCursor(NSString *cursorName, SEL fallback)
|
||||
{
|
||||
NSString *cursorPath = [@"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/Resources/cursors" stringByAppendingPathComponent:cursorName];
|
||||
NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[cursorPath stringByAppendingPathComponent:@"info.plist"]];
|
||||
/* we can't do animation atm. :/ */
|
||||
const int frames = (int)[[info valueForKey:@"frames"] integerValue];
|
||||
NSCursor *cursor;
|
||||
NSImage *image = [[NSImage alloc] initWithContentsOfFile:[cursorPath stringByAppendingPathComponent:@"cursor.pdf"]];
|
||||
if ((image == nil) || (image.isValid == NO)) {
|
||||
return [NSCursor performSelector:fallback];
|
||||
}
|
||||
|
||||
if (frames > 1) {
|
||||
#ifdef MAC_OS_VERSION_12_0 /* same value as deprecated symbol. */
|
||||
const NSCompositingOperation operation = NSCompositingOperationCopy;
|
||||
#else
|
||||
const NSCompositingOperation operation = NSCompositeCopy;
|
||||
#endif
|
||||
const NSSize cropped_size = NSMakeSize(image.size.width, (int)(image.size.height / frames));
|
||||
NSImage *cropped = [[NSImage alloc] initWithSize:cropped_size];
|
||||
if (cropped == nil) {
|
||||
return [NSCursor performSelector:fallback];
|
||||
}
|
||||
|
||||
[cropped lockFocus];
|
||||
{
|
||||
const NSRect cropped_rect = NSMakeRect(0, 0, cropped_size.width, cropped_size.height);
|
||||
[image drawInRect:cropped_rect fromRect:cropped_rect operation:operation fraction:1];
|
||||
}
|
||||
[cropped unlockFocus];
|
||||
image = cropped;
|
||||
}
|
||||
|
||||
cursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint([[info valueForKey:@"hotx"] doubleValue], [[info valueForKey:@"hoty"] doubleValue])];
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static SDL_Cursor *Cocoa_CreateSystemCursor(SDL_SystemCursor id)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSCursor *nscursor = NULL;
|
||||
SDL_Cursor *cursor = NULL;
|
||||
|
||||
switch (id) {
|
||||
case SDL_SYSTEM_CURSOR_ARROW:
|
||||
nscursor = [NSCursor arrowCursor];
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_IBEAM:
|
||||
nscursor = [NSCursor IBeamCursor];
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_CROSSHAIR:
|
||||
nscursor = [NSCursor crosshairCursor];
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WAIT: /* !!! FIXME: this is more like WAITARROW */
|
||||
nscursor = LoadHiddenSystemCursor(@"busybutclickable", @selector(arrowCursor));
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WAITARROW: /* !!! FIXME: this is meant to be animated */
|
||||
nscursor = LoadHiddenSystemCursor(@"busybutclickable", @selector(arrowCursor));
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENWSE:
|
||||
nscursor = LoadHiddenSystemCursor(@"resizenorthwestsoutheast", @selector(closedHandCursor));
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENESW:
|
||||
nscursor = LoadHiddenSystemCursor(@"resizenortheastsouthwest", @selector(closedHandCursor));
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEWE:
|
||||
nscursor = LoadHiddenSystemCursor(@"resizeeastwest", @selector(resizeLeftRightCursor));
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENS:
|
||||
nscursor = LoadHiddenSystemCursor(@"resizenorthsouth", @selector(resizeUpDownCursor));
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEALL:
|
||||
nscursor = LoadHiddenSystemCursor(@"move", @selector(closedHandCursor));
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_NO:
|
||||
nscursor = [NSCursor operationNotAllowedCursor];
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_HAND:
|
||||
nscursor = [NSCursor pointingHandCursor];
|
||||
break;
|
||||
default:
|
||||
SDL_assert(!"Unknown system cursor");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (nscursor) {
|
||||
cursor = SDL_calloc(1, sizeof(*cursor));
|
||||
if (cursor) {
|
||||
/* We'll free it later, so retain it here */
|
||||
cursor->driverdata = (void *)CFBridgingRetain(nscursor);
|
||||
}
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
static void Cocoa_FreeCursor(SDL_Cursor *cursor)
|
||||
{
|
||||
@autoreleasepool {
|
||||
CFBridgingRelease(cursor->driverdata);
|
||||
SDL_free(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
static int Cocoa_ShowCursor(SDL_Cursor *cursor)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_VideoDevice *device = SDL_GetVideoDevice();
|
||||
SDL_Window *window = (device ? device->windows : NULL);
|
||||
for (; window != NULL; window = window->next) {
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if(mouse->focus) {
|
||||
if (mouse->cursor_shown && mouse->cur_cursor && !mouse->relative_mode) {
|
||||
[(__bridge NSCursor*)mouse->cur_cursor->driverdata set];
|
||||
} else {
|
||||
[[NSCursor invisibleCursor] set];
|
||||
}
|
||||
} else {
|
||||
[[NSCursor arrowCursor] set];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_Window *SDL_FindWindowAtPoint(const float x, const float y)
|
||||
{
|
||||
const SDL_FPoint pt = { x, y };
|
||||
SDL_Window *i;
|
||||
for (i = SDL_GetVideoDevice()->windows; i; i = i->next) {
|
||||
const SDL_FRect r = { (float)i->x, (float)i->y, (float)i->w, (float)i->h };
|
||||
if (SDL_PointInRectFloat(&pt, &r)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int Cocoa_WarpMouseGlobal(float x, float y)
|
||||
{
|
||||
CGPoint point;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if (mouse->focus) {
|
||||
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)mouse->focus->driverdata;
|
||||
if ([data.listener isMovingOrFocusClickPending]) {
|
||||
DLog("Postponing warp, window being moved or focused.");
|
||||
[data.listener setPendingMoveX:x Y:y];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
point = CGPointMake(x, y);
|
||||
|
||||
Cocoa_HandleMouseWarp(point.x, point.y);
|
||||
|
||||
CGWarpMouseCursorPosition(point);
|
||||
|
||||
/* CGWarpMouse causes a short delay by default, which is preventable by
|
||||
* Calling this directly after. CGSetLocalEventsSuppressionInterval can also
|
||||
* prevent it, but it's deprecated as macOS 10.6.
|
||||
*/
|
||||
if (!mouse->relative_mode) {
|
||||
CGAssociateMouseAndMouseCursorPosition(YES);
|
||||
}
|
||||
|
||||
/* CGWarpMouseCursorPosition doesn't generate a window event, unlike our
|
||||
* other implementations' APIs. Send what's appropriate.
|
||||
*/
|
||||
if (!mouse->relative_mode) {
|
||||
SDL_Window *win = SDL_FindWindowAtPoint(x, y);
|
||||
SDL_SetMouseFocus(win);
|
||||
if (win) {
|
||||
SDL_assert(win == mouse->focus);
|
||||
SDL_SendMouseMotion(0, win, mouse->mouseID, 0, x - win->x, y - win->y);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Cocoa_WarpMouse(SDL_Window *window, float x, float y)
|
||||
{
|
||||
return Cocoa_WarpMouseGlobal(window->x + x, window->y + y);
|
||||
}
|
||||
|
||||
static int Cocoa_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
SDL_Window *window = SDL_GetKeyboardFocus();
|
||||
CGError result;
|
||||
SDL_CocoaWindowData *data;
|
||||
if (enabled) {
|
||||
if (window) {
|
||||
/* make sure the mouse isn't at the corner of the window, as this can confuse things if macOS thinks a window resize is happening on the first click. */
|
||||
const CGPoint point = CGPointMake((float)(window->x + (window->w / 2)), (float)(window->y + (window->h / 2)));
|
||||
Cocoa_HandleMouseWarp(point.x, point.y);
|
||||
CGWarpMouseCursorPosition(point);
|
||||
}
|
||||
DLog("Turning on.");
|
||||
result = CGAssociateMouseAndMouseCursorPosition(NO);
|
||||
} else {
|
||||
DLog("Turning off.");
|
||||
result = CGAssociateMouseAndMouseCursorPosition(YES);
|
||||
}
|
||||
if (result != kCGErrorSuccess) {
|
||||
return SDL_SetError("CGAssociateMouseAndMouseCursorPosition() failed");
|
||||
}
|
||||
|
||||
/* We will re-apply the non-relative mode when the window gets focus, if it
|
||||
* doesn't have focus right now.
|
||||
*/
|
||||
if (!window) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We will re-apply the non-relative mode when the window finishes being moved,
|
||||
* if it is being moved right now.
|
||||
*/
|
||||
data = (__bridge SDL_CocoaWindowData *)window->driverdata;
|
||||
if ([data.listener isMovingOrFocusClickPending]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The hide/unhide calls are redundant most of the time, but they fix
|
||||
* https://bugzilla.libsdl.org/show_bug.cgi?id=2550
|
||||
*/
|
||||
if (enabled) {
|
||||
[NSCursor hide];
|
||||
} else {
|
||||
[NSCursor unhide];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Cocoa_CaptureMouse(SDL_Window *window)
|
||||
{
|
||||
/* our Cocoa event code already tracks the mouse outside the window,
|
||||
so all we have to do here is say "okay" and do what we always do. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Uint32 Cocoa_GetGlobalMouseState(float *x, float *y)
|
||||
{
|
||||
const NSUInteger cocoaButtons = [NSEvent pressedMouseButtons];
|
||||
const NSPoint cocoaLocation = [NSEvent mouseLocation];
|
||||
Uint32 retval = 0;
|
||||
|
||||
*x = cocoaLocation.x;
|
||||
*y = (CGDisplayPixelsHigh(kCGDirectMainDisplay) - cocoaLocation.y);
|
||||
|
||||
retval |= (cocoaButtons & (1 << 0)) ? SDL_BUTTON_LMASK : 0;
|
||||
retval |= (cocoaButtons & (1 << 1)) ? SDL_BUTTON_RMASK : 0;
|
||||
retval |= (cocoaButtons & (1 << 2)) ? SDL_BUTTON_MMASK : 0;
|
||||
retval |= (cocoaButtons & (1 << 3)) ? SDL_BUTTON_X1MASK : 0;
|
||||
retval |= (cocoaButtons & (1 << 4)) ? SDL_BUTTON_X2MASK : 0;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int Cocoa_InitMouse(SDL_VideoDevice *_this)
|
||||
{
|
||||
NSPoint location;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_MouseData *driverdata = (SDL_MouseData *)SDL_calloc(1, sizeof(SDL_MouseData));
|
||||
if (driverdata == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
mouse->driverdata = driverdata;
|
||||
mouse->CreateCursor = Cocoa_CreateCursor;
|
||||
mouse->CreateSystemCursor = Cocoa_CreateSystemCursor;
|
||||
mouse->ShowCursor = Cocoa_ShowCursor;
|
||||
mouse->FreeCursor = Cocoa_FreeCursor;
|
||||
mouse->WarpMouse = Cocoa_WarpMouse;
|
||||
mouse->WarpMouseGlobal = Cocoa_WarpMouseGlobal;
|
||||
mouse->SetRelativeMouseMode = Cocoa_SetRelativeMouseMode;
|
||||
mouse->CaptureMouse = Cocoa_CaptureMouse;
|
||||
mouse->GetGlobalMouseState = Cocoa_GetGlobalMouseState;
|
||||
|
||||
SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
|
||||
|
||||
location = [NSEvent mouseLocation];
|
||||
driverdata->lastMoveX = location.x;
|
||||
driverdata->lastMoveY = location.y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Cocoa_HandleTitleButtonEvent(SDL_VideoDevice *_this, NSEvent *event)
|
||||
{
|
||||
SDL_Window *window;
|
||||
NSWindow *nswindow = [event window];
|
||||
|
||||
/* You might land in this function before SDL_Init if showing a message box.
|
||||
Don't dereference a NULL pointer if that happens. */
|
||||
if (_this == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (window = _this->windows; window; window = window->next) {
|
||||
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)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(SDL_VideoDevice *_this, NSEvent *event)
|
||||
{
|
||||
SDL_Mouse *mouse;
|
||||
SDL_MouseData *driverdata;
|
||||
SDL_MouseID mouseID;
|
||||
NSPoint location;
|
||||
CGFloat lastMoveX, lastMoveY;
|
||||
float deltaX, deltaY;
|
||||
SDL_bool seenWarp;
|
||||
switch ([event type]) {
|
||||
case NSEventTypeMouseMoved:
|
||||
case NSEventTypeLeftMouseDragged:
|
||||
case NSEventTypeRightMouseDragged:
|
||||
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;
|
||||
}
|
||||
|
||||
mouse = SDL_GetMouse();
|
||||
driverdata = (SDL_MouseData *)mouse->driverdata;
|
||||
if (!driverdata) {
|
||||
return; /* can happen when returning from fullscreen Space on shutdown */
|
||||
}
|
||||
|
||||
mouseID = mouse ? mouse->mouseID : 0;
|
||||
seenWarp = driverdata->seenWarp;
|
||||
driverdata->seenWarp = NO;
|
||||
|
||||
location = [NSEvent mouseLocation];
|
||||
lastMoveX = driverdata->lastMoveX;
|
||||
lastMoveY = driverdata->lastMoveY;
|
||||
driverdata->lastMoveX = location.x;
|
||||
driverdata->lastMoveY = location.y;
|
||||
DLog("Last seen mouse: (%g, %g)", location.x, location.y);
|
||||
|
||||
/* Non-relative movement is handled in -[Cocoa_WindowListener mouseMoved:] */
|
||||
if (!mouse->relative_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ignore events that aren't inside the client area (i.e. title bar.) */
|
||||
if ([event window]) {
|
||||
NSRect windowRect = [[[event window] contentView] frame];
|
||||
if (!NSMouseInRect([event locationInWindow], windowRect, NO)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
deltaX = [event deltaX];
|
||||
deltaY = [event deltaY];
|
||||
|
||||
if (seenWarp) {
|
||||
deltaX += (lastMoveX - driverdata->lastWarpX);
|
||||
deltaY += ((CGDisplayPixelsHigh(kCGDirectMainDisplay) - lastMoveY) - driverdata->lastWarpY);
|
||||
|
||||
DLog("Motion was (%g, %g), offset to (%g, %g)", [event deltaX], [event deltaY], deltaX, deltaY);
|
||||
}
|
||||
|
||||
SDL_SendMouseMotion(Cocoa_GetEventTimestamp([event timestamp]), mouse->focus, mouseID, 1, deltaX, deltaY);
|
||||
}
|
||||
|
||||
void Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
|
||||
{
|
||||
SDL_MouseID mouseID;
|
||||
SDL_MouseWheelDirection direction;
|
||||
CGFloat x, y;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if (!mouse) {
|
||||
return;
|
||||
}
|
||||
|
||||
mouseID = mouse->mouseID;
|
||||
x = -[event deltaX];
|
||||
y = [event deltaY];
|
||||
direction = SDL_MOUSEWHEEL_NORMAL;
|
||||
|
||||
if ([event isDirectionInvertedFromDevice] == YES) {
|
||||
direction = SDL_MOUSEWHEEL_FLIPPED;
|
||||
}
|
||||
|
||||
/* 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 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(Cocoa_GetEventTimestamp([event timestamp]), window, mouseID, x, y, direction);
|
||||
}
|
||||
|
||||
void Cocoa_HandleMouseWarp(CGFloat x, CGFloat y)
|
||||
{
|
||||
/* This makes Cocoa_HandleMouseEvent ignore the delta caused by the warp,
|
||||
* since it gets included in the next movement event.
|
||||
*/
|
||||
SDL_MouseData *driverdata = (SDL_MouseData *)SDL_GetMouse()->driverdata;
|
||||
driverdata->lastWarpX = x;
|
||||
driverdata->lastWarpY = y;
|
||||
driverdata->seenWarp = SDL_TRUE;
|
||||
|
||||
DLog("(%g, %g)", x, y);
|
||||
}
|
||||
|
||||
void Cocoa_QuitMouse(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if (mouse) {
|
||||
if (mouse->driverdata) {
|
||||
SDL_free(mouse->driverdata);
|
||||
mouse->driverdata = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
89
external/sdl/SDL/src/video/cocoa/SDL_cocoaopengl.h
vendored
Normal file
89
external/sdl/SDL/src/video/cocoa/SDL_cocoaopengl.h
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoaopengl_h_
|
||||
#define SDL_cocoaopengl_h_
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_CGL
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <QuartzCore/CVDisplayLink.h>
|
||||
|
||||
/* We still support OpenGL as long as Apple offers it, deprecated or not, so disable deprecation warnings about it. */
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
struct SDL_GLDriverData
|
||||
{
|
||||
int initialized;
|
||||
};
|
||||
|
||||
@interface SDLOpenGLContext : NSOpenGLContext
|
||||
{
|
||||
SDL_AtomicInt dirty;
|
||||
SDL_Window *window;
|
||||
CVDisplayLinkRef displayLink;
|
||||
@public
|
||||
SDL_Mutex *swapIntervalMutex;
|
||||
@public
|
||||
SDL_Condition *swapIntervalCond;
|
||||
@public
|
||||
SDL_AtomicInt swapIntervalSetting;
|
||||
@public
|
||||
SDL_AtomicInt swapIntervalsPassed;
|
||||
}
|
||||
|
||||
- (id)initWithFormat:(NSOpenGLPixelFormat *)format
|
||||
shareContext:(NSOpenGLContext *)share;
|
||||
- (void)scheduleUpdate;
|
||||
- (void)updateIfNeeded;
|
||||
- (void)movedToNewScreen;
|
||||
- (void)setWindow:(SDL_Window *)window;
|
||||
- (SDL_Window *)window;
|
||||
- (void)explicitUpdate;
|
||||
- (void)cleanup;
|
||||
|
||||
@property(retain, nonatomic) NSOpenGLPixelFormat *openglPixelFormat; // macOS 10.10 has -[NSOpenGLContext pixelFormat] but this handles older OS releases.
|
||||
|
||||
@end
|
||||
|
||||
/* OpenGL functions */
|
||||
extern int Cocoa_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path);
|
||||
extern SDL_FunctionPointer Cocoa_GL_GetProcAddress(SDL_VideoDevice *_this, const char *proc);
|
||||
extern void Cocoa_GL_UnloadLibrary(SDL_VideoDevice *_this);
|
||||
extern SDL_GLContext Cocoa_GL_CreateContext(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int Cocoa_GL_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window,
|
||||
SDL_GLContext context);
|
||||
extern int Cocoa_GL_SetSwapInterval(SDL_VideoDevice *_this, int interval);
|
||||
extern int Cocoa_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval);
|
||||
extern int Cocoa_GL_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int Cocoa_GL_DeleteContext(SDL_VideoDevice *_this, SDL_GLContext context);
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif /* SDL_VIDEO_OPENGL_CGL */
|
||||
|
||||
#endif /* SDL_cocoaopengl_h_ */
|
541
external/sdl/SDL/src/video/cocoa/SDL_cocoaopengl.m
vendored
Normal file
541
external/sdl/SDL/src/video/cocoa/SDL_cocoaopengl.m
vendored
Normal file
@ -0,0 +1,541 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
/* NSOpenGL implementation of SDL OpenGL support */
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_CGL
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "SDL_cocoaopengl.h"
|
||||
#include "SDL_cocoaopengles.h"
|
||||
|
||||
#include <OpenGL/CGLTypes.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenGL/CGLRenderers.h>
|
||||
|
||||
#include <SDL3/SDL_opengl.h>
|
||||
#include "../../SDL_hints_c.h"
|
||||
|
||||
#define DEFAULT_OPENGL "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
|
||||
|
||||
/* We still support OpenGL as long as Apple offers it, deprecated or not, so disable deprecation warnings about it. */
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
/* _Nullable is available starting Xcode 7 */
|
||||
#ifdef __has_feature
|
||||
#if __has_feature(nullability)
|
||||
#define HAS_FEATURE_NULLABLE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HAS_FEATURE_NULLABLE
|
||||
#define _Nullable
|
||||
#endif
|
||||
|
||||
static SDL_bool SDL_opengl_async_dispatch = SDL_FALSE;
|
||||
|
||||
static void SDLCALL SDL_OpenGLAsyncDispatchChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_opengl_async_dispatch = SDL_GetStringBoolean(hint, SDL_FALSE);
|
||||
}
|
||||
|
||||
static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext)
|
||||
{
|
||||
SDLOpenGLContext *nscontext = (__bridge SDLOpenGLContext *)displayLinkContext;
|
||||
|
||||
/*printf("DISPLAY LINK! %u\n", (unsigned int) SDL_GetTicks()); */
|
||||
const int setting = SDL_AtomicGet(&nscontext->swapIntervalSetting);
|
||||
if (setting != 0) { /* nothing to do if vsync is disabled, don't even lock */
|
||||
SDL_LockMutex(nscontext->swapIntervalMutex);
|
||||
SDL_AtomicAdd(&nscontext->swapIntervalsPassed, 1);
|
||||
SDL_SignalCondition(nscontext->swapIntervalCond);
|
||||
SDL_UnlockMutex(nscontext->swapIntervalMutex);
|
||||
}
|
||||
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
|
||||
@implementation SDLOpenGLContext : NSOpenGLContext
|
||||
|
||||
- (id)initWithFormat:(NSOpenGLPixelFormat *)format
|
||||
shareContext:(NSOpenGLContext *)share
|
||||
{
|
||||
self = [super initWithFormat:format shareContext:share];
|
||||
if (self) {
|
||||
self.openglPixelFormat = format;
|
||||
SDL_AtomicSet(&self->dirty, 0);
|
||||
self->window = NULL;
|
||||
SDL_AtomicSet(&self->swapIntervalSetting, 0);
|
||||
SDL_AtomicSet(&self->swapIntervalsPassed, 0);
|
||||
self->swapIntervalCond = SDL_CreateCondition();
|
||||
self->swapIntervalMutex = SDL_CreateMutex();
|
||||
if (!self->swapIntervalCond || !self->swapIntervalMutex) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* !!! FIXME: check return values. */
|
||||
CVDisplayLinkCreateWithActiveCGDisplays(&self->displayLink);
|
||||
CVDisplayLinkSetOutputCallback(self->displayLink, &DisplayLinkCallback, (__bridge void *_Nullable)self);
|
||||
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(self->displayLink, [self CGLContextObj], [format CGLPixelFormatObj]);
|
||||
CVDisplayLinkStart(displayLink);
|
||||
}
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_MAC_OPENGL_ASYNC_DISPATCH, SDL_OpenGLAsyncDispatchChanged, NULL);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)movedToNewScreen
|
||||
{
|
||||
if (self->displayLink) {
|
||||
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(self->displayLink, [self CGLContextObj], [[self openglPixelFormat] CGLPixelFormatObj]);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)scheduleUpdate
|
||||
{
|
||||
SDL_AtomicAdd(&self->dirty, 1);
|
||||
}
|
||||
|
||||
/* This should only be called on the thread on which a user is using the context. */
|
||||
- (void)updateIfNeeded
|
||||
{
|
||||
const int value = SDL_AtomicSet(&self->dirty, 0);
|
||||
if (value > 0) {
|
||||
/* We call the real underlying update here, since -[SDLOpenGLContext update] just calls us. */
|
||||
[self explicitUpdate];
|
||||
}
|
||||
}
|
||||
|
||||
/* This should only be called on the thread on which a user is using the context. */
|
||||
- (void)update
|
||||
{
|
||||
/* This ensures that regular 'update' calls clear the atomic dirty flag. */
|
||||
[self scheduleUpdate];
|
||||
[self updateIfNeeded];
|
||||
}
|
||||
|
||||
/* Updates the drawable for the contexts and manages related state. */
|
||||
- (void)setWindow:(SDL_Window *)newWindow
|
||||
{
|
||||
if (self->window) {
|
||||
SDL_CocoaWindowData *oldwindowdata = (__bridge SDL_CocoaWindowData *)self->window->driverdata;
|
||||
|
||||
/* Make sure to remove us from the old window's context list, or we'll get scheduled updates from it too. */
|
||||
NSMutableArray *contexts = oldwindowdata.nscontexts;
|
||||
@synchronized(contexts) {
|
||||
[contexts removeObject:self];
|
||||
}
|
||||
}
|
||||
|
||||
self->window = newWindow;
|
||||
|
||||
if (newWindow) {
|
||||
SDL_CocoaWindowData *windowdata = (__bridge SDL_CocoaWindowData *)newWindow->driverdata;
|
||||
NSView *contentview = windowdata.sdlContentView;
|
||||
|
||||
/* Now sign up for scheduled updates for the new window. */
|
||||
NSMutableArray *contexts = windowdata.nscontexts;
|
||||
@synchronized(contexts) {
|
||||
[contexts addObject:self];
|
||||
}
|
||||
|
||||
if ([self view] != contentview) {
|
||||
if ([NSThread isMainThread]) {
|
||||
[self setView:contentview];
|
||||
} else {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
[self setView:contentview];
|
||||
});
|
||||
}
|
||||
if (self == [NSOpenGLContext currentContext]) {
|
||||
[self explicitUpdate];
|
||||
} else {
|
||||
[self scheduleUpdate];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ([NSThread isMainThread]) {
|
||||
[self setView:nil];
|
||||
} else {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{ [self setView:nil]; });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (SDL_Window *)window
|
||||
{
|
||||
return self->window;
|
||||
}
|
||||
|
||||
- (void)explicitUpdate
|
||||
{
|
||||
if ([NSThread isMainThread]) {
|
||||
[super update];
|
||||
} else {
|
||||
if (SDL_opengl_async_dispatch) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[super update];
|
||||
});
|
||||
} else {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
[super update];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cleanup
|
||||
{
|
||||
[self setWindow:NULL];
|
||||
|
||||
SDL_DelHintCallback(SDL_HINT_MAC_OPENGL_ASYNC_DISPATCH, SDL_OpenGLAsyncDispatchChanged, NULL);
|
||||
if (self->displayLink) {
|
||||
CVDisplayLinkRelease(self->displayLink);
|
||||
self->displayLink = nil;
|
||||
}
|
||||
if (self->swapIntervalCond) {
|
||||
SDL_DestroyCondition(self->swapIntervalCond);
|
||||
self->swapIntervalCond = NULL;
|
||||
}
|
||||
if (self->swapIntervalMutex) {
|
||||
SDL_DestroyMutex(self->swapIntervalMutex);
|
||||
self->swapIntervalMutex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int Cocoa_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
||||
{
|
||||
/* Load the OpenGL library */
|
||||
if (path == NULL) {
|
||||
path = SDL_getenv("SDL_OPENGL_LIBRARY");
|
||||
}
|
||||
if (path == NULL) {
|
||||
path = DEFAULT_OPENGL;
|
||||
}
|
||||
_this->gl_config.dll_handle = SDL_LoadObject(path);
|
||||
if (!_this->gl_config.dll_handle) {
|
||||
return -1;
|
||||
}
|
||||
SDL_strlcpy(_this->gl_config.driver_path, path,
|
||||
SDL_arraysize(_this->gl_config.driver_path));
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_FunctionPointer Cocoa_GL_GetProcAddress(SDL_VideoDevice *_this, const char *proc)
|
||||
{
|
||||
return SDL_LoadFunction(_this->gl_config.dll_handle, proc);
|
||||
}
|
||||
|
||||
void Cocoa_GL_UnloadLibrary(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_UnloadObject(_this->gl_config.dll_handle);
|
||||
_this->gl_config.dll_handle = NULL;
|
||||
}
|
||||
|
||||
SDL_GLContext Cocoa_GL_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_VideoDisplay *display = SDL_GetVideoDisplayForWindow(window);
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
|
||||
NSOpenGLPixelFormatAttribute attr[32];
|
||||
NSOpenGLPixelFormat *fmt;
|
||||
SDLOpenGLContext *context;
|
||||
SDL_GLContext sdlcontext;
|
||||
NSOpenGLContext *share_context = nil;
|
||||
int i = 0;
|
||||
const char *glversion;
|
||||
int glversion_major;
|
||||
int glversion_minor;
|
||||
NSOpenGLPixelFormatAttribute profile;
|
||||
int interval;
|
||||
int opaque;
|
||||
|
||||
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
/* Switch to EGL based functions */
|
||||
Cocoa_GL_UnloadLibrary(_this);
|
||||
_this->GL_LoadLibrary = Cocoa_GLES_LoadLibrary;
|
||||
_this->GL_GetProcAddress = Cocoa_GLES_GetProcAddress;
|
||||
_this->GL_UnloadLibrary = Cocoa_GLES_UnloadLibrary;
|
||||
_this->GL_CreateContext = Cocoa_GLES_CreateContext;
|
||||
_this->GL_MakeCurrent = Cocoa_GLES_MakeCurrent;
|
||||
_this->GL_SetSwapInterval = Cocoa_GLES_SetSwapInterval;
|
||||
_this->GL_GetSwapInterval = Cocoa_GLES_GetSwapInterval;
|
||||
_this->GL_SwapWindow = Cocoa_GLES_SwapWindow;
|
||||
_this->GL_DeleteContext = Cocoa_GLES_DeleteContext;
|
||||
|
||||
if (Cocoa_GLES_LoadLibrary(_this, NULL) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
return Cocoa_GLES_CreateContext(_this, window);
|
||||
#else
|
||||
SDL_SetError("SDL not configured with EGL support");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
attr[i++] = NSOpenGLPFAAllowOfflineRenderers;
|
||||
|
||||
profile = NSOpenGLProfileVersionLegacy;
|
||||
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_CORE) {
|
||||
profile = NSOpenGLProfileVersion3_2Core;
|
||||
}
|
||||
attr[i++] = NSOpenGLPFAOpenGLProfile;
|
||||
attr[i++] = profile;
|
||||
|
||||
attr[i++] = NSOpenGLPFAColorSize;
|
||||
attr[i++] = SDL_BYTESPERPIXEL(display->current_mode->format) * 8;
|
||||
|
||||
attr[i++] = NSOpenGLPFADepthSize;
|
||||
attr[i++] = _this->gl_config.depth_size;
|
||||
|
||||
if (_this->gl_config.double_buffer) {
|
||||
attr[i++] = NSOpenGLPFADoubleBuffer;
|
||||
}
|
||||
|
||||
if (_this->gl_config.stereo) {
|
||||
attr[i++] = NSOpenGLPFAStereo;
|
||||
}
|
||||
|
||||
if (_this->gl_config.stencil_size) {
|
||||
attr[i++] = NSOpenGLPFAStencilSize;
|
||||
attr[i++] = _this->gl_config.stencil_size;
|
||||
}
|
||||
|
||||
if ((_this->gl_config.accum_red_size +
|
||||
_this->gl_config.accum_green_size +
|
||||
_this->gl_config.accum_blue_size +
|
||||
_this->gl_config.accum_alpha_size) > 0) {
|
||||
attr[i++] = NSOpenGLPFAAccumSize;
|
||||
attr[i++] = _this->gl_config.accum_red_size + _this->gl_config.accum_green_size + _this->gl_config.accum_blue_size + _this->gl_config.accum_alpha_size;
|
||||
}
|
||||
|
||||
if (_this->gl_config.multisamplebuffers) {
|
||||
attr[i++] = NSOpenGLPFASampleBuffers;
|
||||
attr[i++] = _this->gl_config.multisamplebuffers;
|
||||
}
|
||||
|
||||
if (_this->gl_config.multisamplesamples) {
|
||||
attr[i++] = NSOpenGLPFASamples;
|
||||
attr[i++] = _this->gl_config.multisamplesamples;
|
||||
attr[i++] = NSOpenGLPFANoRecovery;
|
||||
}
|
||||
if (_this->gl_config.floatbuffers) {
|
||||
attr[i++] = NSOpenGLPFAColorFloat;
|
||||
}
|
||||
|
||||
if (_this->gl_config.accelerated >= 0) {
|
||||
if (_this->gl_config.accelerated) {
|
||||
attr[i++] = NSOpenGLPFAAccelerated;
|
||||
} else {
|
||||
attr[i++] = NSOpenGLPFARendererID;
|
||||
attr[i++] = kCGLRendererGenericFloatID;
|
||||
}
|
||||
}
|
||||
|
||||
attr[i++] = NSOpenGLPFAScreenMask;
|
||||
attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
|
||||
attr[i] = 0;
|
||||
|
||||
fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
|
||||
if (fmt == nil) {
|
||||
SDL_SetError("Failed creating OpenGL pixel format");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_this->gl_config.share_with_current_context) {
|
||||
share_context = (__bridge NSOpenGLContext *)SDL_GL_GetCurrentContext();
|
||||
}
|
||||
|
||||
context = [[SDLOpenGLContext alloc] initWithFormat:fmt shareContext:share_context];
|
||||
|
||||
if (context == nil) {
|
||||
SDL_SetError("Failed creating OpenGL context");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sdlcontext = (SDL_GLContext)CFBridgingRetain(context);
|
||||
|
||||
/* vsync is handled separately by synchronizing with a display link. */
|
||||
interval = 0;
|
||||
[context setValues:&interval forParameter:NSOpenGLCPSwapInterval];
|
||||
|
||||
opaque = (window->flags & SDL_WINDOW_TRANSPARENT) ? 0 : 1;
|
||||
[context setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
|
||||
|
||||
if (Cocoa_GL_MakeCurrent(_this, window, sdlcontext) < 0) {
|
||||
SDL_GL_DeleteContext(sdlcontext);
|
||||
SDL_SetError("Failed making OpenGL context current");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_this->gl_config.major_version < 3 &&
|
||||
_this->gl_config.profile_mask == 0 &&
|
||||
_this->gl_config.flags == 0) {
|
||||
/* This is a legacy profile, so to match other backends, we're done. */
|
||||
} else {
|
||||
const GLubyte *(APIENTRY * glGetStringFunc)(GLenum);
|
||||
|
||||
glGetStringFunc = (const GLubyte *(APIENTRY *)(GLenum))SDL_GL_GetProcAddress("glGetString");
|
||||
if (!glGetStringFunc) {
|
||||
SDL_GL_DeleteContext(sdlcontext);
|
||||
SDL_SetError("Failed getting OpenGL glGetString entry point");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
glversion = (const char *)glGetStringFunc(GL_VERSION);
|
||||
if (glversion == NULL) {
|
||||
SDL_GL_DeleteContext(sdlcontext);
|
||||
SDL_SetError("Failed getting OpenGL context version");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SDL_sscanf(glversion, "%d.%d", &glversion_major, &glversion_minor) != 2) {
|
||||
SDL_GL_DeleteContext(sdlcontext);
|
||||
SDL_SetError("Failed parsing OpenGL context version");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((glversion_major < _this->gl_config.major_version) ||
|
||||
((glversion_major == _this->gl_config.major_version) && (glversion_minor < _this->gl_config.minor_version))) {
|
||||
SDL_GL_DeleteContext(sdlcontext);
|
||||
SDL_SetError("Failed creating OpenGL context at version requested");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* In the future we'll want to do this, but to match other platforms
|
||||
we'll leave the OpenGL version the way it is for now
|
||||
*/
|
||||
/*_this->gl_config.major_version = glversion_major;*/
|
||||
/*_this->gl_config.minor_version = glversion_minor;*/
|
||||
}
|
||||
return sdlcontext;
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_GL_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context)
|
||||
{
|
||||
@autoreleasepool {
|
||||
if (context) {
|
||||
SDLOpenGLContext *nscontext = (__bridge SDLOpenGLContext *)context;
|
||||
if ([nscontext window] != window) {
|
||||
[nscontext setWindow:window];
|
||||
[nscontext updateIfNeeded];
|
||||
}
|
||||
[nscontext makeCurrentContext];
|
||||
} else {
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_GL_SetSwapInterval(SDL_VideoDevice *_this, int interval)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDLOpenGLContext *nscontext = (__bridge SDLOpenGLContext *)SDL_GL_GetCurrentContext();
|
||||
int status;
|
||||
|
||||
if (nscontext == nil) {
|
||||
status = SDL_SetError("No current OpenGL context");
|
||||
} else {
|
||||
SDL_LockMutex(nscontext->swapIntervalMutex);
|
||||
SDL_AtomicSet(&nscontext->swapIntervalsPassed, 0);
|
||||
SDL_AtomicSet(&nscontext->swapIntervalSetting, interval);
|
||||
SDL_UnlockMutex(nscontext->swapIntervalMutex);
|
||||
status = 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDLOpenGLContext *nscontext = (__bridge SDLOpenGLContext *)SDL_GL_GetCurrentContext();
|
||||
if (nscontext) {
|
||||
*interval = SDL_AtomicGet(&nscontext->swapIntervalSetting);
|
||||
return 0;
|
||||
} else {
|
||||
return SDL_SetError("no OpenGL context");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_GL_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDLOpenGLContext *nscontext = (__bridge SDLOpenGLContext *)SDL_GL_GetCurrentContext();
|
||||
SDL_CocoaVideoData *videodata = (__bridge SDL_CocoaVideoData *)_this->driverdata;
|
||||
const int setting = SDL_AtomicGet(&nscontext->swapIntervalSetting);
|
||||
|
||||
if (setting == 0) {
|
||||
/* nothing to do if vsync is disabled, don't even lock */
|
||||
} else if (setting < 0) { /* late swap tearing */
|
||||
SDL_LockMutex(nscontext->swapIntervalMutex);
|
||||
while (SDL_AtomicGet(&nscontext->swapIntervalsPassed) == 0) {
|
||||
SDL_WaitCondition(nscontext->swapIntervalCond, nscontext->swapIntervalMutex);
|
||||
}
|
||||
SDL_AtomicSet(&nscontext->swapIntervalsPassed, 0);
|
||||
SDL_UnlockMutex(nscontext->swapIntervalMutex);
|
||||
} else {
|
||||
SDL_LockMutex(nscontext->swapIntervalMutex);
|
||||
do { /* always wait here so we know we just hit a swap interval. */
|
||||
SDL_WaitCondition(nscontext->swapIntervalCond, nscontext->swapIntervalMutex);
|
||||
} while ((SDL_AtomicGet(&nscontext->swapIntervalsPassed) % setting) != 0);
|
||||
SDL_AtomicSet(&nscontext->swapIntervalsPassed, 0);
|
||||
SDL_UnlockMutex(nscontext->swapIntervalMutex);
|
||||
}
|
||||
|
||||
/*{ static Uint64 prev = 0; const Uint64 now = SDL_GetTicks(); const unsigned int diff = (unsigned int) (now - prev); prev = now; printf("GLSWAPBUFFERS TICKS %u\n", diff); }*/
|
||||
|
||||
/* on 10.14 ("Mojave") and later, this deadlocks if two contexts in two
|
||||
threads try to swap at the same time, so put a mutex around it. */
|
||||
SDL_LockMutex(videodata.swaplock);
|
||||
[nscontext flushBuffer];
|
||||
[nscontext updateIfNeeded];
|
||||
SDL_UnlockMutex(videodata.swaplock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_GL_DeleteContext(SDL_VideoDevice *_this, SDL_GLContext context)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDLOpenGLContext *nscontext = (__bridge SDLOpenGLContext *)context;
|
||||
[nscontext cleanup];
|
||||
CFRelease(context);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We still support OpenGL as long as Apple offers it, deprecated or not, so disable deprecation warnings about it. */
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif /* SDL_VIDEO_OPENGL_CGL */
|
48
external/sdl/SDL/src/video/cocoa/SDL_cocoaopengles.h
vendored
Normal file
48
external/sdl/SDL/src/video/cocoa/SDL_cocoaopengles.h
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoaopengles_h_
|
||||
#define SDL_cocoaopengles_h_
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
|
||||
/* OpenGLES functions */
|
||||
#define Cocoa_GLES_GetAttribute SDL_EGL_GetAttribute
|
||||
#define Cocoa_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal
|
||||
#define Cocoa_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
|
||||
#define Cocoa_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
|
||||
#define Cocoa_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
|
||||
|
||||
extern int Cocoa_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path);
|
||||
extern SDL_GLContext Cocoa_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int Cocoa_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int Cocoa_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context);
|
||||
extern int Cocoa_GLES_DeleteContext(SDL_VideoDevice *_this, SDL_GLContext context);
|
||||
extern int Cocoa_GLES_SetupWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern SDL_EGLSurface Cocoa_GLES_GetEGLSurface(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
|
||||
#endif /* SDL_VIDEO_OPENGL_EGL */
|
||||
|
||||
#endif /* SDL_cocoaopengles_h_ */
|
156
external/sdl/SDL/src/video/cocoa/SDL_cocoaopengles.m
vendored
Normal file
156
external/sdl/SDL/src/video/cocoa/SDL_cocoaopengles.m
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if defined(SDL_VIDEO_DRIVER_COCOA) && defined(SDL_VIDEO_OPENGL_EGL)
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "SDL_cocoaopengles.h"
|
||||
#include "SDL_cocoaopengl.h"
|
||||
|
||||
/* EGL implementation of SDL OpenGL support */
|
||||
|
||||
int Cocoa_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
||||
{
|
||||
/* If the profile requested is not GL ES, switch over to WIN_GL functions */
|
||||
if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) {
|
||||
#ifdef SDL_VIDEO_OPENGL_CGL
|
||||
Cocoa_GLES_UnloadLibrary(_this);
|
||||
_this->GL_LoadLibrary = Cocoa_GL_LoadLibrary;
|
||||
_this->GL_GetProcAddress = Cocoa_GL_GetProcAddress;
|
||||
_this->GL_UnloadLibrary = Cocoa_GL_UnloadLibrary;
|
||||
_this->GL_CreateContext = Cocoa_GL_CreateContext;
|
||||
_this->GL_MakeCurrent = Cocoa_GL_MakeCurrent;
|
||||
_this->GL_SetSwapInterval = Cocoa_GL_SetSwapInterval;
|
||||
_this->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval;
|
||||
_this->GL_SwapWindow = Cocoa_GL_SwapWindow;
|
||||
_this->GL_DeleteContext = Cocoa_GL_DeleteContext;
|
||||
_this->GL_GetEGLSurface = NULL;
|
||||
return Cocoa_GL_LoadLibrary(_this, path);
|
||||
#else
|
||||
return SDL_SetError("SDL not configured with OpenGL/CGL support");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (_this->egl_data == NULL) {
|
||||
return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, _this->gl_config.egl_platform);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_GLContext Cocoa_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_GLContext context;
|
||||
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata;
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_CGL
|
||||
if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) {
|
||||
/* Switch to CGL based functions */
|
||||
Cocoa_GLES_UnloadLibrary(_this);
|
||||
_this->GL_LoadLibrary = Cocoa_GL_LoadLibrary;
|
||||
_this->GL_GetProcAddress = Cocoa_GL_GetProcAddress;
|
||||
_this->GL_UnloadLibrary = Cocoa_GL_UnloadLibrary;
|
||||
_this->GL_CreateContext = Cocoa_GL_CreateContext;
|
||||
_this->GL_MakeCurrent = Cocoa_GL_MakeCurrent;
|
||||
_this->GL_SetSwapInterval = Cocoa_GL_SetSwapInterval;
|
||||
_this->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval;
|
||||
_this->GL_SwapWindow = Cocoa_GL_SwapWindow;
|
||||
_this->GL_DeleteContext = Cocoa_GL_DeleteContext;
|
||||
_this->GL_GetEGLSurface = NULL;
|
||||
|
||||
if (Cocoa_GL_LoadLibrary(_this, NULL) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Cocoa_GL_CreateContext(_this, window);
|
||||
}
|
||||
#endif
|
||||
|
||||
context = SDL_EGL_CreateContext(_this, data.egl_surface);
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_GLES_DeleteContext(SDL_VideoDevice *_this, SDL_GLContext context)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_EGL_DeleteContext(_this, context);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Cocoa_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
return SDL_EGL_SwapBuffers(_this, ((__bridge SDL_CocoaWindowData *)window->driverdata).egl_surface);
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context)
|
||||
{
|
||||
@autoreleasepool {
|
||||
return SDL_EGL_MakeCurrent(_this, window ? ((__bridge SDL_CocoaWindowData *)window->driverdata).egl_surface : EGL_NO_SURFACE, context);
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_GLES_SetupWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSView *v;
|
||||
/* The current context is lost in here; save it and reset it. */
|
||||
SDL_CocoaWindowData *windowdata = (__bridge SDL_CocoaWindowData *)window->driverdata;
|
||||
SDL_Window *current_win = SDL_GL_GetCurrentWindow();
|
||||
SDL_GLContext current_ctx = SDL_GL_GetCurrentContext();
|
||||
|
||||
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, _this->gl_config.egl_platform) < 0) {
|
||||
SDL_EGL_UnloadLibrary(_this);
|
||||
return -1;
|
||||
}
|
||||
_this->gl_config.driver_loaded = 1;
|
||||
}
|
||||
|
||||
/* Create the GLES window surface */
|
||||
v = windowdata.nswindow.contentView;
|
||||
windowdata.egl_surface = SDL_EGL_CreateSurface(_this, window, (__bridge NativeWindowType)[v layer]);
|
||||
|
||||
if (windowdata.egl_surface == EGL_NO_SURFACE) {
|
||||
return SDL_SetError("Could not create GLES window surface");
|
||||
}
|
||||
|
||||
return Cocoa_GLES_MakeCurrent(_this, current_win, current_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_EGLSurface Cocoa_GLES_GetEGLSurface(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
return ((__bridge SDL_CocoaWindowData *)window->driverdata).egl_surface;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA && SDL_VIDEO_OPENGL_EGL */
|
38
external/sdl/SDL/src/video/cocoa/SDL_cocoashape.h
vendored
Normal file
38
external/sdl/SDL/src/video/cocoa/SDL_cocoashape.h
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoashape_h_
|
||||
#define SDL_cocoashape_h_
|
||||
|
||||
#include "../SDL_shape_internals.h"
|
||||
|
||||
@interface SDL_ShapeData : NSObject
|
||||
@property(nonatomic) NSGraphicsContext *context;
|
||||
@property(nonatomic) SDL_bool saved;
|
||||
@property(nonatomic) SDL_ShapeTree *shape;
|
||||
@end
|
||||
|
||||
extern SDL_WindowShaper *Cocoa_CreateShaper(SDL_Window *window);
|
||||
extern int Cocoa_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode);
|
||||
|
||||
#endif /* SDL_cocoashape_h_ */
|
115
external/sdl/SDL/src/video/cocoa/SDL_cocoashape.m
vendored
Normal file
115
external/sdl/SDL/src/video/cocoa/SDL_cocoashape.m
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_COCOA
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "SDL_cocoashape.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
@implementation SDL_ShapeData
|
||||
@end
|
||||
|
||||
@interface SDL_CocoaClosure : NSObject
|
||||
@property(nonatomic) NSView *view;
|
||||
@property(nonatomic) NSBezierPath *path;
|
||||
@property(nonatomic) SDL_Window *window;
|
||||
@end
|
||||
|
||||
@implementation SDL_CocoaClosure
|
||||
@end
|
||||
|
||||
SDL_WindowShaper *Cocoa_CreateShaper(SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_WindowShaper *result;
|
||||
SDL_ShapeData *data;
|
||||
SDL_CocoaWindowData *windata = (__bridge SDL_CocoaWindowData *)window->driverdata;
|
||||
|
||||
result = (SDL_WindowShaper *)SDL_malloc(sizeof(SDL_WindowShaper));
|
||||
if (!result) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
[windata.nswindow setOpaque:NO];
|
||||
|
||||
[windata.nswindow setStyleMask:NSWindowStyleMaskBorderless];
|
||||
|
||||
result->window = window;
|
||||
result->mode.mode = ShapeModeDefault;
|
||||
result->mode.parameters.binarizationCutoff = 1;
|
||||
window->shaper = result;
|
||||
|
||||
data = [[SDL_ShapeData alloc] init];
|
||||
data.context = [windata.nswindow graphicsContext];
|
||||
data.saved = SDL_FALSE;
|
||||
data.shape = NULL;
|
||||
|
||||
/* TODO: There's no place to release this... */
|
||||
result->driverdata = (void *)CFBridgingRetain(data);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertRects(SDL_ShapeTree *tree, void *closure)
|
||||
{
|
||||
SDL_CocoaClosure *data = (__bridge SDL_CocoaClosure *)closure;
|
||||
if (tree->kind == OpaqueShape) {
|
||||
NSRect rect = NSMakeRect(tree->data.shape.x, data.window->h - tree->data.shape.y, tree->data.shape.w, tree->data.shape.h);
|
||||
[data.path appendBezierPathWithRect:[data.view convertRect:rect toView:nil]];
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_SetWindowShape(SDL_WindowShaper *shaper, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_ShapeData *data = (__bridge SDL_ShapeData *)shaper->driverdata;
|
||||
SDL_CocoaWindowData *windata = (__bridge SDL_CocoaWindowData *)shaper->window->driverdata;
|
||||
SDL_CocoaClosure *closure;
|
||||
if (data.saved == SDL_TRUE) {
|
||||
[data.context restoreGraphicsState];
|
||||
data.saved = SDL_FALSE;
|
||||
}
|
||||
|
||||
/*[data.context saveGraphicsState];*/
|
||||
/*data.saved = SDL_TRUE;*/
|
||||
[NSGraphicsContext setCurrentContext:data.context];
|
||||
|
||||
[[NSColor clearColor] set];
|
||||
NSRectFill([windata.sdlContentView frame]);
|
||||
data.shape = SDL_CalculateShapeTree(*shape_mode, shape);
|
||||
|
||||
closure = [[SDL_CocoaClosure alloc] init];
|
||||
|
||||
closure.view = windata.sdlContentView;
|
||||
closure.path = [NSBezierPath bezierPath];
|
||||
closure.window = shaper->window;
|
||||
SDL_TraverseShapeTree(data.shape, &ConvertRects, (__bridge void *)closure);
|
||||
[closure.path addClip];
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
119
external/sdl/SDL/src/video/cocoa/SDL_cocoavideo.h
vendored
Normal file
119
external/sdl/SDL/src/video/cocoa/SDL_cocoavideo.h
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoavideo_h_
|
||||
#define SDL_cocoavideo_h_
|
||||
|
||||
#include <SDL3/SDL_opengl.h>
|
||||
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <IOKit/pwr_mgt/IOPMLib.h>
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#include "SDL_cocoaclipboard.h"
|
||||
#include "SDL_cocoaevents.h"
|
||||
#include "SDL_cocoakeyboard.h"
|
||||
#include "SDL_cocoamodes.h"
|
||||
#include "SDL_cocoamouse.h"
|
||||
#include "SDL_cocoaopengl.h"
|
||||
#include "SDL_cocoawindow.h"
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_12
|
||||
#define DECLARE_EVENT(name) static const NSEventType NSEventType##name = NS##name
|
||||
DECLARE_EVENT(LeftMouseDown);
|
||||
DECLARE_EVENT(LeftMouseUp);
|
||||
DECLARE_EVENT(RightMouseDown);
|
||||
DECLARE_EVENT(RightMouseUp);
|
||||
DECLARE_EVENT(OtherMouseDown);
|
||||
DECLARE_EVENT(OtherMouseUp);
|
||||
DECLARE_EVENT(MouseMoved);
|
||||
DECLARE_EVENT(LeftMouseDragged);
|
||||
DECLARE_EVENT(RightMouseDragged);
|
||||
DECLARE_EVENT(OtherMouseDragged);
|
||||
DECLARE_EVENT(ScrollWheel);
|
||||
DECLARE_EVENT(KeyDown);
|
||||
DECLARE_EVENT(KeyUp);
|
||||
DECLARE_EVENT(FlagsChanged);
|
||||
#undef DECLARE_EVENT
|
||||
|
||||
static const NSEventMask NSEventMaskAny = NSAnyEventMask;
|
||||
|
||||
#define DECLARE_MODIFIER_FLAG(name) static const NSUInteger NSEventModifierFlag##name = NS##name##KeyMask
|
||||
DECLARE_MODIFIER_FLAG(Shift);
|
||||
DECLARE_MODIFIER_FLAG(Control);
|
||||
DECLARE_MODIFIER_FLAG(Command);
|
||||
DECLARE_MODIFIER_FLAG(NumericPad);
|
||||
DECLARE_MODIFIER_FLAG(Help);
|
||||
DECLARE_MODIFIER_FLAG(Function);
|
||||
#undef DECLARE_MODIFIER_FLAG
|
||||
static const NSUInteger NSEventModifierFlagCapsLock = NSAlphaShiftKeyMask;
|
||||
static const NSUInteger NSEventModifierFlagOption = NSAlternateKeyMask;
|
||||
|
||||
#define DECLARE_WINDOW_MASK(name) static const unsigned int NSWindowStyleMask##name = NS##name##WindowMask
|
||||
DECLARE_WINDOW_MASK(Borderless);
|
||||
DECLARE_WINDOW_MASK(Titled);
|
||||
DECLARE_WINDOW_MASK(Closable);
|
||||
DECLARE_WINDOW_MASK(Miniaturizable);
|
||||
DECLARE_WINDOW_MASK(Resizable);
|
||||
DECLARE_WINDOW_MASK(TexturedBackground);
|
||||
DECLARE_WINDOW_MASK(UnifiedTitleAndToolbar);
|
||||
DECLARE_WINDOW_MASK(FullScreen);
|
||||
/*DECLARE_WINDOW_MASK(FullSizeContentView);*/ /* Not used, fails compile on older SDKs */
|
||||
static const unsigned int NSWindowStyleMaskUtilityWindow = NSUtilityWindowMask;
|
||||
static const unsigned int NSWindowStyleMaskDocModalWindow = NSDocModalWindowMask;
|
||||
static const unsigned int NSWindowStyleMaskHUDWindow = NSHUDWindowMask;
|
||||
#undef DECLARE_WINDOW_MASK
|
||||
|
||||
#define DECLARE_ALERT_STYLE(name) static const NSUInteger NSAlertStyle##name = NS##name##AlertStyle
|
||||
DECLARE_ALERT_STYLE(Warning);
|
||||
DECLARE_ALERT_STYLE(Informational);
|
||||
DECLARE_ALERT_STYLE(Critical);
|
||||
#undef DECLARE_ALERT_STYLE
|
||||
#endif
|
||||
|
||||
/* Private display data */
|
||||
|
||||
@class SDLTranslatorResponder;
|
||||
|
||||
@interface SDL_CocoaVideoData : NSObject
|
||||
@property(nonatomic) int allow_spaces;
|
||||
@property(nonatomic) int trackpad_is_touch_only;
|
||||
@property(nonatomic) unsigned int modifierFlags;
|
||||
@property(nonatomic) void *key_layout;
|
||||
@property(nonatomic) SDLTranslatorResponder *fieldEdit;
|
||||
@property(nonatomic) NSInteger clipboard_count;
|
||||
@property(nonatomic) IOPMAssertionID screensaver_assertion;
|
||||
@property(nonatomic) SDL_Mutex *swaplock;
|
||||
@end
|
||||
|
||||
/* Utility functions */
|
||||
extern SDL_SystemTheme Cocoa_GetSystemTheme(void);
|
||||
extern NSImage *Cocoa_CreateImage(SDL_Surface *surface);
|
||||
|
||||
/* Fix build with the 10.11 SDK */
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||
#define NSEventSubtypeMouseEvent NSMouseEventSubtype
|
||||
#endif
|
||||
|
||||
#endif /* SDL_cocoavideo_h_ */
|
314
external/sdl/SDL/src/video/cocoa/SDL_cocoavideo.m
vendored
Normal file
314
external/sdl/SDL/src/video/cocoa/SDL_cocoavideo.m
vendored
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_COCOA
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
#error SDL must be built with Objective-C ARC (automatic reference counting) enabled
|
||||
#endif
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "SDL_cocoashape.h"
|
||||
#include "SDL_cocoavulkan.h"
|
||||
#include "SDL_cocoametalview.h"
|
||||
#include "SDL_cocoaopengles.h"
|
||||
|
||||
@implementation SDL_CocoaVideoData
|
||||
|
||||
@end
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int Cocoa_VideoInit(SDL_VideoDevice *_this);
|
||||
static void Cocoa_VideoQuit(SDL_VideoDevice *_this);
|
||||
|
||||
/* Cocoa driver bootstrap functions */
|
||||
|
||||
static void Cocoa_DeleteDevice(SDL_VideoDevice *device)
|
||||
{
|
||||
@autoreleasepool {
|
||||
if (device->wakeup_lock) {
|
||||
SDL_DestroyMutex(device->wakeup_lock);
|
||||
}
|
||||
CFBridgingRelease(device->driverdata);
|
||||
SDL_free(device);
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_VideoDevice *Cocoa_CreateDevice(void)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_VideoDevice *device;
|
||||
SDL_CocoaVideoData *data;
|
||||
|
||||
Cocoa_RegisterApp();
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
|
||||
if (device) {
|
||||
data = [[SDL_CocoaVideoData alloc] init];
|
||||
} else {
|
||||
data = nil;
|
||||
}
|
||||
if (!data) {
|
||||
SDL_OutOfMemory();
|
||||
SDL_free(device);
|
||||
return NULL;
|
||||
}
|
||||
device->driverdata = (SDL_VideoData *)CFBridgingRetain(data);
|
||||
device->wakeup_lock = SDL_CreateMutex();
|
||||
device->system_theme = Cocoa_GetSystemTheme();
|
||||
|
||||
/* Set the function pointers */
|
||||
device->VideoInit = Cocoa_VideoInit;
|
||||
device->VideoQuit = Cocoa_VideoQuit;
|
||||
device->GetDisplayBounds = Cocoa_GetDisplayBounds;
|
||||
device->GetDisplayUsableBounds = Cocoa_GetDisplayUsableBounds;
|
||||
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;
|
||||
device->CreateSDLWindowFrom = Cocoa_CreateWindowFrom;
|
||||
device->SetWindowTitle = Cocoa_SetWindowTitle;
|
||||
device->SetWindowIcon = Cocoa_SetWindowIcon;
|
||||
device->SetWindowPosition = Cocoa_SetWindowPosition;
|
||||
device->SetWindowSize = Cocoa_SetWindowSize;
|
||||
device->SetWindowMinimumSize = Cocoa_SetWindowMinimumSize;
|
||||
device->SetWindowMaximumSize = Cocoa_SetWindowMaximumSize;
|
||||
device->SetWindowOpacity = Cocoa_SetWindowOpacity;
|
||||
device->GetWindowSizeInPixels = Cocoa_GetWindowSizeInPixels;
|
||||
device->ShowWindow = Cocoa_ShowWindow;
|
||||
device->HideWindow = Cocoa_HideWindow;
|
||||
device->RaiseWindow = Cocoa_RaiseWindow;
|
||||
device->MaximizeWindow = Cocoa_MaximizeWindow;
|
||||
device->MinimizeWindow = Cocoa_MinimizeWindow;
|
||||
device->RestoreWindow = Cocoa_RestoreWindow;
|
||||
device->SetWindowBordered = Cocoa_SetWindowBordered;
|
||||
device->SetWindowResizable = Cocoa_SetWindowResizable;
|
||||
device->SetWindowAlwaysOnTop = Cocoa_SetWindowAlwaysOnTop;
|
||||
device->SetWindowFullscreen = Cocoa_SetWindowFullscreen;
|
||||
device->GetWindowICCProfile = Cocoa_GetWindowICCProfile;
|
||||
device->GetDisplayForWindow = Cocoa_GetDisplayForWindow;
|
||||
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;
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_CGL
|
||||
device->GL_LoadLibrary = Cocoa_GL_LoadLibrary;
|
||||
device->GL_GetProcAddress = Cocoa_GL_GetProcAddress;
|
||||
device->GL_UnloadLibrary = Cocoa_GL_UnloadLibrary;
|
||||
device->GL_CreateContext = Cocoa_GL_CreateContext;
|
||||
device->GL_MakeCurrent = Cocoa_GL_MakeCurrent;
|
||||
device->GL_SetSwapInterval = Cocoa_GL_SetSwapInterval;
|
||||
device->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval;
|
||||
device->GL_SwapWindow = Cocoa_GL_SwapWindow;
|
||||
device->GL_DeleteContext = Cocoa_GL_DeleteContext;
|
||||
device->GL_GetEGLSurface = NULL;
|
||||
#endif
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
#ifdef SDL_VIDEO_OPENGL_CGL
|
||||
if (SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, SDL_FALSE)) {
|
||||
#endif
|
||||
device->GL_LoadLibrary = Cocoa_GLES_LoadLibrary;
|
||||
device->GL_GetProcAddress = Cocoa_GLES_GetProcAddress;
|
||||
device->GL_UnloadLibrary = Cocoa_GLES_UnloadLibrary;
|
||||
device->GL_CreateContext = Cocoa_GLES_CreateContext;
|
||||
device->GL_MakeCurrent = Cocoa_GLES_MakeCurrent;
|
||||
device->GL_SetSwapInterval = Cocoa_GLES_SetSwapInterval;
|
||||
device->GL_GetSwapInterval = Cocoa_GLES_GetSwapInterval;
|
||||
device->GL_SwapWindow = Cocoa_GLES_SwapWindow;
|
||||
device->GL_DeleteContext = Cocoa_GLES_DeleteContext;
|
||||
device->GL_GetEGLSurface = Cocoa_GLES_GetEGLSurface;
|
||||
#ifdef SDL_VIDEO_OPENGL_CGL
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SDL_VIDEO_VULKAN
|
||||
device->Vulkan_LoadLibrary = Cocoa_Vulkan_LoadLibrary;
|
||||
device->Vulkan_UnloadLibrary = Cocoa_Vulkan_UnloadLibrary;
|
||||
device->Vulkan_GetInstanceExtensions = Cocoa_Vulkan_GetInstanceExtensions;
|
||||
device->Vulkan_CreateSurface = Cocoa_Vulkan_CreateSurface;
|
||||
#endif
|
||||
|
||||
#ifdef SDL_VIDEO_METAL
|
||||
device->Metal_CreateView = Cocoa_Metal_CreateView;
|
||||
device->Metal_DestroyView = Cocoa_Metal_DestroyView;
|
||||
device->Metal_GetLayer = Cocoa_Metal_GetLayer;
|
||||
#endif
|
||||
|
||||
device->StartTextInput = Cocoa_StartTextInput;
|
||||
device->StopTextInput = Cocoa_StopTextInput;
|
||||
device->SetTextInputRect = Cocoa_SetTextInputRect;
|
||||
|
||||
device->SetClipboardData = Cocoa_SetClipboardData;
|
||||
device->GetClipboardData = Cocoa_GetClipboardData;
|
||||
device->HasClipboardData = Cocoa_HasClipboardData;
|
||||
|
||||
device->free = Cocoa_DeleteDevice;
|
||||
|
||||
device->quirk_flags = VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT;
|
||||
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
VideoBootStrap COCOA_bootstrap = {
|
||||
"cocoa", "SDL Cocoa video driver",
|
||||
Cocoa_CreateDevice
|
||||
};
|
||||
|
||||
int Cocoa_VideoInit(SDL_VideoDevice *_this)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata;
|
||||
|
||||
Cocoa_InitModes(_this);
|
||||
Cocoa_InitKeyboard(_this);
|
||||
if (Cocoa_InitMouse(_this) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data.allow_spaces = SDL_GetHintBoolean(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_TRUE);
|
||||
data.trackpad_is_touch_only = SDL_GetHintBoolean(SDL_HINT_TRACKPAD_IS_TOUCH_ONLY, SDL_FALSE);
|
||||
|
||||
data.swaplock = SDL_CreateMutex();
|
||||
if (!data.swaplock) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Cocoa_VideoQuit(SDL_VideoDevice *_this)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata;
|
||||
Cocoa_QuitModes(_this);
|
||||
Cocoa_QuitKeyboard(_this);
|
||||
Cocoa_QuitMouse(_this);
|
||||
SDL_DestroyMutex(data.swaplock);
|
||||
data.swaplock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function assumes that it's called from within an autorelease pool */
|
||||
SDL_SystemTheme Cocoa_GetSystemTheme(void)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 /* Added in the 10.14.0 SDK. */
|
||||
if ([[NSApplication sharedApplication] respondsToSelector:@selector(effectiveAppearance)]) {
|
||||
NSAppearance* appearance = [[NSApplication sharedApplication] effectiveAppearance];
|
||||
|
||||
if ([appearance.name containsString: @"Dark"]) {
|
||||
return SDL_SYSTEM_THEME_DARK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return SDL_SYSTEM_THEME_LIGHT;
|
||||
}
|
||||
|
||||
/* This function assumes that it's called from within an autorelease pool */
|
||||
NSImage *Cocoa_CreateImage(SDL_Surface *surface)
|
||||
{
|
||||
SDL_Surface *converted;
|
||||
NSBitmapImageRep *imgrep;
|
||||
Uint8 *pixels;
|
||||
int i;
|
||||
NSImage *img;
|
||||
|
||||
converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGBA32);
|
||||
if (!converted) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
imgrep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
|
||||
pixelsWide:converted->w
|
||||
pixelsHigh:converted->h
|
||||
bitsPerSample:8
|
||||
samplesPerPixel:4
|
||||
hasAlpha:YES
|
||||
isPlanar:NO
|
||||
colorSpaceName:NSDeviceRGBColorSpace
|
||||
bytesPerRow:converted->pitch
|
||||
bitsPerPixel:converted->format->BitsPerPixel];
|
||||
if (imgrep == nil) {
|
||||
SDL_DestroySurface(converted);
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* Copy the pixels */
|
||||
pixels = [imgrep bitmapData];
|
||||
SDL_memcpy(pixels, converted->pixels, (size_t)converted->h * converted->pitch);
|
||||
SDL_DestroySurface(converted);
|
||||
|
||||
/* Premultiply the alpha channel */
|
||||
for (i = (surface->h * surface->w); i--;) {
|
||||
Uint8 alpha = pixels[3];
|
||||
pixels[0] = (Uint8)(((Uint16)pixels[0] * alpha) / 255);
|
||||
pixels[1] = (Uint8)(((Uint16)pixels[1] * alpha) / 255);
|
||||
pixels[2] = (Uint8)(((Uint16)pixels[2] * alpha) / 255);
|
||||
pixels += 4;
|
||||
}
|
||||
|
||||
img = [[NSImage alloc] initWithSize:NSMakeSize(surface->w, surface->h)];
|
||||
if (img != nil) {
|
||||
[img addRepresentation:imgrep];
|
||||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
/*
|
||||
* macOS log support.
|
||||
*
|
||||
* This doesn't really have anything to do with the interfaces of the SDL video
|
||||
* subsystem, but we need to stuff this into an Objective-C source code file.
|
||||
*
|
||||
* NOTE: This is copypasted in src/video/uikit/SDL_uikitvideo.m! Be sure both
|
||||
* versions remain identical!
|
||||
*/
|
||||
|
||||
void SDL_NSLog(const char *prefix, const char *text)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSString *nsText = [NSString stringWithUTF8String:text];
|
||||
if (prefix) {
|
||||
NSString *nsPrefix = [NSString stringWithUTF8String:prefix];
|
||||
NSLog(@"%@: %@", nsPrefix, nsText);
|
||||
} else {
|
||||
NSLog(@"%@", nsText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
49
external/sdl/SDL/src/video/cocoa/SDL_cocoavulkan.h
vendored
Normal file
49
external/sdl/SDL/src/video/cocoa/SDL_cocoavulkan.h
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.h.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoavulkan_h_
|
||||
#define SDL_cocoavulkan_h_
|
||||
|
||||
#include "../SDL_vulkan_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_COCOA)
|
||||
|
||||
int Cocoa_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path);
|
||||
void Cocoa_Vulkan_UnloadLibrary(SDL_VideoDevice *_this);
|
||||
SDL_bool Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
|
||||
unsigned *count,
|
||||
const char **names);
|
||||
SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SDL_cocoavulkan_h_ */
|
304
external/sdl/SDL/src/video/cocoa/SDL_cocoavulkan.m
vendored
Normal file
304
external/sdl/SDL/src/video/cocoa/SDL_cocoavulkan.m
vendored
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
|
||||
* SDL_x11vulkan.c.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_COCOA)
|
||||
|
||||
#include "SDL_cocoavideo.h"
|
||||
#include "SDL_cocoawindow.h"
|
||||
|
||||
#include "SDL_cocoametalview.h"
|
||||
#include "SDL_cocoavulkan.h"
|
||||
|
||||
#include <SDL3/SDL_syswm.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
const char *defaultPaths[] = {
|
||||
"vulkan.framework/vulkan",
|
||||
"libvulkan.1.dylib",
|
||||
"libvulkan.dylib",
|
||||
"MoltenVK.framework/MoltenVK",
|
||||
"libMoltenVK.dylib"
|
||||
};
|
||||
|
||||
/* Since libSDL is most likely a .dylib, need RTLD_DEFAULT not RTLD_SELF. */
|
||||
#define DEFAULT_HANDLE RTLD_DEFAULT
|
||||
|
||||
int Cocoa_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
||||
{
|
||||
VkExtensionProperties *extensions = NULL;
|
||||
Uint32 extensionCount = 0;
|
||||
SDL_bool hasSurfaceExtension = SDL_FALSE;
|
||||
SDL_bool hasMetalSurfaceExtension = SDL_FALSE;
|
||||
SDL_bool hasMacOSSurfaceExtension = SDL_FALSE;
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
|
||||
|
||||
if (_this->vulkan_config.loader_handle) {
|
||||
return SDL_SetError("Vulkan Portability library is already loaded.");
|
||||
}
|
||||
|
||||
/* Load the Vulkan loader library */
|
||||
if (!path) {
|
||||
path = SDL_getenv("SDL_VULKAN_LIBRARY");
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
/* Handle the case where Vulkan Portability is linked statically. */
|
||||
vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE,
|
||||
"vkGetInstanceProcAddr");
|
||||
}
|
||||
|
||||
if (vkGetInstanceProcAddr) {
|
||||
_this->vulkan_config.loader_handle = DEFAULT_HANDLE;
|
||||
} else {
|
||||
const char **paths;
|
||||
const char *foundPath = NULL;
|
||||
int numPaths;
|
||||
int i;
|
||||
|
||||
if (path) {
|
||||
paths = &path;
|
||||
numPaths = 1;
|
||||
} else {
|
||||
/* Look for framework or .dylib packaged with the application
|
||||
* instead. */
|
||||
paths = defaultPaths;
|
||||
numPaths = SDL_arraysize(defaultPaths);
|
||||
}
|
||||
|
||||
for (i = 0; i < numPaths && _this->vulkan_config.loader_handle == NULL; i++) {
|
||||
foundPath = paths[i];
|
||||
_this->vulkan_config.loader_handle = SDL_LoadObject(foundPath);
|
||||
}
|
||||
|
||||
if (_this->vulkan_config.loader_handle == NULL) {
|
||||
return SDL_SetError("Failed to load Vulkan Portability library");
|
||||
}
|
||||
|
||||
SDL_strlcpy(_this->vulkan_config.loader_path, foundPath,
|
||||
SDL_arraysize(_this->vulkan_config.loader_path));
|
||||
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
|
||||
_this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
|
||||
}
|
||||
|
||||
if (!vkGetInstanceProcAddr) {
|
||||
SDL_SetError("Failed to find %s in either executable or %s: %s",
|
||||
"vkGetInstanceProcAddr",
|
||||
_this->vulkan_config.loader_path,
|
||||
(const char *)dlerror());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
_this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties =
|
||||
(void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
|
||||
VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
|
||||
if (!_this->vulkan_config.vkEnumerateInstanceExtensionProperties) {
|
||||
goto fail;
|
||||
}
|
||||
extensions = SDL_Vulkan_CreateInstanceExtensionsList(
|
||||
(PFN_vkEnumerateInstanceExtensionProperties)
|
||||
_this->vulkan_config.vkEnumerateInstanceExtensionProperties,
|
||||
&extensionCount);
|
||||
if (!extensions) {
|
||||
goto fail;
|
||||
}
|
||||
for (Uint32 i = 0; i < extensionCount; i++) {
|
||||
if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
|
||||
hasSurfaceExtension = SDL_TRUE;
|
||||
} else if (SDL_strcmp(VK_EXT_METAL_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
|
||||
hasMetalSurfaceExtension = SDL_TRUE;
|
||||
} else if (SDL_strcmp(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) {
|
||||
hasMacOSSurfaceExtension = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
SDL_free(extensions);
|
||||
if (!hasSurfaceExtension) {
|
||||
SDL_SetError("Installed Vulkan Portability library doesn't implement the " VK_KHR_SURFACE_EXTENSION_NAME " extension");
|
||||
goto fail;
|
||||
} else if (!hasMetalSurfaceExtension && !hasMacOSSurfaceExtension) {
|
||||
SDL_SetError("Installed Vulkan Portability library doesn't implement the " VK_EXT_METAL_SURFACE_EXTENSION_NAME " or " VK_MVK_MACOS_SURFACE_EXTENSION_NAME " extensions");
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Cocoa_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
|
||||
{
|
||||
if (_this->vulkan_config.loader_handle) {
|
||||
if (_this->vulkan_config.loader_handle != DEFAULT_HANDLE) {
|
||||
SDL_UnloadObject(_this->vulkan_config.loader_handle);
|
||||
}
|
||||
_this->vulkan_config.loader_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool Cocoa_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
|
||||
unsigned *count,
|
||||
const char **names)
|
||||
{
|
||||
static const char *const extensionsForCocoa[] = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_METAL_SURFACE_EXTENSION_NAME
|
||||
};
|
||||
if (!_this->vulkan_config.loader_handle) {
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_Vulkan_GetInstanceExtensions_Helper(
|
||||
count, names, SDL_arraysize(extensionsForCocoa),
|
||||
extensionsForCocoa);
|
||||
}
|
||||
|
||||
static SDL_bool Cocoa_Vulkan_CreateSurfaceViaMetalView(SDL_VideoDevice *_this,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface,
|
||||
PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT,
|
||||
PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK)
|
||||
{
|
||||
VkResult result;
|
||||
SDL_MetalView metalview = Cocoa_Metal_CreateView(_this, window);
|
||||
if (metalview == NULL) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (vkCreateMetalSurfaceEXT) {
|
||||
VkMetalSurfaceCreateInfoEXT createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = 0;
|
||||
createInfo.pLayer = (__bridge const CAMetalLayer *)
|
||||
Cocoa_Metal_GetLayer(_this, metalview);
|
||||
result = vkCreateMetalSurfaceEXT(instance, &createInfo, NULL, surface);
|
||||
if (result != VK_SUCCESS) {
|
||||
Cocoa_Metal_DestroyView(_this, metalview);
|
||||
SDL_SetError("vkCreateMetalSurfaceEXT failed: %s",
|
||||
SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
} else {
|
||||
VkMacOSSurfaceCreateInfoMVK createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = 0;
|
||||
createInfo.pView = (const void *)metalview;
|
||||
result = vkCreateMacOSSurfaceMVK(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if (result != VK_SUCCESS) {
|
||||
Cocoa_Metal_DestroyView(_this, metalview);
|
||||
SDL_SetError("vkCreateMacOSSurfaceMVK failed: %s",
|
||||
SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unfortunately there's no SDL_Vulkan_DestroySurface function we can call
|
||||
* Metal_DestroyView from. Right now the metal view's ref count is +2 (one
|
||||
* from returning a new view object in CreateView, and one because it's
|
||||
* a subview of the window.) If we release the view here to make it +1, it
|
||||
* will be destroyed when the window is destroyed. */
|
||||
CFBridgingRelease(metalview);
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this,
|
||||
SDL_Window *window,
|
||||
VkInstance instance,
|
||||
VkSurfaceKHR *surface)
|
||||
{
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
|
||||
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
|
||||
PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT =
|
||||
(PFN_vkCreateMetalSurfaceEXT)vkGetInstanceProcAddr(
|
||||
instance,
|
||||
"vkCreateMetalSurfaceEXT");
|
||||
PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK =
|
||||
(PFN_vkCreateMacOSSurfaceMVK)vkGetInstanceProcAddr(
|
||||
instance,
|
||||
"vkCreateMacOSSurfaceMVK");
|
||||
VkResult result;
|
||||
|
||||
if (!_this->vulkan_config.loader_handle) {
|
||||
SDL_SetError("Vulkan is not loaded");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (!vkCreateMetalSurfaceEXT && !vkCreateMacOSSurfaceMVK) {
|
||||
SDL_SetError(VK_EXT_METAL_SURFACE_EXTENSION_NAME " or " VK_MVK_MACOS_SURFACE_EXTENSION_NAME
|
||||
" extensions are not enabled in the Vulkan instance.");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (window->flags & SDL_WINDOW_FOREIGN) {
|
||||
@autoreleasepool {
|
||||
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->driverdata;
|
||||
if (![data.sdlContentView.layer isKindOfClass:[CAMetalLayer class]]) {
|
||||
[data.sdlContentView setLayer:[CAMetalLayer layer]];
|
||||
}
|
||||
|
||||
if (vkCreateMetalSurfaceEXT) {
|
||||
VkMetalSurfaceCreateInfoEXT createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = 0;
|
||||
createInfo.pLayer = (CAMetalLayer *)data.sdlContentView.layer;
|
||||
result = vkCreateMetalSurfaceEXT(instance, &createInfo, NULL, surface);
|
||||
if (result != VK_SUCCESS) {
|
||||
SDL_SetError("vkCreateMetalSurfaceEXT failed: %s",
|
||||
SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
} else {
|
||||
VkMacOSSurfaceCreateInfoMVK createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
|
||||
createInfo.pNext = NULL;
|
||||
createInfo.flags = 0;
|
||||
createInfo.pView = (__bridge const void *)data.sdlContentView;
|
||||
result = vkCreateMacOSSurfaceMVK(instance, &createInfo,
|
||||
NULL, surface);
|
||||
if (result != VK_SUCCESS) {
|
||||
SDL_SetError("vkCreateMacOSSurfaceMVK failed: %s",
|
||||
SDL_Vulkan_GetResultString(result));
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Cocoa_Vulkan_CreateSurfaceViaMetalView(_this, window, instance, surface, vkCreateMetalSurfaceEXT, vkCreateMacOSSurfaceMVK);
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
#endif
|
173
external/sdl/SDL/src/video/cocoa/SDL_cocoawindow.h
vendored
Normal file
173
external/sdl/SDL/src/video/cocoa/SDL_cocoawindow.h
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_cocoawindow_h_
|
||||
#define SDL_cocoawindow_h_
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
#include "../SDL_egl_c.h"
|
||||
#endif
|
||||
|
||||
@class SDL_CocoaWindowData;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PENDING_OPERATION_NONE,
|
||||
PENDING_OPERATION_ENTER_FULLSCREEN,
|
||||
PENDING_OPERATION_LEAVE_FULLSCREEN,
|
||||
PENDING_OPERATION_MINIMIZE
|
||||
} PendingWindowOperation;
|
||||
|
||||
@interface Cocoa_WindowListener : NSResponder <NSWindowDelegate>
|
||||
{
|
||||
/* SDL_CocoaWindowData owns this Listener and has a strong reference to it.
|
||||
* To avoid reference cycles, we could have either a weak or an
|
||||
* unretained ref to the WindowData. */
|
||||
__weak SDL_CocoaWindowData *_data;
|
||||
BOOL observingVisible;
|
||||
BOOL wasCtrlLeft;
|
||||
BOOL wasVisible;
|
||||
BOOL isFullscreenSpace;
|
||||
BOOL inFullscreenTransition;
|
||||
PendingWindowOperation pendingWindowOperation;
|
||||
BOOL isMoving;
|
||||
NSInteger focusClickPending;
|
||||
float pendingWindowWarpX, pendingWindowWarpY;
|
||||
BOOL isDragAreaRunning;
|
||||
}
|
||||
|
||||
- (BOOL)isTouchFromTrackpad:(NSEvent *)theEvent;
|
||||
- (void)listen:(SDL_CocoaWindowData *)data;
|
||||
- (void)pauseVisibleObservation;
|
||||
- (void)resumeVisibleObservation;
|
||||
- (BOOL)setFullscreenSpace:(BOOL)state;
|
||||
- (BOOL)isInFullscreenSpace;
|
||||
- (BOOL)isInFullscreenSpaceTransition;
|
||||
- (void)addPendingWindowOperation:(PendingWindowOperation)operation;
|
||||
- (void)close;
|
||||
|
||||
- (BOOL)isMoving;
|
||||
- (BOOL)isMovingOrFocusClickPending;
|
||||
- (void)setFocusClickPending:(NSInteger)button;
|
||||
- (void)clearFocusClickPending:(NSInteger)button;
|
||||
- (void)setPendingMoveX:(float)x Y:(float)y;
|
||||
- (void)windowDidFinishMoving;
|
||||
- (void)onMovingOrFocusClickPendingStateCleared;
|
||||
|
||||
/* Window delegate functionality */
|
||||
- (BOOL)windowShouldClose:(id)sender;
|
||||
- (void)windowDidExpose:(NSNotification *)aNotification;
|
||||
- (void)windowDidMove:(NSNotification *)aNotification;
|
||||
- (void)windowDidResize:(NSNotification *)aNotification;
|
||||
- (void)windowDidMiniaturize:(NSNotification *)aNotification;
|
||||
- (void)windowDidDeminiaturize:(NSNotification *)aNotification;
|
||||
- (void)windowDidBecomeKey:(NSNotification *)aNotification;
|
||||
- (void)windowDidResignKey:(NSNotification *)aNotification;
|
||||
- (void)windowDidChangeBackingProperties:(NSNotification *)aNotification;
|
||||
- (void)windowDidChangeScreenProfile:(NSNotification *)aNotification;
|
||||
- (void)windowDidChangeScreen:(NSNotification *)aNotification;
|
||||
- (void)windowWillEnterFullScreen:(NSNotification *)aNotification;
|
||||
- (void)windowDidEnterFullScreen:(NSNotification *)aNotification;
|
||||
- (void)windowWillExitFullScreen:(NSNotification *)aNotification;
|
||||
- (void)windowDidExitFullScreen:(NSNotification *)aNotification;
|
||||
- (NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions;
|
||||
|
||||
/* See if event is in a drag area, toggle on window dragging. */
|
||||
- (BOOL)processHitTest:(NSEvent *)theEvent;
|
||||
|
||||
/* Window event handling */
|
||||
- (void)mouseDown:(NSEvent *)theEvent;
|
||||
- (void)rightMouseDown:(NSEvent *)theEvent;
|
||||
- (void)otherMouseDown:(NSEvent *)theEvent;
|
||||
- (void)mouseUp:(NSEvent *)theEvent;
|
||||
- (void)rightMouseUp:(NSEvent *)theEvent;
|
||||
- (void)otherMouseUp:(NSEvent *)theEvent;
|
||||
- (void)mouseMoved:(NSEvent *)theEvent;
|
||||
- (void)mouseDragged:(NSEvent *)theEvent;
|
||||
- (void)rightMouseDragged:(NSEvent *)theEvent;
|
||||
- (void)otherMouseDragged:(NSEvent *)theEvent;
|
||||
- (void)scrollWheel:(NSEvent *)theEvent;
|
||||
- (void)touchesBeganWithEvent:(NSEvent *)theEvent;
|
||||
- (void)touchesMovedWithEvent:(NSEvent *)theEvent;
|
||||
- (void)touchesEndedWithEvent:(NSEvent *)theEvent;
|
||||
- (void)touchesCancelledWithEvent:(NSEvent *)theEvent;
|
||||
|
||||
/* Touch event handling */
|
||||
- (void)handleTouches:(NSTouchPhase)phase withEvent:(NSEvent *)theEvent;
|
||||
|
||||
@end
|
||||
/* *INDENT-ON* */
|
||||
|
||||
@class SDLOpenGLContext;
|
||||
@class SDL_CocoaVideoData;
|
||||
|
||||
@interface SDL_CocoaWindowData : NSObject
|
||||
@property(nonatomic) SDL_Window *window;
|
||||
@property(nonatomic) NSWindow *nswindow;
|
||||
@property(nonatomic) NSView *sdlContentView;
|
||||
@property(nonatomic) NSMutableArray *nscontexts;
|
||||
@property(nonatomic) SDL_bool created;
|
||||
@property(nonatomic) SDL_bool inWindowFullscreenTransition;
|
||||
@property(nonatomic) NSInteger window_number;
|
||||
@property(nonatomic) NSInteger flash_request;
|
||||
@property(nonatomic) SDL_Window *keyboard_focus;
|
||||
@property(nonatomic) Cocoa_WindowListener *listener;
|
||||
@property(nonatomic) SDL_CocoaVideoData *videodata;
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
@property(nonatomic) EGLSurface egl_surface;
|
||||
#endif
|
||||
@end
|
||||
|
||||
extern int Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int Cocoa_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window *window,
|
||||
const void *data);
|
||||
extern void Cocoa_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int Cocoa_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon);
|
||||
extern int Cocoa_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Cocoa_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Cocoa_SetWindowMinimumSize(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Cocoa_SetWindowMaximumSize(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Cocoa_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *w, int *h);
|
||||
extern int Cocoa_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opacity);
|
||||
extern void Cocoa_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Cocoa_HideWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Cocoa_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Cocoa_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Cocoa_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Cocoa_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Cocoa_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool bordered);
|
||||
extern void Cocoa_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool resizable);
|
||||
extern void Cocoa_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool on_top);
|
||||
extern void Cocoa_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
|
||||
extern void *Cocoa_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size);
|
||||
extern SDL_DisplayID Cocoa_GetDisplayForWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Cocoa_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void Cocoa_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
|
||||
extern void Cocoa_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int Cocoa_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window *window, struct SDL_SysWMinfo *info);
|
||||
extern int Cocoa_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
|
||||
extern void Cocoa_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept);
|
||||
extern int Cocoa_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);
|
||||
|
||||
#endif /* SDL_cocoawindow_h_ */
|
2674
external/sdl/SDL/src/video/cocoa/SDL_cocoawindow.m
vendored
Normal file
2674
external/sdl/SDL/src/video/cocoa/SDL_cocoawindow.m
vendored
Normal file
File diff suppressed because it is too large
Load Diff
38
external/sdl/SDL/src/video/dummy/SDL_nullevents.c
vendored
Normal file
38
external/sdl/SDL/src/video/dummy/SDL_nullevents.c
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_DUMMY
|
||||
|
||||
/* Being a null driver, there's no event stream. We just define stubs for
|
||||
most of the API. */
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#include "SDL_nullvideo.h"
|
||||
#include "SDL_nullevents_c.h"
|
||||
|
||||
void DUMMY_PumpEvents(SDL_VideoDevice *_this)
|
||||
{
|
||||
/* do nothing. */
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_DUMMY */
|
31
external/sdl/SDL/src/video/dummy/SDL_nullevents_c.h
vendored
Normal file
31
external/sdl/SDL/src/video/dummy/SDL_nullevents_c.h
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_nullevents_c_h_
|
||||
#define SDL_nullevents_c_h_
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_nullvideo.h"
|
||||
|
||||
extern void DUMMY_PumpEvents(SDL_VideoDevice *_this);
|
||||
|
||||
#endif /* SDL_nullevents_c_h_ */
|
82
external/sdl/SDL/src/video/dummy/SDL_nullframebuffer.c
vendored
Normal file
82
external/sdl/SDL/src/video/dummy/SDL_nullframebuffer.c
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_DUMMY
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "SDL_nullframebuffer_c.h"
|
||||
|
||||
#define DUMMY_SURFACE "_SDL_DummySurface"
|
||||
|
||||
int SDL_DUMMY_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, Uint32 *format, void **pixels, int *pitch)
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
const Uint32 surface_format = SDL_PIXELFORMAT_XRGB8888;
|
||||
int w, h;
|
||||
|
||||
/* Free the old framebuffer surface */
|
||||
SDL_DUMMY_DestroyWindowFramebuffer(_this, window);
|
||||
|
||||
/* Create a new one */
|
||||
SDL_GetWindowSizeInPixels(window, &w, &h);
|
||||
surface = SDL_CreateSurface(w, h, surface_format);
|
||||
if (surface == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Save the info and return! */
|
||||
SDL_SetWindowData(window, DUMMY_SURFACE, surface);
|
||||
*format = surface_format;
|
||||
*pixels = surface->pixels;
|
||||
*pitch = surface->pitch;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_DUMMY_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, int numrects)
|
||||
{
|
||||
static int frame_number;
|
||||
SDL_Surface *surface;
|
||||
|
||||
surface = (SDL_Surface *)SDL_GetWindowData(window, DUMMY_SURFACE);
|
||||
if (surface == NULL) {
|
||||
return SDL_SetError("Couldn't find dummy surface for window");
|
||||
}
|
||||
|
||||
/* Send the data to the display */
|
||||
if (SDL_getenv("SDL_VIDEO_DUMMY_SAVE_FRAMES")) {
|
||||
char file[128];
|
||||
(void)SDL_snprintf(file, sizeof(file), "SDL_window%" SDL_PRIu32 "-%8.8d.bmp",
|
||||
SDL_GetWindowID(window), ++frame_number);
|
||||
SDL_SaveBMP(surface, file);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDL_DUMMY_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
|
||||
surface = (SDL_Surface *)SDL_SetWindowData(window, DUMMY_SURFACE, NULL);
|
||||
SDL_DestroySurface(surface);
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_DUMMY */
|
31
external/sdl/SDL/src/video/dummy/SDL_nullframebuffer_c.h
vendored
Normal file
31
external/sdl/SDL/src/video/dummy/SDL_nullframebuffer_c.h
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_nullframebuffer_c_h_
|
||||
#define SDL_nullframebuffer_c_h_
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
extern int SDL_DUMMY_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, Uint32 *format, void **pixels, int *pitch);
|
||||
extern int SDL_DUMMY_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, int numrects);
|
||||
extern void SDL_DUMMY_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
|
||||
#endif /* SDL_nullframebuffer_c_h_ */
|
166
external/sdl/SDL/src/video/dummy/SDL_nullvideo.c
vendored
Normal file
166
external/sdl/SDL/src/video/dummy/SDL_nullvideo.c
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_DUMMY
|
||||
|
||||
/* Dummy SDL video driver implementation; this is just enough to make an
|
||||
* SDL-based application THINK it's got a working video driver, for
|
||||
* applications that call SDL_Init(SDL_INIT_VIDEO) when they don't need it,
|
||||
* and also for use as a collection of stubs when porting SDL to a new
|
||||
* platform for which you haven't yet written a valid video driver.
|
||||
*
|
||||
* This is also a great way to determine bottlenecks: if you think that SDL
|
||||
* is a performance problem for a given platform, enable this driver, and
|
||||
* then see if your application runs faster without video overhead.
|
||||
*
|
||||
* Initial work by Ryan C. Gordon (icculus@icculus.org). A good portion
|
||||
* of this was cut-and-pasted from Stephane Peter's work in the AAlib
|
||||
* SDL video driver. Renamed to "DUMMY" by Sam Lantinga.
|
||||
*/
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_pixels_c.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#ifdef SDL_INPUT_LINUXEV
|
||||
#include "../../core/linux/SDL_evdev.h"
|
||||
#endif
|
||||
|
||||
#include "SDL_nullvideo.h"
|
||||
#include "SDL_nullevents_c.h"
|
||||
#include "SDL_nullframebuffer_c.h"
|
||||
|
||||
#define DUMMYVID_DRIVER_NAME "dummy"
|
||||
#define DUMMYVID_DRIVER_EVDEV_NAME "evdev"
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int DUMMY_VideoInit(SDL_VideoDevice *_this);
|
||||
static void DUMMY_VideoQuit(SDL_VideoDevice *_this);
|
||||
|
||||
/* DUMMY driver bootstrap functions */
|
||||
|
||||
static int DUMMY_Available(const char *enable_hint)
|
||||
{
|
||||
const char *hint = SDL_GetHint(SDL_HINT_VIDEO_DRIVER);
|
||||
if (hint) {
|
||||
if (SDL_strcmp(hint, enable_hint) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void DUMMY_DeleteDevice(SDL_VideoDevice *device)
|
||||
{
|
||||
SDL_free(device);
|
||||
}
|
||||
|
||||
static SDL_VideoDevice *DUMMY_InternalCreateDevice(const char *enable_hint)
|
||||
{
|
||||
SDL_VideoDevice *device;
|
||||
|
||||
if (!DUMMY_Available(enable_hint)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
|
||||
if (device == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
device->is_dummy = SDL_TRUE;
|
||||
|
||||
/* Set the function pointers */
|
||||
device->VideoInit = DUMMY_VideoInit;
|
||||
device->VideoQuit = DUMMY_VideoQuit;
|
||||
device->PumpEvents = DUMMY_PumpEvents;
|
||||
device->CreateWindowFramebuffer = SDL_DUMMY_CreateWindowFramebuffer;
|
||||
device->UpdateWindowFramebuffer = SDL_DUMMY_UpdateWindowFramebuffer;
|
||||
device->DestroyWindowFramebuffer = SDL_DUMMY_DestroyWindowFramebuffer;
|
||||
device->free = DUMMY_DeleteDevice;
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static SDL_VideoDevice *DUMMY_CreateDevice(void)
|
||||
{
|
||||
return DUMMY_InternalCreateDevice(DUMMYVID_DRIVER_NAME);
|
||||
}
|
||||
|
||||
VideoBootStrap DUMMY_bootstrap = {
|
||||
DUMMYVID_DRIVER_NAME, "SDL dummy video driver",
|
||||
DUMMY_CreateDevice
|
||||
};
|
||||
|
||||
#ifdef SDL_INPUT_LINUXEV
|
||||
|
||||
static void DUMMY_EVDEV_Poll(SDL_VideoDevice *_this)
|
||||
{
|
||||
(void)_this;
|
||||
SDL_EVDEV_Poll();
|
||||
}
|
||||
|
||||
static SDL_VideoDevice *DUMMY_EVDEV_CreateDevice(void)
|
||||
{
|
||||
SDL_VideoDevice *device = DUMMY_InternalCreateDevice(DUMMYVID_DRIVER_EVDEV_NAME);
|
||||
if (device) {
|
||||
device->PumpEvents = DUMMY_EVDEV_Poll;
|
||||
}
|
||||
return device;
|
||||
}
|
||||
|
||||
VideoBootStrap DUMMY_evdev_bootstrap = {
|
||||
DUMMYVID_DRIVER_EVDEV_NAME, "SDL dummy video driver with evdev",
|
||||
DUMMY_EVDEV_CreateDevice
|
||||
};
|
||||
|
||||
#endif /* SDL_INPUT_LINUXEV */
|
||||
|
||||
int DUMMY_VideoInit(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_DisplayMode mode;
|
||||
|
||||
/* Use a fake 32-bpp desktop mode */
|
||||
SDL_zero(mode);
|
||||
mode.format = SDL_PIXELFORMAT_XRGB8888;
|
||||
mode.w = 1024;
|
||||
mode.h = 768;
|
||||
if (SDL_AddBasicVideoDisplay(&mode) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef SDL_INPUT_LINUXEV
|
||||
SDL_EVDEV_Init();
|
||||
#endif
|
||||
|
||||
/* We're done! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DUMMY_VideoQuit(SDL_VideoDevice *_this)
|
||||
{
|
||||
#ifdef SDL_INPUT_LINUXEV
|
||||
SDL_EVDEV_Quit();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_DUMMY */
|
28
external/sdl/SDL/src/video/dummy/SDL_nullvideo.h
vendored
Normal file
28
external/sdl/SDL/src/video/dummy/SDL_nullvideo.h
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_nullvideo_h_
|
||||
#define SDL_nullvideo_h_
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#endif /* SDL_nullvideo_h_ */
|
1019
external/sdl/SDL/src/video/emscripten/SDL_emscriptenevents.c
vendored
Normal file
1019
external/sdl/SDL/src/video/emscripten/SDL_emscriptenevents.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
31
external/sdl/SDL/src/video/emscripten/SDL_emscriptenevents.h
vendored
Normal file
31
external/sdl/SDL/src/video/emscripten/SDL_emscriptenevents.h
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_emscriptenevents_h_
|
||||
#define SDL_emscriptenevents_h_
|
||||
|
||||
#include "SDL_emscriptenvideo.h"
|
||||
|
||||
extern void Emscripten_RegisterEventHandlers(SDL_WindowData *data);
|
||||
extern void Emscripten_UnregisterEventHandlers(SDL_WindowData *data);
|
||||
extern EM_BOOL Emscripten_HandleCanvasResize(int eventType, const void *reserved, void *userData);
|
||||
|
||||
#endif /* SDL_emscriptenevents_h_ */
|
161
external/sdl/SDL/src/video/emscripten/SDL_emscriptenframebuffer.c
vendored
Normal file
161
external/sdl/SDL/src/video/emscripten/SDL_emscriptenframebuffer.c
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_EMSCRIPTEN
|
||||
|
||||
#include "SDL_emscriptenvideo.h"
|
||||
#include "SDL_emscriptenframebuffer.h"
|
||||
|
||||
#include <emscripten/threading.h>
|
||||
|
||||
int Emscripten_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, Uint32 *format, void **pixels, int *pitch)
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
const Uint32 surface_format = SDL_PIXELFORMAT_XBGR8888;
|
||||
int w, h;
|
||||
|
||||
/* Free the old framebuffer surface */
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
surface = data->surface;
|
||||
SDL_DestroySurface(surface);
|
||||
|
||||
/* Create a new one */
|
||||
SDL_GetWindowSizeInPixels(window, &w, &h);
|
||||
|
||||
surface = SDL_CreateSurface(w, h, surface_format);
|
||||
if (surface == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Save the info and return! */
|
||||
data->surface = surface;
|
||||
*format = surface_format;
|
||||
*pixels = surface->pixels;
|
||||
*pitch = surface->pitch;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Emscripten_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, int numrects)
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
surface = data->surface;
|
||||
if (surface == NULL) {
|
||||
return SDL_SetError("Couldn't find framebuffer surface for window");
|
||||
}
|
||||
|
||||
/* Send the data to the display */
|
||||
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
MAIN_THREAD_EM_ASM({
|
||||
var w = $0;
|
||||
var h = $1;
|
||||
var pixels = $2;
|
||||
var canvasId = UTF8ToString($3);
|
||||
var canvas = document.querySelector(canvasId);
|
||||
|
||||
//TODO: this should store a context per canvas
|
||||
if (!Module['SDL3']) Module['SDL3'] = {};
|
||||
var SDL3 = Module['SDL3'];
|
||||
if (SDL3.ctxCanvas !== canvas) {
|
||||
SDL3.ctx = Module['createContext'](canvas, false, true);
|
||||
SDL3.ctxCanvas = canvas;
|
||||
}
|
||||
if (SDL3.w !== w || SDL3.h !== h || SDL3.imageCtx !== SDL3.ctx) {
|
||||
SDL3.image = SDL3.ctx.createImageData(w, h);
|
||||
SDL3.w = w;
|
||||
SDL3.h = h;
|
||||
SDL3.imageCtx = SDL3.ctx;
|
||||
}
|
||||
var data = SDL3.image.data;
|
||||
var src = pixels >> 2;
|
||||
var dst = 0;
|
||||
var num;
|
||||
|
||||
if (SDL3.data32Data !== data) {
|
||||
SDL3.data32 = new Int32Array(data.buffer);
|
||||
SDL3.data8 = new Uint8Array(data.buffer);
|
||||
SDL3.data32Data = data;
|
||||
}
|
||||
var data32 = SDL3.data32;
|
||||
num = data32.length;
|
||||
// logically we need to do
|
||||
// while (dst < num) {
|
||||
// data32[dst++] = HEAP32[src++] | 0xff000000
|
||||
// }
|
||||
// the following code is faster though, because
|
||||
// .set() is almost free - easily 10x faster due to
|
||||
// native SDL_memcpy efficiencies, and the remaining loop
|
||||
// just stores, not load + store, so it is faster
|
||||
data32.set(HEAP32.subarray(src, src + num));
|
||||
var data8 = SDL3.data8;
|
||||
var i = 3;
|
||||
var j = i + 4*num;
|
||||
if (num % 8 == 0) {
|
||||
// unrolling gives big speedups
|
||||
while (i < j) {
|
||||
data8[i] = 0xff;
|
||||
i = i + 4 | 0;
|
||||
data8[i] = 0xff;
|
||||
i = i + 4 | 0;
|
||||
data8[i] = 0xff;
|
||||
i = i + 4 | 0;
|
||||
data8[i] = 0xff;
|
||||
i = i + 4 | 0;
|
||||
data8[i] = 0xff;
|
||||
i = i + 4 | 0;
|
||||
data8[i] = 0xff;
|
||||
i = i + 4 | 0;
|
||||
data8[i] = 0xff;
|
||||
i = i + 4 | 0;
|
||||
data8[i] = 0xff;
|
||||
i = i + 4 | 0;
|
||||
}
|
||||
} else {
|
||||
while (i < j) {
|
||||
data8[i] = 0xff;
|
||||
i = i + 4 | 0;
|
||||
}
|
||||
}
|
||||
|
||||
SDL3.ctx.putImageData(SDL3.image, 0, 0);
|
||||
}, surface->w, surface->h, surface->pixels, data->canvas_id);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
|
||||
if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, SDL_TRUE)) {
|
||||
/* give back control to browser for screen refresh */
|
||||
emscripten_sleep(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Emscripten_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
|
||||
SDL_DestroySurface(data->surface);
|
||||
data->surface = NULL;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
|
30
external/sdl/SDL/src/video/emscripten/SDL_emscriptenframebuffer.h
vendored
Normal file
30
external/sdl/SDL/src/video/emscripten/SDL_emscriptenframebuffer.h
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifndef SDL_emscriptenframebuffer_h_
|
||||
#define SDL_emscriptenframebuffer_h_
|
||||
|
||||
extern int Emscripten_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, Uint32 *format, void **pixels, int *pitch);
|
||||
extern int Emscripten_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, int numrects);
|
||||
extern void Emscripten_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
|
||||
#endif /* SDL_emscriptenframebuffer_h_ */
|
251
external/sdl/SDL/src/video/emscripten/SDL_emscriptenmouse.c
vendored
Normal file
251
external/sdl/SDL/src/video/emscripten/SDL_emscriptenmouse.c
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_EMSCRIPTEN
|
||||
|
||||
#include <emscripten/emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
#include <emscripten/threading.h>
|
||||
|
||||
#include "SDL_emscriptenmouse.h"
|
||||
#include "SDL_emscriptenvideo.h"
|
||||
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
|
||||
static SDL_Cursor *Emscripten_CreateCursorFromString(const char *cursor_str, SDL_bool is_custom)
|
||||
{
|
||||
SDL_Cursor *cursor;
|
||||
Emscripten_CursorData *curdata;
|
||||
|
||||
cursor = SDL_calloc(1, sizeof(SDL_Cursor));
|
||||
if (cursor) {
|
||||
curdata = (Emscripten_CursorData *)SDL_calloc(1, sizeof(*curdata));
|
||||
if (curdata == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
SDL_free(cursor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
curdata->system_cursor = cursor_str;
|
||||
curdata->is_custom = is_custom;
|
||||
cursor->driverdata = curdata;
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static SDL_Cursor *Emscripten_CreateDefaultCursor()
|
||||
{
|
||||
return Emscripten_CreateCursorFromString("default", SDL_FALSE);
|
||||
}
|
||||
|
||||
EM_JS_DEPS(sdlmouse, "$stringToUTF8,$UTF8ToString");
|
||||
|
||||
static SDL_Cursor *Emscripten_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
|
||||
{
|
||||
const char *cursor_url = NULL;
|
||||
SDL_Surface *conv_surf;
|
||||
|
||||
conv_surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888);
|
||||
|
||||
if (conv_surf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
cursor_url = (const char *)MAIN_THREAD_EM_ASM_INT({
|
||||
var w = $0;
|
||||
var h = $1;
|
||||
var hot_x = $2;
|
||||
var hot_y = $3;
|
||||
var pixels = $4;
|
||||
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
|
||||
var ctx = canvas.getContext("2d");
|
||||
|
||||
var image = ctx.createImageData(w, h);
|
||||
var data = image.data;
|
||||
var src = pixels >> 2;
|
||||
|
||||
var data32 = new Int32Array(data.buffer);
|
||||
data32.set(HEAP32.subarray(src, src + data32.length));
|
||||
|
||||
ctx.putImageData(image, 0, 0);
|
||||
var url = hot_x === 0 && hot_y === 0
|
||||
? "url(" + canvas.toDataURL() + "), auto"
|
||||
: "url(" + canvas.toDataURL() + ") " + hot_x + " " + hot_y + ", auto";
|
||||
|
||||
var urlBuf = _malloc(url.length + 1);
|
||||
stringToUTF8(url, urlBuf, url.length + 1);
|
||||
|
||||
return urlBuf;
|
||||
}, surface->w, surface->h, hot_x, hot_y, conv_surf->pixels);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
|
||||
SDL_DestroySurface(conv_surf);
|
||||
|
||||
return Emscripten_CreateCursorFromString(cursor_url, SDL_TRUE);
|
||||
}
|
||||
|
||||
static SDL_Cursor *Emscripten_CreateSystemCursor(SDL_SystemCursor id)
|
||||
{
|
||||
const char *cursor_name = NULL;
|
||||
|
||||
switch (id) {
|
||||
case SDL_SYSTEM_CURSOR_ARROW:
|
||||
cursor_name = "default";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_IBEAM:
|
||||
cursor_name = "text";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WAIT:
|
||||
cursor_name = "wait";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_CROSSHAIR:
|
||||
cursor_name = "crosshair";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WAITARROW:
|
||||
cursor_name = "progress";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENWSE:
|
||||
cursor_name = "nwse-resize";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENESW:
|
||||
cursor_name = "nesw-resize";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEWE:
|
||||
cursor_name = "ew-resize";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENS:
|
||||
cursor_name = "ns-resize";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEALL:
|
||||
cursor_name = "move";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_NO:
|
||||
cursor_name = "not-allowed";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_HAND:
|
||||
cursor_name = "pointer";
|
||||
break;
|
||||
default:
|
||||
SDL_assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Emscripten_CreateCursorFromString(cursor_name, SDL_FALSE);
|
||||
}
|
||||
|
||||
static void Emscripten_FreeCursor(SDL_Cursor *cursor)
|
||||
{
|
||||
Emscripten_CursorData *curdata;
|
||||
if (cursor) {
|
||||
curdata = (Emscripten_CursorData *)cursor->driverdata;
|
||||
|
||||
if (curdata != NULL) {
|
||||
if (curdata->is_custom) {
|
||||
SDL_free((char *)curdata->system_cursor);
|
||||
}
|
||||
SDL_free(cursor->driverdata);
|
||||
}
|
||||
|
||||
SDL_free(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
static int Emscripten_ShowCursor(SDL_Cursor *cursor)
|
||||
{
|
||||
Emscripten_CursorData *curdata;
|
||||
if (SDL_GetMouseFocus() != NULL) {
|
||||
if (cursor && cursor->driverdata) {
|
||||
curdata = (Emscripten_CursorData *)cursor->driverdata;
|
||||
|
||||
if (curdata->system_cursor) {
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
MAIN_THREAD_EM_ASM({
|
||||
if (Module['canvas']) {
|
||||
Module['canvas'].style['cursor'] = UTF8ToString($0);
|
||||
}
|
||||
}, curdata->system_cursor);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
}
|
||||
} else {
|
||||
/* *INDENT-OFF* */ /* clang-format off */
|
||||
MAIN_THREAD_EM_ASM(
|
||||
if (Module['canvas']) {
|
||||
Module['canvas'].style['cursor'] = 'none';
|
||||
}
|
||||
);
|
||||
/* *INDENT-ON* */ /* clang-format on */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Emscripten_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
SDL_Window *window;
|
||||
SDL_WindowData *window_data;
|
||||
|
||||
/* TODO: pointer lock isn't actually enabled yet */
|
||||
if (enabled) {
|
||||
window = SDL_GetMouseFocus();
|
||||
if (window == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
window_data = window->driverdata;
|
||||
|
||||
if (emscripten_request_pointerlock(window_data->canvas_id, 1) >= EMSCRIPTEN_RESULT_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (emscripten_exit_pointerlock() >= EMSCRIPTEN_RESULT_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Emscripten_InitMouse()
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
mouse->CreateCursor = Emscripten_CreateCursor;
|
||||
mouse->ShowCursor = Emscripten_ShowCursor;
|
||||
mouse->FreeCursor = Emscripten_FreeCursor;
|
||||
mouse->CreateSystemCursor = Emscripten_CreateSystemCursor;
|
||||
mouse->SetRelativeMouseMode = Emscripten_SetRelativeMouseMode;
|
||||
|
||||
SDL_SetDefaultCursor(Emscripten_CreateDefaultCursor());
|
||||
}
|
||||
|
||||
void Emscripten_FiniMouse()
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
|
37
external/sdl/SDL/src/video/emscripten/SDL_emscriptenmouse.h
vendored
Normal file
37
external/sdl/SDL/src/video/emscripten/SDL_emscriptenmouse.h
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_emscriptenmouse_h_
|
||||
#define SDL_emscriptenmouse_h_
|
||||
|
||||
typedef struct _Emscripten_CursorData
|
||||
{
|
||||
const char *system_cursor;
|
||||
SDL_bool is_custom;
|
||||
} Emscripten_CursorData;
|
||||
|
||||
extern void
|
||||
Emscripten_InitMouse();
|
||||
|
||||
extern void
|
||||
Emscripten_FiniMouse();
|
||||
|
||||
#endif /* SDL_emscriptenmouse_h_ */
|
158
external/sdl/SDL/src/video/emscripten/SDL_emscriptenopengles.c
vendored
Normal file
158
external/sdl/SDL/src/video/emscripten/SDL_emscriptenopengles.c
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_EMSCRIPTEN
|
||||
|
||||
#include <emscripten/emscripten.h>
|
||||
#include <emscripten/html5_webgl.h>
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include "SDL_emscriptenvideo.h"
|
||||
#include "SDL_emscriptenopengles.h"
|
||||
|
||||
int Emscripten_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Emscripten_GLES_UnloadLibrary(SDL_VideoDevice *_this)
|
||||
{
|
||||
}
|
||||
|
||||
SDL_FunctionPointer Emscripten_GLES_GetProcAddress(SDL_VideoDevice *_this, const char *proc)
|
||||
{
|
||||
return emscripten_webgl_get_proc_address(proc);
|
||||
}
|
||||
|
||||
int Emscripten_GLES_SetSwapInterval(SDL_VideoDevice *_this, int interval)
|
||||
{
|
||||
if (interval < 0) {
|
||||
return SDL_SetError("Late swap tearing currently unsupported");
|
||||
} else if (interval == 0) {
|
||||
emscripten_set_main_loop_timing(EM_TIMING_SETTIMEOUT, 0);
|
||||
} else {
|
||||
emscripten_set_main_loop_timing(EM_TIMING_RAF, interval);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Emscripten_GLES_GetSwapInterval(SDL_VideoDevice *_this, int *interval)
|
||||
{
|
||||
int mode, value;
|
||||
|
||||
emscripten_get_main_loop_timing(&mode, &value);
|
||||
|
||||
if (mode == EM_TIMING_RAF) {
|
||||
*interval = value;
|
||||
return 0;
|
||||
} else {
|
||||
*interval = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_GLContext Emscripten_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *window_data;
|
||||
|
||||
EmscriptenWebGLContextAttributes attribs;
|
||||
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context;
|
||||
|
||||
emscripten_webgl_init_context_attributes(&attribs);
|
||||
|
||||
attribs.alpha = _this->gl_config.alpha_size > 0;
|
||||
attribs.depth = _this->gl_config.depth_size > 0;
|
||||
attribs.stencil = _this->gl_config.stencil_size > 0;
|
||||
attribs.antialias = _this->gl_config.multisamplebuffers == 1;
|
||||
|
||||
if (_this->gl_config.major_version == 3)
|
||||
attribs.majorVersion = 2; /* WebGL 2.0 ~= GLES 3.0 */
|
||||
|
||||
window_data = window->driverdata;
|
||||
|
||||
if (window_data->gl_context) {
|
||||
SDL_SetError("Cannot create multiple webgl contexts per window");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context = emscripten_webgl_create_context(window_data->canvas_id, &attribs);
|
||||
|
||||
if (context < 0) {
|
||||
SDL_SetError("Could not create webgl context");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (emscripten_webgl_make_context_current(context) != EMSCRIPTEN_RESULT_SUCCESS) {
|
||||
emscripten_webgl_destroy_context(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
window_data->gl_context = (SDL_GLContext)context;
|
||||
|
||||
return (SDL_GLContext)context;
|
||||
}
|
||||
|
||||
int Emscripten_GLES_DeleteContext(SDL_VideoDevice *_this, SDL_GLContext context)
|
||||
{
|
||||
SDL_Window *window;
|
||||
|
||||
/* remove the context from its window */
|
||||
for (window = _this->windows; window != NULL; window = window->next) {
|
||||
SDL_WindowData *window_data = window->driverdata;
|
||||
|
||||
if (window_data->gl_context == context) {
|
||||
window_data->gl_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
emscripten_webgl_destroy_context((EMSCRIPTEN_WEBGL_CONTEXT_HANDLE)context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Emscripten_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, SDL_TRUE)) {
|
||||
/* give back control to browser for screen refresh */
|
||||
emscripten_sleep(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Emscripten_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context)
|
||||
{
|
||||
/* it isn't possible to reuse contexts across canvases */
|
||||
if (window && context) {
|
||||
SDL_WindowData *window_data = window->driverdata;
|
||||
|
||||
if (context != window_data->gl_context) {
|
||||
return SDL_SetError("Cannot make context current to another window");
|
||||
}
|
||||
}
|
||||
|
||||
if (emscripten_webgl_make_context_current((EMSCRIPTEN_WEBGL_CONTEXT_HANDLE)context) != EMSCRIPTEN_RESULT_SUCCESS) {
|
||||
return SDL_SetError("Unable to make context current");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user