mirror of
https://github.com/Ryujinx/SDL.git
synced 2025-01-25 17:51:14 +00:00
Fixed bug #6990: fix computation of alpha in BlitRGBtoRGBPixelAlphaMMX
This commit is contained in:
parent
a099172754
commit
0ebda87425
|
@ -332,9 +332,19 @@ static void BlitRGBtoRGBPixelAlphaMMX(SDL_BlitInfo *info)
|
||||||
Uint32 ashift = sf->Ashift;
|
Uint32 ashift = sf->Ashift;
|
||||||
Uint64 multmask, multmask2;
|
Uint64 multmask, multmask2;
|
||||||
|
|
||||||
__m64 src1, dst1, mm_alpha, mm_zero, mm_alpha2;
|
__m64 src1, dst1, mm_alpha, mm_zero, mm_alpha2, mm_one_alpha;
|
||||||
|
|
||||||
mm_zero = _mm_setzero_si64(); /* 0 -> mm_zero */
|
mm_zero = _mm_setzero_si64(); /* 0 -> mm_zero */
|
||||||
|
if (amask == 0xFF000000) { /* 1 in the alpha channel -> mm_one_alpha */
|
||||||
|
mm_one_alpha = _mm_set_pi16(1, 0, 0, 0);
|
||||||
|
} else if (amask == 0x00FF0000) {
|
||||||
|
mm_one_alpha = _mm_set_pi16(0, 1, 0, 0);
|
||||||
|
} else if (amask == 0x0000FF00) {
|
||||||
|
mm_one_alpha = _mm_set_pi16(0, 0, 1, 0);
|
||||||
|
} else {
|
||||||
|
mm_one_alpha = _mm_set_pi16(0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
multmask = 0x00FF;
|
multmask = 0x00FF;
|
||||||
multmask <<= (ashift * 2);
|
multmask <<= (ashift * 2);
|
||||||
multmask2 = 0x00FF00FF00FF00FFULL;
|
multmask2 = 0x00FF00FF00FF00FFULL;
|
||||||
|
@ -361,14 +371,33 @@ static void BlitRGBtoRGBPixelAlphaMMX(SDL_BlitInfo *info)
|
||||||
mm_alpha = _mm_or_si64(mm_alpha2, *(__m64 *) & multmask); /* 0F0A0A0A -> mm_alpha */
|
mm_alpha = _mm_or_si64(mm_alpha2, *(__m64 *) & multmask); /* 0F0A0A0A -> mm_alpha */
|
||||||
mm_alpha2 = _mm_xor_si64(mm_alpha2, *(__m64 *) & multmask2); /* 255 - mm_alpha -> mm_alpha */
|
mm_alpha2 = _mm_xor_si64(mm_alpha2, *(__m64 *) & multmask2); /* 255 - mm_alpha -> mm_alpha */
|
||||||
|
|
||||||
/* blend */
|
/*
|
||||||
|
Alpha blending is:
|
||||||
|
dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
|
||||||
|
dstA = srcA + (dstA * (1-srcA)) *
|
||||||
|
|
||||||
|
Here, 'src1' is:
|
||||||
|
srcRGB * srcA
|
||||||
|
srcA
|
||||||
|
And 'dst1' is:
|
||||||
|
dstRGB * (1-srcA)
|
||||||
|
dstA * (1-srcA)
|
||||||
|
so that *dstp is 'src1 + dst1'
|
||||||
|
|
||||||
|
src1 is computed using mullo_pi16: (X * mask) >> 8, but is approximate for srcA ((srcA * 255) >> 8).
|
||||||
|
|
||||||
|
need to a 1 to get an exact result: (srcA * 256) >> 8 == srcA
|
||||||
|
*/
|
||||||
|
mm_alpha = _mm_add_pi16(mm_alpha, mm_one_alpha);
|
||||||
|
|
||||||
|
/* blend */
|
||||||
src1 = _mm_mullo_pi16(src1, mm_alpha);
|
src1 = _mm_mullo_pi16(src1, mm_alpha);
|
||||||
src1 = _mm_srli_pi16(src1, 8);
|
src1 = _mm_srli_pi16(src1, 8);
|
||||||
dst1 = _mm_mullo_pi16(dst1, mm_alpha2);
|
dst1 = _mm_mullo_pi16(dst1, mm_alpha2);
|
||||||
dst1 = _mm_srli_pi16(dst1, 8);
|
dst1 = _mm_srli_pi16(dst1, 8);
|
||||||
dst1 = _mm_add_pi16(src1, dst1);
|
dst1 = _mm_add_pi16(src1, dst1);
|
||||||
dst1 = _mm_packs_pu16(dst1, mm_zero);
|
dst1 = _mm_packs_pu16(dst1, mm_zero);
|
||||||
|
|
||||||
*dstp = _mm_cvtsi64_si32(dst1); /* dst1 -> pixel */
|
*dstp = _mm_cvtsi64_si32(dst1); /* dst1 -> pixel */
|
||||||
}
|
}
|
||||||
++srcp;
|
++srcp;
|
||||||
|
@ -664,14 +693,14 @@ static void BlitRGBtoRGBPixelAlphaMMX3DNOW(SDL_BlitInfo *info)
|
||||||
mm_alpha2 = _mm_xor_si64(mm_alpha2, *(__m64 *) & multmask2); /* 255 - mm_alpha -> mm_alpha */
|
mm_alpha2 = _mm_xor_si64(mm_alpha2, *(__m64 *) & multmask2); /* 255 - mm_alpha -> mm_alpha */
|
||||||
|
|
||||||
|
|
||||||
/* blend */
|
/* blend */
|
||||||
src1 = _mm_mullo_pi16(src1, mm_alpha);
|
src1 = _mm_mullo_pi16(src1, mm_alpha);
|
||||||
src1 = _mm_srli_pi16(src1, 8);
|
src1 = _mm_srli_pi16(src1, 8);
|
||||||
dst1 = _mm_mullo_pi16(dst1, mm_alpha2);
|
dst1 = _mm_mullo_pi16(dst1, mm_alpha2);
|
||||||
dst1 = _mm_srli_pi16(dst1, 8);
|
dst1 = _mm_srli_pi16(dst1, 8);
|
||||||
dst1 = _mm_add_pi16(src1, dst1);
|
dst1 = _mm_add_pi16(src1, dst1);
|
||||||
dst1 = _mm_packs_pu16(dst1, mm_zero);
|
dst1 = _mm_packs_pu16(dst1, mm_zero);
|
||||||
|
|
||||||
*dstp = _mm_cvtsi64_si32(dst1); /* dst1 -> pixel */
|
*dstp = _mm_cvtsi64_si32(dst1); /* dst1 -> pixel */
|
||||||
}
|
}
|
||||||
++srcp;
|
++srcp;
|
||||||
|
@ -1024,7 +1053,7 @@ static void Blit555to555SurfaceAlphaMMX(SDL_BlitInfo *info)
|
||||||
dst2 = _mm_and_si64(dst2, rmask); /* dst2 & MASKRED -> dst2 */
|
dst2 = _mm_and_si64(dst2, rmask); /* dst2 & MASKRED -> dst2 */
|
||||||
|
|
||||||
mm_res = dst2; /* RED -> mm_res */
|
mm_res = dst2; /* RED -> mm_res */
|
||||||
|
|
||||||
/* green -- process the bits in place */
|
/* green -- process the bits in place */
|
||||||
src2 = src1;
|
src2 = src1;
|
||||||
src2 = _mm_and_si64(src2, gmask); /* src & MASKGREEN -> src2 */
|
src2 = _mm_and_si64(src2, gmask); /* src & MASKGREEN -> src2 */
|
||||||
|
@ -1166,7 +1195,7 @@ static void BlitARGBto565PixelAlpha(SDL_BlitInfo *info)
|
||||||
compositioning used (>>8 instead of /255) doesn't handle
|
compositioning used (>>8 instead of /255) doesn't handle
|
||||||
it correctly. Also special-case alpha=0 for speed?
|
it correctly. Also special-case alpha=0 for speed?
|
||||||
Benchmark this! */
|
Benchmark this! */
|
||||||
if (alpha) {
|
if (alpha) {
|
||||||
if (alpha == (SDL_ALPHA_OPAQUE >> 3)) {
|
if (alpha == (SDL_ALPHA_OPAQUE >> 3)) {
|
||||||
*dstp = (Uint16)((s >> 8 & 0xf800) + (s >> 5 & 0x7e0) + (s >> 3 & 0x1f));
|
*dstp = (Uint16)((s >> 8 & 0xf800) + (s >> 5 & 0x7e0) + (s >> 3 & 0x1f));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1212,7 +1241,7 @@ static void BlitARGBto555PixelAlpha(SDL_BlitInfo *info)
|
||||||
compositioning used (>>8 instead of /255) doesn't handle
|
compositioning used (>>8 instead of /255) doesn't handle
|
||||||
it correctly. Also special-case alpha=0 for speed?
|
it correctly. Also special-case alpha=0 for speed?
|
||||||
Benchmark this! */
|
Benchmark this! */
|
||||||
if (alpha) {
|
if (alpha) {
|
||||||
if (alpha == (SDL_ALPHA_OPAQUE >> 3)) {
|
if (alpha == (SDL_ALPHA_OPAQUE >> 3)) {
|
||||||
*dstp = (Uint16)((s >> 9 & 0x7c00) + (s >> 6 & 0x3e0) + (s >> 3 & 0x1f));
|
*dstp = (Uint16)((s >> 9 & 0x7c00) + (s >> 6 & 0x3e0) + (s >> 3 & 0x1f));
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue