Skip to content

Commit

Permalink
Fix bug 4053: Blit issues on Big Endian CPU
Browse files Browse the repository at this point in the history
  • Loading branch information
1bsyl committed Feb 18, 2019
1 parent ea4c4cf commit e9a7b69
Showing 1 changed file with 158 additions and 8 deletions.
166 changes: 158 additions & 8 deletions src/video/SDL_blit_N.c
Expand Up @@ -2155,7 +2155,13 @@ get_permutation(SDL_PixelFormat *srcfmt, SDL_PixelFormat *dstfmt,
int *_p0 , int *_p1, int *_p2, int *_p3, int *_alpha_channel)
{
int alpha_channel = 0, p0, p1, p2, p3;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
int Pixel = 0x04030201; /* identity permutation */
#else
int Pixel = 0x01020304; /* identity permutation */
int srcbpp = srcfmt->BytesPerPixel;
int dstbpp = dstfmt->BytesPerPixel;
#endif

if (srcfmt->Amask) {
RGBA_FROM_PIXEL(Pixel, srcfmt, p0, p1, p2, p3);
Expand All @@ -2174,10 +2180,17 @@ get_permutation(SDL_PixelFormat *srcfmt, SDL_PixelFormat *dstfmt,
PIXEL_FROM_RGB(Pixel, dstfmt, p0, p1, p2);
}

#if SDL_BYTEORDER == SDL_LIL_ENDIAN
p0 = Pixel & 0xFF;
p1 = (Pixel >> 8) & 0xFF;
p2 = (Pixel >> 16) & 0xFF;
p3 = (Pixel >> 24) & 0xFF;
#else
p3 = Pixel & 0xFF;
p2 = (Pixel >> 8) & 0xFF;
p1 = (Pixel >> 16) & 0xFF;
p0 = (Pixel >> 24) & 0xFF;
#endif

if (p0 == 0) {
p0 = 1;
Expand All @@ -2193,6 +2206,19 @@ get_permutation(SDL_PixelFormat *srcfmt, SDL_PixelFormat *dstfmt,
alpha_channel = 3;
}

#if SDL_BYTEORDER == SDL_LIL_ENDIAN
#else
if (srcbpp == 3 && dstbpp == 4) {
if (p0 != 1) p0--;
if (p1 != 1) p1--;
if (p2 != 1) p2--;
if (p3 != 1) p3--;
} else if (srcbpp == 4 && dstbpp == 3) {
p0 = p1;
p1 = p2;
p2 = p3;
}
#endif
*_p0 = p0 - 1;
*_p1 = p1 - 1;
*_p2 = p2 - 1;
Expand Down Expand Up @@ -2597,9 +2623,15 @@ BlitNtoNKey(SDL_BlitInfo * info)
if ((sfmt == SDL_PIXELFORMAT_RGB24 && dfmt == SDL_PIXELFORMAT_RGB24) ||
(sfmt == SDL_PIXELFORMAT_BGR24 && dfmt == SDL_PIXELFORMAT_BGR24)) {

Uint8 k0 = ckey & 0x000000FF;
Uint8 k1 = (ckey & 0x0000FF00) >> 8;
Uint8 k2 = (ckey & 0x00FF0000) >> 16;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
Uint8 k0 = ckey & 0xFF;
Uint8 k1 = (ckey >> 8) & 0xFF;
Uint8 k2 = (ckey >> 16) & 0xFF;
#else
Uint8 k0 = (ckey >> 16) & 0xFF;
Uint8 k1 = (ckey >> 8) & 0xFF;
Uint8 k2 = ckey & 0xFF;
#endif

while (height--) {
/* *INDENT-OFF* */
Expand Down Expand Up @@ -2629,9 +2661,15 @@ BlitNtoNKey(SDL_BlitInfo * info)
if ((sfmt == SDL_PIXELFORMAT_RGB24 && dfmt == SDL_PIXELFORMAT_BGR24) ||
(sfmt == SDL_PIXELFORMAT_BGR24 && dfmt == SDL_PIXELFORMAT_RGB24)) {

#if SDL_BYTEORDER == SDL_LIL_ENDIAN
Uint8 k0 = ckey & 0xFF;
Uint8 k1 = (ckey >> 8) & 0xFF;
Uint8 k2 = (ckey >> 16) & 0xFF;
#else
Uint8 k0 = (ckey >> 16) & 0xFF;
Uint8 k1 = (ckey >> 8) & 0xFF;
Uint8 k2 = ckey & 0xFF;
#endif

while (height--) {
/* *INDENT-OFF* */
Expand Down Expand Up @@ -2693,9 +2731,15 @@ BlitNtoNKey(SDL_BlitInfo * info)

Uint32 *dst32 = (Uint32*)dst;

#if SDL_BYTEORDER == SDL_LIL_ENDIAN
Uint8 k0 = ckey & 0xFF;
Uint8 k1 = (ckey >> 8) & 0xFF;
Uint8 k2 = (ckey >> 16) & 0xFF;
#else
Uint8 k0 = (ckey >> 16) & 0xFF;
Uint8 k1 = (ckey >> 8) & 0xFF;
Uint8 k2 = ckey & 0xFF;
#endif

/* Find the appropriate permutation */
int alpha_channel, p0, p1, p2, p3;
Expand Down Expand Up @@ -2939,6 +2983,13 @@ Blit_3or4_to_3or4__same_rgb(SDL_BlitInfo * info)
/* SET_ALPHA */
Uint32 mask = info->a << dstfmt->Ashift;
int last_line = 0;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
#else
int i0 = srcbpp - 1 - 0;
int i1 = srcbpp - 1 - 1;
int i2 = srcbpp - 1 - 2;
#endif

if (srcbpp == 3 && height) {
height -= 1;
last_line = 1;
Expand All @@ -2949,8 +3000,15 @@ Blit_3or4_to_3or4__same_rgb(SDL_BlitInfo * info)
DUFFS_LOOP(
{
Uint32 *dst32 = (Uint32*)dst;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
Uint32 *src32 = (Uint32*)src;
*dst32 = *src32 | mask;
#else
Uint8 s0 = src[i0];
Uint8 s1 = src[i1];
Uint8 s2 = src[i2];
*dst32 = (s0) | (s1 << 8) | (s2 << 16) | mask;
#endif
dst += 4;
src += srcbpp;
}, width);
Expand All @@ -2962,18 +3020,44 @@ Blit_3or4_to_3or4__same_rgb(SDL_BlitInfo * info)
if (last_line) {
while (width--) {
Uint32 *dst32 = (Uint32*)dst;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
Uint8 s0 = src[0];
Uint8 s1 = src[1];
Uint8 s2 = src[2];
#else
Uint8 s0 = src[i0];
Uint8 s1 = src[i1];
Uint8 s2 = src[i2];
#endif
*dst32 = (s0) | (s1 << 8) | (s2 << 16) | mask;
dst += 4;
src += srcbpp;
}
}
} else {
/* NO_ALPHA */
int mask = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask;
int last_line = 0;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
int mask = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask;
#else
int i0 = srcbpp - 1 - 0;
int i1 = srcbpp - 1 - 1;
int i2 = srcbpp - 1 - 2;
int j0 = dstbpp - 1 - 0;
int j1 = dstbpp - 1 - 1;
int j2 = dstbpp - 1 - 2;
int shift0, shift1, shift2;
if (dstbpp == 4) {
shift2 = 16;
shift1 = 8;
shift0 = 0;
} else { /* dstbpp 3 */
shift2 = 24;
shift1 = 16;
shift0 = 8;
}
#endif

if ((dstbpp == 3 || srcbpp == 3) && height) {
height -= 1;
last_line = 1;
Expand All @@ -2984,8 +3068,15 @@ Blit_3or4_to_3or4__same_rgb(SDL_BlitInfo * info)
DUFFS_LOOP(
{
Uint32 *dst32 = (Uint32*)dst;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
Uint32 *src32 = (Uint32*)src;
*dst32 = *src32 & mask;
#else
Uint8 s0 = src[i0];
Uint8 s1 = src[i1];
Uint8 s2 = src[i2];
*dst32 = (s0 << shift0) | (s1 << shift1) | (s2 << shift2);
#endif
dst += dstbpp;
src += srcbpp;
}, width);
Expand All @@ -2996,12 +3087,21 @@ Blit_3or4_to_3or4__same_rgb(SDL_BlitInfo * info)

if (last_line) {
while (width--) {
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
Uint8 s0 = src[0];
Uint8 s1 = src[1];
Uint8 s2 = src[2];
dst[0] = s0;
dst[1] = s1;
dst[2] = s2;
#else
Uint8 s0 = src[i0];
Uint8 s1 = src[i1];
Uint8 s2 = src[i2];
dst[j0] = s0;
dst[j1] = s1;
dst[j2] = s2;
#endif
dst += dstbpp;
src += srcbpp;
}
Expand Down Expand Up @@ -3034,10 +3134,17 @@ Blit_3or4_to_3or4__inversed_rgb(SDL_BlitInfo * info)
DUFFS_LOOP(
{
Uint32 *dst32 = (Uint32*)dst;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
Uint8 s0 = src[0];
Uint8 s1 = src[1];
Uint8 s2 = src[2];
Uint32 alphashift = src[3] << dstfmt->Ashift;
#else
Uint8 s0 = src[3];
Uint8 s1 = src[2];
Uint8 s2 = src[1];
Uint32 alphashift = src[0] << dstfmt->Ashift;
#endif
/* inversed, compared to Blit_3or4_to_3or4__same_rgb */
*dst32 = (s0 << 16) | (s1 << 8) | (s2) | alphashift;
dst += dstbpp;
Expand All @@ -3050,14 +3157,27 @@ Blit_3or4_to_3or4__inversed_rgb(SDL_BlitInfo * info)
} else {
/* SET_ALPHA */
Uint32 mask = info->a << dstfmt->Ashift;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
#else
int i0 = srcbpp - 1 - 0;
int i1 = srcbpp - 1 - 1;
int i2 = srcbpp - 1 - 2;
#endif

while (height--) {
/* *INDENT-OFF* */
DUFFS_LOOP(
{
Uint32 *dst32 = (Uint32*)dst;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
Uint8 s0 = src[0];
Uint8 s1 = src[1];
Uint8 s2 = src[2];
#else
Uint8 s0 = src[i0];
Uint8 s1 = src[i1];
Uint8 s2 = src[i2];
#endif
/* inversed, compared to Blit_3or4_to_3or4__same_rgb */
*dst32 = (s0 << 16) | (s1 << 8) | (s2) | mask;
dst += dstbpp;
Expand All @@ -3071,6 +3191,23 @@ Blit_3or4_to_3or4__inversed_rgb(SDL_BlitInfo * info)
} else {
/* NO_ALPHA */
int last_line = 0;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
#else
int i0 = srcbpp - 1 - 0;
int i1 = srcbpp - 1 - 1;
int i2 = srcbpp - 1 - 2;
int shift0, shift1, shift2;
if (dstbpp == 4) {
shift0 = 16;
shift1 = 8;
shift2 = 0;
} else { /* dstbpp 3 */
shift0 = 24;
shift1 = 16;
shift2 = 8;
}
#endif

if (dstbpp == 3 && height) {
height -= 1;
last_line = 1;
Expand All @@ -3081,11 +3218,18 @@ Blit_3or4_to_3or4__inversed_rgb(SDL_BlitInfo * info)
DUFFS_LOOP(
{
Uint32 *dst32 = (Uint32*)dst;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
Uint8 s0 = src[0];
Uint8 s1 = src[1];
Uint8 s2 = src[2];
/* inversed, compared to Blit_3or4_to_3or4__same_rgb */
*dst32 = (s0 << 16) | (s1 << 8) | (s2);
#else
Uint8 s0 = src[i0];
Uint8 s1 = src[i1];
Uint8 s2 = src[i2];
*dst32 = (s0 << shift0) | (s1 << shift1) | (s2 << shift2);
#endif
dst += dstbpp;
src += srcbpp;
}, width);
Expand All @@ -3096,13 +3240,23 @@ Blit_3or4_to_3or4__inversed_rgb(SDL_BlitInfo * info)

if (last_line) {
while (width--) {
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
Uint8 s0 = src[0];
Uint8 s1 = src[1];
Uint8 s2 = src[2];
/* inversed, compared to Blit_3or4_to_3or4__same_rgb */
dst[0] = s2;
dst[1] = s1;
dst[2] = s0;
#else
Uint8 s0 = src[i0];
Uint8 s1 = src[i1];
Uint8 s2 = src[i2];
/* inversed, compared to Blit_3or4_to_3or4__same_rgb */
dst[0] = s0;
dst[1] = s1;
dst[2] = s2;
#endif
dst += dstbpp;
src += srcbpp;
}
Expand Down Expand Up @@ -3151,7 +3305,6 @@ static const struct blit_table normal_blit_2[] = {
};

static const struct blit_table normal_blit_3[] = {
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
/* 3->4 with same rgb triplet */
{0x000000FF, 0x0000FF00, 0x00FF0000, 4, 0x000000FF, 0x0000FF00, 0x00FF0000,
0, Blit_3or4_to_3or4__same_rgb, NO_ALPHA | SET_ALPHA},
Expand All @@ -3167,7 +3320,6 @@ static const struct blit_table normal_blit_3[] = {
0, Blit_3or4_to_3or4__inversed_rgb, NO_ALPHA },
{0x00FF0000, 0x0000FF00, 0x000000FF, 3, 0x000000FF, 0x0000FF00, 0x00FF0000,
0, Blit_3or4_to_3or4__inversed_rgb, NO_ALPHA },
#endif
/* Default for 24-bit RGB source, never optimized */
{0, 0, 0, 0, 0, 0, 0, 0, BlitNtoN, 0}
};
Expand All @@ -3184,7 +3336,6 @@ static const struct blit_table normal_blit_4[] = {
{0x00000000, 0x00000000, 0x00000000, 2, 0x0000F800, 0x000007E0, 0x0000001F,
2, Blit_RGB888_RGB565Altivec, NO_ALPHA},
#endif
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
/* 4->3 with same rgb triplet */
{0x000000FF, 0x0000FF00, 0x00FF0000, 3, 0x000000FF, 0x0000FF00, 0x00FF0000,
0, Blit_3or4_to_3or4__same_rgb, NO_ALPHA | SET_ALPHA},
Expand All @@ -3195,7 +3346,6 @@ static const struct blit_table normal_blit_4[] = {
0, Blit_3or4_to_3or4__inversed_rgb, NO_ALPHA | SET_ALPHA},
{0x00FF0000, 0x0000FF00, 0x000000FF, 3, 0x000000FF, 0x0000FF00, 0x00FF0000,
0, Blit_3or4_to_3or4__inversed_rgb, NO_ALPHA | SET_ALPHA},
#endif
/* 4->4 with inversed rgb triplet, and COPY_ALPHA to switch ABGR8888 <-> ARGB8888 */
{0x000000FF, 0x0000FF00, 0x00FF0000, 4, 0x00FF0000, 0x0000FF00, 0x000000FF,
0, Blit_3or4_to_3or4__inversed_rgb, NO_ALPHA | SET_ALPHA | COPY_ALPHA},
Expand Down

0 comments on commit e9a7b69

Please sign in to comment.