You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
3.8 KiB
88 lines
3.8 KiB
Correct vec_perm() application on little-endian 64-bit PowerPC
|
|
|
|
The LE transformation for vec_perm has an implicit assumption that the
|
|
permutation is being used to reorder vector elements (in this case 4-byte
|
|
integer word elements), not to reorder bytes within those elements. Although
|
|
this is legal behavior, it is not anticipated by the transformation performed
|
|
by the compilers.
|
|
|
|
This causes pygame-1.9.1 test failure on PPC64LE because blitted pixmaps are
|
|
corrupted there due to how SDL uses vec_perm().
|
|
|
|
<https://bugzilla.redhat.com/show_bug.cgi?id=1392465>
|
|
|
|
--- SDL-1.2.15/src/video/SDL_blit_N.c.ori 2017-09-04 05:56:17.759347525 -0400
|
|
+++ SDL-1.2.15/src/video/SDL_blit_N.c 2017-09-06 05:36:20.570789610 -0400
|
|
@@ -146,6 +146,32 @@ static vector unsigned char calc_swizzle
|
|
return(vswiz);
|
|
}
|
|
|
|
+/* 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);
|
|
+}
|
|
+
|
|
static void Blit_RGB888_RGB565(SDL_BlitInfo *info);
|
|
static void Blit_RGB888_RGB565Altivec(SDL_BlitInfo *info) {
|
|
int height = info->d_height;
|
|
@@ -631,6 +657,12 @@ static void Blit32to32KeyAltivec(SDL_Bli
|
|
vsel = (vector unsigned char)vec_and(vs, vrgbmask);
|
|
vsel = (vector unsigned char)vec_cmpeq(vs, vckey);
|
|
/* permute the src vec to the dest format */
|
|
+
|
|
+#if defined(__powerpc__) && (SDL_BYTEORDER == SDL_LIL_ENDIAN)
|
|
+ /* reorder bytes for PowerPC little endian */
|
|
+ vpermute = reorder_ppc64le_vec(vpermute);
|
|
+#endif
|
|
+
|
|
vs = vec_perm(vs, valpha, vpermute);
|
|
/* load the destination vec */
|
|
vd = vec_ld(0, dstp);
|
|
@@ -704,6 +736,12 @@ static void ConvertAltivec32to32_noprefe
|
|
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;
|
|
@@ -786,6 +824,12 @@ static void ConvertAltivec32to32_prefetc
|
|
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;
|