Updates SDL to 2.0.12

This commit is contained in:
Areloch 2020-08-12 11:56:18 -05:00
parent 3108a08650
commit a526029f2f
861 changed files with 25596 additions and 8904 deletions

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -20,6 +20,8 @@
*/
#include "../SDL_internal.h"
#if SDL_HAVE_RLE
/*
* RLE encoding for software colorkey and alpha-channel acceleration
*
@ -295,10 +297,10 @@
} while(0)
#define ALPHA_BLIT16_565_50(to, from, length, bpp, alpha) \
ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xf7de)
ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xf7deU)
#define ALPHA_BLIT16_555_50(to, from, length, bpp, alpha) \
ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xfbde)
ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xfbdeU)
#define CHOOSE_BLIT(blitter, alpha, fmt) \
do { \
@ -445,7 +447,7 @@ RLEClipBlit(int w, Uint8 * srcbuf, SDL_Surface * surf_dst,
/* blit a colorkeyed RLE surface */
int SDLCALL
static int SDLCALL
SDL_RLEBlit(SDL_Surface * surf_src, SDL_Rect * srcrect,
SDL_Surface * surf_dst, SDL_Rect * dstrect)
{
@ -723,7 +725,7 @@ RLEAlphaClipBlit(int w, Uint8 * srcbuf, SDL_Surface * surf_dst,
}
/* blit a pixel-alpha RLE surface */
int SDLCALL
static int SDLCALL
SDL_RLEAlphaBlit(SDL_Surface * surf_src, SDL_Rect * srcrect,
SDL_Surface * surf_dst, SDL_Rect * dstrect)
{
@ -1237,19 +1239,19 @@ RLEAlphaSurface(SDL_Surface * surface)
}
static Uint32
getpix_8(Uint8 * srcbuf)
getpix_8(const Uint8 * srcbuf)
{
return *srcbuf;
}
static Uint32
getpix_16(Uint8 * srcbuf)
getpix_16(const Uint8 * srcbuf)
{
return *(Uint16 *) srcbuf;
return *(const Uint16 *) srcbuf;
}
static Uint32
getpix_24(Uint8 * srcbuf)
getpix_24(const Uint8 * srcbuf)
{
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
return srcbuf[0] + (srcbuf[1] << 8) + (srcbuf[2] << 16);
@ -1259,12 +1261,12 @@ getpix_24(Uint8 * srcbuf)
}
static Uint32
getpix_32(Uint8 * srcbuf)
getpix_32(const Uint8 * srcbuf)
{
return *(Uint32 *) srcbuf;
return *(const Uint32 *) srcbuf;
}
typedef Uint32(*getpix_func) (Uint8 *);
typedef Uint32(*getpix_func) (const Uint8 *);
static const getpix_func getpixes[4] = {
getpix_8, getpix_16, getpix_24, getpix_32
@ -1430,7 +1432,7 @@ SDL_RLESurface(SDL_Surface * surface)
/* Pass on combinations not supported */
if ((flags & SDL_COPY_MODULATE_COLOR) ||
((flags & SDL_COPY_MODULATE_ALPHA) && surface->format->Amask) ||
(flags & (SDL_COPY_ADD | SDL_COPY_MOD)) ||
(flags & (SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL)) ||
(flags & SDL_COPY_NEAREST)) {
return -1;
}
@ -1584,4 +1586,6 @@ SDL_UnRLESurface(SDL_Surface * surface, int recode)
}
}
#endif /* SDL_HAVE_RLE */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -27,10 +27,6 @@
/* Useful functions and variables from SDL_RLEaccel.c */
extern int SDL_RLESurface(SDL_Surface * surface);
extern int SDLCALL SDL_RLEBlit (SDL_Surface * src, SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect);
extern int SDLCALL SDL_RLEAlphaBlit(SDL_Surface * src, SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect);
extern void SDL_UnRLESurface(SDL_Surface * surface, int recode);
#endif /* SDL_RLEaccel_c_h_ */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -99,6 +99,8 @@ SDL_SoftBlit(SDL_Surface * src, SDL_Rect * srcrect,
return (okay ? 0 : -1);
}
#if SDL_HAVE_BLIT_AUTO
#ifdef __MACOSX__
#include <sys/sysctl.h>
@ -128,11 +130,11 @@ static SDL_BlitFunc
SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int flags,
SDL_BlitFuncEntry * entries)
{
int i, flagcheck;
static Uint32 features = 0xffffffff;
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 == 0xffffffff) {
if (features == 0x7fffffff) {
const char *override = SDL_getenv("SDL_BLIT_CPU_FEATURES");
features = SDL_CPU_ANY;
@ -172,36 +174,13 @@ SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int flags,
continue;
}
/* Check modulation flags */
flagcheck =
(flags & (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA));
if ((flagcheck & entries[i].flags) != flagcheck) {
continue;
}
/* Check blend flags */
flagcheck =
(flags &
(SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD));
if ((flagcheck & entries[i].flags) != flagcheck) {
continue;
}
/* Check colorkey flag */
flagcheck = (flags & SDL_COPY_COLORKEY);
if ((flagcheck & entries[i].flags) != flagcheck) {
continue;
}
/* Check scaling flags */
flagcheck = (flags & SDL_COPY_NEAREST);
/* Check flags */
if ((flagcheck & entries[i].flags) != flagcheck) {
continue;
}
/* Check CPU features */
flagcheck = entries[i].cpu;
if ((flagcheck & features) != flagcheck) {
if ((entries[i].cpu & features) != entries[i].cpu) {
continue;
}
@ -210,6 +189,7 @@ SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int flags,
}
return NULL;
}
#endif /* SDL_HAVE_BLIT_AUTO */
/* Figure out which of many blit routines to set up on a surface */
int
@ -225,22 +205,27 @@ SDL_CalculateBlit(SDL_Surface * surface)
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)) {
@ -249,17 +234,30 @@ SDL_CalculateBlit(SDL_Surface * surface)
/* Greater than 8 bits per channel not supported yet */
SDL_InvalidateMap(map);
return SDL_SetError("Blit combination not supported");
} else if (surface->format->BitsPerPixel < 8 &&
}
#if SDL_HAVE_BLIT_0
else if (surface->format->BitsPerPixel < 8 &&
SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
blit = SDL_CalculateBlit0(surface);
} else if (surface->format->BytesPerPixel == 1 &&
}
#endif
#if SDL_HAVE_BLIT_1
else if (surface->format->BytesPerPixel == 1 &&
SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
blit = SDL_CalculateBlit1(surface);
} else if (map->info.flags & SDL_COPY_BLEND) {
}
#endif
#if SDL_HAVE_BLIT_A
else if (map->info.flags & SDL_COPY_BLEND) {
blit = SDL_CalculateBlitA(surface);
} else {
}
#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;
@ -268,6 +266,8 @@ SDL_CalculateBlit(SDL_Surface * surface)
SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags,
SDL_GeneratedBlitFuncTable);
}
#endif
#ifndef TEST_SLOW_BLIT
if (blit == NULL)
#endif

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -36,6 +36,7 @@ extern Uint8* SDL_expand_byte[9];
#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

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -20,6 +20,8 @@
*/
#include "../SDL_internal.h"
#if SDL_HAVE_BLIT_0
#include "SDL_video.h"
#include "SDL_blit.h"
@ -480,4 +482,6 @@ SDL_CalculateBlit0(SDL_Surface * surface)
return (SDL_BlitFunc) NULL;
}
#endif /* SDL_HAVE_BLIT_0 */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -20,6 +20,8 @@
*/
#include "../SDL_internal.h"
#if SDL_HAVE_BLIT_1
#include "SDL_video.h"
#include "SDL_blit.h"
#include "SDL_sysvideo.h"
@ -549,4 +551,6 @@ SDL_CalculateBlit1(SDL_Surface * surface)
return (SDL_BlitFunc) NULL;
}
#endif /* SDL_HAVE_BLIT_1 */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -20,6 +20,8 @@
*/
#include "../SDL_internal.h"
#if SDL_HAVE_BLIT_A
#include "SDL_video.h"
#include "SDL_blit.h"
@ -389,6 +391,70 @@ BlitRGBtoRGBPixelAlphaMMX(SDL_BlitInfo * info)
#endif /* __MMX__ */
#if SDL_ARM_SIMD_BLITTERS
void BlitARGBto565PixelAlphaARMSIMDAsm(int32_t w, int32_t h, uint16_t *dst, int32_t dst_stride, uint32_t *src, int32_t src_stride);
static void
BlitARGBto565PixelAlphaARMSIMD(SDL_BlitInfo * info)
{
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint16_t *dstp = (uint16_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 1);
uint32_t *srcp = (uint32_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 2);
BlitARGBto565PixelAlphaARMSIMDAsm(width, height, dstp, dststride, srcp, srcstride);
}
void BlitRGBtoRGBPixelAlphaARMSIMDAsm(int32_t w, int32_t h, uint32_t *dst, int32_t dst_stride, uint32_t *src, int32_t src_stride);
static void
BlitRGBtoRGBPixelAlphaARMSIMD(SDL_BlitInfo * info)
{
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint32_t *dstp = (uint32_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 2);
uint32_t *srcp = (uint32_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 2);
BlitRGBtoRGBPixelAlphaARMSIMDAsm(width, height, dstp, dststride, srcp, srcstride);
}
#endif
#if SDL_ARM_NEON_BLITTERS
void BlitARGBto565PixelAlphaARMNEONAsm(int32_t w, int32_t h, uint16_t *dst, int32_t dst_stride, uint32_t *src, int32_t src_stride);
static void
BlitARGBto565PixelAlphaARMNEON(SDL_BlitInfo * info)
{
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint16_t *dstp = (uint16_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 1);
uint32_t *srcp = (uint32_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 2);
BlitARGBto565PixelAlphaARMNEONAsm(width, height, dstp, dststride, srcp, srcstride);
}
void BlitRGBtoRGBPixelAlphaARMNEONAsm(int32_t w, int32_t h, uint32_t *dst, int32_t dst_stride, uint32_t *src, int32_t src_stride);
static void
BlitRGBtoRGBPixelAlphaARMNEON(SDL_BlitInfo * info)
{
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint32_t *dstp = (uint32_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 2);
uint32_t *srcp = (uint32_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 2);
BlitRGBtoRGBPixelAlphaARMNEONAsm(width, height, dstp, dststride, srcp, srcstride);
}
#endif
/* fast RGB888->(A)RGB888 blending with surface alpha=128 special case */
static void
BlitRGBtoRGBSurfaceAlpha128(SDL_BlitInfo * info)
@ -1284,6 +1350,22 @@ SDL_CalculateBlitA(SDL_Surface * surface)
}
case 2:
#if SDL_ARM_NEON_BLITTERS || SDL_ARM_SIMD_BLITTERS
if (sf->BytesPerPixel == 4 && sf->Amask == 0xff000000
&& sf->Gmask == 0xff00 && df->Gmask == 0x7e0
&& ((sf->Rmask == 0xff && df->Rmask == 0x1f)
|| (sf->Bmask == 0xff && df->Bmask == 0x1f)))
{
#if SDL_ARM_NEON_BLITTERS
if (SDL_HasNEON())
return BlitARGBto565PixelAlphaARMNEON;
#endif
#if SDL_ARM_SIMD_BLITTERS
if (SDL_HasARMSIMD())
return BlitARGBto565PixelAlphaARMSIMD;
#endif
}
#endif
if (sf->BytesPerPixel == 4 && sf->Amask == 0xff000000
&& sf->Gmask == 0xff00
&& ((sf->Rmask == 0xff && df->Rmask == 0x1f)
@ -1315,6 +1397,14 @@ SDL_CalculateBlitA(SDL_Surface * surface)
}
#endif /* __MMX__ || __3dNOW__ */
if (sf->Amask == 0xff000000) {
#if SDL_ARM_NEON_BLITTERS
if (SDL_HasNEON())
return BlitRGBtoRGBPixelAlphaARMNEON;
#endif
#if SDL_ARM_SIMD_BLITTERS
if (SDL_HasARMSIMD())
return BlitRGBtoRGBPixelAlphaARMSIMD;
#endif
return BlitRGBtoRGBPixelAlpha;
}
}
@ -1401,4 +1491,6 @@ SDL_CalculateBlitA(SDL_Surface * surface)
return NULL;
}
#endif /* SDL_HAVE_BLIT_A */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -20,6 +20,8 @@
*/
#include "../SDL_internal.h"
#if SDL_HAVE_BLIT_N
#include "SDL_video.h"
#include "SDL_endian.h"
#include "SDL_cpuinfo.h"
@ -38,6 +40,14 @@
/* Functions to blit from N-bit surfaces to other surfaces */
enum blit_features {
BLIT_FEATURE_NONE = 0,
BLIT_FEATURE_HAS_MMX = 1,
BLIT_FEATURE_HAS_ALTIVEC = 2,
BLIT_FEATURE_ALTIVEC_DONT_USE_PREFETCH = 4,
BLIT_FEATURE_HAS_ARM_SIMD = 8
};
#if SDL_ALTIVEC_BLITTERS
#ifdef HAVE_ALTIVEC_H
#include <altivec.h>
@ -165,6 +175,34 @@ calc_swizzle32(const SDL_PixelFormat * srcfmt, const SDL_PixelFormat * dstfmt)
return (vswiz);
}
#if defined(__powerpc__) && (SDL_BYTEORDER == SDL_LIL_ENDIAN)
/* reorder bytes for PowerPC little endian */
static vector unsigned char reorder_ppc64le_vec(vector unsigned char vpermute)
{
/* The result vector of calc_swizzle32 reorder bytes using vec_perm.
The LE transformation for vec_perm has an implicit assumption
that the permutation is being used to reorder vector elements,
not to reorder bytes within those elements.
Unfortunatly the result order is not the expected one for powerpc
little endian when the two first vector parameters of vec_perm are
not of type 'vector char'. This is because the numbering from the
left for BE, and numbering from the right for LE, produces a
different interpretation of what the odd and even lanes are.
Refer to fedora bug 1392465
*/
const vector unsigned char ppc64le_reorder = VECUINT8_LITERAL(
0x01, 0x00, 0x03, 0x02,
0x05, 0x04, 0x07, 0x06,
0x09, 0x08, 0x0B, 0x0A,
0x0D, 0x0C, 0x0F, 0x0E );
vector unsigned char vswiz_ppc64le;
vswiz_ppc64le = vec_perm(vpermute, vpermute, ppc64le_reorder);
return(vswiz_ppc64le);
}
#endif
static void Blit_RGB888_RGB565(SDL_BlitInfo * info);
static void
Blit_RGB888_RGB565Altivec(SDL_BlitInfo * info)
@ -658,6 +696,10 @@ Blit32to32KeyAltivec(SDL_BlitInfo * info)
/* vsel is set for items that match the key */
vsel = (vector unsigned char) vec_and(vs, vrgbmask);
vsel = (vector unsigned char) vec_cmpeq(vs, vckey);
#if defined(__powerpc__) && (SDL_BYTEORDER == SDL_LIL_ENDIAN)
/* reorder bytes for PowerPC little endian */
vpermute = reorder_ppc64le_vec(vpermute);
#endif
/* permute the src vec to the dest format */
vs = vec_perm(vs, valpha, vpermute);
/* load the destination vec */
@ -737,6 +779,10 @@ ConvertAltivec32to32_noprefetch(SDL_BlitInfo * info)
src += 4;
width -= 4;
vbits = vec_perm(vbits, voverflow, valigner); /* src is ready. */
#if defined(__powerpc__) && (SDL_BYTEORDER == SDL_LIL_ENDIAN)
/* reorder bytes for PowerPC little endian */
vpermute = reorder_ppc64le_vec(vpermute);
#endif
vbits = vec_perm(vbits, vzero, vpermute); /* swizzle it. */
vec_st(vbits, 0, dst); /* store it back out. */
dst += 4;
@ -828,6 +874,10 @@ ConvertAltivec32to32_prefetch(SDL_BlitInfo * info)
src += 4;
width -= 4;
vbits = vec_perm(vbits, voverflow, valigner); /* src is ready. */
#if defined(__powerpc__) && (SDL_BYTEORDER == SDL_LIL_ENDIAN)
/* reorder bytes for PowerPC little endian */
vpermute = reorder_ppc64le_vec(vpermute);
#endif
vbits = vec_perm(vbits, vzero, vpermute); /* swizzle it. */
vec_st(vbits, 0, dst); /* store it back out. */
dst += 4;
@ -854,25 +904,26 @@ ConvertAltivec32to32_prefetch(SDL_BlitInfo * info)
vec_dss(DST_CHAN_DEST);
}
static Uint32
static enum blit_features
GetBlitFeatures(void)
{
static Uint32 features = 0xffffffff;
if (features == 0xffffffff) {
static enum blit_features features = -1;
if (features == (enum blit_features) -1) {
/* Provide an override for testing .. */
char *override = SDL_getenv("SDL_ALTIVEC_BLIT_FEATURES");
if (override) {
features = 0;
SDL_sscanf(override, "%u", &features);
unsigned int features_as_uint = 0;
SDL_sscanf(override, "%u", &features_as_uint);
features = (enum blit_features) features_as_uint;
} else {
features = (0
/* Feature 1 is has-MMX */
| ((SDL_HasMMX())? 1 : 0)
| ((SDL_HasMMX())? BLIT_FEATURE_HAS_MMX : 0)
/* Feature 2 is has-AltiVec */
| ((SDL_HasAltiVec())? 2 : 0)
| ((SDL_HasAltiVec())? BLIT_FEATURE_HAS_ALTIVEC : 0)
/* Feature 4 is dont-use-prefetch */
/* !!!! FIXME: Check for G5 or later, not the cache size! Always prefetch on a G4. */
| ((GetL3CacheSize() == 0) ? 4 : 0)
| ((GetL3CacheSize() == 0) ? BLIT_FEATURE_ALTIVEC_DONT_USE_PREFETCH : 0)
);
}
}
@ -884,7 +935,39 @@ GetBlitFeatures(void)
#endif
#else
/* Feature 1 is has-MMX */
#define GetBlitFeatures() ((Uint32)(SDL_HasMMX() ? 1 : 0))
#define GetBlitFeatures() ((SDL_HasMMX() ? BLIT_FEATURE_HAS_MMX : 0) | (SDL_HasARMSIMD() ? BLIT_FEATURE_HAS_ARM_SIMD : 0))
#endif
#if SDL_ARM_SIMD_BLITTERS
void Blit_BGR888_RGB888ARMSIMDAsm(int32_t w, int32_t h, uint32_t *dst, int32_t dst_stride, uint32_t *src, int32_t src_stride);
static void
Blit_BGR888_RGB888ARMSIMD(SDL_BlitInfo * info)
{
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint32_t *dstp = (uint32_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 2);
uint32_t *srcp = (uint32_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 2);
Blit_BGR888_RGB888ARMSIMDAsm(width, height, dstp, dststride, srcp, srcstride);
}
void Blit_RGB444_RGB888ARMSIMDAsm(int32_t w, int32_t h, uint32_t *dst, int32_t dst_stride, uint16_t *src, int32_t src_stride);
static void
Blit_RGB444_RGB888ARMSIMD(SDL_BlitInfo * info)
{
int32_t width = info->dst_w;
int32_t height = info->dst_h;
uint32_t *dstp = (uint32_t *)info->dst;
int32_t dststride = width + (info->dst_skip >> 2);
uint16_t *srcp = (uint16_t *)info->src;
int32_t srcstride = width + (info->src_skip >> 1);
Blit_RGB444_RGB888ARMSIMDAsm(width, height, dstp, dststride, srcp, srcstride);
}
#endif
/* This is now endian dependent */
@ -1369,6 +1452,8 @@ Blit_RGB888_RGB565(SDL_BlitInfo * info)
}
#if SDL_HAVE_BLIT_N_RGB565
/* Special optimized blit for RGB 5-6-5 --> 32-bit RGB surfaces */
#define RGB565_32(dst, src, map) (map[src[LO]*2] + map[src[HI]*2+1])
static void
@ -1385,7 +1470,7 @@ Blit_RGB565_32(SDL_BlitInfo * info, const Uint32 * map)
/* Set up some basic variables */
width = info->dst_w;
height = info->dst_h;
src = (Uint8 *) info->src;
src = info->src;
srcskip = info->src_skip;
dst = (Uint32 *) info->dst;
dstskip = info->dst_skip / 4;
@ -1987,6 +2072,8 @@ Blit_RGB565_BGRA8888(SDL_BlitInfo * info)
Blit_RGB565_32(info, RGB565_BGRA8888_LUT);
}
#endif /* SDL_HAVE_BLIT_N_RGB565 */
static void
BlitNto1(SDL_BlitInfo * info)
{
@ -2236,7 +2323,6 @@ get_permutation(SDL_PixelFormat *srcfmt, SDL_PixelFormat *dstfmt,
if (_alpha_channel) {
*_alpha_channel = alpha_channel;
}
return;
}
@ -3028,7 +3114,6 @@ Blit_3or4_to_3or4__same_rgb(SDL_BlitInfo * info)
dst += dstskip;
}
}
return;
}
/* Blit_3or4_to_3or4__inversed_rgb: 3 or 4 bpp, inversed RGB triplet */
@ -3133,7 +3218,6 @@ Blit_3or4_to_3or4__inversed_rgb(SDL_BlitInfo * info)
dst += dstskip;
}
}
return;
}
/* Normal N to N optimized blitters */
@ -3145,7 +3229,7 @@ struct blit_table
Uint32 srcR, srcG, srcB;
int dstbpp;
Uint32 dstR, dstG, dstB;
Uint32 blit_features;
enum blit_features blit_features;
SDL_BlitFunc blitfunc;
Uint32 alpha; /* bitwise NO_ALPHA, SET_ALPHA, COPY_ALPHA */
};
@ -3158,10 +3242,15 @@ static const struct blit_table normal_blit_2[] = {
#if SDL_ALTIVEC_BLITTERS
/* has-altivec */
{0x0000F800, 0x000007E0, 0x0000001F, 4, 0x00000000, 0x00000000, 0x00000000,
2, Blit_RGB565_32Altivec, NO_ALPHA | COPY_ALPHA | SET_ALPHA},
BLIT_FEATURE_HAS_ALTIVEC, Blit_RGB565_32Altivec, NO_ALPHA | COPY_ALPHA | SET_ALPHA},
{0x00007C00, 0x000003E0, 0x0000001F, 4, 0x00000000, 0x00000000, 0x00000000,
2, Blit_RGB555_32Altivec, NO_ALPHA | COPY_ALPHA | SET_ALPHA},
BLIT_FEATURE_HAS_ALTIVEC, Blit_RGB555_32Altivec, NO_ALPHA | COPY_ALPHA | SET_ALPHA},
#endif
#if SDL_ARM_SIMD_BLITTERS
{0x00000F00, 0x000000F0, 0x0000000F, 4, 0x00FF0000, 0x0000FF00, 0x000000FF,
BLIT_FEATURE_HAS_ARM_SIMD, Blit_RGB444_RGB888ARMSIMD, NO_ALPHA | COPY_ALPHA},
#endif
#if SDL_HAVE_BLIT_N_RGB565
{0x0000F800, 0x000007E0, 0x0000001F, 4, 0x00FF0000, 0x0000FF00, 0x000000FF,
0, Blit_RGB565_ARGB8888, NO_ALPHA | COPY_ALPHA | SET_ALPHA},
{0x0000F800, 0x000007E0, 0x0000001F, 4, 0x000000FF, 0x0000FF00, 0x00FF0000,
@ -3170,6 +3259,7 @@ static const struct blit_table normal_blit_2[] = {
0, Blit_RGB565_RGBA8888, NO_ALPHA | COPY_ALPHA | SET_ALPHA},
{0x0000F800, 0x000007E0, 0x0000001F, 4, 0x0000FF00, 0x00FF0000, 0xFF000000,
0, Blit_RGB565_BGRA8888, NO_ALPHA | COPY_ALPHA | SET_ALPHA},
#endif
/* Default for 16-bit RGB source, used if no other blitter matches */
{0, 0, 0, 0, 0, 0, 0, 0, BlitNtoN, 0}
@ -3215,13 +3305,17 @@ static const struct blit_table normal_blit_4[] = {
#if SDL_ALTIVEC_BLITTERS
/* has-altivec | dont-use-prefetch */
{0x00000000, 0x00000000, 0x00000000, 4, 0x00000000, 0x00000000, 0x00000000,
6, ConvertAltivec32to32_noprefetch, NO_ALPHA | COPY_ALPHA | SET_ALPHA},
BLIT_FEATURE_HAS_ALTIVEC | BLIT_FEATURE_ALTIVEC_DONT_USE_PREFETCH, ConvertAltivec32to32_noprefetch, NO_ALPHA | COPY_ALPHA | SET_ALPHA},
/* has-altivec */
{0x00000000, 0x00000000, 0x00000000, 4, 0x00000000, 0x00000000, 0x00000000,
2, ConvertAltivec32to32_prefetch, NO_ALPHA | COPY_ALPHA | SET_ALPHA},
BLIT_FEATURE_HAS_ALTIVEC, ConvertAltivec32to32_prefetch, NO_ALPHA | COPY_ALPHA | SET_ALPHA},
/* has-altivec */
{0x00000000, 0x00000000, 0x00000000, 2, 0x0000F800, 0x000007E0, 0x0000001F,
2, Blit_RGB888_RGB565Altivec, NO_ALPHA},
BLIT_FEATURE_HAS_ALTIVEC, Blit_RGB888_RGB565Altivec, NO_ALPHA},
#endif
#if SDL_ARM_SIMD_BLITTERS
{0x000000FF, 0x0000FF00, 0x00FF0000, 4, 0x00FF0000, 0x0000FF00, 0x000000FF,
BLIT_FEATURE_HAS_ARM_SIMD, Blit_BGR888_RGB888ARMSIMD, NO_ALPHA | COPY_ALPHA },
#endif
/* 4->3 with same rgb triplet */
{0x000000FF, 0x0000FF00, 0x00FF0000, 3, 0x000000FF, 0x0000FF00, 0x00FF0000,
@ -3373,4 +3467,6 @@ SDL_CalculateBlitN(SDL_Surface * surface)
return NULL;
}
#endif /* SDL_HAVE_BLIT_N */
/* vi: set ts=4 sw=4 expandtab: */

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/* DO NOT EDIT! This file is generated by sdlgenblit.pl */
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -21,10 +21,14 @@
*/
#include "../SDL_internal.h"
#if SDL_HAVE_BLIT_AUTO
/* *INDENT-OFF* */
extern SDL_BlitFuncEntry SDL_GeneratedBlitFuncTable[];
/* *INDENT-ON* */
#endif /* SDL_HAVE_BLIT_AUTO */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -56,7 +56,7 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
while (info->dst_h--) {
Uint8 *src = 0;
Uint8 *dst = (Uint8 *) info->dst;
Uint8 *dst = info->dst;
int n = info->dst_w;
srcx = -1;
posx = 0x10000L;
@ -118,7 +118,7 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
srcB = (srcB * srcA) / 255;
}
}
switch (flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD)) {
switch (flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL)) {
case 0:
dstR = srcR;
dstG = srcG;
@ -147,6 +147,20 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
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;
dstA = ((srcA * dstA) + (dstA * (255 - srcA))) / 255;
if (dstA > 255)
dstA = 255;
break;
}
if (dst_fmt->Amask) {
ASSEMBLE_RGBA(dst, dstbpp, dst_fmt, dstR, dstG, dstB, dstA);

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -54,6 +54,92 @@
#define LCS_WINDOWS_COLOR_SPACE 0x57696E20
#endif
static int 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)
for (;;) {
if (!SDL_RWread(src, &ch, 1, 1)) return 1;
/*
| encoded mode starts with a run length, and then a byte
| with two colour indexes to alternate between for the run
*/
if (ch) {
Uint8 pixel;
if (!SDL_RWread(src, &pixel, 1, 1)) return 1;
if (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, 1)) return 1;
switch (ch) {
case 0: /* end of line */
ofs = 0;
bits -= pitch; /* go to previous */
break;
case 1: /* end of bitmap */
return 0; /* success! */
case 2: /* delta */
if (!SDL_RWread(src, &ch, 1, 1)) return 1;
ofs += ch;
if (!SDL_RWread(src, &ch, 1, 1)) return 1;
bits -= (ch * pitch);
break;
default: /* no compression */
if (isRle8) {
needsPad = (ch & 1);
do {
Uint8 pixel;
if (!SDL_RWread(src, &pixel, 1, 1)) return 1;
COPY_PIXEL(pixel);
} while (--ch);
} else {
needsPad = (((ch+1)>>1) & 1); /* (ch+1)>>1: bytes size */
for (;;) {
Uint8 pixel;
if (!SDL_RWread(src, &pixel, 1, 1)) return 1;
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, 1)) return 1;
break;
}
}
}
}
static void CorrectAlphaChannel(SDL_Surface *surface)
{
/* Check to see if there is any alpha channel data */
@ -106,26 +192,23 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
/* The Win32 BMP file header (14 bytes) */
char magic[2];
/* Uint32 bfSize = 0; */
/* Uint16 bfReserved1 = 0; */
/* Uint16 bfReserved2 = 0; */
Uint32 bfOffBits = 0;
/* Uint32 bfSize; */
/* Uint16 bfReserved1; */
/* Uint16 bfReserved2; */
Uint32 bfOffBits;
/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
Uint32 biSize = 0;
Uint32 biSize;
Sint32 biWidth = 0;
Sint32 biHeight = 0;
/* Uint16 biPlanes = 0; */
/* Uint16 biPlanes; */
Uint16 biBitCount = 0;
Uint32 biCompression = 0;
/* Uint32 biSizeImage = 0; */
/* Sint32 biXPelsPerMeter = 0; */
/* Sint32 biYPelsPerMeter = 0; */
/* Uint32 biSizeImage; */
/* Sint32 biXPelsPerMeter; */
/* Sint32 biYPelsPerMeter; */
Uint32 biClrUsed = 0;
/* Uint32 biClrImportant = 0; */
(void) haveRGBMasks;
(void) haveAlphaMask;
/* Uint32 biClrImportant; */
/* Make sure we are passed a valid data source */
surface = NULL;
@ -148,10 +231,10 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
was_error = SDL_TRUE;
goto done;
}
/* bfSize = */ SDL_ReadLE32(src);
/* bfSize = */ SDL_ReadLE32(src);
/* bfReserved1 = */ SDL_ReadLE16(src);
/* bfReserved2 = */ SDL_ReadLE16(src);
bfOffBits = SDL_ReadLE32(src);
bfOffBits = SDL_ReadLE32(src);
/* Read the Win32 BITMAPINFOHEADER */
biSize = SDL_ReadLE32(src);
@ -161,6 +244,11 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
/* 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);
@ -175,15 +263,7 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
/* biClrImportant = */ SDL_ReadLE32(src);
/* 64 == BITMAPCOREHEADER2, an incompatible OS/2 2.x extension. Skip this stuff for now. */
if (biSize == 64) {
/* ignore these extra fields. */
if (biCompression == BI_BITFIELDS) {
/* this value is actually huffman compression in this variant. */
SDL_SetError("Compressed BMP files not supported");
was_error = SDL_TRUE;
goto done;
}
} else {
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
@ -226,6 +306,11 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
SDL_RWseek(src, (biSize - headerSize), RW_SEEK_CUR);
}
}
if (biWidth <= 0 || biHeight == 0) {
SDL_SetError("BMP file with bad dimensions (%dx%d)", biWidth, biHeight);
was_error = SDL_TRUE;
goto done;
}
if (biHeight < 0) {
topDown = SDL_TRUE;
biHeight = -biHeight;
@ -246,12 +331,13 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
ExpandBMP = biBitCount;
biBitCount = 8;
break;
case 0:
case 2:
case 3:
case 5:
case 6:
case 7:
SDL_SetError("%d-bpp BMP images are not supported", biBitCount);
SDL_SetError("%d-bpp BMP images are not supported", biBitCount);
was_error = SDL_TRUE;
goto done;
default:
@ -259,7 +345,7 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
break;
}
/* We don't support any BMP compression right now */
/* RLE4 and RLE8 BMP compression is supported */
switch (biCompression) {
case BI_RGB:
/* If there are no masks, use the defaults */
@ -301,9 +387,7 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
break; /* we handled this in the info header. */
default:
SDL_SetError("Compressed BMP files not supported");
was_error = SDL_TRUE;
goto done;
break;
}
/* Create a compatible surface, note that the colors are RGB ordered */
@ -318,31 +402,19 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
/* Load the palette, if any */
palette = (surface->format)->palette;
if (palette) {
SDL_assert(biBitCount <= 8);
if (biClrUsed == 0) {
biClrUsed = 1 << biBitCount;
} else if (biClrUsed > (Uint32)(1 << biBitCount)) {
SDL_SetError("BMP file has an invalid number of colors");
was_error = SDL_TRUE;
goto done;
}
if ((int) biClrUsed > palette->ncolors) {
SDL_Color *colors;
int ncolors = biClrUsed;
colors =
(SDL_Color *) SDL_realloc(palette->colors,
ncolors *
sizeof(*palette->colors));
if (!colors) {
SDL_OutOfMemory();
was_error = SDL_TRUE;
goto done;
}
palette->ncolors = ncolors;
palette->colors = colors;
} else if ((int) biClrUsed < palette->ncolors) {
palette->ncolors = biClrUsed;
if (SDL_RWseek(src, fp_offset+14+biSize, RW_SEEK_SET) < 0) {
SDL_Error(SDL_EFSEEK);
was_error = SDL_TRUE;
goto done;
}
/*
| guich: always use 1<<bpp b/c some bitmaps can bring wrong information
| for colorsUsed
*/
/* if (biClrUsed == 0) { */
biClrUsed = 1 << biBitCount;
/* } */
if (biSize == 12) {
for (i = 0; i < (int) biClrUsed; ++i) {
SDL_RWread(src, &palette->colors[i].b, 1, 1);
@ -364,6 +436,7 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
palette->colors[i].a = SDL_ALPHA_OPAQUE;
}
}
palette->ncolors = biClrUsed;
}
/* Read the surface pixels. Note that the bmp image is upside down */
@ -372,6 +445,11 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
was_error = SDL_TRUE;
goto done;
}
if ((biCompression == BI_RLE4) || (biCompression == BI_RLE8)) {
was_error = (SDL_bool)readRlePixels(surface, src, biCompression == BI_RLE8);
if (was_error) SDL_SetError("Error reading from BMP");
goto done;
}
top = (Uint8 *)surface->pixels;
end = (Uint8 *)surface->pixels+(surface->h*surface->pitch);
switch (ExpandBMP) {
@ -407,11 +485,11 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
}
}
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;
}
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;
}
}
@ -423,15 +501,15 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
was_error = SDL_TRUE;
goto done;
}
if (biBitCount == 8 && palette && biClrUsed < (Uint32)(1 << 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 (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. */
@ -475,7 +553,9 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
if (src) {
SDL_RWseek(src, fp_offset, RW_SEEK_SET);
}
SDL_FreeSurface(surface);
if (surface) {
SDL_FreeSurface(surface);
}
surface = NULL;
}
if (freesrc && src) {

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
* Simple DirectMedia Layer
* Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
* Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@ -82,6 +82,13 @@
#define DEFAULT_OGL_ES "libGLESv1_CM.so.1"
#endif /* SDL_VIDEO_DRIVER_RPI */
/** If we happen to not have this defined because of an older EGL version, just define it 0x0
as eglGetPlatformDisplayEXT will most likely be NULL if this is missing
*/
#ifndef EGL_PLATFORM_DEVICE_EXT
#define EGL_PLATFORM_DEVICE_EXT 0x0
#endif
#ifdef SDL_VIDEO_STATIC_ANGLE
#define LOAD_FUNC(NAME) \
_this->egl_data->NAME = (void *)NAME;
@ -94,6 +101,11 @@ if (!_this->egl_data->NAME) \
}
#endif
/* it is allowed to not have some of the EGL extensions on start - attempts to use them will fail later. */
#define LOAD_FUNC_EGLEXT(NAME) \
_this->egl_data->NAME = _this->egl_data->eglGetProcAddress(#NAME);
static const char * SDL_EGL_GetErrorName(EGLint eglErrorCode)
{
#define SDL_EGL_ERROR_TRANSLATE(e) case e: return #e;
@ -210,25 +222,35 @@ static SDL_bool SDL_EGL_HasExtension(_THIS, SDL_EGL_ExtensionType type, const ch
void *
SDL_EGL_GetProcAddress(_THIS, const char *proc)
{
static char procname[1024];
void *retval;
/* eglGetProcAddress is busted on Android http://code.google.com/p/android/issues/detail?id=7681 */
#if !defined(SDL_VIDEO_DRIVER_ANDROID)
if (_this->egl_data->eglGetProcAddress) {
const Uint32 eglver = (((Uint32) _this->egl_data->egl_version_major) << 16) | ((Uint32) _this->egl_data->egl_version_minor);
const SDL_bool is_egl_15_or_later = eglver >= ((((Uint32) 1) << 16) | 5);
void *retval = NULL;
/* EGL 1.5 can use eglGetProcAddress() for any symbol. 1.4 and earlier can't use it for core entry points. */
if (!retval && is_egl_15_or_later && _this->egl_data->eglGetProcAddress) {
retval = _this->egl_data->eglGetProcAddress(proc);
}
/* Try SDL_LoadFunction() first for EGL <= 1.4, or as a fallback for >= 1.5. */
if (!retval) {
static char procname[64];
retval = SDL_LoadFunction(_this->egl_data->egl_dll_handle, proc);
/* just in case you need an underscore prepended... */
if (!retval && (SDL_strlen(proc) < (sizeof (procname) - 1))) {
procname[0] = '_';
SDL_strlcpy(procname + 1, proc, sizeof (procname) - 1);
retval = SDL_LoadFunction(_this->egl_data->egl_dll_handle, procname);
}
}
/* Try eglGetProcAddress if we on <= 1.4 and still searching... */
if (!retval && !is_egl_15_or_later && _this->egl_data->eglGetProcAddress) {
retval = _this->egl_data->eglGetProcAddress(proc);
if (retval) {
return retval;
}
}
#endif
retval = SDL_LoadFunction(_this->egl_data->egl_dll_handle, proc);
if (!retval && SDL_strlen(proc) <= 1022) {
procname[0] = '_';
SDL_strlcpy(procname + 1, proc, 1022);
retval = SDL_LoadFunction(_this->egl_data->egl_dll_handle, procname);
}
return retval;
}
@ -256,11 +278,10 @@ SDL_EGL_UnloadLibrary(_THIS)
}
int
SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display, EGLenum platform)
SDL_EGL_LoadLibraryOnly(_THIS, const char *egl_path)
{
void *dll_handle = NULL, *egl_dll_handle = NULL; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */
const char *path = NULL;
int egl_version_major = 0, egl_version_minor = 0;
#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
const char *d3dcompiler;
#endif
@ -406,23 +427,53 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
LOAD_FUNC(eglWaitNative);
LOAD_FUNC(eglWaitGL);
LOAD_FUNC(eglBindAPI);
LOAD_FUNC(eglQueryAPI);
LOAD_FUNC(eglQueryString);
LOAD_FUNC(eglGetError);
LOAD_FUNC_EGLEXT(eglQueryDevicesEXT);
LOAD_FUNC_EGLEXT(eglGetPlatformDisplayEXT);
_this->gl_config.driver_loaded = 1;
if (path) {
SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
} else {
*_this->gl_config.driver_path = '\0';
}
return 0;
}
static void
SDL_EGL_GetVersion(_THIS) {
if (_this->egl_data->eglQueryString) {
/* EGL 1.5 allows querying for client version */
const char *egl_version = _this->egl_data->eglQueryString(EGL_NO_DISPLAY, EGL_VERSION);
if (egl_version != NULL) {
if (SDL_sscanf(egl_version, "%d.%d", &egl_version_major, &egl_version_minor) != 2) {
egl_version_major = 0;
egl_version_minor = 0;
const char *egl_version = _this->egl_data->eglQueryString(_this->egl_data->egl_display, EGL_VERSION);
if (egl_version) {
int major = 0, minor = 0;
if (SDL_sscanf(egl_version, "%d.%d", &major, &minor) == 2) {
_this->egl_data->egl_version_major = major;
_this->egl_data->egl_version_minor = minor;
} else {
SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not parse EGL version string: %s", egl_version);
}
}
}
}
_this->egl_data->egl_version_major = egl_version_major;
_this->egl_data->egl_version_minor = egl_version_minor;
int
SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display, EGLenum platform)
{
int egl_version_major, egl_version_minor;
int library_load_retcode = SDL_EGL_LoadLibraryOnly(_this, egl_path);
if (library_load_retcode != 0) {
return library_load_retcode;
}
/* EGL 1.5 allows querying for client version with EGL_NO_DISPLAY */
SDL_EGL_GetVersion(_this);
egl_version_major = _this->egl_data->egl_version_major;
egl_version_minor = _this->egl_data->egl_version_minor;
if (egl_version_major == 1 && egl_version_minor == 5) {
LOAD_FUNC(eglGetPlatformDisplay);
@ -447,20 +498,111 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
_this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
}
if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
_this->gl_config.driver_loaded = 0;
*_this->gl_config.driver_path = '\0';
return SDL_SetError("Could not get EGL display");
}
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
_this->gl_config.driver_loaded = 0;
*_this->gl_config.driver_path = '\0';
return SDL_SetError("Could not initialize EGL");
}
#endif
if (path) {
SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
} else {
*_this->gl_config.driver_path = '\0';
/* Get the EGL version with a valid egl_display, for EGL <= 1.4 */
SDL_EGL_GetVersion(_this);
_this->egl_data->is_offscreen = 0;
return 0;
}
/**
On multi GPU machines EGL device 0 is not always the first valid GPU.
Container environments can restrict access to some GPUs that are still listed in the EGL
device list. If the requested device is a restricted GPU and cannot be used
(eglInitialize() will fail) then attempt to automatically and silently select the next
valid available GPU for EGL to use.
*/
int
SDL_EGL_InitializeOffscreen(_THIS, int device)
{
void *egl_devices[SDL_EGL_MAX_DEVICES];
EGLint num_egl_devices = 0;
const char *egl_device_hint;
if (_this->gl_config.driver_loaded != 1) {
return SDL_SetError("SDL_EGL_LoadLibraryOnly() has not been called or has failed.");
}
/* Check for all extensions that are optional until used and fail if any is missing */
if (_this->egl_data->eglQueryDevicesEXT == NULL) {
return SDL_SetError("eglQueryDevicesEXT is missing (EXT_device_enumeration not supported by the drivers?)");
}
if (_this->egl_data->eglGetPlatformDisplayEXT == NULL) {
return SDL_SetError("eglGetPlatformDisplayEXT is missing (EXT_platform_base not supported by the drivers?)");
}
if (_this->egl_data->eglQueryDevicesEXT(SDL_EGL_MAX_DEVICES, egl_devices, &num_egl_devices) != EGL_TRUE) {
return SDL_SetError("eglQueryDevicesEXT() failed");
}
egl_device_hint = SDL_GetHint("SDL_HINT_EGL_DEVICE");
if (egl_device_hint) {
device = SDL_atoi(egl_device_hint);
if (device >= num_egl_devices) {
return SDL_SetError("Invalid EGL device is requested.");
}
_this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, egl_devices[device], NULL);
if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
return SDL_SetError("eglGetPlatformDisplayEXT() failed.");
}
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
return SDL_SetError("Could not initialize EGL");
}
}
else {
int i;
SDL_bool found = SDL_FALSE;
EGLDisplay attempted_egl_display;
/* If no hint is provided lets look for the first device/display that will allow us to eglInit */
for (i = 0; i < num_egl_devices; i++) {
attempted_egl_display = _this->egl_data->eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, egl_devices[i], NULL);
if (attempted_egl_display == EGL_NO_DISPLAY) {
continue;
}
if (_this->egl_data->eglInitialize(attempted_egl_display, NULL, NULL) != EGL_TRUE) {
_this->egl_data->eglTerminate(attempted_egl_display);
continue;
}
/* We did not fail, we'll pick this one! */
_this->egl_data->egl_display = attempted_egl_display;
found = SDL_TRUE;
break;
}
if (!found) {
return SDL_SetError("Could not find a valid EGL device to initialize");
}
}
/* Get the EGL version with a valid egl_display, for EGL <= 1.4 */
SDL_EGL_GetVersion(_this);
_this->egl_data->is_offscreen = 1;
return 0;
}
@ -580,6 +722,11 @@ SDL_EGL_ChooseConfig(_THIS)
attribs[i++] = _this->gl_config.multisamplesamples;
}
if (_this->egl_data->is_offscreen) {
attribs[i++] = EGL_SURFACE_TYPE;
attribs[i++] = EGL_PBUFFER_BIT;
}
attribs[i++] = EGL_RENDERABLE_TYPE;
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
#ifdef EGL_KHR_create_context
@ -931,6 +1078,25 @@ SDL_EGL_CreateSurface(_THIS, NativeWindowType nw)
return surface;
}
EGLSurface
SDL_EGL_CreateOffscreenSurface(_THIS, int width, int height)
{
EGLint attributes[] = {
EGL_WIDTH, width,
EGL_HEIGHT, height,
EGL_NONE
};
if (SDL_EGL_ChooseConfig(_this) != 0) {
return EGL_NO_SURFACE;
}
return _this->egl_data->eglCreatePbufferSurface(
_this->egl_data->egl_display,
_this->egl_data->egl_config,
attributes);
}
void
SDL_EGL_DestroySurface(_THIS, EGLSurface egl_surface)
{

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -29,6 +29,8 @@
#include "SDL_sysvideo.h"
#define SDL_EGL_MAX_DEVICES 8
typedef struct SDL_EGL_VideoData
{
void *egl_dll_handle, *dll_handle;
@ -81,6 +83,8 @@ typedef struct SDL_EGL_VideoData
EGLBoolean(EGLAPIENTRY *eglSwapInterval) (EGLDisplay dpy, EGLint interval);
const char *(EGLAPIENTRY *eglQueryString) (EGLDisplay dpy, EGLint name);
EGLenum(EGLAPIENTRY *eglQueryAPI)(void);
EGLBoolean(EGLAPIENTRY *eglGetConfigAttrib) (EGLDisplay dpy, EGLConfig config,
EGLint attribute, EGLint * value);
@ -93,6 +97,13 @@ typedef struct SDL_EGL_VideoData
EGLint(EGLAPIENTRY *eglGetError)(void);
EGLBoolean(EGLAPIENTRY *eglQueryDevicesEXT)(EGLint max_devices,
void **devices,
EGLint *num_devices);
/* whether EGL display was offscreen */
int is_offscreen;
} SDL_EGL_VideoData;
/* OpenGLES functions */
@ -100,6 +111,7 @@ extern int SDL_EGL_GetAttribute(_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(_THIS, const char *path);
extern int SDL_EGL_LoadLibrary(_THIS, const char *path, NativeDisplayType native_display, EGLenum platform);
extern void *SDL_EGL_GetProcAddress(_THIS, const char *proc);
extern void SDL_EGL_UnloadLibrary(_THIS);
@ -111,6 +123,10 @@ extern void SDL_EGL_DeleteContext(_THIS, SDL_GLContext context);
extern EGLSurface *SDL_EGL_CreateSurface(_THIS, NativeWindowType nw);
extern void SDL_EGL_DestroySurface(_THIS, EGLSurface egl_surface);
extern EGLSurface SDL_EGL_CreateOffscreenSurface(_THIS, int width, int height);
/* Assumes that LoadLibraryOnly() has succeeded */
extern int SDL_EGL_InitializeOffscreen(_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(_THIS, EGLSurface egl_surface);
extern int SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context);

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -22,6 +22,7 @@
#include "SDL_video.h"
#include "SDL_blit.h"
#include "SDL_cpuinfo.h"
#ifdef __SSE__
@ -235,9 +236,74 @@ SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
*/
int
SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color)
{
if (!dst) {
return SDL_SetError("Passed NULL destination surface");
}
/* If 'rect' == NULL, then fill the whole surface */
if (!rect) {
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_FillRects(dst, rect, 1, color);
}
#if SDL_ARM_NEON_BLITTERS
void FillRect8ARMNEONAsm(int32_t w, int32_t h, uint8_t *dst, int32_t dst_stride, uint8_t src);
void FillRect16ARMNEONAsm(int32_t w, int32_t h, uint16_t *dst, int32_t dst_stride, uint16_t src);
void FillRect32ARMNEONAsm(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) {
FillRect8ARMNEONAsm(w, h, (uint8_t *) pixels, pitch >> 0, color);
return;
}
static void fill_16_neon(Uint8 * pixels, int pitch, Uint32 color, int w, int h) {
FillRect16ARMNEONAsm(w, h, (uint16_t *) pixels, pitch >> 1, color);
return;
}
static void fill_32_neon(Uint8 * pixels, int pitch, Uint32 color, int w, int h) {
FillRect32ARMNEONAsm(w, h, (uint32_t *) pixels, pitch >> 2, color);
return;
}
#endif
#if SDL_ARM_SIMD_BLITTERS
void FillRect8ARMSIMDAsm(int32_t w, int32_t h, uint8_t *dst, int32_t dst_stride, uint8_t src);
void FillRect16ARMSIMDAsm(int32_t w, int32_t h, uint16_t *dst, int32_t dst_stride, uint16_t src);
void FillRect32ARMSIMDAsm(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) {
FillRect8ARMSIMDAsm(w, h, (uint8_t *) pixels, pitch >> 0, color);
return;
}
static void fill_16_simd(Uint8 * pixels, int pitch, Uint32 color, int w, int h) {
FillRect16ARMSIMDAsm(w, h, (uint16_t *) pixels, pitch >> 1, color);
return;
}
static void fill_32_simd(Uint8 * pixels, int pitch, Uint32 color, int w, int h) {
FillRect32ARMSIMDAsm(w, h, (uint32_t *) pixels, pitch >> 2, color);
return;
}
#endif
int
SDL_FillRects(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) {
return SDL_SetError("Passed NULL destination surface");
@ -248,96 +314,115 @@ SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color)
return SDL_SetError("SDL_FillRect(): Unsupported surface format");
}
/* If 'rect' == NULL, then fill the whole surface */
if (rect) {
/* Perform clipping */
if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
return 0;
}
rect = &clipped;
} else {
rect = &dst->clip_rect;
/* Don't attempt to fill if the surface's clip_rect is empty */
if (SDL_RectEmpty(rect)) {
return 0;
}
}
/* Perform software fill */
if (!dst->pixels) {
return SDL_SetError("SDL_FillRect(): You must lock the surface");
}
pixels = (Uint8 *) dst->pixels + rect->y * dst->pitch +
rect->x * dst->format->BytesPerPixel;
if (!rects) {
return SDL_SetError("SDL_FillRects() passed NULL rects");
}
switch (dst->format->BytesPerPixel) {
case 1:
{
color |= (color << 8);
color |= (color << 16);
#if 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
#if 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 __SSE__
if (SDL_HasSSE()) {
SDL_FillRect1SSE(pixels, dst->pitch, color, rect->w, rect->h);
if (SDL_HasSSE()) {
fill_function = SDL_FillRect1SSE;
break;
}
#endif
fill_function = SDL_FillRect1;
break;
}
#endif
SDL_FillRect1(pixels, dst->pitch, color, rect->w, rect->h);
break;
}
case 2:
{
color |= (color << 16);
case 2:
{
color |= (color << 16);
#ifdef __SSE__
if (SDL_HasSSE()) {
SDL_FillRect2SSE(pixels, dst->pitch, color, rect->w, rect->h);
if (SDL_HasSSE()) {
fill_function = SDL_FillRect2SSE;
break;
}
#endif
fill_function = SDL_FillRect2;
break;
}
#endif
SDL_FillRect2(pixels, dst->pitch, color, rect->w, rect->h);
break;
}
case 3:
/* 24-bit RGB is a slow path, at least for now. */
{
SDL_FillRect3(pixels, dst->pitch, color, rect->w, rect->h);
break;
}
case 4:
{
#ifdef __SSE__
if (SDL_HasSSE()) {
SDL_FillRect4SSE(pixels, dst->pitch, color, rect->w, rect->h);
case 3:
/* 24-bit RGB is a slow path, at least for now. */
{
fill_function = SDL_FillRect3;
break;
}
case 4:
{
#ifdef __SSE__
if (SDL_HasSSE()) {
fill_function = SDL_FillRect4SSE;
break;
}
#endif
SDL_FillRect4(pixels, dst->pitch, color, rect->w, rect->h);
break;
fill_function = SDL_FillRect4;
break;
}
default:
return SDL_SetError("Unsupported pixel format");
}
}
for (i = 0; i < count; ++i) {
rect = &rects[i];
/* Perform clipping */
if (!SDL_IntersectRect(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;
}
int
SDL_FillRects(SDL_Surface * dst, const SDL_Rect * rects, int count,
Uint32 color)
{
int i;
int status = 0;
if (!rects) {
return SDL_SetError("SDL_FillRects() passed NULL rects");
}
for (i = 0; i < count; ++i) {
status += SDL_FillRect(dst, &rects[i], color);
}
return status;
}
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -94,6 +94,7 @@ SDL_GetPixelFormatName(Uint32 format)
CASE(SDL_PIXELFORMAT_INDEX8)
CASE(SDL_PIXELFORMAT_RGB332)
CASE(SDL_PIXELFORMAT_RGB444)
CASE(SDL_PIXELFORMAT_BGR444)
CASE(SDL_PIXELFORMAT_RGB555)
CASE(SDL_PIXELFORMAT_BGR555)
CASE(SDL_PIXELFORMAT_ARGB4444)
@ -321,6 +322,12 @@ SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
Amask == 0x0000) {
return SDL_PIXELFORMAT_RGB444;
}
if (Rmask == 0x000F &&
Gmask == 0x00F0 &&
Bmask == 0x0F00 &&
Amask == 0x0000) {
return SDL_PIXELFORMAT_BGR444;
}
break;
case 15:
if (Rmask == 0) {
@ -996,9 +1003,11 @@ SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
/* Clear out any previous mapping */
map = src->map;
#if SDL_HAVE_RLE
if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
SDL_UnRLESurface(src, 1);
}
#endif
SDL_InvalidateMap(map);
/* Figure out what kind of mapping we're doing */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -88,7 +88,7 @@ SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode,SDL_Surface *shape,Uint8* bitm
pixel = (Uint8 *)(shape->pixels) + (y*shape->pitch) + (x*shape->format->BytesPerPixel);
switch(shape->format->BytesPerPixel) {
case(1):
pixel_value = *(Uint8*)pixel;
pixel_value = *pixel;
break;
case(2):
pixel_value = *(Uint16*)pixel;
@ -141,7 +141,7 @@ RecursivelyCalculateShapeTree(SDL_WindowShapeMode mode,SDL_Surface* mask,SDL_Rec
pixel = (Uint8 *)(mask->pixels) + (y*mask->pitch) + (x*mask->format->BytesPerPixel);
switch(mask->format->BytesPerPixel) {
case(1):
pixel_value = *(Uint8*)pixel;
pixel_value = *pixel;
break;
case(2):
pixel_value = *(Uint16*)pixel;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -42,19 +42,12 @@ SDL_CalculatePitch(Uint32 format, int width)
{
int pitch;
/* Surface should be 4-byte aligned for speed */
pitch = width * SDL_BYTESPERPIXEL(format);
switch (SDL_BITSPERPIXEL(format)) {
case 1:
pitch = (pitch + 7) / 8;
break;
case 4:
pitch = (pitch + 1) / 2;
break;
default:
break;
if (SDL_ISPIXELFORMAT_FOURCC(format) || SDL_BITSPERPIXEL(format) >= 8) {
pitch = (width * SDL_BYTESPERPIXEL(format));
} else {
pitch = ((width * SDL_BITSPERPIXEL(format)) + 7) / 8;
}
pitch = (pitch + 3) & ~3; /* 4-byte aligning */
pitch = (pitch + 3) & ~3; /* 4-byte aligning for speed */
return pitch;
}
@ -502,7 +495,7 @@ SDL_SetSurfaceBlendMode(SDL_Surface * surface, SDL_BlendMode blendMode)
status = 0;
flags = surface->map->info.flags;
surface->map->info.flags &=
~(SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD);
~(SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL);
switch (blendMode) {
case SDL_BLENDMODE_NONE:
break;
@ -515,6 +508,9 @@ SDL_SetSurfaceBlendMode(SDL_Surface * surface, SDL_BlendMode blendMode)
case SDL_BLENDMODE_MOD:
surface->map->info.flags |= SDL_COPY_MOD;
break;
case SDL_BLENDMODE_MUL:
surface->map->info.flags |= SDL_COPY_MUL;
break;
default:
status = SDL_Unsupported();
break;
@ -539,7 +535,7 @@ SDL_GetSurfaceBlendMode(SDL_Surface * surface, SDL_BlendMode *blendMode)
}
switch (surface->map->
info.flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD)) {
info.flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL)) {
case SDL_COPY_BLEND:
*blendMode = SDL_BLENDMODE_BLEND;
break;
@ -549,6 +545,9 @@ SDL_GetSurfaceBlendMode(SDL_Surface * surface, SDL_BlendMode *blendMode)
case SDL_COPY_MOD:
*blendMode = SDL_BLENDMODE_MOD;
break;
case SDL_COPY_MUL:
*blendMode = SDL_BLENDMODE_MUL;
break;
default:
*blendMode = SDL_BLENDMODE_NONE;
break;
@ -881,7 +880,7 @@ SDL_LowerBlitScaled(SDL_Surface * src, SDL_Rect * srcrect,
{
static const Uint32 complex_copy_flags = (
SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA |
SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD |
SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL |
SDL_COPY_COLORKEY
);
@ -906,11 +905,13 @@ int
SDL_LockSurface(SDL_Surface * surface)
{
if (!surface->locked) {
#if SDL_HAVE_RLE
/* Perform the lock */
if (surface->flags & SDL_RLEACCEL) {
SDL_UnRLESurface(surface, 1);
surface->flags |= SDL_RLEACCEL; /* save accel'd state */
}
#endif
}
/* Increment the surface lock count, for recursive locks */
@ -931,11 +932,13 @@ SDL_UnlockSurface(SDL_Surface * surface)
return;
}
#if SDL_HAVE_RLE
/* Update RLE encoded surface with new data */
if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
surface->flags &= ~SDL_RLEACCEL; /* stop lying */
SDL_RLESurface(surface);
}
#endif
}
/*
@ -959,6 +962,10 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
SDL_Color copy_color;
SDL_Rect bounds;
int ret;
SDL_bool palette_ck_transform = SDL_FALSE;
int palette_ck_value = 0;
SDL_bool palette_has_alpha = SDL_FALSE;
Uint8 *palette_saved_alpha = NULL;
if (!surface) {
SDL_InvalidParamError("surface");
@ -1019,8 +1026,67 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
bounds.y = 0;
bounds.w = surface->w;
bounds.h = surface->h;
/* Source surface has a palette with no real alpha (0 or OPAQUE).
* Destination format has alpha.
* -> set alpha channel to be opaque */
if (surface->format->palette && format->Amask) {
SDL_bool set_opaque = SDL_FALSE;
{
int i;
for (i = 0; i < surface->format->palette->ncolors; i++) {
Uint8 alpha_value = surface->format->palette->colors[i].a;
if (alpha_value != 0 && alpha_value != SDL_ALPHA_OPAQUE) {
/* Palette has at least one alpha value. Don't do anything */
set_opaque = SDL_FALSE;
palette_has_alpha = SDL_TRUE;
break;
}
if (alpha_value == 0) {
set_opaque = SDL_TRUE;
}
}
}
/* Set opaque and backup palette alpha values */
if (set_opaque) {
int i;
palette_saved_alpha = SDL_stack_alloc(Uint8, surface->format->palette->ncolors);
for (i = 0; i < surface->format->palette->ncolors; i++) {
palette_saved_alpha[i] = surface->format->palette->colors[i].a;
surface->format->palette->colors[i].a = SDL_ALPHA_OPAQUE;
}
}
}
/* Transform colorkey to alpha. for cases where source palette has duplicate values, and colorkey is one of them */
if (copy_flags & SDL_COPY_COLORKEY) {
if (surface->format->palette && !format->palette) {
palette_ck_transform = SDL_TRUE;
palette_has_alpha = SDL_TRUE;
palette_ck_value = surface->format->palette->colors[surface->map->info.colorkey].a;
surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_TRANSPARENT;
}
}
ret = SDL_LowerBlit(surface, &bounds, convert, &bounds);
/* Restore colorkey alpha value */
if (palette_ck_transform) {
surface->format->palette->colors[surface->map->info.colorkey].a = palette_ck_value;
}
/* Restore palette alpha values */
if (palette_saved_alpha) {
int i;
for (i = 0; i < surface->format->palette->ncolors; i++) {
surface->format->palette->colors[i].a = palette_saved_alpha[i];
}
SDL_stack_free(palette_saved_alpha);
}
/* Clean up the original surface, and update converted surface */
convert->map->info.r = copy_color.r;
convert->map->info.g = copy_color.g;
@ -1046,7 +1112,6 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
if (copy_flags & SDL_COPY_COLORKEY) {
SDL_bool set_colorkey_by_color = SDL_FALSE;
SDL_bool ignore_alpha = SDL_TRUE; /* Ignore, or not, alpha in colorkey comparison */
if (surface->format->palette) {
if (format->palette &&
@ -1055,9 +1120,8 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
surface->format->palette->ncolors * sizeof(SDL_Color)) == 0)) {
/* The palette is identical, just set the same colorkey */
SDL_SetColorKey(convert, 1, surface->map->info.colorkey);
} else if (format->Amask) {
set_colorkey_by_color = SDL_TRUE;
ignore_alpha = SDL_FALSE;
} else if (!format->palette) {
/* Was done by 'palette_ck_transform' */
} else {
set_colorkey_by_color = SDL_TRUE;
}
@ -1098,7 +1162,7 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
SDL_SetColorKey(convert, 1, converted_colorkey);
/* This is needed when converting for 3D texture upload */
SDL_ConvertColorkeyToAlpha(convert, ignore_alpha);
SDL_ConvertColorkeyToAlpha(convert, SDL_TRUE);
}
}
SDL_SetClipRect(convert, &surface->clip_rect);
@ -1106,6 +1170,7 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
/* Enable alpha blending by default if the new surface has an
* alpha channel or alpha modulation */
if ((surface->format->Amask && format->Amask) ||
(palette_has_alpha && format->Amask) ||
(copy_flags & SDL_COPY_MODULATE_ALPHA)) {
SDL_SetSurfaceBlendMode(convert, SDL_BLENDMODE_BLEND);
}
@ -1192,6 +1257,7 @@ int SDL_ConvertPixels(int width, int height,
return SDL_InvalidParamError("dst_pitch");
}
#if SDL_HAVE_YUV
if (SDL_ISPIXELFORMAT_FOURCC(src_format) && SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
return SDL_ConvertPixels_YUV_to_YUV(width, height, src_format, src, src_pitch, dst_format, dst, dst_pitch);
} else if (SDL_ISPIXELFORMAT_FOURCC(src_format)) {
@ -1199,6 +1265,12 @@ int SDL_ConvertPixels(int width, int height,
} else if (SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
return SDL_ConvertPixels_RGB_to_YUV(width, height, src_format, src, src_pitch, dst_format, dst, dst_pitch);
}
#else
if (SDL_ISPIXELFORMAT_FOURCC(src_format) || SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
SDL_SetError("SDL not built with YUV support");
return -1;
}
#endif
/* Fast path for same format copy */
if (src_format == dst_format) {
@ -1251,9 +1323,11 @@ SDL_FreeSurface(SDL_Surface * surface)
while (surface->locked > 0) {
SDL_UnlockSurface(surface);
}
#if SDL_HAVE_RLE
if (surface->flags & SDL_RLEACCEL) {
SDL_UnRLESurface(surface, 0);
}
#endif
if (surface->format) {
SDL_SetSurfacePalette(surface, NULL);
SDL_FreeFormat(surface->format);

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -26,6 +26,7 @@
#include "SDL_messagebox.h"
#include "SDL_shape.h"
#include "SDL_thread.h"
#include "SDL_metal.h"
#include "SDL_vulkan_internal.h"
@ -274,6 +275,13 @@ struct SDL_VideoDevice
SDL_bool (*Vulkan_CreateSurface) (_THIS, SDL_Window *window, VkInstance instance, VkSurfaceKHR *surface);
void (*Vulkan_GetDrawableSize) (_THIS, SDL_Window * window, int *w, int *h);
/* * * */
/*
* Metal support
*/
SDL_MetalView (*Metal_CreateView) (_THIS, SDL_Window * window);
void (*Metal_DestroyView) (_THIS, SDL_MetalView view);
/* * * */
/*
* Event manager functions
@ -421,6 +429,7 @@ extern VideoBootStrap NACL_bootstrap;
extern VideoBootStrap VIVANTE_bootstrap;
extern VideoBootStrap Emscripten_bootstrap;
extern VideoBootStrap QNX_bootstrap;
extern VideoBootStrap OFFSCREEN_bootstrap;
extern SDL_VideoDevice *SDL_GetVideoDevice(void);
extern int SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode);
@ -430,6 +439,7 @@ extern int SDL_GetIndexOfDisplay(SDL_VideoDisplay *display);
extern SDL_VideoDisplay *SDL_GetDisplay(int displayIndex);
extern SDL_VideoDisplay *SDL_GetDisplayForWindow(SDL_Window *window);
extern void *SDL_GetDisplayDriverData( int displayIndex );
extern SDL_bool SDL_IsVideoContextExternal(void);
extern void SDL_GL_DeduceMaxSupportedESProfile(int* major, int* minor);
@ -452,13 +462,6 @@ extern SDL_bool SDL_ShouldAllowTopmost(void);
extern float SDL_ComputeDiagonalDPI(int hpix, int vpix, float hinches, float vinches);
extern void SDL_OnApplicationWillTerminate(void);
extern void SDL_OnApplicationDidReceiveMemoryWarning(void);
extern void SDL_OnApplicationWillResignActive(void);
extern void SDL_OnApplicationDidEnterBackground(void);
extern void SDL_OnApplicationWillEnterForeground(void);
extern void SDL_OnApplicationDidBecomeActive(void);
extern void SDL_ToggleDragAndDropSupport(void);
#endif /* SDL_sysvideo_h_ */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -37,9 +37,9 @@
#include "SDL_opengl.h"
#endif /* SDL_VIDEO_OPENGL */
#if SDL_VIDEO_OPENGL_ES
#if SDL_VIDEO_OPENGL_ES && !SDL_VIDEO_OPENGL
#include "SDL_opengles.h"
#endif /* SDL_VIDEO_OPENGL_ES */
#endif /* SDL_VIDEO_OPENGL_ES && !SDL_VIDEO_OPENGL */
/* GL and GLES2 headers conflict on Linux 32 bits */
#if SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL
@ -109,6 +109,9 @@ static VideoBootStrap *bootstrap[] = {
#if SDL_VIDEO_DRIVER_QNX
&QNX_bootstrap,
#endif
#if SDL_VIDEO_DRIVER_OFFSCREEN
&OFFSCREEN_bootstrap,
#endif
#if SDL_VIDEO_DRIVER_DUMMY
&DUMMY_bootstrap,
#endif
@ -661,6 +664,12 @@ SDL_GetDisplayDriverData(int displayIndex)
return _this->displays[displayIndex].driverdata;
}
SDL_bool
SDL_IsVideoContextExternal(void)
{
return SDL_GetHintBoolean(SDL_HINT_VIDEO_EXTERNAL_CONTEXT, SDL_FALSE);
}
const char *
SDL_GetDisplayName(int displayIndex)
{
@ -697,13 +706,25 @@ SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
return 0; /* !!! FIXME: should this be an error if (rect==NULL) ? */
}
int SDL_GetDisplayUsableBounds(int displayIndex, SDL_Rect * rect)
static int
ParseDisplayUsableBoundsHint(SDL_Rect *rect)
{
const char *hint = SDL_GetHint(SDL_HINT_DISPLAY_USABLE_BOUNDS);
return hint && (SDL_sscanf(hint, "%d,%d,%d,%d", &rect->x, &rect->y, &rect->w, &rect->h) == 4);
}
int
SDL_GetDisplayUsableBounds(int displayIndex, SDL_Rect * rect)
{
CHECK_DISPLAY_INDEX(displayIndex, -1);
if (rect) {
SDL_VideoDisplay *display = &_this->displays[displayIndex];
if ((displayIndex == 0) && ParseDisplayUsableBoundsHint(rect)) {
return 0;
}
if (_this->GetDisplayUsableBounds) {
if (_this->GetDisplayUsableBounds(_this, display, rect) == 0) {
return 0;
@ -1434,7 +1455,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
/* Some platforms have OpenGL enabled by default */
#if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__ || __NACL__
if (!_this->is_dummy && !(flags & SDL_WINDOW_VULKAN)) {
if (!_this->is_dummy && !(flags & SDL_WINDOW_VULKAN) && !SDL_IsVideoContextExternal()) {
flags |= SDL_WINDOW_OPENGL;
}
#endif
@ -3843,9 +3864,12 @@ SDL_IsScreenKeyboardShown(SDL_Window *window)
#if SDL_VIDEO_DRIVER_X11
#include "x11/SDL_x11messagebox.h"
#endif
#if SDL_VIDEO_DRIVER_HAIKU
#include "haiku/SDL_bmessagebox.h"
#endif
#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT || SDL_VIDEO_DRIVER_COCOA || SDL_VIDEO_DRIVER_UIKIT || SDL_VIDEO_DRIVER_X11
#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT || SDL_VIDEO_DRIVER_COCOA || SDL_VIDEO_DRIVER_UIKIT || SDL_VIDEO_DRIVER_X11 || SDL_VIDEO_DRIVER_HAIKU
static SDL_bool SDL_MessageboxValidForDriver(const SDL_MessageBoxData *messageboxdata, SDL_SYSWM_TYPE drivertype)
{
SDL_SysWMinfo info;
@ -3937,6 +3961,13 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
X11_ShowMessageBox(messageboxdata, buttonid) == 0) {
retval = 0;
}
#endif
#if SDL_VIDEO_DRIVER_HAIKU
if (retval == -1 &&
SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_HAIKU) &&
HAIKU_ShowMessageBox(messageboxdata, buttonid) == 0) {
retval = 0;
}
#endif
if (retval == -1) {
SDL_SetError("No message system available");
@ -4183,4 +4214,25 @@ void SDL_Vulkan_GetDrawableSize(SDL_Window * window, int *w, int *h)
}
}
SDL_MetalView
SDL_Metal_CreateView(SDL_Window * window)
{
CHECK_WINDOW_MAGIC(window, NULL);
if (_this->Metal_CreateView) {
return _this->Metal_CreateView(_this, window);
} else {
SDL_SetError("Metal is not supported.");
return NULL;
}
}
void
SDL_Metal_DestroyView(SDL_MetalView view)
{
if (_this && view && _this->Metal_DestroyView) {
_this->Metal_DestroyView(_this, view);
}
}
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -56,6 +56,8 @@ SDL_YUV_CONVERSION_MODE SDL_GetYUVConversionModeForResolution(int width, int hei
return mode;
}
#if SDL_HAVE_YUV
static int GetYUVConversionType(int width, int height, YCbCrType *yuv_type)
{
switch (SDL_GetYUVConversionModeForResolution(width, height)) {
@ -1221,6 +1223,7 @@ SDL_ConvertPixels_Planar2x2_to_Planar2x2(int width, int height,
return SDL_SetError("SDL_ConvertPixels_Planar2x2_to_Planar2x2: Unsupported YUV conversion: %s -> %s", SDL_GetPixelFormatName(src_format), SDL_GetPixelFormatName(dst_format));
}
#ifdef __SSE2__
#define PACKED4_TO_PACKED4_ROW_SSE2(shuffle) \
while (x >= 4) { \
__m128i yuv = _mm_loadu_si128((__m128i*)srcYUV); \
@ -1237,6 +1240,8 @@ SDL_ConvertPixels_Planar2x2_to_Planar2x2(int width, int height,
x -= 4; \
} \
#endif
static int
SDL_ConvertPixels_YUY2_to_UYVY(int width, int height, const void *src, int src_pitch, void *dst, int dst_pitch)
{
@ -1806,11 +1811,14 @@ SDL_ConvertPixels_Packed4_to_Planar2x2(int width, int height,
return 0;
}
#endif /* SDL_HAVE_YUV */
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)
{
#if SDL_HAVE_YUV
if (src_format == dst_format) {
if (src == dst) {
/* Nothing to do */
@ -1830,6 +1838,9 @@ SDL_ConvertPixels_YUV_to_YUV(int width, int height,
} else {
return SDL_SetError("SDL_ConvertPixels_YUV_to_YUV: Unsupported YUV conversion: %s -> %s", SDL_GetPixelFormatName(src_format), SDL_GetPixelFormatName(dst_format));
}
#else
return SDL_SetError("SDL not built with YUV support");
#endif
}
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -26,6 +26,8 @@
#include "SDL_events.h"
#include "SDL_androidkeyboard.h"
#include "SDL_androidwindow.h"
#include "../SDL_sysvideo.h"
#include "../../events/SDL_events_c.h"
/* Can't include sysaudio "../../audio/android/SDL_androidaudio.h"
* because of THIS redefinition */
@ -66,6 +68,7 @@ android_egl_context_restore(SDL_Window *window)
event.type = SDL_RENDER_DEVICE_RESET;
SDL_PushEvent(&event);
}
data->backup_done = 0;
}
}
@ -78,6 +81,7 @@ android_egl_context_backup(SDL_Window *window)
data->egl_context = SDL_GL_GetCurrentContext();
/* We need to do this so the EGLSurface can be freed */
SDL_GL_MakeCurrent(window, NULL);
data->backup_done = 1;
}
}
@ -95,11 +99,14 @@ Android_PumpEvents_Blocking(_THIS)
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
if (videodata->isPaused) {
SDL_bool isContextExternal = SDL_IsVideoContextExternal();
/* Make sure this is the last thing we do before pausing */
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_backup(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
if (!isContextExternal) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_backup(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
}
ANDROIDAUDIO_PauseDevices();
openslES_PauseDevices();
@ -108,11 +115,16 @@ Android_PumpEvents_Blocking(_THIS)
videodata->isPaused = 0;
/* Android_ResumeSem was signaled */
SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESTORED, 0, 0);
ANDROIDAUDIO_ResumeDevices();
openslES_ResumeDevices();
/* Restore the GL Context from here, as this operation is thread dependent */
if (!SDL_HasEvent(SDL_QUIT)) {
if (!isContextExternal && !SDL_HasEvent(SDL_QUIT)) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_restore(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
@ -125,6 +137,14 @@ Android_PumpEvents_Blocking(_THIS)
}
} else {
if (videodata->isPausing || SDL_SemTryWait(Android_PauseSem) == 0) {
/* Android_PauseSem was signaled */
if (videodata->isPausing == 0) {
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
}
/* 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 */
@ -146,11 +166,14 @@ Android_PumpEvents_NonBlocking(_THIS)
if (videodata->isPaused) {
SDL_bool isContextExternal = SDL_IsVideoContextExternal();
if (backup_context) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_backup(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
if (!isContextExternal) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_backup(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
}
ANDROIDAUDIO_PauseDevices();
openslES_PauseDevices();
@ -163,11 +186,16 @@ Android_PumpEvents_NonBlocking(_THIS)
videodata->isPaused = 0;
/* Android_ResumeSem was signaled */
SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESTORED, 0, 0);
ANDROIDAUDIO_ResumeDevices();
openslES_ResumeDevices();
/* Restore the GL Context from here, as this operation is thread dependent */
if (!SDL_HasEvent(SDL_QUIT)) {
if (!isContextExternal && !SDL_HasEvent(SDL_QUIT)) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_restore(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
@ -180,6 +208,14 @@ Android_PumpEvents_NonBlocking(_THIS)
}
} else {
if (videodata->isPausing || SDL_SemTryWait(Android_PauseSem) == 0) {
/* Android_PauseSem was signaled */
if (videodata->isPausing == 0) {
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
}
/* 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 */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -35,8 +35,8 @@
#define ACTION_DOWN 0
#define ACTION_UP 1
#define ACTION_MOVE 2
#define ACTION_CANCEL 3
#define ACTION_OUTSIDE 4
/* #define ACTION_CANCEL 3 */
/* #define ACTION_OUTSIDE 4 */
#define ACTION_POINTER_DOWN 5
#define ACTION_POINTER_UP 6
@ -48,7 +48,6 @@ void Android_InitTouch(void)
void Android_QuitTouch(void)
{
return;
}
void Android_OnTouch(SDL_Window *window, int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p)
@ -69,16 +68,16 @@ void Android_OnTouch(SDL_Window *window, int touch_device_id_in, int pointer_fin
switch (action) {
case ACTION_DOWN:
case ACTION_POINTER_DOWN:
SDL_SendTouch(touchDeviceId, fingerId, SDL_TRUE, x, y, p);
SDL_SendTouch(touchDeviceId, fingerId, window, SDL_TRUE, x, y, p);
break;
case ACTION_MOVE:
SDL_SendTouchMotion(touchDeviceId, fingerId, x, y, p);
SDL_SendTouchMotion(touchDeviceId, fingerId, window, x, y, p);
break;
case ACTION_UP:
case ACTION_POINTER_UP:
SDL_SendTouch(touchDeviceId, fingerId, SDL_FALSE, x, y, p);
SDL_SendTouch(touchDeviceId, fingerId, window, SDL_FALSE, x, y, p);
break;
default:

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -137,7 +137,7 @@ SDL_bool Android_Vulkan_CreateSurface(_THIS,
(PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR =
(PFN_vkCreateAndroidSurfaceKHR)vkGetInstanceProcAddr(
(VkInstance)instance,
instance,
"vkCreateAndroidSurfaceKHR");
VkAndroidSurfaceCreateInfoKHR createInfo;
VkResult result;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -58,7 +58,6 @@ Android_CreateWindow(_THIS, SDL_Window * window)
window->w = Android_SurfaceWidth;
window->h = Android_SurfaceHeight;
window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizeable */
window->flags &= ~SDL_WINDOW_HIDDEN;
window->flags |= SDL_WINDOW_SHOWN; /* only one window on Android */
@ -82,7 +81,7 @@ Android_CreateWindow(_THIS, SDL_Window * window)
/* Do not create EGLSurface for Vulkan window since it will then make the window
incompatible with vkCreateAndroidSurfaceKHR */
if ((window->flags & SDL_WINDOW_VULKAN) == 0) {
if ((window->flags & SDL_WINDOW_OPENGL) != 0) {
data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window);
if (data->egl_surface == EGL_NO_SURFACE) {

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -39,6 +39,7 @@ typedef struct
{
EGLSurface egl_surface;
EGLContext egl_context; /* We use this to preserve the context when losing focus */
SDL_bool backup_done;
ANativeWindow *native_window;
} SDL_WindowData;

View 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

View 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 intruduces 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 FillRect32ARMNEONAsm, 32, 2
generate_fillrect_function FillRect16ARMNEONAsm, 16, 1
generate_fillrect_function FillRect8ARMNEONAsm, 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

File diff suppressed because it is too large Load diff

View 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 \
FillRect32ARMSIMDAsm, 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 \
FillRect16ARMSIMDAsm, 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 \
FillRect8ARMSIMDAsm, 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&reg, ror #8
uxtb16&cond WK&reg, WK&reg, ror #16
orr&cond WK&reg, WK&reg, tmp, lsl #8
.endm
.macro BGR888toRGB888_2pixels cond, reg1, reg2, tmp1, tmp2
uxtb16&cond tmp1, WK&reg1, ror #8
uxtb16&cond WK&reg1, WK&reg1, ror #16
uxtb16&cond tmp2, WK&reg2, ror #8
uxtb16&cond WK&reg2, WK&reg2, ror #16
orr&cond WK&reg1, WK&reg1, tmp1, lsl #8
orr&cond WK&reg2, WK&reg2, 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_BGR888_RGB888ARMSIMDAsm, 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&reg, WK&reg, WK&reg, lsl #12 @ 0000aaaarrrrggggaaaarrrrggggbbbb
and WK&reg, mask, WK&reg @ 0000aaaa0000gggg0000rrrr0000bbbb
orr WK&reg, WK&reg, WK&reg, lsl #4 @ aaaaaaaaggggggggrrrrrrrrbbbbbbbb
pkhtb tmp, WK&reg, WK&reg, asr #8 @ aaaaaaaaggggggggggggggggrrrrrrrr
pkhbt WK&reg, WK&reg, WK&reg, lsl #8 @ ggggggggrrrrrrrrrrrrrrrrbbbbbbbb
sel WK&reg, WK&reg, 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_RGB888ARMSIMDAsm, 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

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -21,6 +21,7 @@
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_COCOA
#include "SDL_timer.h"
#include "SDL_cocoavideo.h"
@ -238,6 +239,12 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
* 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];
}
@ -267,6 +274,25 @@ GetApplicationName(void)
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)
{
@ -281,7 +307,7 @@ CreateApplicationMenus(void)
if (NSApp == nil) {
return;
}
mainMenu = [[NSMenu alloc] init];
/* Create the main menu bar */
@ -385,8 +411,17 @@ Cocoa_RegisterApp(void)
[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) {
CreateApplicationMenus();
bool nibLoaded;
nibLoaded = LoadMainMenuNibIfAvailable();
if (!nibLoaded) {
CreateApplicationMenus();
}
}
[NSApp finishLaunching];
if ([NSApp delegate]) {

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -473,7 +473,7 @@ Cocoa_InitKeyboard(_THIS)
SDL_SetScancodeName(SDL_SCANCODE_RALT, "Right Option");
SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Command");
data->modifierFlags = [NSEvent modifierFlags];
data->modifierFlags = (unsigned int)[NSEvent modifierFlags];
SDL_ToggleModState(KMOD_CAPS, (data->modifierFlags & NSEventModifierFlagCapsLock) != 0);
}
@ -590,7 +590,7 @@ Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
break;
case NSEventTypeFlagsChanged:
/* FIXME CW 2007-08-14: check if this whole mess that takes up half of this file is really necessary */
HandleModifiers(_this, scancode, [event modifierFlags]);
HandleModifiers(_this, scancode, (unsigned int)[event modifierFlags]);
break;
default: /* just to avoid compiler warnings */
break;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -112,10 +112,19 @@ Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
int i;
for (i = 0; i < messageboxdata->numbuttons; ++i) {
NSButton *button = [alert addButtonWithTitle:[NSString stringWithUTF8String:buttons[i].text]];
if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
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 (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
} else if (sdlButton->flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
[button setKeyEquivalent:@"\033"];
} else {
[button setKeyEquivalent:@""];
@ -132,6 +141,9 @@ Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
NSInteger 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;
} else {
returnValue = SDL_SetError("Did not get a valid `clicked button' id: %ld", (long)clicked);

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -24,14 +24,16 @@
* Thanks to Alex Szpakowski, @slime73 on GitHub, for his gist showing
* how to add a CAMetalLayer backed view.
*/
#include "../../SDL_internal.h"
#ifndef SDL_cocoametalview_h_
#define SDL_cocoametalview_h_
#import "../SDL_sysvideo.h"
#import "SDL_cocoawindow.h"
#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL)
#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL)
#import "../SDL_sysvideo.h"
#import "SDL_cocoawindow.h"
#import <Cocoa/Cocoa.h>
#import <Metal/Metal.h>
@ -42,20 +44,25 @@
@interface SDL_cocoametalview : NSView
- (instancetype)initWithFrame:(NSRect)frame
highDPI:(BOOL)highDPI;
highDPI:(BOOL)highDPI
windowID:(Uint32)windowID;
- (void)updateDrawableSize;
/* Override superclass tag so this class can set it. */
@property (assign, readonly) NSInteger tag;
@property (nonatomic) BOOL highDPI;
@property (nonatomic) Uint32 sdlWindowID;
@end
SDL_cocoametalview* Cocoa_Mtl_AddMetalView(SDL_Window* window);
SDL_MetalView Cocoa_Metal_CreateView(_THIS, SDL_Window * window);
void Cocoa_Metal_DestroyView(_THIS, SDL_MetalView view);
void Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h);
void Cocoa_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h);
#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL) */
#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
#endif /* SDL_cocoametalview_h_ */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -27,9 +27,31 @@
#import "SDL_cocoametalview.h"
#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL)
#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL)
#include "SDL_assert.h"
#include "SDL_events.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_WINDOWEVENT && event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
@autoreleasepool {
SDL_cocoametalview *view = (__bridge SDL_cocoametalview *)userdata;
if (view.sdlWindowID == event->window.windowID) {
[view updateDrawableSize];
}
}
}
return 0;
}
@implementation SDL_cocoametalview
@ -55,20 +77,30 @@
- (instancetype)initWithFrame:(NSRect)frame
highDPI:(BOOL)highDPI
windowID:(Uint32)windowID;
{
if ((self = [super initWithFrame:frame])) {
self.highDPI = highDPI;
self.sdlWindowID = windowID;
self.wantsLayer = YES;
/* Allow resize. */
self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
SDL_AddEventWatch(SDL_MetalViewEventWatch, self);
[self updateDrawableSize];
}
return self;
}
- (void)dealloc
{
SDL_DelEventWatch(SDL_MetalViewEventWatch, self);
[super dealloc];
}
- (NSInteger)tag
{
return METALVIEW_TAG;
@ -77,8 +109,8 @@
- (void)updateDrawableSize
{
CAMetalLayer *metalLayer = (CAMetalLayer *)self.layer;
CGSize size = self.bounds.size;
CGSize backingSize = size;
NSSize size = self.bounds.size;
NSSize backingSize = size;
if (self.highDPI) {
/* Note: NSHighResolutionCapable must be set to true in the app's
@ -88,34 +120,46 @@
}
metalLayer.contentsScale = backingSize.height / size.height;
metalLayer.drawableSize = backingSize;
}
/* Set the size of the metal drawables when the view is resized. */
- (void)resizeWithOldSuperviewSize:(NSSize)oldSize
{
[super resizeWithOldSuperviewSize:oldSize];
[self updateDrawableSize];
metalLayer.drawableSize = NSSizeToCGSize(backingSize);
}
@end
SDL_cocoametalview*
Cocoa_Mtl_AddMetalView(SDL_Window* window)
{
SDL_MetalView
Cocoa_Metal_CreateView(_THIS, SDL_Window * window)
{ @autoreleasepool {
SDL_WindowData* data = (__bridge SDL_WindowData *)window->driverdata;
NSView *view = data->nswindow.contentView;
BOOL highDPI = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
SDL_cocoametalview *metalview;
Uint32 windowID = SDL_GetWindowID(window);
SDL_cocoametalview *newview;
SDL_MetalView metalview;
newview = [[SDL_cocoametalview alloc] initWithFrame:view.frame
highDPI:highDPI
windowID:windowID];
if (newview == nil) {
return NULL;
}
[view addSubview:newview];
metalview = (SDL_MetalView)CFBridgingRetain(newview);
[newview release];
metalview = [[SDL_cocoametalview alloc] initWithFrame:view.frame highDPI:highDPI];
[view addSubview:metalview];
return metalview;
}
}}
void
Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h)
{
Cocoa_Metal_DestroyView(_THIS, SDL_MetalView view)
{ @autoreleasepool {
SDL_cocoametalview *metalview = CFBridgingRelease(view);
[metalview removeFromSuperview];
}}
void
Cocoa_Metal_GetDrawableSize(SDL_Window * window, int * w, int * h)
{ @autoreleasepool {
SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
NSView *view = data->nswindow.contentView;
SDL_cocoametalview* metalview = [view viewWithTag:METALVIEW_TAG];
@ -131,8 +175,8 @@ Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h)
} else {
SDL_GetWindowSize(window, w, h);
}
}
}}
#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL) */
#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL) */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -30,7 +30,7 @@ typedef struct
typedef struct
{
CGDisplayModeRef moderef;
CFMutableArrayRef modes;
} SDL_DisplayModeData;
extern void Cocoa_InitModes(_THIS);

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -38,6 +38,10 @@
/* This gets us MAC_OS_X_VERSION_MIN_REQUIRED... */
#include <AvailabilityMacros.h>
#ifndef MAC_OS_X_VERSION_10_13
#define NSAppKitVersionNumber10_12 1504
#endif
static void
Cocoa_ToggleMenuBar(const BOOL show)
@ -99,43 +103,12 @@ CG_SetError(const char *prefix, CGDisplayErr result)
return SDL_SetError("%s: %s", prefix, error);
}
static SDL_bool
GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CVDisplayLinkRef link, SDL_DisplayMode *mode)
static int
GetDisplayModeRefreshRate(CGDisplayModeRef vidmode, CVDisplayLinkRef link)
{
SDL_DisplayModeData *data;
int width = 0;
int height = 0;
int bpp = 0;
int refreshRate = 0;
CFStringRef fmt;
int refreshRate = (int) (CGDisplayModeGetRefreshRate(vidmode) + 0.5);
data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
if (!data) {
return SDL_FALSE;
}
data->moderef = vidmode;
fmt = CGDisplayModeCopyPixelEncoding(vidmode);
width = (int) CGDisplayModeGetWidth(vidmode);
height = (int) CGDisplayModeGetHeight(vidmode);
refreshRate = (int) (CGDisplayModeGetRefreshRate(vidmode) + 0.5);
if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
bpp = 32;
} else if (CFStringCompare(fmt, CFSTR(IO16BitDirectPixels),
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
bpp = 16;
} else if (CFStringCompare(fmt, CFSTR(kIO30BitDirectPixels),
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
bpp = 30;
} else {
bpp = 0; /* ignore 8-bit and such for now. */
}
CFRelease(fmt);
/* CGDisplayModeGetRefreshRate returns 0 for many non-CRT displays. */
/* 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) {
@ -143,25 +116,181 @@ GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CVDisplayLinkRef link, SDL_Displ
}
}
mode->format = SDL_PIXELFORMAT_UNKNOWN;
switch (bpp) {
case 16:
mode->format = SDL_PIXELFORMAT_ARGB1555;
break;
case 30:
mode->format = SDL_PIXELFORMAT_ARGB2101010;
break;
case 32:
mode->format = SDL_PIXELFORMAT_ARGB8888;
break;
case 8: /* We don't support palettized modes now */
default: /* Totally unrecognizable bit depth. */
SDL_free(data);
return refreshRate;
}
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(_THIS, CGDisplayModeRef vidmode, CFArrayRef modelist, CVDisplayLinkRef link, SDL_DisplayMode *mode)
{
SDL_DisplayModeData *data;
bool usableForGUI = CGDisplayModeIsUsableForDesktopGUI(vidmode);
int width = (int) CGDisplayModeGetWidth(vidmode);
int height = (int) CGDisplayModeGetHeight(vidmode);
uint32_t ioflags = CGDisplayModeGetIOFlags(vidmode);
int refreshrate = GetDisplayModeRefreshRate(vidmode, link);
Uint32 format = GetDisplayModePixelFormat(vidmode);
bool interlaced = (ioflags & kDisplayModeInterlacedFlag) != 0;
CFMutableArrayRef modes;
if (format == SDL_PIXELFORMAT_UNKNOWN) {
return SDL_FALSE;
}
if (!HasValidDisplayModeFlags(vidmode)) {
return SDL_FALSE;
}
modes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
CFArrayAppendValue(modes, vidmode);
/* If a list of possible diplay 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
* prefered, and it can add CGDisplayModes to the DisplayModeData's list of
* modes to try (see comment below for why that's necessary).
* CGDisplayModeGetPixelWidth and friends are only available in 10.8+. */
#ifdef MAC_OS_X_VERSION_10_8
if (modelist != NULL && floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_7) {
int pixelW = (int) CGDisplayModeGetPixelWidth(vidmode);
int pixelH = (int) CGDisplayModeGetPixelHeight(vidmode);
CFIndex modescount = CFArrayGetCount(modelist);
for (int i = 0; i < modescount; i++) {
CGDisplayModeRef othermode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modelist, i);
uint32_t otherioflags = CGDisplayModeGetIOFlags(othermode);
if (CFEqual(vidmode, othermode)) {
continue;
}
if (!HasValidDisplayModeFlags(othermode)) {
continue;
}
int otherW = (int) CGDisplayModeGetWidth(othermode);
int otherH = (int) CGDisplayModeGetHeight(othermode);
int otherpixelW = (int) CGDisplayModeGetPixelWidth(othermode);
int otherpixelH = (int) CGDisplayModeGetPixelHeight(othermode);
int otherrefresh = GetDisplayModeRefreshRate(othermode, link);
Uint32 otherformat = GetDisplayModePixelFormat(othermode);
bool otherGUI = CGDisplayModeIsUsableForDesktopGUI(othermode);
/* Ignore this mode if it's low-dpi (@1x) and we have a high-dpi
* mode in the list with the same size in points.
*/
if (width == pixelW && height == pixelH
&& width == otherW && height == otherH
&& refreshrate == otherrefresh && format == otherformat
&& (otherpixelW != otherW || otherpixelH != otherH)) {
CFRelease(modes);
return SDL_FALSE;
}
/* 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_AddDisplayMode as being
* a duplicate.
*/
if (width == otherW && height == otherH && pixelW == otherpixelW
&& pixelH == otherpixelH && usableForGUI == otherGUI
&& refreshrate == otherrefresh && format == otherformat) {
CFArrayAppendValue(modes, othermode);
}
}
}
#endif
data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
if (!data) {
CFRelease(modes);
return SDL_FALSE;
}
data->modes = modes;
mode->format = format;
mode->w = width;
mode->h = height;
mode->refresh_rate = refreshRate;
mode->refresh_rate = refreshrate;
mode->driverdata = data;
return SDL_TRUE;
}
@ -169,7 +298,9 @@ GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CVDisplayLinkRef link, SDL_Displ
static const char *
Cocoa_GetDisplayName(CGDirectDisplayID displayID)
{
CFDictionaryRef deviceInfo = IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName);
/* 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 = [(NSDictionary *)deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
const char* displayName = NULL;
@ -244,7 +375,7 @@ Cocoa_InitModes(_THIS)
SDL_zero(display);
/* this returns a stddup'ed string */
display.name = (char *)Cocoa_GetDisplayName(displays[i]);
if (!GetDisplayMode(_this, moderef, link, &mode)) {
if (!GetDisplayMode(_this, moderef, NULL, link, &mode)) {
CVDisplayLinkRelease(link);
CGDisplayModeRelease(moderef);
SDL_free(display.name);
@ -253,6 +384,7 @@ Cocoa_InitModes(_THIS)
}
CVDisplayLinkRelease(link);
CGDisplayModeRelease(moderef);
display.desktop_mode = mode;
display.current_mode = mode;
@ -311,27 +443,41 @@ Cocoa_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
int
Cocoa_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi)
{ @autoreleasepool
{
const float MM_IN_INCH = 25.4f;
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
CGSize displaySize = CGDisplayScreenSize(data->display);
int pixelWidth = (int) CGDisplayPixelsWide(data->display);
int pixelHeight = (int) CGDisplayPixelsHigh(data->display);
/* we need the backingScaleFactor for Retina displays, which is only exposed through NSScreen, not CGDisplay, afaik, so find our screen... */
CGFloat scaleFactor = 1.0f;
NSArray *screens = [NSScreen screens];
for (NSScreen *screen in screens) {
const CGDirectDisplayID dpyid = (const CGDirectDisplayID ) [[[screen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
if (dpyid == data->display) {
if ([screen respondsToSelector:@selector(backingScaleFactor)]) { // Mac OS X 10.7 and later
scaleFactor = [screen backingScaleFactor];
break;
}
}
}
const CGSize displaySize = CGDisplayScreenSize(data->display);
const int pixelWidth = (int) CGDisplayPixelsWide(data->display);
const int pixelHeight = (int) CGDisplayPixelsHigh(data->display);
if (ddpi) {
*ddpi = SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH);
*ddpi = (SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH)) * scaleFactor;
}
if (hdpi) {
*hdpi = pixelWidth * MM_IN_INCH / displaySize.width;
*hdpi = (pixelWidth * MM_IN_INCH / displaySize.width) * scaleFactor;
}
if (vdpi) {
*vdpi = pixelHeight * MM_IN_INCH / displaySize.height;
*vdpi = (pixelHeight * MM_IN_INCH / displaySize.height) * scaleFactor;
}
return 0;
}
}}
void
Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
@ -341,6 +487,7 @@ Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
CGDisplayModeRef desktopmoderef;
SDL_DisplayMode desktopmode;
CFArrayRef modes;
CFDictionaryRef dict = NULL;
CVDisplayLinkCreateWithCGDisplay(data->display, &link);
@ -352,16 +499,44 @@ Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
* sure there are no duplicates so it's safe to always add the desktop mode
* even in cases where it is in the CopyAllDisplayModes list.
*/
if (desktopmoderef && GetDisplayMode(_this, desktopmoderef, link, &desktopmode)) {
if (desktopmoderef && GetDisplayMode(_this, desktopmoderef, NULL, link, &desktopmode)) {
if (!SDL_AddDisplayMode(display, &desktopmode)) {
CGDisplayModeRelease(desktopmoderef);
CFRelease(((SDL_DisplayModeData*)desktopmode.driverdata)->modes);
SDL_free(desktopmode.driverdata);
}
} else {
CGDisplayModeRelease(desktopmoderef);
}
modes = CGDisplayCopyAllDisplayModes(data->display, NULL);
CGDisplayModeRelease(desktopmoderef);
/* 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
*/
#ifdef MAC_OS_X_VERSION_10_8
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_7) {
const CFStringRef dictkeys[] = {kCGDisplayShowDuplicateLowResolutionModes};
const CFBooleanRef dictvalues[] = {kCFBooleanTrue};
dict = CFDictionaryCreate(NULL,
(const void **)dictkeys,
(const void **)dictvalues,
1,
&kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
#endif
modes = CGDisplayCopyAllDisplayModes(data->display, dict);
if (dict) {
CFRelease(dict);
}
if (modes) {
CFIndex i;
@ -371,10 +546,9 @@ Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
CGDisplayModeRef moderef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
SDL_DisplayMode mode;
if (GetDisplayMode(_this, moderef, link, &mode)) {
if (SDL_AddDisplayMode(display, &mode)) {
CGDisplayModeRetain(moderef);
} else {
if (GetDisplayMode(_this, moderef, modes, link, &mode)) {
if (!SDL_AddDisplayMode(display, &mode)) {
CFRelease(((SDL_DisplayModeData*)mode.driverdata)->modes);
SDL_free(mode.driverdata);
}
}
@ -386,6 +560,25 @@ Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
CVDisplayLinkRelease(link);
}
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(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
{
@ -401,7 +594,7 @@ Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
if (data == display->desktop_mode.driverdata) {
/* Restoring desktop mode */
CGDisplaySetDisplayMode(displaydata->display, data->moderef, NULL);
SetDisplayModeForDisplay(displaydata->display, data);
if (CGDisplayIsMain(displaydata->display)) {
CGReleaseAllDisplays();
@ -426,7 +619,7 @@ Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
}
/* Do the physical switch */
result = CGDisplaySetDisplayMode(displaydata->display, data->moderef, NULL);
result = SetDisplayModeForDisplay(displaydata->display, data);
if (result != kCGErrorSuccess) {
CG_SetError("CGDisplaySwitchToMode()", result);
goto ERR_NO_SWITCH;
@ -448,7 +641,11 @@ Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
/* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
ERR_NO_SWITCH:
CGDisplayRelease(displaydata->display);
if (CGDisplayIsMain(displaydata->display)) {
CGReleaseAllDisplays();
} else {
CGDisplayRelease(displaydata->display);
}
ERR_NO_CAPTURE:
if (fade_token != kCGDisplayFadeReservationInvalidToken) {
CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
@ -471,13 +668,12 @@ Cocoa_QuitModes(_THIS)
}
mode = (SDL_DisplayModeData *) display->desktop_mode.driverdata;
CGDisplayModeRelease(mode->moderef);
CFRelease(mode->modes);
for (j = 0; j < display->num_display_modes; j++) {
mode = (SDL_DisplayModeData*) display->display_modes[j].driverdata;
CGDisplayModeRelease(mode->moderef);
CFRelease(mode->modes);
}
}
Cocoa_ToggleMenuBar(YES);
}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -113,9 +113,8 @@ typedef struct SDL_VideoData
/* Utility functions */
extern NSImage * Cocoa_CreateImage(SDL_Surface * surface);
/* Fix build with the 10.10 SDK */
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101100
#define NSEventSubtypeTouch NSTouchEventSubtype
/* Fix build with the 10.11 SDK */
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
#define NSEventSubtypeMouseEvent NSMouseEventSubtype
#endif

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -27,6 +27,7 @@
#include "SDL_cocoavideo.h"
#include "SDL_cocoashape.h"
#include "SDL_cocoavulkan.h"
#include "SDL_cocoametalview.h"
#include "SDL_assert.h"
/* Initialization/Query functions */
@ -142,6 +143,11 @@ Cocoa_CreateDevice(int devindex)
device->Vulkan_GetDrawableSize = Cocoa_Vulkan_GetDrawableSize;
#endif
#if SDL_VIDEO_METAL
device->Metal_CreateView = Cocoa_Metal_CreateView;
device->Metal_DestroyView = Cocoa_Metal_DestroyView;
#endif
device->StartTextInput = Cocoa_StartTextInput;
device->StopTextInput = Cocoa_StopTextInput;
device->SetTextInputRect = Cocoa_SetTextInputRect;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -23,7 +23,6 @@
* @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
* SDL_x11vulkan.c.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_COCOA
@ -194,6 +193,7 @@ SDL_bool Cocoa_Vulkan_CreateSurface(_THIS,
"vkCreateMacOSSurfaceMVK");
VkMacOSSurfaceCreateInfoMVK createInfo = {};
VkResult result;
SDL_MetalView metalview;
if (!_this->vulkan_config.loader_handle) {
SDL_SetError("Vulkan is not loaded");
@ -205,23 +205,38 @@ SDL_bool Cocoa_Vulkan_CreateSurface(_THIS,
" extension is not enabled in the Vulkan instance.");
return SDL_FALSE;
}
metalview = Cocoa_Metal_CreateView(_this, window);
if (metalview == NULL) {
return SDL_FALSE;
}
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
createInfo.pNext = NULL;
createInfo.flags = 0;
createInfo.pView = Cocoa_Mtl_AddMetalView(window);
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;
}
void Cocoa_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
{
Cocoa_Mtl_GetDrawableSize(window, w, h);
Cocoa_Metal_GetDrawableSize(window, w, h);
}
#endif

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -116,7 +116,7 @@ struct SDL_WindowData
NSView *sdlContentView; /* nil if window is created via CreateWindowFrom */
NSMutableArray *nscontexts;
SDL_bool created;
SDL_bool inWindowMove;
SDL_bool inWindowFullscreenTransition;
Cocoa_WindowListener *listener;
struct SDL_VideoData *videodata;
#if SDL_VIDEO_OPENGL_EGL

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -261,6 +261,22 @@ GetHintCtrlClickEmulateRightClick()
return SDL_GetHintBoolean(SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, SDL_FALSE);
}
static NSUInteger
GetWindowWindowedStyle(SDL_Window * window)
{
NSUInteger style = 0;
if (window->flags & SDL_WINDOW_BORDERLESS) {
style = NSWindowStyleMaskBorderless;
} else {
style = (NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskMiniaturizable);
}
if (window->flags & SDL_WINDOW_RESIZABLE) {
style |= NSWindowStyleMaskResizable;
}
return style;
}
static NSUInteger
GetWindowStyle(SDL_Window * window)
{
@ -269,14 +285,7 @@ GetWindowStyle(SDL_Window * window)
if (window->flags & SDL_WINDOW_FULLSCREEN) {
style = NSWindowStyleMaskBorderless;
} else {
if (window->flags & SDL_WINDOW_BORDERLESS) {
style = NSWindowStyleMaskBorderless;
} else {
style = (NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskMiniaturizable);
}
if (window->flags & SDL_WINDOW_RESIZABLE) {
style |= NSWindowStyleMaskResizable;
}
style = GetWindowWindowedStyle(window);
}
return style;
}
@ -754,10 +763,15 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
isFullscreenSpace = NO;
inFullscreenTransition = YES;
/* As of OS X 10.11, the window seems to need to be resizable when exiting
/* As of macOS 10.11, the window seems to need to be resizable when exiting
a Space, in order for it to resize back to its windowed-mode size.
As of macOS 10.15, the window decorations can go missing sometimes after
certain fullscreen-desktop->exlusive-fullscreen->windowed mode flows
sometimes. Making sure the style mask always uses the windowed mode style
when returning to windowed mode from a space (instead of using a pending
fullscreen mode style mask) seems to work around that issue.
*/
SetWindowStyle(window, GetWindowStyle(window) | NSWindowStyleMaskResizable);
SetWindowStyle(window, GetWindowWindowedStyle(window) | NSWindowStyleMaskResizable);
}
- (void)windowDidFailToExitFullScreen:(NSNotification *)aNotification
@ -780,12 +794,23 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
{
SDL_Window *window = _data->window;
NSWindow *nswindow = _data->nswindow;
NSButton *button = nil;
inFullscreenTransition = NO;
SetWindowStyle(window, GetWindowStyle(window));
/* As of macOS 10.15, the window decorations can go missing sometimes after
certain fullscreen-desktop->exlusive-fullscreen->windowed mode flows
sometimes. Making sure the style mask always uses the windowed mode style
when returning to windowed mode from a space (instead of using a pending
fullscreen mode style mask) seems to work around that issue.
*/
SetWindowStyle(window, GetWindowWindowedStyle(window));
[nswindow setLevel:kCGNormalWindowLevel];
if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) {
[nswindow setLevel:NSFloatingWindowLevel];
} else {
[nswindow setLevel:kCGNormalWindowLevel];
}
if (pendingWindowOperation == PENDING_OPERATION_ENTER_FULLSCREEN) {
pendingWindowOperation = PENDING_OPERATION_NONE;
@ -841,6 +866,22 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
Cocoa_ShowWindow(SDL_GetVideoDevice(), window);
}
}
/* There's some state that isn't quite back to normal when
windowDidExitFullScreen triggers. For example, the minimize button on
the titlebar doesn't actually enable for another 200 milliseconds or
so on this MacBook. Camp here and wait for that to happen before
going on, in case we're exiting fullscreen to minimize, which need
that window state to be normal before it will work. */
button = [nswindow standardWindowButton:NSWindowMiniaturizeButton];
if (button) {
int iterations = 0;
while (![button isEnabled] && (iterations < 100)) {
SDL_Delay(10);
SDL_PumpEvents();
iterations++;
}
}
}
-(NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions
@ -1132,7 +1173,13 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
DLog("Reset Lost Fingers: %d", numFingers);
for (--numFingers; numFingers >= 0; --numFingers) {
SDL_Finger* finger = SDL_GetTouchFinger(touchID, numFingers);
SDL_SendTouch(touchID, finger->id, SDL_FALSE, 0, 0, 0);
/* trackpad touches have no window. If we really wanted one we could
* use the window that has mouse or keyboard focus.
* Sending a null window currently also prevents synthetic mouse
* events from being generated from touch events.
*/
SDL_Window *window = NULL;
SDL_SendTouch(touchID, finger->id, window, SDL_FALSE, 0, 0, 0);
}
}
@ -1167,10 +1214,24 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
const SDL_TouchID touchId = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[touch device];
SDL_TouchDeviceType devtype = SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE;
/* trackpad touches have no window. If we really wanted one we could
* use the window that has mouse or keyboard focus.
* Sending a null window currently also prevents synthetic mouse events
* from being generated from touch events.
*/
SDL_Window *window = NULL;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101202 /* Added in the 10.12.2 SDK. */
if ([touch respondsToSelector:@selector(type)]) {
/* TODO: Before implementing direct touch support here, we need to
* figure out whether the OS generates mouse events from them on its
* own. If it does, we should prevent SendTouch from generating
* synthetic mouse events for these touches itself (while also
* sending a window.) It will also need to use normalized window-
* relative coordinates via [touch locationInView:].
*/
if ([touch type] == NSTouchTypeDirect) {
devtype = SDL_TOUCH_DEVICE_DIRECT;
continue;
}
}
#endif
@ -1187,14 +1248,14 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
switch (phase) {
case NSTouchPhaseBegan:
SDL_SendTouch(touchId, fingerId, SDL_TRUE, x, y, 1.0f);
SDL_SendTouch(touchId, fingerId, window, SDL_TRUE, x, y, 1.0f);
break;
case NSTouchPhaseEnded:
case NSTouchPhaseCancelled:
SDL_SendTouch(touchId, fingerId, SDL_FALSE, x, y, 1.0f);
SDL_SendTouch(touchId, fingerId, window, SDL_FALSE, x, y, 1.0f);
break;
case NSTouchPhaseMoved:
SDL_SendTouchMotion(touchId, fingerId, x, y, 1.0f);
SDL_SendTouchMotion(touchId, fingerId, window, x, y, 1.0f);
break;
default:
break;
@ -1226,23 +1287,32 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
_sdlWindow = window;
}
/* this is used on older macOS revisions. 10.8 and later use updateLayer. */
/* this is used on older macOS revisions, and newer ones which emulate old
NSOpenGLContext behaviour while still using a layer under the hood. 10.8 and
later use updateLayer, up until 10.14.2 or so, which uses drawRect without
a GraphicsContext and with a layer active instead (for OpenGL contexts). */
- (void)drawRect:(NSRect)dirtyRect
{
/* Force the graphics context to clear to black so we don't get a flash of
white until the app is ready to draw. In practice on modern macOS, this
only gets called for window creation and other extraordinary events. */
[[NSColor blackColor] setFill];
NSRectFill(dirtyRect);
if ([NSGraphicsContext currentContext]) {
[[NSColor blackColor] setFill];
NSRectFill(dirtyRect);
} else if (self.layer) {
self.layer.backgroundColor = CGColorGetConstantColor(kCGColorBlack);
}
SDL_SendWindowEvent(_sdlWindow, SDL_WINDOWEVENT_EXPOSED, 0, 0);
}
-(BOOL) wantsUpdateLayer
- (BOOL)wantsUpdateLayer
{
return YES;
}
-(void) updateLayer
/* This is also called when a Metal layer is active. */
- (void)updateLayer
{
/* Force the graphics context to clear to black so we don't get a flash of
white until the app is ready to draw. In practice on modern macOS, this
@ -1436,6 +1506,10 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window)
}
}
if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) {
[nswindow setLevel:NSFloatingWindowLevel];
}
/* Create a default view for this window */
rect = [nswindow contentRectForFrameRect:[nswindow frame]];
SDLView *contentView = [[SDLView alloc] initWithFrame:rect];
@ -1446,10 +1520,11 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
if ([contentView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
[contentView setWantsBestResolutionOpenGLSurface:YES];
}
/* Note: as of the macOS 10.15 SDK, this defaults to YES instead of NO when
* the NSHighResolutionCapable boolean is set in Info.plist. */
if ([contentView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
BOOL highdpi = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
[contentView setWantsBestResolutionOpenGLSurface:highdpi];
}
#ifdef __clang__
#pragma clang diagnostic pop
@ -1665,7 +1740,6 @@ Cocoa_MinimizeWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
NSWindow *nswindow = data->nswindow;
if ([data->listener isInFullscreenSpaceTransition]) {
[data->listener addPendingWindowOperation:PENDING_OPERATION_MINIMIZE];
} else {
@ -1735,10 +1809,17 @@ Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display
rect.size.height = bounds.h;
ConvertNSRect([nswindow screen], fullscreen, &rect);
/* Hack to fix origin on Mac OS X 10.4 */
NSRect screenRect = [[nswindow screen] frame];
if (screenRect.size.height >= 1.0f) {
rect.origin.y += (screenRect.size.height - rect.size.height);
/* Hack to fix origin on Mac OS X 10.4
This is no longer needed as of Mac OS X 10.15, according to bug 4822.
*/
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
NSOperatingSystemVersion version = { 10, 15, 0 };
if (![processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] ||
![processInfo isOperatingSystemAtLeastVersion:version]) {
NSRect screenRect = [[nswindow screen] frame];
if (screenRect.size.height >= 1.0f) {
rect.origin.y += (screenRect.size.height - rect.size.height);
}
}
[nswindow setStyleMask:NSWindowStyleMaskBorderless];
@ -1749,7 +1830,13 @@ Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display
rect.size.height = window->windowed.h;
ConvertNSRect([nswindow screen], fullscreen, &rect);
[nswindow setStyleMask:GetWindowStyle(window)];
/* The window is not meant to be fullscreen, but its flags might have a
* fullscreen bit set if it's scheduled to go fullscreen immediately
* after. Always using the windowed mode style here works around bugs in
* macOS 10.15 where the window doesn't properly restore the windowed
* mode decorations after exiting fullscreen-desktop, when the window
* was created as fullscreen-desktop. */
[nswindow setStyleMask:GetWindowWindowedStyle(window)];
/* Hack to restore window decorations on Mac OS X 10.10 */
NSRect frameRect = [nswindow frame];
@ -1775,6 +1862,8 @@ Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display
if (SDL_ShouldAllowTopmost() && fullscreen) {
/* OpenGL is rendering to the window, so make it visible! */
[nswindow setLevel:CGShieldingWindowLevel()];
} else if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) {
[nswindow setLevel:NSFloatingWindowLevel];
} else {
[nswindow setLevel:kCGNormalWindowLevel];
}
@ -1868,6 +1957,8 @@ Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
/* OpenGL is rendering to the window, so make it visible! */
/* Doing this in 10.11 while in a Space breaks things (bug #3152) */
[data->nswindow setLevel:CGShieldingWindowLevel()];
} else if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) {
[data->nswindow setLevel:NSFloatingWindowLevel];
} else {
[data->nswindow setLevel:kCGNormalWindowLevel];
}
@ -1939,6 +2030,11 @@ Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state)
SDL_bool succeeded = SDL_FALSE;
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (data->inWindowFullscreenTransition) {
return SDL_FALSE;
}
data->inWindowFullscreenTransition = SDL_TRUE;
if ([data->listener setFullscreenSpace:(state ? YES : NO)]) {
const int maxattempts = 3;
int attempt = 0;
@ -1965,6 +2061,7 @@ Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state)
/* Return TRUE to prevent non-space fullscreen logic from running */
succeeded = SDL_TRUE;
}
data->inWindowFullscreenTransition = SDL_FALSE;
return succeeded;
}}

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -236,7 +236,7 @@ ProcessWindowEvent(_THIS, SDL_Window *sdlwin, DFBWindowEvent * evt)
/* printf("Scancode %d %d %d\n", keysym.scancode, evt->key_code, evt->key_id); */
SDL_SendKeyboardKey_ex(0, SDL_PRESSED, keysym.scancode);
if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
SDL_zero(text);
SDL_zeroa(text);
UnicodeToUtf8(unicode, text);
if (*text) {
SDL_SendKeyboardText_ex(0, text);
@ -372,7 +372,7 @@ ProcessInputEvent(_THIS, DFBInputEvent * ievt)
/* printf("Scancode %d %d %d\n", keysym.scancode, evt->key_code, evt->key_id); */
SDL_SendKeyboardKey_ex(kbd_idx, SDL_PRESSED, keysym.scancode);
if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
SDL_zero(text);
SDL_zeroa(text);
UnicodeToUtf8(unicode, text);
if (*text) {
SDL_SendKeyboardText_ex(kbd_idx, text);

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -199,6 +199,14 @@ SetBlendMode(DirectFB_RenderData * data, int blendMode,
break;
}
case SDL_BLENDMODE_MUL:
data->blitFlags = DSBLIT_BLEND_ALPHACHANNEL;
data->drawFlags = DSDRAW_BLEND;
SDL_DFB_CHECK(destsurf->SetSrcBlendFunction(destsurf, DSBF_DSTCOLOR));
SDL_DFB_CHECK(destsurf->SetDstBlendFunction(destsurf, DSBF_INVSRCALPHA));
break;
}
data->lastBlendMode = blendMode;
}
}
@ -223,6 +231,7 @@ PrepareDraw(SDL_Renderer * renderer, const SDL_RenderCommand *cmd)
break;
case SDL_BLENDMODE_ADD:
case SDL_BLENDMODE_MOD:
case SDL_BLENDMODE_MUL:
r = ((int) r * (int) a) / 255;
g = ((int) g * (int) a) / 255;
b = ((int) b * (int) a) / 255;
@ -550,6 +559,11 @@ DirectFB_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
}
}
static void
DirectFB_SetTextureScaleMode()
{
}
#if 0
static void
DirectFB_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
@ -966,6 +980,7 @@ DirectFB_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->UpdateTexture = DirectFB_UpdateTexture;
renderer->LockTexture = DirectFB_LockTexture;
renderer->UnlockTexture = DirectFB_UnlockTexture;
renderer->SetTextureScaleMode = DirectFB_SetTextureScaleMode;
renderer->QueueSetViewport = DirectFB_QueueSetViewport;
renderer->QueueSetDrawColor = DirectFB_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = DirectFB_QueueDrawPoints;

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

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