Melee scaling is now trilinear by default, but it's still possible to

choose nearest neighbour with --meleescale; fixes #34


git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@885 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
gewlitys
2003-03-15 21:40:09 +00:00
parent f9e2747507
commit e6a8d4fe7c
10 changed files with 519 additions and 45 deletions
+2
View File
@@ -1,4 +1,6 @@
Changes towards version 0.3: Changes towards version 0.3:
- Melee scaling is now trilinear by default, but it's still possible to
choose nearest neighbour with --meleescale; fixes #34 -Mika
- Minimum scaling extent is now 1,1; fixes mostly small-objects-disappearing - Minimum scaling extent is now 1,1; fixes mostly small-objects-disappearing
problem in melee, from chmmravatar problem in melee, from chmmravatar
- Fixed a long standing memory leak relating to planet surface -PhracturedBlue - Fixed a long standing memory leak relating to planet surface -PhracturedBlue
+6
View File
@@ -41,6 +41,12 @@ faster as well -- but it also may not work on older cards.
Graphics scaling mode (bilinear, biadapt or biadv). Default is none. Graphics scaling mode (bilinear, biadapt or biadv). Default is none.
Try these to get smoother graphics with cost on performance. Try these to get smoother graphics with cost on performance.
-b (or --meleescale=mode)
Melee scaling mode (nearest or trilinear). Default is trilinear.
Slower machine owners can set it to nearest to get better performance
in melee but degraded visual quality.
-s (or --scanlines) -s (or --scanlines)
Simulates interlaced displays. Simulates interlaced displays.
+2
View File
@@ -22,6 +22,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "libs/graphics/gfx_common.h"
#include "compiler.h" #include "compiler.h"
#include "options.h" #include "options.h"
#include "file.h" #include "file.h"
@@ -32,6 +33,7 @@ int optWhichCoarseScan = OPT_3DO;
int optWhichMenu = OPT_3DO; int optWhichMenu = OPT_3DO;
int optWhichFonts = OPT_PC; int optWhichFonts = OPT_PC;
int optSmoothScroll = OPT_PC; int optSmoothScroll = OPT_PC;
int optMeleeScale = TFB_SCALE_TRILINEAR;
char *configDir, *saveDir, *meleeDir; char *configDir, *saveDir, *meleeDir;
BOOLEAN optSubtitles = TRUE; BOOLEAN optSubtitles = TRUE;
+1
View File
@@ -31,6 +31,7 @@ extern int optWhichCoarseScan;
extern int optWhichMenu; extern int optWhichMenu;
extern int optWhichFonts; extern int optWhichFonts;
extern int optSmoothScroll; extern int optSmoothScroll;
extern int optMeleeScale;
extern BOOLEAN optSubtitles; extern BOOLEAN optSubtitles;
@@ -150,7 +150,7 @@ FRAMEPTR stretch_frame (FRAMEPTR FramePtr, int neww, int newh, int destroy)
dst = NewFrame->image->NormalImg; dst = NewFrame->image->NormalImg;
ext.width = neww; ext.width = neww;
ext.height = newh; ext.height = newh;
TFB_DrawCanvas_Rescale (src, dst, ext); TFB_DrawCanvas_Rescale_Nearest (src, dst, ext);
UnlockMutex (tfbImg->mutex); UnlockMutex (tfbImg->mutex);
if (destroy) if (destroy)
DestroyDrawable (ReleaseDrawable (FramePtr)); DestroyDrawable (ReleaseDrawable (FramePtr));
+454 -16
View File
@@ -3,6 +3,7 @@
#include "libs/graphics/gfx_common.h" #include "libs/graphics/gfx_common.h"
#include "libs/graphics/sdl/primitives.h" #include "libs/graphics/sdl/primitives.h"
#include "libs/graphics/tfb_draw.h" #include "libs/graphics/tfb_draw.h"
#include "options.h"
typedef SDL_Surface *NativeCanvas; typedef SDL_Surface *NativeCanvas;
@@ -50,7 +51,24 @@ TFB_DrawCanvas_Image (TFB_Image *img, int x, int y, int scale, TFB_Palette *pale
if (scale != 0 && scale != GSCALE_IDENTITY) if (scale != 0 && scale != GSCALE_IDENTITY)
{ {
TFB_DrawImage_FixScaling (img, scale); int type;
if (optMeleeScale == TFB_SCALE_TRILINEAR && img->MipmapImg)
{
type = TFB_SCALE_TRILINEAR;
if (palette)
{
if (((SDL_Surface *)img->NormalImg)->format->palette)
SDL_SetColors (img->NormalImg, (SDL_Color*)palette, 0, 256);
if (((SDL_Surface *)img->MipmapImg)->format->palette)
SDL_SetColors (img->MipmapImg, (SDL_Color*)palette, 0, 256);
}
}
else
{
type = TFB_SCALE_NEAREST;
}
TFB_DrawImage_FixScaling (img, scale, type);
surf = img->ScaledImg; surf = img->ScaledImg;
srcRect.x = 0; srcRect.x = 0;
srcRect.y = 0; srcRect.y = 0;
@@ -101,7 +119,7 @@ TFB_DrawCanvas_FilledImage (TFB_Image *img, int x, int y, int scale, int r, int
if (scale != 0 && scale != GSCALE_IDENTITY) if (scale != 0 && scale != GSCALE_IDENTITY)
{ {
TFB_DrawImage_FixScaling (img, scale); TFB_DrawImage_FixScaling (img, scale, TFB_SCALE_NEAREST);
surf = img->ScaledImg; surf = img->ScaledImg;
srcRect.x = 0; srcRect.x = 0;
srcRect.y = 0; srcRect.y = 0;
@@ -163,20 +181,46 @@ TFB_DrawCanvas_New_Paletted (int w, int h, TFB_Palette *palette, int transparent
} }
TFB_Canvas TFB_Canvas
TFB_DrawCanvas_New_ScaleTarget (TFB_Canvas canvas) TFB_DrawCanvas_New_ScaleTarget (TFB_Canvas canvas, TFB_Canvas oldcanvas, int type, int last_type)
{ {
SDL_Surface *src = (SDL_Surface *)canvas; SDL_Surface *src = (SDL_Surface *)canvas;
SDL_Surface *newsurf = SDL_CreateRGBSurface (SDL_SWSURFACE, src->w, SDL_Surface *old = (SDL_Surface *)oldcanvas;
src->h, SDL_Surface *newsurf = old;
src->format->BitsPerPixel,
src->format->Rmask, if (type == TFB_SCALE_NEAREST)
src->format->Gmask,
src->format->Bmask,
src->format->Amask);
if (src->format->palette)
{ {
TFB_DrawCanvas_SetTransparentIndex (newsurf, TFB_DrawCanvas_GetTransparentIndex (src)); if (old && type != last_type)
{
TFB_DrawCanvas_Delete (old);
old = NULL;
}
if (!old)
{
newsurf = SDL_CreateRGBSurface (SDL_SWSURFACE, src->w,
src->h,
src->format->BitsPerPixel,
src->format->Rmask,
src->format->Gmask,
src->format->Bmask,
src->format->Amask);
if (src->format->palette)
TFB_DrawCanvas_SetTransparentIndex (newsurf, TFB_DrawCanvas_GetTransparentIndex (src));
}
} }
else
{
if (old && type != last_type)
{
TFB_DrawCanvas_Delete (old);
old = NULL;
}
if (!old)
{
newsurf = SDL_CreateRGBSurface (SDL_SWSURFACE, src->w, src->h, 32,
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
}
}
return newsurf; return newsurf;
} }
@@ -268,11 +312,31 @@ TFB_DrawCanvas_SetTransparentIndex (TFB_Canvas canvas, int index)
} }
void void
TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, int scale, PEXTENT size) TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, TFB_Canvas src_mipmap, int scale, PEXTENT size)
{ {
SDL_Surface *src = (SDL_Surface *)src_canvas; SDL_Surface *src = (SDL_Surface *)src_canvas;
size->width = (int) (src->w * scale / (float)GSCALE_IDENTITY);
size->height = (int) (src->h * scale / (float)GSCALE_IDENTITY); if (!src_mipmap)
{
size->width = (int) (src->w * scale / (float)GSCALE_IDENTITY);
size->height = (int) (src->h * scale / (float)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;
else if (ratio > 1.0f)
ratio = 1.0f;
size->width = (int)((src->w - mipmap->w) * ratio + mipmap->w);
size->height = (int)((src->h - mipmap->h) * ratio + mipmap->h);
}
if (!size->width && src->w) if (!size->width && src->w)
size->width = 1; size->width = 1;
if (!size->height && src->h) if (!size->height && src->h)
@@ -280,7 +344,7 @@ TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, int scale, PEXTENT size)
} }
void void
TFB_DrawCanvas_Rescale (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, EXTENT size) TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, EXTENT size)
{ {
SDL_Surface *src = (SDL_Surface *)src_canvas; SDL_Surface *src = (SDL_Surface *)src_canvas;
SDL_Surface *dst = (SDL_Surface *)dest_canvas; SDL_Surface *dst = (SDL_Surface *)dest_canvas;
@@ -382,3 +446,377 @@ TFB_DrawCanvas_Rescale (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, EXTENT si
SDL_UnlockSurface (dst); SDL_UnlockSurface (dst);
SDL_UnlockSurface (src); SDL_UnlockSurface (src);
} }
void
TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src_canvas, TFB_Canvas dest_canvas, TFB_Canvas src_mipmap, EXTENT size)
{
// TODO: this can be optimized a lot..
// - make everything integer-only, use lookup tables, read/modify
// pixels directly instead of SDL_GetRGB(), etc.
SDL_Surface *src = (SDL_Surface *)src_canvas;
SDL_Surface *dst = (SDL_Surface *)dest_canvas;
SDL_Surface *mipmap = (SDL_Surface *)src_mipmap;
const int w = size.width, h = size.height;
const int ALPHA_THRESHOLD = 128;
float ratio = ((float)w / src->w) * 2.0f - 1.0f;
float om_ratio;
if (ratio < 0.0f)
ratio = 0.0f;
if (ratio > 1.0f)
ratio = 1.0f;
om_ratio = 1.0f - ratio;
if (size.width > dst->w || size.height > dst->h)
{
fprintf (stderr, "TFB_DrawCanvas_Rescale_Trilinear: Tried to scale image to size %d %d when dest_canvas has only dimensions of %d %d! Failing.\n",
size.width, size.height, dst->w, dst->h);
return;
}
if (src->format->BytesPerPixel == 1 && dst->format->BytesPerPixel == 4 &&
mipmap->format->BytesPerPixel == 1)
{
float fsx0 = (float)src->w / w;
float fsy0 = (float)src->h / h;
float fsx1 = (float)mipmap->w / w;
float fsy1 = (float)mipmap->h / h;
float v0 = 0.0f;
float v1 = 0.0f;
Uint32 ck0 = src->format->colorkey;
Uint32 ck1 = mipmap->format->colorkey;
int x, y;
SDL_LockSurface(src);
SDL_LockSurface(dst);
SDL_LockSurface(mipmap);
for (y = 0; y < h; ++y)
{
float u0 = 0.0f;
float u1 = 0.0f;
int iv0 = (int)v0;
int iv1 = (int)v1;
float decy0 = v0 - iv0;
float decy1 = v1 - iv1;
for (x = 0; x < w; ++x)
{
int iu0 = (int)u0;
int iu1 = (int)u1;
float decx0 = u0 - iu0;
float decx1 = u1 - iu1;
float ul0 = (1.0f - decx0) * (1.0f - decy0);
float ul1 = (1.0f - decx1) * (1.0f - decy1);
float ur0 = decx0 * (1.0f - decy0);
float ur1 = decx1 * (1.0f - decy1);
float ll0 = (1.0f - decx0) * decy0;
float ll1 = (1.0f - decx1) * decy1;
float lr0 = decx0 * decy0;
float lr1 = decx1 * decy1;
Uint8 r0[5], r1[5], g0[5], g1[5], b0[5], b1[5], a0[5], a1[5];
Uint8 c;
Uint8 *src_p0 = (Uint8 *)src->pixels + iv0 * src->pitch + iu0;
Uint8 *src_p1 = (Uint8 *)mipmap->pixels + iv1 * mipmap->pitch + iu1;
Uint32 *dst_p = (Uint32 *)dst->pixels + y * dst->w + x;
if (iu0 <= src->w - 2)
{
a0[0] = ((c = *src_p0) == ck0) ? 0 : 255;
SDL_GetRGB (c, src->format, &r0[0], &g0[0], &b0[0]);
a0[1] = ((c = *(src_p0 + 1)) == ck0) ? 0 : 255;
SDL_GetRGB (c, src->format, &r0[1], &g0[1], &b0[1]);
if (iv0 <= src->h - 2)
{
a0[2] = ((c = *(src_p0 + src->pitch)) == ck0) ? 0 : 255;
SDL_GetRGB (c, src->format, &r0[2], &g0[2], &b0[2]);
a0[3] = ((c = *(src_p0 + src->pitch + 1)) == ck0) ? 0 : 255;
SDL_GetRGB (c, src->format, &r0[3], &g0[3], &b0[3]);
}
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
{
a0[0] = ((c = *src_p0) == ck0) ? 0 : 255;
SDL_GetRGB (c, src->format, &r0[0], &g0[0], &b0[0]);
r0[1] = r0[0];
g0[1] = g0[0];
b0[1] = b0[0];
a0[1] = a0[0];
if (iv0 <= src->h - 2)
{
a0[2] = ((c = *(src_p0 + src->pitch)) == ck0) ? 0 : 255;
SDL_GetRGB (c, src->format, &r0[2], &g0[2], &b0[2]);
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 (iu1 <= mipmap->w - 2)
{
a1[0] = ((c = *src_p1) == ck1) ? 0 : 255;
SDL_GetRGB (c, mipmap->format, &r1[0], &g1[0], &b1[0]);
a1[1] = ((c = *(src_p1 + 1)) == ck1) ? 0 : 255;
SDL_GetRGB (c, mipmap->format, &r1[1], &g1[1], &b1[1]);
if (iv1 <= mipmap->h - 2)
{
a1[2] = ((c = *(src_p1 + mipmap->pitch)) == ck1) ? 0 : 255;
SDL_GetRGB (c, mipmap->format, &r1[2], &g1[2], &b1[2]);
a1[3] = ((c = *(src_p1 + mipmap->pitch + 1)) == ck1) ? 0 : 255;
SDL_GetRGB (c, mipmap->format, &r1[3], &g1[3], &b1[3]);
}
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
{
a1[0] = ((c = *src_p1) == ck1) ? 0 : 255;
SDL_GetRGB (c, mipmap->format, &r1[0], &g1[0], &b1[0]);
r1[1] = r1[0];
g1[1] = g1[0];
b1[1] = b1[0];
a1[1] = a1[0];
if (iv1 <= mipmap->h - 2)
{
a1[2] = ((c = *(src_p1 + mipmap->pitch)) == ck1) ? 0 : 255;
SDL_GetRGB (c, mipmap->format, &r1[2], &g1[2], &b1[2]);
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];
}
}
r0[4] = (Uint8)(ul0 * r0[0] + ur0 * r0[1] + ll0 * r0[2] + lr0 * r0[3]);
g0[4] = (Uint8)(ul0 * g0[0] + ur0 * g0[1] + ll0 * g0[2] + lr0 * g0[3]);
b0[4] = (Uint8)(ul0 * b0[0] + ur0 * b0[1] + ll0 * b0[2] + lr0 * b0[3]);
a0[4] = (Uint8)(ul0 * a0[0] + ur0 * a0[1] + ll0 * a0[2] + lr0 * a0[3]);
r1[4] = (Uint8)(ul1 * r1[0] + ur1 * r1[1] + ll1 * r1[2] + lr1 * r1[3]);
g1[4] = (Uint8)(ul1 * g1[0] + ur1 * g1[1] + ll1 * g1[2] + lr1 * g1[3]);
b1[4] = (Uint8)(ul1 * b1[0] + ur1 * b1[1] + ll1 * b1[2] + lr1 * b1[3]);
a1[4] = (Uint8)(ul1 * a1[0] + ur1 * a1[1] + ll1 * a1[2] + lr1 * a1[3]);
*dst_p = SDL_MapRGBA(dst->format,
(Uint8)(ratio * r0[4] + om_ratio * r1[4]),
(Uint8)(ratio * g0[4] + om_ratio * g1[4]),
(Uint8)(ratio * b0[4] + om_ratio * b1[4]),
(Uint8)((ratio * a0[4] + om_ratio * a1[4]) > ALPHA_THRESHOLD ? 255 : 0));
u0 += fsx0;
u1 += fsx1;
}
v0 += fsy0;
v1 += fsy1;
}
SDL_UnlockSurface(mipmap);
SDL_UnlockSurface(dst);
SDL_UnlockSurface(src);
}
else if (src->format->BytesPerPixel == 4 && dst->format->BytesPerPixel == 4 &&
mipmap->format->BytesPerPixel == 4)
{
float fsx0 = (float)src->w / w;
float fsy0 = (float)src->h / h;
float fsx1 = (float)mipmap->w / w;
float fsy1 = (float)mipmap->h / h;
float v0 = 0.0f;
float v1 = 0.0f;
int x, y;
SDL_LockSurface(src);
SDL_LockSurface(dst);
SDL_LockSurface(mipmap);
for (y = 0; y < h; ++y)
{
float u0 = 0.0f;
float u1 = 0.0f;
int iv0 = (int)v0;
int iv1 = (int)v1;
float decy0 = v0 - iv0;
float decy1 = v1 - iv1;
for (x = 0; x < w; ++x)
{
int iu0 = (int)u0;
int iu1 = (int)u1;
float decx0 = u0 - iu0;
float decx1 = u1 - iu1;
float ul0 = (1.0f - decx0) * (1.0f - decy0);
float ul1 = (1.0f - decx1) * (1.0f - decy1);
float ur0 = decx0 * (1.0f - decy0);
float ur1 = decx1 * (1.0f - decy1);
float ll0 = (1.0f - decx0) * decy0;
float ll1 = (1.0f - decx1) * decy1;
float lr0 = decx0 * decy0;
float lr1 = decx1 * decy1;
Uint8 r0[5], r1[5], g0[5], g1[5], b0[5], b1[5], a0[5], a1[5];
Uint32 *src_p0 = (Uint32 *)src->pixels + iv0 * src->w + iu0;
Uint32 *src_p1 = (Uint32 *)mipmap->pixels + iv1 * mipmap->w + iu1;
Uint32 *dst_p = (Uint32 *)dst->pixels + y * dst->w + x;
if (iu0 <= 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 (iv0 <= 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]);
}
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]);
r0[1] = r0[0];
g0[1] = g0[0];
b0[1] = b0[0];
a0[1] = a0[0];
if (iv0 <= src->h - 2)
{
SDL_GetRGBA (*(src_p0 + src->w), src->format, &r0[2], &g0[2], &b0[2], &a0[2]);
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 (iu1 <= 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 (iv1 <= 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]);
}
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]);
r1[1] = r1[0];
g1[1] = g1[0];
b1[1] = b1[0];
a1[1] = a1[0];
if (iv1 <= mipmap->h - 2)
{
SDL_GetRGBA (*(src_p1 + mipmap->w), mipmap->format, &r1[2], &g1[2], &b1[2], &a1[2]);
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];
}
}
r0[4] = (Uint8)(ul0 * r0[0] + ur0 * r0[1] + ll0 * r0[2] + lr0 * r0[3]);
g0[4] = (Uint8)(ul0 * g0[0] + ur0 * g0[1] + ll0 * g0[2] + lr0 * g0[3]);
b0[4] = (Uint8)(ul0 * b0[0] + ur0 * b0[1] + ll0 * b0[2] + lr0 * b0[3]);
a0[4] = (Uint8)(ul0 * a0[0] + ur0 * a0[1] + ll0 * a0[2] + lr0 * a0[3]);
r1[4] = (Uint8)(ul1 * r1[0] + ur1 * r1[1] + ll1 * r1[2] + lr1 * r1[3]);
g1[4] = (Uint8)(ul1 * g1[0] + ur1 * g1[1] + ll1 * g1[2] + lr1 * g1[3]);
b1[4] = (Uint8)(ul1 * b1[0] + ur1 * b1[1] + ll1 * b1[2] + lr1 * b1[3]);
a1[4] = (Uint8)(ul1 * a1[0] + ur1 * a1[1] + ll1 * a1[2] + lr1 * a1[3]);
*dst_p = SDL_MapRGBA(dst->format,
(Uint8)(ratio * r0[4] + om_ratio * r1[4]),
(Uint8)(ratio * g0[4] + om_ratio * g1[4]),
(Uint8)(ratio * b0[4] + om_ratio * b1[4]),
(Uint8)((ratio * a0[4] + om_ratio * a1[4]) > ALPHA_THRESHOLD ? 255 : 0));
u0 += fsx0;
u1 += fsx1;
}
v0 += fsy0;
v1 += fsy1;
}
SDL_UnlockSurface(mipmap);
SDL_UnlockSurface(dst);
SDL_UnlockSurface(src);
}
else
{
fprintf (stderr, "Tried to deal with unknown BPP: %d -> %d, mipmap %d\n",
src->format->BitsPerPixel, dst->format->BitsPerPixel, mipmap->format->BitsPerPixel);
}
}
+14 -18
View File
@@ -86,7 +86,6 @@ TFB_DrawScreen_Image (TFB_Image *img, int x, int y, int scale, TFB_Palette *pale
DC.data.image.y = y; DC.data.image.y = y;
DC.data.image.scale = (scale == GSCALE_IDENTITY) ? 0 : scale; DC.data.image.scale = (scale == GSCALE_IDENTITY) ? 0 : scale;
if (palette != NULL) if (palette != NULL)
{ {
int i, changed; int i, changed;
@@ -250,7 +249,9 @@ TFB_DrawImage_New (TFB_Canvas canvas)
TFB_Image *img = HMalloc (sizeof (TFB_Image)); TFB_Image *img = HMalloc (sizeof (TFB_Image));
img->mutex = CreateMutex (); img->mutex = CreateMutex ();
img->ScaledImg = NULL; img->ScaledImg = NULL;
img->MipmapImg = NULL;
img->colormap_index = -1; img->colormap_index = -1;
img->last_scale_type = -1;
img->Palette = TFB_DrawCanvas_ExtractPalette (canvas); img->Palette = TFB_DrawCanvas_ExtractPalette (canvas);
@@ -293,29 +294,24 @@ TFB_DrawImage_Delete (TFB_Image *image)
} }
void void
TFB_DrawImage_FixScaling (TFB_Image *image, int target) TFB_DrawImage_FixScaling (TFB_Image *image, int target, int type)
{ {
EXTENT old = image->extent; EXTENT old = image->extent;
TFB_DrawCanvas_GetScaledExtent (image->NormalImg, target, &image->extent); TFB_DrawCanvas_GetScaledExtent (image->NormalImg, image->MipmapImg, target, &image->extent);
if ((old.width != image->extent.width) || (old.height != image->extent.height) || if ((old.width != image->extent.width) || (old.height != image->extent.height) ||
image->dirty || !image->ScaledImg) image->dirty || !image->ScaledImg || type != image->last_scale_type)
{ {
image->dirty = FALSE; image->dirty = FALSE;
if (!image->ScaledImg) image->ScaledImg = TFB_DrawCanvas_New_ScaleTarget (image->NormalImg,
image->ScaledImg = TFB_DrawCanvas_New_ScaleTarget (image->NormalImg); image->ScaledImg, type, image->last_scale_type);
TFB_DrawCanvas_Rescale (image->NormalImg, image->ScaledImg, image->extent); image->last_scale_type = type;
}
/*
if (TFB_DrawCanvas_IsPaletted (image->ScaledImg))
{
int colorkey = TFB_DrawCanvas_GetTransparentIndex (image->NormalImg);
TFB_DrawCanvas_SetPalette (image->ScaledImg, image->Palette); if (type == TFB_SCALE_NEAREST)
if (colorkey != -1) TFB_DrawCanvas_Rescale_Nearest (image->NormalImg, image->ScaledImg,
{ image->extent);
TFB_DrawCanvas_SetTransparentIndex (image->ScaledImg, colorkey); else
} TFB_DrawCanvas_Rescale_Trilinear (image->NormalImg, image->ScaledImg,
image->MipmapImg, image->extent);
} }
*/
} }
+12 -6
View File
@@ -31,6 +31,11 @@ typedef enum {
TFB_GFX_NUMSCREENS TFB_GFX_NUMSCREENS
} SCREEN; } SCREEN;
typedef enum {
TFB_SCALE_NEAREST,
TFB_SCALE_TRILINEAR
} SCALE;
typedef struct tfb_palette typedef struct tfb_palette
{ {
UBYTE r; UBYTE r;
@@ -43,8 +48,10 @@ typedef struct tfb_image
{ {
TFB_Canvas NormalImg; TFB_Canvas NormalImg;
TFB_Canvas ScaledImg; TFB_Canvas ScaledImg;
TFB_Canvas MipmapImg;
TFB_Palette *Palette; TFB_Palette *Palette;
int colormap_index; int colormap_index;
int last_scale_type;
EXTENT extent; EXTENT extent;
Mutex mutex; Mutex mutex;
BOOLEAN dirty; BOOLEAN dirty;
@@ -66,7 +73,7 @@ void TFB_FlushPaletteCache (void);
TFB_Image *TFB_DrawImage_New (TFB_Canvas canvas); TFB_Image *TFB_DrawImage_New (TFB_Canvas canvas);
void TFB_DrawImage_Delete (TFB_Image *image); void TFB_DrawImage_Delete (TFB_Image *image);
void TFB_DrawImage_FixScaling (TFB_Image *image, int target); void TFB_DrawImage_FixScaling (TFB_Image *image, int target, int type);
void TFB_DrawImage_Line (int x1, int y1, int x2, int y2, int r, int g, int b, TFB_Image *dest); void TFB_DrawImage_Line (int x1, int y1, int x2, int y2, int r, int g, int b, TFB_Image *dest);
void TFB_DrawImage_Rect (PRECT rect, int r, int g, int b, TFB_Image *image); void TFB_DrawImage_Rect (PRECT rect, int r, int g, int b, TFB_Image *image);
@@ -75,13 +82,12 @@ void TFB_DrawImage_FilledImage (TFB_Image *img, int x, int y, int scale, int r,
TFB_Canvas TFB_DrawCanvas_New_TrueColor (int w, int h, BOOLEAN hasalpha); TFB_Canvas TFB_DrawCanvas_New_TrueColor (int w, int h, BOOLEAN hasalpha);
TFB_Canvas TFB_DrawCanvas_New_Paletted (int w, int h, TFB_Palette *palette, int transparent_index); TFB_Canvas TFB_DrawCanvas_New_Paletted (int w, int h, TFB_Palette *palette, int transparent_index);
TFB_Canvas TFB_DrawCanvas_New_Scaled (TFB_Canvas src, int scale); TFB_Canvas TFB_DrawCanvas_New_ScaleTarget (TFB_Canvas canvas, TFB_Canvas oldcanvas, int type, int last_type);
TFB_Canvas TFB_DrawCanvas_New_ScaleTarget (TFB_Canvas canvas);
TFB_Canvas TFB_DrawCanvas_ToScreenFormat (TFB_Canvas canvas); TFB_Canvas TFB_DrawCanvas_ToScreenFormat (TFB_Canvas canvas);
BOOLEAN TFB_DrawCanvas_IsPaletted (TFB_Canvas canvas); BOOLEAN TFB_DrawCanvas_IsPaletted (TFB_Canvas canvas);
void TFB_DrawCanvas_Rescale (TFB_Canvas src, TFB_Canvas dst, EXTENT size); void TFB_DrawCanvas_Rescale_Nearest (TFB_Canvas src, TFB_Canvas dst, EXTENT size);
void TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, int scale, PEXTENT size); void TFB_DrawCanvas_Rescale_Trilinear (TFB_Canvas src, TFB_Canvas dst, TFB_Canvas mipmap, EXTENT size);
void TFB_DrawCanvas_GetScaledExtent (TFB_Canvas src_canvas, TFB_Canvas src_mipmap, int scale, PEXTENT size);
void TFB_DrawCanvas_Delete (TFB_Canvas canvas); void TFB_DrawCanvas_Delete (TFB_Canvas canvas);
+15
View File
@@ -18,6 +18,7 @@
#include "starcon.h" #include "starcon.h"
#include "libs/graphics/gfx_common.h" #include "libs/graphics/gfx_common.h"
#include "libs/graphics/drawable.h"
COUNT DisplayFreeList; COUNT DisplayFreeList;
PRIMITIVE DisplayArray[MAX_DISPLAY_PRIMS]; PRIMITIVE DisplayArray[MAX_DISPLAY_PRIMS];
@@ -980,6 +981,20 @@ PostProcessQueue (register VIEW_STATE view_state, register SIZE scroll_x,
[index], [index],
ElementPtr->next.image.frame); ElementPtr->next.image.frame);
#endif /* SAFE */ #endif /* SAFE */
if (index < 2 && scale != 256)
{
// assigns next (smaller) zoom level image as mipmap, needed for trilinear scaling
((PFRAME_DESC)ElementPtr->next.image.frame)->image->MipmapImg =
((PFRAME_DESC)SetEquFrameIndex (
ElementPtr->next.image.farray
[index + 1],
ElementPtr->next.image.frame))->image->NormalImg;
}
else
{
((PFRAME_DESC)ElementPtr->next.image.frame)->image->MipmapImg = NULL;
}
#endif #endif
} }
DisplayArray[ElementPtr->PrimIndex].Object.Stamp.frame = DisplayArray[ElementPtr->PrimIndex].Object.Stamp.frame =
+11 -3
View File
@@ -108,6 +108,7 @@ main (int argc, char *argv[])
{"fullscreen", 0, NULL, 'f'}, {"fullscreen", 0, NULL, 'f'},
{"opengl", 0, NULL, 'o'}, {"opengl", 0, NULL, 'o'},
{"scale", 1, NULL, 'c'}, {"scale", 1, NULL, 'c'},
{"meleescale", 1, NULL, 'b'},
{"scanlines", 0, NULL, 's'}, {"scanlines", 0, NULL, 's'},
{"fps", 0, NULL, 'p'}, {"fps", 0, NULL, 'p'},
{"contentdir", 1, NULL, 'n'}, {"contentdir", 1, NULL, 'n'},
@@ -140,7 +141,7 @@ main (int argc, char *argv[])
strcpy (contentdir, "content"); strcpy (contentdir, "content");
#endif #endif
while ((c = getopt_long(argc, argv, "r:d:foc:spn:?hM:S:T:m:q:ug:", long_options, &option_index)) != -1) while ((c = getopt_long(argc, argv, "r:d:foc:b:spn:?hM:S:T:m:q:ug:", long_options, &option_index)) != -1)
{ {
switch (c) { switch (c) {
case 'r': case 'r':
@@ -169,6 +170,12 @@ main (int argc, char *argv[])
gfxflags |= TFB_GFXFLAGS_SCALE_BIADAPTADV; gfxflags |= TFB_GFXFLAGS_SCALE_BIADAPTADV;
} }
break; break;
case 'b':
if (!strcmp (optarg, "nearest"))
optMeleeScale = TFB_SCALE_NEAREST;
else if (!strcmp (optarg, "trilinear"))
optMeleeScale = TFB_SCALE_TRILINEAR;
break;
case 's': case 's':
gfxflags |= TFB_GFXFLAGS_SCANLINES; gfxflags |= TFB_GFXFLAGS_SCANLINES;
break; break;
@@ -279,7 +286,8 @@ main (int argc, char *argv[])
printf(" -d, --bpp=BITSPERPIXEL (default 16)\n"); printf(" -d, --bpp=BITSPERPIXEL (default 16)\n");
printf(" -f, --fullscreen (default off)\n"); printf(" -f, --fullscreen (default off)\n");
printf(" -o, --opengl (default off)\n"); printf(" -o, --opengl (default off)\n");
printf(" -c, --scale=mode (bilinear, biadapt or biadv, default is none)\n"); printf(" -c, --scale=MODE (bilinear, biadapt or biadv, default is none)\n");
printf(" -b, --meleescale=MODE (nearest or trilinear, default is trilinear)\n");
printf(" -s, --scanlines (default off)\n"); printf(" -s, --scanlines (default off)\n");
printf(" -p, --fps (default off)\n"); printf(" -p, --fps (default off)\n");
printf(" -g, --gamma=CORRECTIONVALUE (default 1.0, which causes no change)\n"); printf(" -g, --gamma=CORRECTIONVALUE (default 1.0, which causes no change)\n");
@@ -288,8 +296,8 @@ main (int argc, char *argv[])
printf(" -S, --sfxvol=VOLUME (0-100, default 100)\n"); printf(" -S, --sfxvol=VOLUME (0-100, default 100)\n");
printf(" -T, --speechvol=VOLUME (0-100, default 100)\n"); printf(" -T, --speechvol=VOLUME (0-100, default 100)\n");
printf(" -q, --audioquality=QUALITY (high, medium or low, default medium)\n"); printf(" -q, --audioquality=QUALITY (high, medium or low, default medium)\n");
printf(" --sound=DRIVER (openal, mixsdl, none; default mixsdl)\n");
printf(" -u, --nosubtitles\n"); printf(" -u, --nosubtitles\n");
printf(" --sound=DRIVER (openal, mixsdl, none; default mixsdl)\n");
printf("The following options can take either '3do' or 'pc' as an option:\n"); printf("The following options can take either '3do' or 'pc' as an option:\n");
printf(" -m, --music : Music version (default 3do)\n"); printf(" -m, --music : Music version (default 3do)\n");
printf(" --cscan : coarse-scan display, pc=text, 3do=hieroglyphs (default 3do)\n"); printf(" --cscan : coarse-scan display, pc=text, 3do=hieroglyphs (default 3do)\n");