Trilinear scaler overhaul: moving image hotspot processing to tfb_draw/DCQ; proper handling of src and dst alpha surfaces; src and mipmap alignment fixes; code cleanup
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2029 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
|
||||
typedef SDL_Surface *NativeCanvas;
|
||||
|
||||
// BYTE x BYTE weight (mult >> 8) table
|
||||
static Uint8 btable[256][256];
|
||||
|
||||
void
|
||||
@@ -18,7 +19,8 @@ TFB_DrawCanvas_Initialize (void)
|
||||
int i, j;
|
||||
for (i = 0; i < 256; ++i)
|
||||
for (j = 0; j < 256; ++j)
|
||||
btable[j][i] = (j * i) >> 8;
|
||||
btable[j][i] = (j * i + 0x80) >> 8;
|
||||
// need error correction here
|
||||
}
|
||||
|
||||
void
|
||||
@@ -71,8 +73,6 @@ TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale, TFB_Palette *pale
|
||||
}
|
||||
|
||||
LockMutex (img->mutex);
|
||||
targetRect.x = x;
|
||||
targetRect.y = y;
|
||||
|
||||
if (palette == 0)
|
||||
palette = img->Palette;
|
||||
@@ -100,17 +100,23 @@ TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale, TFB_Palette *pale
|
||||
srcRect.w = img->extent.width;
|
||||
srcRect.h = img->extent.height;
|
||||
pSrcRect = &srcRect;
|
||||
|
||||
targetRect.x = x - img->last_scale_hs.x;
|
||||
targetRect.y = y - img->last_scale_hs.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
surf = img->NormalImg;
|
||||
pSrcRect = NULL;
|
||||
|
||||
targetRect.x = x - img->NormalHs.x;
|
||||
targetRect.y = y - img->NormalHs.y;
|
||||
}
|
||||
|
||||
if (surf->format->palette)
|
||||
SDL_SetColors (surf, (SDL_Color*)palette, 0, 256);
|
||||
|
||||
SDL_BlitSurface(surf, pSrcRect, (NativeCanvas) target, &targetRect);
|
||||
SDL_BlitSurface (surf, pSrcRect, (NativeCanvas) target, &targetRect);
|
||||
UnlockMutex (img->mutex);
|
||||
}
|
||||
|
||||
@@ -217,9 +223,6 @@ TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int
|
||||
|
||||
LockMutex (img->mutex);
|
||||
|
||||
targetRect.x = x;
|
||||
targetRect.y = y;
|
||||
|
||||
if (scale != 0 && scale != GSCALE_IDENTITY)
|
||||
{
|
||||
TFB_DrawImage_FixScaling (img, scale, TFB_SCALE_NEAREST);
|
||||
@@ -229,11 +232,17 @@ TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int
|
||||
srcRect.w = img->extent.width;
|
||||
srcRect.h = img->extent.height;
|
||||
pSrcRect = &srcRect;
|
||||
|
||||
targetRect.x = x - img->last_scale_hs.x;
|
||||
targetRect.y = y - img->last_scale_hs.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
surf = img->NormalImg;
|
||||
pSrcRect = NULL;
|
||||
|
||||
targetRect.x = x - img->NormalHs.x;
|
||||
targetRect.y = y - img->NormalHs.y;
|
||||
}
|
||||
|
||||
if (surf->format->palette)
|
||||
@@ -586,21 +595,26 @@ TFB_DrawCanvas_SetTransparentColor (TFB_Canvas canvas, int r, int g, int b, BOOL
|
||||
}
|
||||
|
||||
void
|
||||
TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, TFB_Canvas src_mipmap, int scale, PEXTENT size)
|
||||
TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, HOT_SPOT src_hs,
|
||||
TFB_Canvas src_mipmap, HOT_SPOT mm_hs,
|
||||
int scale, PEXTENT size, HOT_SPOT *hs)
|
||||
{
|
||||
SDL_Surface *src = (SDL_Surface *)src_canvas;
|
||||
|
||||
if (!src_mipmap)
|
||||
{
|
||||
size->width = (int) (src->w * scale / (float)GSCALE_IDENTITY + 0.5);
|
||||
size->height = (int) (src->h * scale / (float)GSCALE_IDENTITY + 0.5);
|
||||
size->width = src->w * scale / GSCALE_IDENTITY;
|
||||
size->height = src->h * scale / GSCALE_IDENTITY;
|
||||
|
||||
hs->x = src_hs.x * scale / GSCALE_IDENTITY;
|
||||
hs->y = src_hs.y * scale / GSCALE_IDENTITY;
|
||||
}
|
||||
else
|
||||
{
|
||||
// interpolates extents between src and mipmap to get smoother
|
||||
// transition when surface changes
|
||||
|
||||
SDL_Surface *mipmap = (SDL_Surface *)src_mipmap;
|
||||
|
||||
float ratio = (scale / (float)GSCALE_IDENTITY) * 2.0f - 1.0f;
|
||||
if (ratio < 0.0f)
|
||||
ratio = 0.0f;
|
||||
@@ -609,6 +623,9 @@ TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, TFB_Canvas src_mipmap, in
|
||||
|
||||
size->width = (int)((src->w - mipmap->w) * ratio + mipmap->w + 0.5);
|
||||
size->height = (int)((src->h - mipmap->h) * ratio + mipmap->h + 0.5);
|
||||
|
||||
hs->x = (int)((src_hs.x - mm_hs.x) * ratio + mm_hs.x + 0.5);
|
||||
hs->y = (int)((src_hs.y - mm_hs.y) * ratio + mm_hs.y + 0.5);
|
||||
}
|
||||
|
||||
if (!size->width && src->w)
|
||||
@@ -650,9 +667,9 @@ TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, E
|
||||
|
||||
sx = sy = 0;
|
||||
if (size.width > 1)
|
||||
sx = 65536 * (src->w - 1) / (size.width - 1);
|
||||
sx = ((src->w - 1) << 16) / (size.width - 1);
|
||||
if (size.height > 1)
|
||||
sy = 65536 * (src->h - 1) / (size.height - 1);
|
||||
sy = ((src->h - 1) << 16) / (size.height - 1);
|
||||
|
||||
sax = saspace;
|
||||
say = saspace + size.width;
|
||||
@@ -737,19 +754,142 @@ TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, E
|
||||
SDL_UnlockSurface (src);
|
||||
}
|
||||
|
||||
typedef union
|
||||
{
|
||||
Uint32 value;
|
||||
Uint8 chan[4];
|
||||
struct
|
||||
{
|
||||
Uint8 r, g, b, a;
|
||||
} c;
|
||||
} pixel_t;
|
||||
|
||||
static inline Uint8
|
||||
dot_product_8_4 (pixel_t* p, int c, Uint8* v)
|
||||
{ // math expanded for speed
|
||||
#if 0
|
||||
return (
|
||||
(Uint32)p[0].chan[c] * v[0] + (Uint32)p[1].chan[c] * v[1] +
|
||||
(Uint32)p[2].chan[c] * v[2] + (Uint32)p[3].chan[c] * v[3]
|
||||
) >> 8;
|
||||
#else
|
||||
// mult-table driven version
|
||||
return
|
||||
btable[p[0].chan[c]][v[0]] + btable[p[1].chan[c]][v[1]] +
|
||||
btable[p[2].chan[c]][v[2]] + btable[p[3].chan[c]][v[3]];
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline Uint8
|
||||
weight_product_8_4 (pixel_t* p, int c, Uint8* w)
|
||||
{ // math expanded for speed
|
||||
return (
|
||||
(Uint32)p[0].chan[c] * w[0] + (Uint32)p[1].chan[c] * w[1] +
|
||||
(Uint32)p[2].chan[c] * w[2] + (Uint32)p[3].chan[c] * w[3]
|
||||
) / (w[0] + w[1] + w[2] + w[3]);
|
||||
}
|
||||
|
||||
static inline Uint8
|
||||
blend_ratio_2 (Uint8 c1, Uint8 c2, int ratio)
|
||||
{ // blend 2 color values according to ratio (0..256)
|
||||
// identical to proper alpha blending
|
||||
return (((c1 - c2) * ratio) >> 8) + c2;
|
||||
}
|
||||
|
||||
static inline Uint32
|
||||
tri_get_pixel (void* ppix, SDL_PixelFormat *fmt, SDL_Color *pal,
|
||||
Uint32 mask, Uint32 key)
|
||||
{
|
||||
pixel_t p;
|
||||
|
||||
// start off with non-present pixel
|
||||
p.value = 0;
|
||||
|
||||
if (pal)
|
||||
{ // paletted pixel; mask not used
|
||||
Uint32 c = *(Uint8 *)ppix;
|
||||
|
||||
if (c != key)
|
||||
{
|
||||
p.c.r = pal[c].r;
|
||||
p.c.g = pal[c].g;
|
||||
p.c.b = pal[c].b;
|
||||
p.c.a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // RGB(A) pixel; (pix & mask) != key
|
||||
Uint32 c = *(Uint32 *)ppix;
|
||||
|
||||
if ((c & mask) != key)
|
||||
{
|
||||
#if 0
|
||||
SDL_GetRGBA (c, fmt, &p.c.r, &p.c.g, &p.c.b, &p.c.a);
|
||||
#else
|
||||
p.c.r = (c >> fmt->Rshift) & 0xff;
|
||||
p.c.g = (c >> fmt->Gshift) & 0xff;
|
||||
p.c.b = (c >> fmt->Bshift) & 0xff;
|
||||
if (fmt->Amask)
|
||||
p.c.a = (c >> fmt->Ashift) & 0xff;
|
||||
else
|
||||
p.c.a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return p.value;
|
||||
}
|
||||
|
||||
void
|
||||
TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, TFB_Canvas src_mipmap, EXTENT size)
|
||||
TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas,
|
||||
TFB_Canvas dest_canvas, TFB_Canvas src_mipmap, EXTENT size)
|
||||
{
|
||||
SDL_Surface *src = (SDL_Surface *)src_canvas;
|
||||
SDL_Surface *dst = (SDL_Surface *)dest_canvas;
|
||||
SDL_Surface *mipmap = (SDL_Surface *)src_mipmap;
|
||||
SDL_PixelFormat *srcfmt = src->format;
|
||||
SDL_PixelFormat *mmfmt = mipmap->format;
|
||||
SDL_PixelFormat *dstfmt = dst->format;
|
||||
const int dstopaque = dstfmt->Amask;
|
||||
const int dsttransparent = (dst->flags & SDL_SRCCOLORKEY) ? dstfmt->colorkey : 0;
|
||||
SDL_Color *srcpal = srcfmt->palette? srcfmt->palette->colors : 0;
|
||||
SDL_Color *mmpal = mmfmt->palette ? mmfmt->palette->colors : 0;
|
||||
const int sbpp = srcfmt->BytesPerPixel;
|
||||
const int mmbpp = mmfmt->BytesPerPixel;
|
||||
const int slen = src->pitch;
|
||||
const int mmlen = mipmap->pitch;
|
||||
const int dst_has_alpha = (dstfmt->Amask != 0);
|
||||
const int transparent = (dst->flags & SDL_SRCCOLORKEY) ?
|
||||
dstfmt->colorkey : 0;
|
||||
const int w = size.width, h = size.height;
|
||||
const int ALPHA_THRESHOLD = 128;
|
||||
|
||||
int ratio = (int)(256.0f * (((float)w / src->w) * 2.0f - 1.0f));
|
||||
const int alpha_threshold = dst_has_alpha ? 0 : 127;
|
||||
// src v. mipmap importance factor
|
||||
int ratio;
|
||||
// source masks and keys
|
||||
Uint32 mk0 = 0, ck0 = ~0, mk1 = 0, ck1 = ~0;
|
||||
// source fractional x and y positions
|
||||
int sx0, sy0, sx1, sy1;
|
||||
// source fractional dx and dy increments
|
||||
int fsx0 = 0, fsy0 = 0, fsx1 = 0, fsy1 = 0;
|
||||
// source fractional x and y starting points
|
||||
int ssx0 = 0, ssy0 = 0, ssx1 = 0, ssy1 = 0;
|
||||
int x, y;
|
||||
|
||||
fsx0 = (src->w << 16) / w;
|
||||
fsy0 = (src->h << 16) / h;
|
||||
|
||||
if (w > 1)
|
||||
fsx1 = ((mipmap->w - 1) << 16) / (w - 1);
|
||||
if (h > 1)
|
||||
fsy1 = ((mipmap->h - 1) << 16) / (h - 1);
|
||||
|
||||
// give equal importance to both edges
|
||||
ssx0 = (((src->w - 1) << 16) - fsx0 * (w - 1)) >> 1;
|
||||
ssy0 = (((src->h - 1) << 16) - fsy0 * (h - 1)) >> 1;
|
||||
|
||||
ssx1 = (((mipmap->w - 1) << 16) - fsx1 * (w - 1)) >> 1;
|
||||
ssy1 = (((mipmap->h - 1) << 16) - fsy1 * (h - 1)) >> 1;
|
||||
|
||||
// src v. mipmap importance factor
|
||||
ratio = (w << 9) / src->w - 256;
|
||||
if (ratio < 0)
|
||||
ratio = 0;
|
||||
if (ratio > 256)
|
||||
@@ -762,404 +902,237 @@ TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas dest_canvas,
|
||||
return;
|
||||
}
|
||||
|
||||
if (src->format->BytesPerPixel == 1 && dst->format->BytesPerPixel == 4 &&
|
||||
mipmap->format->BytesPerPixel == 1)
|
||||
{
|
||||
SDL_Color *srcpal = src->format->palette->colors;
|
||||
SDL_Color *mmpal = mipmap->format->palette->colors;
|
||||
int fsx0 = (int)(65536.0f * (float)src->w / w);
|
||||
int fsy0 = (int)(65536.0f * (float)src->h / h);
|
||||
int fsx1 = (int)(65536.0f * (float)mipmap->w / w);
|
||||
int fsy1 = (int)(65536.0f * (float)mipmap->h / h);
|
||||
int sx0 = 0, sy0 = 0, sx1 = 0, sy1 = 0;
|
||||
int x, y;
|
||||
Uint32 ck0 = src->format->colorkey;
|
||||
Uint32 ck1 = mipmap->format->colorkey;
|
||||
|
||||
SDL_LockSurface(src);
|
||||
SDL_LockSurface(dst);
|
||||
SDL_LockSurface(mipmap);
|
||||
|
||||
for (y = 0; y < h; ++y)
|
||||
{
|
||||
Uint32 *dst_p = (Uint32 *)dst->pixels + y * dst->w;
|
||||
Uint8 *src_a0 = (Uint8 *)src->pixels + (sy0 >> 16) * src->pitch;
|
||||
Uint8 *src_a1 = (Uint8 *)mipmap->pixels + (sy1 >> 16) * mipmap->pitch;
|
||||
|
||||
for (x = 0; x < w; ++x)
|
||||
{
|
||||
Uint8 u0 = (sx0 >> 8) & 0xff;
|
||||
Uint8 u1 = (sx1 >> 8) & 0xff;
|
||||
Uint8 v0 = (sy0 >> 8) & 0xff;
|
||||
Uint8 v1 = (sy1 >> 8) & 0xff;
|
||||
Uint8 ul0 = btable[255 - u0][255 - v0];
|
||||
Uint8 ul1 = btable[255 - u1][255 - v1];
|
||||
Uint8 ur0 = btable[u0][255 - v0];
|
||||
Uint8 ur1 = btable[u1][255 - v1];
|
||||
Uint8 ll0 = btable[255 - u0][v0];
|
||||
Uint8 ll1 = btable[255 - u1][v1];
|
||||
Uint8 lr0 = btable[u0][v0];
|
||||
Uint8 lr1 = btable[u1][v1];
|
||||
|
||||
Uint8 r0[5], r1[5], g0[5], g1[5], b0[5], b1[5], a0[5], a1[5];
|
||||
Uint8 c;
|
||||
|
||||
Uint8 *src_p0 = src_a0 + (sx0 >> 16);
|
||||
Uint8 *src_p1 = src_a1 + (sx1 >> 16);
|
||||
|
||||
if ((sx0 >> 16) <= src->w - 2)
|
||||
{
|
||||
a0[0] = ((c = *src_p0) == ck0) ? 0 : 255;
|
||||
r0[0] = srcpal[c].r;
|
||||
g0[0] = srcpal[c].g;
|
||||
b0[0] = srcpal[c].b;
|
||||
a0[1] = ((c = *(src_p0 + 1)) == ck0) ? 0 : 255;
|
||||
r0[1] = srcpal[c].r;
|
||||
g0[1] = srcpal[c].g;
|
||||
b0[1] = srcpal[c].b;
|
||||
|
||||
if ((sy0 >> 16) <= src->h - 2)
|
||||
{
|
||||
a0[2] = ((c = *(src_p0 + src->pitch)) == ck0) ? 0 : 255;
|
||||
r0[2] = srcpal[c].r;
|
||||
g0[2] = srcpal[c].g;
|
||||
b0[2] = srcpal[c].b;
|
||||
a0[3] = ((c = *(src_p0 + src->pitch + 1)) == ck0) ? 0 : 255;
|
||||
r0[3] = srcpal[c].r;
|
||||
g0[3] = srcpal[c].g;
|
||||
b0[3] = srcpal[c].b;
|
||||
}
|
||||
else
|
||||
{
|
||||
a0[2] = a0[0];
|
||||
r0[2] = r0[0];
|
||||
g0[2] = g0[0];
|
||||
b0[2] = b0[0];
|
||||
a0[3] = a0[1];
|
||||
r0[3] = r0[1];
|
||||
g0[3] = g0[1];
|
||||
b0[3] = b0[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a0[0] = a0[1] = ((c = *src_p0) == ck0) ? 0 : 255;
|
||||
r0[0] = r0[1] = srcpal[c].r;
|
||||
g0[0] = g0[1] = srcpal[c].g;
|
||||
b0[0] = b0[1] = srcpal[c].b;
|
||||
if ((sy0 >> 16) <= src->h - 2)
|
||||
{
|
||||
a0[2] = a0[3] = ((c = *(src_p0 + src->pitch)) == ck0) ? 0 : 255;
|
||||
r0[2] = r0[3] = srcpal[c].r;
|
||||
g0[2] = g0[3] = srcpal[c].g;
|
||||
b0[2] = b0[3] = srcpal[c].b;
|
||||
}
|
||||
else
|
||||
{
|
||||
a0[2] = a0[3] = a0[0];
|
||||
r0[2] = r0[3] = r0[0];
|
||||
g0[2] = g0[3] = g0[0];
|
||||
b0[2] = b0[3] = b0[0];
|
||||
}
|
||||
}
|
||||
|
||||
if ((sx1 >> 16) <= mipmap->w - 2)
|
||||
{
|
||||
a1[0] = ((c = *src_p1) == ck1) ? 0 : 255;
|
||||
r1[0] = mmpal[c].r;
|
||||
g1[0] = mmpal[c].g;
|
||||
b1[0] = mmpal[c].b;
|
||||
a1[1] = ((c = *(src_p1 + 1)) == ck1) ? 0 : 255;
|
||||
r1[1] = mmpal[c].r;
|
||||
g1[1] = mmpal[c].g;
|
||||
b1[1] = mmpal[c].b;
|
||||
|
||||
if ((sy1 >> 16) <= mipmap->h - 2)
|
||||
{
|
||||
a1[2] = ((c = *(src_p1 + mipmap->pitch)) == ck1) ? 0 : 255;
|
||||
r1[2] = mmpal[c].r;
|
||||
g1[2] = mmpal[c].g;
|
||||
b1[2] = mmpal[c].b;
|
||||
a1[3] = ((c = *(src_p1 + mipmap->pitch + 1)) == ck1) ? 0 : 255;
|
||||
r1[3] = mmpal[c].r;
|
||||
g1[3] = mmpal[c].g;
|
||||
b1[3] = mmpal[c].b;
|
||||
}
|
||||
else
|
||||
{
|
||||
a1[2] = a1[0];
|
||||
r1[2] = r1[0];
|
||||
g1[2] = g1[0];
|
||||
b1[2] = b1[0];
|
||||
a1[3] = a1[1];
|
||||
r1[3] = r1[1];
|
||||
g1[3] = g1[1];
|
||||
b1[3] = b1[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a1[0] = a1[1] = ((c = *src_p1) == ck1) ? 0 : 255;
|
||||
r1[0] = r1[1] = mmpal[c].r;
|
||||
g1[0] = g1[1] = mmpal[c].g;
|
||||
b1[0] = b1[1] = mmpal[c].b;
|
||||
if ((sy1 >> 16) <= mipmap->h - 2)
|
||||
{
|
||||
a1[2] = a1[3] = ((c = *(src_p1 + mipmap->pitch)) == ck1) ? 0 : 255;
|
||||
r1[2] = r1[3] = mmpal[c].r;
|
||||
g1[2] = g1[3] = mmpal[c].g;
|
||||
b1[2] = b1[3] = mmpal[c].b;
|
||||
}
|
||||
else
|
||||
{
|
||||
a1[2] = a1[3] = a1[0];
|
||||
r1[2] = r1[3] = r1[0];
|
||||
g1[2] = g1[3] = g1[0];
|
||||
b1[2] = b1[3] = b1[0];
|
||||
}
|
||||
}
|
||||
|
||||
a0[4] = ((ul0 * a0[0]) >> 8) + ((ur0 * a0[1]) >> 8) + ((ll0 * a0[2]) >> 8) + ((lr0 * a0[3]) >> 8);
|
||||
a1[4] = ((ul1 * a1[0]) >> 8) + ((ur1 * a1[1]) >> 8) + ((ll1 * a1[2]) >> 8) + ((lr1 * a1[3]) >> 8);
|
||||
|
||||
if ((((a0[4] - a1[4]) * ratio) >> 8) + a1[4] > ALPHA_THRESHOLD)
|
||||
{
|
||||
r0[4] = ((ul0 * r0[0]) >> 8) + ((ur0 * r0[1]) >> 8) + ((ll0 * r0[2]) >> 8) + ((lr0 * r0[3]) >> 8);
|
||||
g0[4] = ((ul0 * g0[0]) >> 8) + ((ur0 * g0[1]) >> 8) + ((ll0 * g0[2]) >> 8) + ((lr0 * g0[3]) >> 8);
|
||||
b0[4] = ((ul0 * b0[0]) >> 8) + ((ur0 * b0[1]) >> 8) + ((ll0 * b0[2]) >> 8) + ((lr0 * b0[3]) >> 8);
|
||||
|
||||
r1[4] = ((ul1 * r1[0]) >> 8) + ((ur1 * r1[1]) >> 8) + ((ll1 * r1[2]) >> 8) + ((lr1 * r1[3]) >> 8);
|
||||
g1[4] = ((ul1 * g1[0]) >> 8) + ((ur1 * g1[1]) >> 8) + ((ll1 * g1[2]) >> 8) + ((lr1 * g1[3]) >> 8);
|
||||
b1[4] = ((ul1 * b1[0]) >> 8) + ((ur1 * b1[1]) >> 8) + ((ll1 * b1[2]) >> 8) + ((lr1 * b1[3]) >> 8);
|
||||
|
||||
*dst_p++ =
|
||||
(((((r0[4] - r1[4]) * ratio) >> 8) + r1[4]) << dstfmt->Rshift) |
|
||||
(((((g0[4] - g1[4]) * ratio) >> 8) + g1[4]) << dstfmt->Gshift) |
|
||||
(((((b0[4] - b1[4]) * ratio) >> 8) + b1[4]) << dstfmt->Bshift) |
|
||||
dstopaque;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst_p++ = dsttransparent;
|
||||
}
|
||||
|
||||
sx0 += fsx0;
|
||||
sx1 += fsx1;
|
||||
}
|
||||
sx0 = sx1 = 0;
|
||||
sy0 += fsy0;
|
||||
sy1 += fsy1;
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(mipmap);
|
||||
SDL_UnlockSurface(dst);
|
||||
SDL_UnlockSurface(src);
|
||||
}
|
||||
else if (src->format->BytesPerPixel == 4 && dst->format->BytesPerPixel == 4 &&
|
||||
mipmap->format->BytesPerPixel == 4)
|
||||
{
|
||||
int fsx0 = (int)(65536.0f * (float)src->w / w);
|
||||
int fsy0 = (int)(65536.0f * (float)src->h / h);
|
||||
int fsx1 = (int)(65536.0f * (float)mipmap->w / w);
|
||||
int fsy1 = (int)(65536.0f * (float)mipmap->h / h);
|
||||
int sx0 = 0, sy0 = 0, sx1 = 0, sy1 = 0;
|
||||
int x, y;
|
||||
Uint32 ck0 = 0; // 0 means alpha=0 too, so it's safe
|
||||
Uint32 ck1 = 0;
|
||||
|
||||
// use colorkeys where appropriate
|
||||
if (src->flags & SDL_SRCCOLORKEY)
|
||||
ck0 = src->format->colorkey;
|
||||
if (mipmap->flags & SDL_SRCCOLORKEY)
|
||||
ck1 = mipmap->format->colorkey;
|
||||
|
||||
SDL_LockSurface(src);
|
||||
SDL_LockSurface(dst);
|
||||
SDL_LockSurface(mipmap);
|
||||
|
||||
for (y = 0; y < h; ++y)
|
||||
{
|
||||
Uint32 *dst_p = (Uint32 *)dst->pixels + y * dst->w;
|
||||
Uint32 *src_a0 = (Uint32 *)src->pixels + (sy0 >> 16) * src->w;
|
||||
Uint32 *src_a1 = (Uint32 *)mipmap->pixels + (sy1 >> 16) * mipmap->w;
|
||||
|
||||
for (x = 0; x < w; ++x)
|
||||
{
|
||||
Uint8 u0 = (sx0 >> 8) & 0xff;
|
||||
Uint8 u1 = (sx1 >> 8) & 0xff;
|
||||
Uint8 v0 = (sy0 >> 8) & 0xff;
|
||||
Uint8 v1 = (sy1 >> 8) & 0xff;
|
||||
Uint8 ul0 = btable[255 - u0][255 - v0];
|
||||
Uint8 ul1 = btable[255 - u1][255 - v1];
|
||||
Uint8 ur0 = btable[u0][255 - v0];
|
||||
Uint8 ur1 = btable[u1][255 - v1];
|
||||
Uint8 ll0 = btable[255 - u0][v0];
|
||||
Uint8 ll1 = btable[255 - u1][v1];
|
||||
Uint8 lr0 = btable[u0][v0];
|
||||
Uint8 lr1 = btable[u1][v1];
|
||||
|
||||
Uint8 r0[5], r1[5], g0[5], g1[5], b0[5], b1[5], a0[5], a1[5];
|
||||
|
||||
Uint32 *src_p0 = src_a0 + (sx0 >> 16);
|
||||
Uint32 *src_p1 = src_a1 + (sx1 >> 16);
|
||||
|
||||
if ((sx0 >> 16) <= src->w - 2)
|
||||
{
|
||||
SDL_GetRGBA (*src_p0, src->format, &r0[0], &g0[0], &b0[0], &a0[0]);
|
||||
SDL_GetRGBA (*(src_p0 + 1), src->format, &r0[1], &g0[1], &b0[1], &a0[1]);
|
||||
if (src_p0[0] == ck0)
|
||||
a0[0] = 0;
|
||||
if (src_p0[1] == ck0)
|
||||
a0[1] = 0;
|
||||
|
||||
if ((sy0 >> 16) <= src->h - 2)
|
||||
{
|
||||
SDL_GetRGBA (*(src_p0 + src->w), src->format, &r0[2], &g0[2], &b0[2], &a0[2]);
|
||||
SDL_GetRGBA (*(src_p0 + src->w + 1), src->format, &r0[3], &g0[3], &b0[3], &a0[3]);
|
||||
if (src_p0[src->w] == ck0)
|
||||
a0[2] = 0;
|
||||
if (src_p0[src->w + 1] == ck0)
|
||||
a0[3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
r0[2] = r0[0];
|
||||
g0[2] = g0[0];
|
||||
b0[2] = b0[0];
|
||||
a0[2] = a0[0];
|
||||
r0[3] = r0[1];
|
||||
g0[3] = g0[1];
|
||||
b0[3] = b0[1];
|
||||
a0[3] = a0[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_GetRGBA (*src_p0, src->format, &r0[0], &g0[0], &b0[0], &a0[0]);
|
||||
if (src_p0[0] == ck0)
|
||||
a0[0] = 0;
|
||||
r0[1] = r0[0];
|
||||
g0[1] = g0[0];
|
||||
b0[1] = b0[0];
|
||||
a0[1] = a0[0];
|
||||
if ((sy0 >> 16) <= src->h - 2)
|
||||
{
|
||||
SDL_GetRGBA (*(src_p0 + src->w), src->format, &r0[2], &g0[2], &b0[2], &a0[2]);
|
||||
if (src_p0[src->w] == ck0)
|
||||
a0[2] = 0;
|
||||
r0[3] = r0[2];
|
||||
g0[3] = g0[2];
|
||||
b0[3] = b0[2];
|
||||
a0[3] = a0[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
r0[2] = r0[3] = r0[0];
|
||||
g0[2] = g0[3] = g0[0];
|
||||
b0[2] = b0[3] = b0[0];
|
||||
a0[2] = a0[3] = a0[0];
|
||||
}
|
||||
}
|
||||
|
||||
if ((sx1 >> 16) <= mipmap->w - 2)
|
||||
{
|
||||
SDL_GetRGBA (*src_p1, mipmap->format, &r1[0], &g1[0], &b1[0], &a1[0]);
|
||||
SDL_GetRGBA (*(src_p1 + 1), mipmap->format, &r1[1], &g1[1], &b1[1], &a1[1]);
|
||||
if (src_p1[0] == ck1)
|
||||
a1[0] = 0;
|
||||
if (src_p1[1] == ck1)
|
||||
a1[1] = 0;
|
||||
|
||||
if ((sy1 >> 16) <= mipmap->h - 2)
|
||||
{
|
||||
SDL_GetRGBA (*(src_p1 + mipmap->w) , mipmap->format, &r1[2], &g1[2], &b1[2], &a1[2]);
|
||||
SDL_GetRGBA (*(src_p1 + mipmap->w + 1), mipmap->format, &r1[3], &g1[3], &b1[3], &a1[3]);
|
||||
if (src_p1[mipmap->w] == ck1)
|
||||
a1[2] = 0;
|
||||
if (src_p1[mipmap->w + 1] == ck1)
|
||||
a1[3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
r1[2] = r1[0];
|
||||
g1[2] = g1[0];
|
||||
b1[2] = b1[0];
|
||||
a1[2] = a1[0];
|
||||
r1[3] = r1[1];
|
||||
g1[3] = g1[1];
|
||||
b1[3] = b1[1];
|
||||
a1[3] = a1[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_GetRGBA (*src_p1, mipmap->format, &r1[0], &g1[0], &b1[0], &a1[0]);
|
||||
if (src_p1[0] == ck1)
|
||||
a1[0] = 0;
|
||||
r1[1] = r1[0];
|
||||
g1[1] = g1[0];
|
||||
b1[1] = b1[0];
|
||||
a1[1] = a1[0];
|
||||
if ((sy1 >> 16) <= mipmap->h - 2)
|
||||
{
|
||||
SDL_GetRGBA (*(src_p1 + mipmap->w), mipmap->format, &r1[2], &g1[2], &b1[2], &a1[2]);
|
||||
if (src_p1[mipmap->w] == ck1)
|
||||
a1[2] = 0;
|
||||
r1[3] = r1[2];
|
||||
g1[3] = g1[2];
|
||||
b1[3] = b1[2];
|
||||
a1[3] = a1[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
r1[2] = r1[3] = r1[0];
|
||||
g1[2] = g1[3] = g1[0];
|
||||
b1[2] = b1[3] = b1[0];
|
||||
a1[2] = a1[3] = a1[0];
|
||||
}
|
||||
}
|
||||
|
||||
a0[4] = ((ul0 * a0[0]) >> 8) + ((ur0 * a0[1]) >> 8) + ((ll0 * a0[2]) >> 8) + ((lr0 * a0[3]) >> 8);
|
||||
a1[4] = ((ul1 * a1[0]) >> 8) + ((ur1 * a1[1]) >> 8) + ((ll1 * a1[2]) >> 8) + ((lr1 * a1[3]) >> 8);
|
||||
|
||||
if ((((a0[4] - a1[4]) * ratio) >> 8) + a1[4] > ALPHA_THRESHOLD)
|
||||
{
|
||||
r0[4] = ((ul0 * r0[0]) >> 8) + ((ur0 * r0[1]) >> 8) + ((ll0 * r0[2]) >> 8) + ((lr0 * r0[3]) >> 8);
|
||||
g0[4] = ((ul0 * g0[0]) >> 8) + ((ur0 * g0[1]) >> 8) + ((ll0 * g0[2]) >> 8) + ((lr0 * g0[3]) >> 8);
|
||||
b0[4] = ((ul0 * b0[0]) >> 8) + ((ur0 * b0[1]) >> 8) + ((ll0 * b0[2]) >> 8) + ((lr0 * b0[3]) >> 8);
|
||||
|
||||
r1[4] = ((ul1 * r1[0]) >> 8) + ((ur1 * r1[1]) >> 8) + ((ll1 * r1[2]) >> 8) + ((lr1 * r1[3]) >> 8);
|
||||
g1[4] = ((ul1 * g1[0]) >> 8) + ((ur1 * g1[1]) >> 8) + ((ll1 * g1[2]) >> 8) + ((lr1 * g1[3]) >> 8);
|
||||
b1[4] = ((ul1 * b1[0]) >> 8) + ((ur1 * b1[1]) >> 8) + ((ll1 * b1[2]) >> 8) + ((lr1 * b1[3]) >> 8);
|
||||
|
||||
*dst_p++ =
|
||||
(((((r0[4] - r1[4]) * ratio) >> 8) + r1[4]) << dstfmt->Rshift) |
|
||||
(((((g0[4] - g1[4]) * ratio) >> 8) + g1[4]) << dstfmt->Gshift) |
|
||||
(((((b0[4] - b1[4]) * ratio) >> 8) + b1[4]) << dstfmt->Bshift) |
|
||||
dstopaque;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst_p++ = dsttransparent;
|
||||
}
|
||||
|
||||
sx0 += fsx0;
|
||||
sx1 += fsx1;
|
||||
}
|
||||
sx0 = sx1 = 0;
|
||||
sy0 += fsy0;
|
||||
sy1 += fsy1;
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(mipmap);
|
||||
SDL_UnlockSurface(dst);
|
||||
SDL_UnlockSurface(src);
|
||||
}
|
||||
else
|
||||
if ((srcfmt->BytesPerPixel != 1 && srcfmt->BytesPerPixel != 4) ||
|
||||
(mmfmt->BytesPerPixel != 1 && mmfmt->BytesPerPixel != 4) ||
|
||||
(dst->format->BytesPerPixel != 4))
|
||||
{
|
||||
fprintf (stderr, "Tried to deal with unknown BPP: %d -> %d, mipmap %d\n",
|
||||
src->format->BitsPerPixel, dst->format->BitsPerPixel, mipmap->format->BitsPerPixel);
|
||||
srcfmt->BitsPerPixel, dst->format->BitsPerPixel, mmfmt->BitsPerPixel);
|
||||
}
|
||||
|
||||
// use colorkeys where appropriate
|
||||
if (srcfmt->Amask)
|
||||
{ // alpha transparency
|
||||
mk0 = srcfmt->Amask;
|
||||
ck0 = 0;
|
||||
}
|
||||
else if (src->flags & SDL_SRCCOLORKEY)
|
||||
{ // colorkey transparency
|
||||
mk0 = ~srcfmt->Amask;
|
||||
ck0 = srcfmt->colorkey & mk0;
|
||||
}
|
||||
|
||||
if (mmfmt->Amask)
|
||||
{ // alpha transparency
|
||||
mk1 = mmfmt->Amask;
|
||||
ck1 = 0;
|
||||
}
|
||||
else if (mipmap->flags & SDL_SRCCOLORKEY)
|
||||
{ // colorkey transparency
|
||||
mk1 = ~mmfmt->Amask;
|
||||
ck1 = mmfmt->colorkey & mk1;
|
||||
}
|
||||
|
||||
SDL_LockSurface(src);
|
||||
SDL_LockSurface(dst);
|
||||
SDL_LockSurface(mipmap);
|
||||
|
||||
for (y = 0, sy0 = ssy0, sy1 = ssy1;
|
||||
y < h;
|
||||
++y, sy0 += fsy0, sy1 += fsy1)
|
||||
{
|
||||
Uint32 *dst_p = (Uint32 *) ((Uint8*)dst->pixels + y * dst->pitch);
|
||||
Uint8 *src_a0 = (Uint8*)src->pixels + (sy0 >> 16) * slen;
|
||||
Uint8 *src_a1 = (Uint8*)mipmap->pixels + (sy1 >> 16) * mmlen;
|
||||
// retrieve the fractional portions of y
|
||||
const Uint8 v0 = (sy0 >> 8) & 0xff;
|
||||
const Uint8 v1 = (sy1 >> 8) & 0xff;
|
||||
Uint8 w0[4], w1[4]; // pixel weight vectors
|
||||
|
||||
for (x = 0, sx0 = ssx0, sx1 = ssx1;
|
||||
x < w;
|
||||
++x, ++dst_p, sx0 += fsx0, sx1 += fsx1)
|
||||
{
|
||||
Uint8 *src_p0 = src_a0 + (sx0 >> 16) * sbpp;
|
||||
Uint8 *src_p1 = src_a1 + (sx1 >> 16) * mmbpp;
|
||||
// retrieve the fractional portions of x
|
||||
const Uint8 u0 = (sx0 >> 8) & 0xff;
|
||||
const Uint8 u1 = (sx1 >> 8) & 0xff;
|
||||
// pixels are examined and numbered in pattern
|
||||
// 0 1
|
||||
// 2 3
|
||||
// the ideal pixel (4) is somewhere between these four
|
||||
// and is calculated from these using weight vector (w)
|
||||
// with a dot product
|
||||
pixel_t p0[5], p1[5];
|
||||
Uint8 res_a;
|
||||
|
||||
w0[0] = btable[255 - u0][255 - v0];
|
||||
w0[1] = btable[u0][255 - v0];
|
||||
w0[2] = btable[255 - u0][v0];
|
||||
w0[3] = btable[u0][v0];
|
||||
w1[0] = btable[255 - u1][255 - v1];
|
||||
w1[1] = btable[u1][255 - v1];
|
||||
w1[2] = btable[255 - u1][v1];
|
||||
w1[3] = btable[u1][v1];
|
||||
|
||||
// collect interesting pixels from src image
|
||||
p0[0].value = tri_get_pixel (src_p0, srcfmt, srcpal, mk0, ck0);
|
||||
|
||||
if ((sx0 >> 16) <= src->w - 2)
|
||||
{
|
||||
p0[1].value = tri_get_pixel (src_p0 + sbpp,
|
||||
srcfmt, srcpal, mk0, ck0);
|
||||
|
||||
if ((sy0 >> 16) <= src->h - 2)
|
||||
{
|
||||
p0[2].value = tri_get_pixel (src_p0 + slen,
|
||||
srcfmt, srcpal, mk0, ck0);
|
||||
p0[3].value = tri_get_pixel (src_p0 + slen + sbpp,
|
||||
srcfmt, srcpal, mk0, ck0);
|
||||
}
|
||||
else
|
||||
{
|
||||
p0[2].value = p0[0].value;
|
||||
p0[3].value = p0[1].value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p0[1].value = p0[0].value;
|
||||
if ((sy0 >> 16) <= src->h - 2)
|
||||
{
|
||||
p0[2].value = tri_get_pixel (src_p0 + slen,
|
||||
srcfmt, srcpal, mk0, ck0);
|
||||
}
|
||||
else
|
||||
{
|
||||
p0[2].value = p0[0].value;
|
||||
}
|
||||
p0[3].value = p0[2].value;
|
||||
}
|
||||
|
||||
// collect interesting pixels from mipmap image
|
||||
p1[0].value = tri_get_pixel (src_p1, mmfmt, mmpal, mk1, ck1);
|
||||
|
||||
if ((sx1 >> 16) <= mipmap->w - 2)
|
||||
{
|
||||
p1[1].value = tri_get_pixel (src_p1 + mmbpp,
|
||||
mmfmt, mmpal, mk1, ck1);
|
||||
|
||||
if ((sy1 >> 16) <= mipmap->h - 2)
|
||||
{
|
||||
p1[2].value = tri_get_pixel (src_p1 + mmlen,
|
||||
mmfmt, mmpal, mk1, ck1);
|
||||
p1[3].value = tri_get_pixel (src_p1 + mmlen + mmbpp,
|
||||
mmfmt, mmpal, mk1, ck1);
|
||||
}
|
||||
else
|
||||
{
|
||||
p1[2].value = p1[0].value;
|
||||
p1[3].value = p1[1].value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p1[1].value = p1[0].value;
|
||||
if ((sy1 >> 16) <= mipmap->h - 2)
|
||||
{
|
||||
p1[2].value = tri_get_pixel (src_p1 + mmlen,
|
||||
mmfmt, mmpal, mk1, ck1);
|
||||
}
|
||||
else
|
||||
{
|
||||
p1[2].value = p1[0].value;
|
||||
}
|
||||
p1[3].value = p1[2].value;
|
||||
}
|
||||
|
||||
p0[4].c.a = dot_product_8_4 (p0, 3, w0);
|
||||
p1[4].c.a = dot_product_8_4 (p1, 3, w1);
|
||||
|
||||
res_a = blend_ratio_2 (p0[4].c.a, p1[4].c.a, ratio);
|
||||
|
||||
if (res_a <= alpha_threshold)
|
||||
{
|
||||
*dst_p = transparent;
|
||||
}
|
||||
else if (!dst_has_alpha)
|
||||
{ // RGB surface handling
|
||||
p0[4].c.r = dot_product_8_4 (p0, 0, w0);
|
||||
p0[4].c.g = dot_product_8_4 (p0, 1, w0);
|
||||
p0[4].c.b = dot_product_8_4 (p0, 2, w0);
|
||||
|
||||
p1[4].c.r = dot_product_8_4 (p1, 0, w1);
|
||||
p1[4].c.g = dot_product_8_4 (p1, 1, w1);
|
||||
p1[4].c.b = dot_product_8_4 (p1, 2, w1);
|
||||
|
||||
p0[4].c.r = blend_ratio_2 (p0[4].c.r, p1[4].c.r, ratio);
|
||||
p0[4].c.g = blend_ratio_2 (p0[4].c.g, p1[4].c.g, ratio);
|
||||
p0[4].c.b = blend_ratio_2 (p0[4].c.b, p1[4].c.b, ratio);
|
||||
|
||||
*dst_p =
|
||||
(p0[4].c.r << dstfmt->Rshift) |
|
||||
(p0[4].c.g << dstfmt->Gshift) |
|
||||
(p0[4].c.b << dstfmt->Bshift);
|
||||
}
|
||||
else
|
||||
{ // RGBA surface handling
|
||||
|
||||
// we do not want to blend with non-present pixels
|
||||
// (pixels that have alpha == 0) as these will
|
||||
// skew the result and make resulting alpha useless
|
||||
if (p0[4].c.a != 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i)
|
||||
if (p0[i].c.a == 0)
|
||||
w0[i] = 0;
|
||||
|
||||
p0[4].c.r = weight_product_8_4 (p0, 0, w0);
|
||||
p0[4].c.g = weight_product_8_4 (p0, 1, w0);
|
||||
p0[4].c.b = weight_product_8_4 (p0, 2, w0);
|
||||
}
|
||||
if (p1[4].c.a != 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i)
|
||||
if (p1[i].c.a == 0)
|
||||
w1[i] = 0;
|
||||
|
||||
p1[4].c.r = weight_product_8_4 (p1, 0, w1);
|
||||
p1[4].c.g = weight_product_8_4 (p1, 1, w1);
|
||||
p1[4].c.b = weight_product_8_4 (p1, 2, w1);
|
||||
}
|
||||
|
||||
if (p0[4].c.a != 0 && p1[4].c.a != 0)
|
||||
{ // blend if both present
|
||||
p0[4].c.r = blend_ratio_2 (p0[4].c.r, p1[4].c.r, ratio);
|
||||
p0[4].c.g = blend_ratio_2 (p0[4].c.g, p1[4].c.g, ratio);
|
||||
p0[4].c.b = blend_ratio_2 (p0[4].c.b, p1[4].c.b, ratio);
|
||||
}
|
||||
else if (p1[4].c.a != 0)
|
||||
{ // other pixel is present
|
||||
p0[4].value = p1[4].value;
|
||||
}
|
||||
|
||||
// error-correct alpha to fully opaque to remove
|
||||
// the often unwanted and unnecessary blending
|
||||
if (res_a > 0xf8)
|
||||
res_a = 0xff;
|
||||
|
||||
*dst_p =
|
||||
(p0[4].c.r << dstfmt->Rshift) |
|
||||
(p0[4].c.g << dstfmt->Gshift) |
|
||||
(p0[4].c.b << dstfmt->Bshift) |
|
||||
(res_a << dstfmt->Ashift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(mipmap);
|
||||
SDL_UnlockSurface(dst);
|
||||
SDL_UnlockSurface(src);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user