1
0
Fork 0

Rendering rewrite for aspect correction and vga vertical stretching

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1411
This commit is contained in:
Sjoerd van der Berg 2003-11-08 09:53:11 +00:00
parent 7b36937c81
commit a1e279829b
6 changed files with 302 additions and 785 deletions

View file

@ -16,10 +16,12 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: render.cpp,v 1.19 2003-10-15 08:20:50 harekiet Exp $ */
/* $Id: render.cpp,v 1.20 2003-11-08 09:53:11 harekiet Exp $ */
#include <sys/types.h>
#include <dirent.h>
#include <assert.h>
#include <math.h>
#include "dosbox.h"
#include "video.h"
@ -29,7 +31,8 @@
#include "cross.h"
#include "support.h"
#define MAX_RES 2048
#define RENDER_MAXWIDTH 1280
#define RENDER_MAXHEIGHT 1024
struct PalData {
struct {
@ -43,6 +46,7 @@ struct PalData {
union {
Bit32u bpp32[256];
Bit16u bpp16[256];
Bit32u yuv[256];
} lookup;
};
@ -53,28 +57,36 @@ static struct {
Bitu height;
Bitu bpp;
Bitu pitch;
Bitu flags;
float ratio;
Bitu scalew;
Bitu scaleh;
double ratio;
RENDER_Draw_Handler draw_handler;
} src;
struct {
Bitu width;
Bitu height;
Bitu pitch;
Bitu bpp; /* The type of BPP the operation requires for input */
GFX_MODES gfx_mode;
RENDER_Operation type;
RENDER_Operation want_type;
RENDER_Part_Handler part_handler;
void * dest;
void * buffer;
void * pixels;
Bit8u * dest;
Bit8u * buffer;
Bit8u * pixels;
} op;
struct {
Bitu count;
Bitu max;
} frameskip;
Bitu flags;
PalData pal;
struct {
Bit8u hlines[RENDER_MAXHEIGHT];
Bit16u hindex[RENDER_MAXHEIGHT];
} normal;
struct {
Bit16u hindex[RENDER_MAXHEIGHT];
Bitu line_starts[RENDER_MAXHEIGHT][3];
} advmame2x;
#if (C_SSHOT)
struct {
RENDER_Operation type;
@ -84,12 +96,14 @@ static struct {
#endif
bool screenshot;
bool active;
bool aspect;
} render;
/* Forward declerations */
static void RENDER_ResetPal(void);
/* Include the different rendering routines */
#include "render_templates.h"
#include "render_normal.h"
#include "render_scale2x.h"
@ -201,28 +215,41 @@ static void EnableScreenShot(void) {
/* This could go kinda bad with multiple threads */
static void Check_Palette(void) {
if (render.pal.first>render.pal.last) return;
switch (render.op.bpp) {
case 8:
Bitu i;
switch (render.op.gfx_mode) {
case GFX_8BPP:
GFX_SetPalette(render.pal.first,render.pal.last-render.pal.first+1,(GFX_PalEntry *)&render.pal.rgb[render.pal.first]);
break;
case 16:
for (;render.pal.first<=render.pal.last;render.pal.first++) {
render.pal.lookup.bpp16[render.pal.first]=GFX_GetRGB(
render.pal.rgb[render.pal.first].red,
render.pal.rgb[render.pal.first].green,
render.pal.rgb[render.pal.first].blue);
case GFX_15BPP:
case GFX_16BPP:
for (i=render.pal.first;i<=render.pal.last;i++) {
Bit8u r=render.pal.rgb[i].red;
Bit8u g=render.pal.rgb[i].green;
Bit8u b=render.pal.rgb[i].blue;
render.pal.lookup.bpp16[i]=GFX_GetRGB(r,g,b);
}
break;
case 32:
for (;render.pal.first<=render.pal.last;render.pal.first++) {
render.pal.lookup.bpp32[render.pal.first]=
GFX_GetRGB(
render.pal.rgb[render.pal.first].red,
render.pal.rgb[render.pal.first].green,
render.pal.rgb[render.pal.first].blue);
case GFX_24BPP:
case GFX_32BPP:
for (i=render.pal.first;i<=render.pal.last;i++) {
Bit8u r=render.pal.rgb[i].red;
Bit8u g=render.pal.rgb[i].green;
Bit8u b=render.pal.rgb[i].blue;
render.pal.lookup.bpp32[i]=GFX_GetRGB(r,g,b);
}
break;
};
case GFX_YUV:
for (i=render.pal.first;i<=render.pal.last;i++) {
Bit8u r=render.pal.rgb[i].red;
Bit8u g=render.pal.rgb[i].green;
Bit8u b=render.pal.rgb[i].blue;
Bit8u y = ( 9797*(r) + 19237*(g) + 3734*(b) ) >> 15;
Bit8u u = (18492*((b)-(y)) >> 15) + 128;
Bit8u v = (23372*((r)-(y)) >> 15) + 128;
render.pal.lookup.yuv[i]=(u << 0) | (y << 8) | (v << 16) | (y << 24);
}
break;
}
/* Setup pal index to startup values */
render.pal.first=256;
render.pal.last=0;
@ -251,19 +278,14 @@ void RENDER_DoUpdate(void) {
GFX_DoUpdate();
}
static void RENDER_DrawScreen(void * data) {
static void RENDER_DrawScreen(Bit8u * data,Bitu pitch) {
render.op.pitch=pitch;
switch (render.op.type) {
#if (C_SSHOT)
doagain:
#endif
case OP_None:
render.op.dest=render.op.pixels=data;
render.src.draw_handler(render.op.part_handler);
break;
case OP_Blit:
render.op.dest=render.op.pixels=data;
render.src.draw_handler(render.op.part_handler);
break;
case OP_Normal2x:
case OP_AdvMame2x:
render.op.dest=render.op.pixels=data;
render.src.draw_handler(render.op.part_handler);
@ -272,8 +294,8 @@ doagain:
case OP_Shot:
render.shot.pitch=render.op.pitch;
render.op.pitch=render.src.width;
render.op.pixels=malloc(render.src.width*render.src.height);
render.src.draw_handler(Normal_DN_8);
render.op.pixels=(Bit8u*)malloc(render.src.width*render.src.height);
// render.src.draw_handler(Normal_DN_8);
TakeScreenShot((Bit8u *)render.op.pixels);
free(render.op.pixels);
render.op.pitch=render.shot.pitch;
@ -283,30 +305,134 @@ doagain:
}
}
static void RENDER_Resize(Bitu * width,Bitu * height) {
/* Calculate the new size the window should be */
if (!*width && !*height) {
/* Special command to reset any resizing for fullscreen */
*width=render.src.width;
*height=render.src.height;
} else {
if ((*width/render.src.ratio)<*height) *height=(Bitu)(*width/render.src.ratio);
else *width=(Bitu)(*height*render.src.ratio);
}
static void SetAdvMameTable(Bitu index,Bits src0,Bits src1,Bits src2) {
if (src0<0) src0=0;
if ((Bitu)src0>=render.src.height) src0=render.src.height-1;
if ((Bitu)src1>=render.src.height) src1=render.src.height-1;
if ((Bitu)src2>=render.src.height) src2=render.src.height-1;
render.advmame2x.line_starts[index][0]=src0*render.src.pitch;
render.advmame2x.line_starts[index][1]=src1*render.src.pitch;
render.advmame2x.line_starts[index][2]=src2*render.src.pitch;
}
static void Render_Blit_CallBack(Bitu width,Bitu height,Bitu bpp,Bitu pitch,Bitu flags) {
void RENDER_ReInit(void) {
Bitu width=render.src.width;
Bitu height=render.src.height;
Bitu bpp=render.src.bpp;
Bitu scalew=render.src.scalew;
Bitu scaleh=render.src.scaleh;
double gfx_scalew=1.0;
double gfx_scaleh=1.0;
if (render.src.ratio>1.0) gfx_scaleh*=render.src.ratio;
else gfx_scalew*=(1/render.src.ratio);
GFX_MODES gfx_mode;Bitu gfx_flags;
gfx_mode=GFX_GetBestMode(render.src.bpp,gfx_flags);
Bitu index;
switch (gfx_mode) {
case GFX_8BPP: index=0;break;
case GFX_15BPP: index=1;break;
case GFX_16BPP: index=1;break;
case GFX_24BPP: index=2;break;
case GFX_32BPP: index=3;break;
case GFX_YUV: index=3;break;
}
/* Initial scaler testing */
switch (render.op.want_type) {
case OP_Normal2x:
case OP_None:
render.op.type=render.op.want_type;
normalop:
if (gfx_flags & GFX_HASSCALING) {
gfx_scalew*=scalew;
gfx_scaleh*=scaleh;
render.op.part_handler=Normal_SINGLE_8[index];
for (Bitu i=0;i<render.src.height;i++) {
render.normal.hindex[i]=i;
render.normal.hlines[i]=0;
}
} else {
gfx_scaleh*=scaleh;
if (scalew==2) {
if (scaleh>1 && (render.op.type==OP_None)) {
render.op.part_handler=Normal_SINGLE_8[index];
scalew>>=1;gfx_scaleh/=2;
} else {
render.op.part_handler=Normal_DOUBLE_8[index];
}
} else render.op.part_handler=Normal_SINGLE_8[index];
width*=scalew;
double lines=0.0;
gfx_scaleh=(gfx_scaleh*render.src.height-(double)render.src.height)/(double)render.src.height;
height=0;
for (Bitu i=0;i<render.src.height;i++) {
render.normal.hindex[i]=height++;
Bitu temp_lines=(Bitu)(lines);
lines=lines+gfx_scaleh-temp_lines;
render.normal.hlines[i]=temp_lines;
height+=temp_lines;
}
}
break;
case OP_AdvMame2x:
if (scalew!=2){
render.op.type=OP_Normal2x;
goto normalop;
}
if (gfx_flags & GFX_HASSCALING) {
height=scaleh*height;
} else {
height=(Bitu)(gfx_scaleh*scaleh*height);
}
width<<=1;
{
Bits i;
double src_add=(double)height/(double)render.src.height;
double src_index=0;
double src_lines=0;
Bitu height=0;
for (i=0;i<=(Bits)render.src.height;i++) {
render.advmame2x.hindex[i]=(Bitu)src_index;
Bitu lines=(Bitu)src_lines;
src_lines-=lines;
src_index+=src_add;
src_lines+=src_add;
switch (lines) {
case 0:
break;
case 1:
SetAdvMameTable(height++,i,i,i);
break;
case 2:
SetAdvMameTable(height++,i-1,i,i+1);
SetAdvMameTable(height++,i+1,i,i-1);
break;
default:
SetAdvMameTable(height++,i-1,i,i+1);
for (lines-=2;lines>0;lines--) SetAdvMameTable(height++,i,i,i);
SetAdvMameTable(height++,i+1,i,i-1);
break;
}
}
render.op.part_handler=AdvMame2x_8_Table[index];
}
break;
}
render.op.gfx_mode=gfx_mode;
render.op.width=width;
render.op.height=height;
render.op.bpp=bpp;
render.op.pitch=pitch;
render.op.type=OP_Blit;
render.op.part_handler=GFX_Render_Blit;
GFX_SetSize(width,height,gfx_mode,gfx_scalew,gfx_scaleh,&RENDER_ReInit,RENDER_DrawScreen);
RENDER_ResetPal();
GFX_Start();
}
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags,RENDER_Draw_Handler draw_handler) {
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu scalew,Bitu scaleh,RENDER_Draw_Handler draw_handler) {
if ((!width) || (!height) || (!pitch)) {
render.active=false;return;
}
@ -315,67 +441,12 @@ void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu
render.src.height=height;
render.src.bpp=bpp;
render.src.pitch=pitch;
render.src.ratio=ratio;
render.src.flags=flags;
render.src.ratio=render.aspect ? ratio : 1.0;
render.src.scalew=scalew;
render.src.scaleh=scaleh;
render.src.draw_handler=draw_handler;
RENDER_ReInit();
GFX_ModeCallBack mode_callback=0;
switch (render.op.want_type) {
case OP_None:
normalop:
switch (render.src.flags) {
case DoubleNone:
flags=0;
break;
case DoubleWidth:
width*=2;
flags=GFX_SHADOW;
break;
case DoubleHeight:
height*=2;
flags=0;
break;
case DoubleBoth:
render.src.flags=0;
flags=0;
break;
}
mode_callback=Render_Normal_CallBack;
break;
case OP_Normal2x:
switch (render.src.flags) {
case DoubleBoth:
width*=2;height*=2;
flags=GFX_SHADOW;
mode_callback=Render_Normal_CallBack;
break;
default:
goto normalop;
}
break;
case OP_AdvMame2x:
switch (render.src.flags) {
case DoubleBoth:
mode_callback=Render_Scale2x_CallBack;
width*=2;height*=2;
#if defined (SCALE2X_MMX)
flags=GFX_SHADOW;
#else
flags=GFX_SHADOW;
#endif
break;
default:
goto normalop;
}
break;
default:
goto normalop;
}
GFX_SetSize(width,height,bpp,flags,mode_callback,RENDER_DrawScreen);
GFX_Start();
}
extern void GFX_SetTitle(Bits cycles, Bits frameskip);
@ -396,6 +467,7 @@ void RENDER_Init(Section * sec) {
render.pal.first=256;
render.pal.last=0;
render.aspect=section->Get_bool("aspect");
render.frameskip.max=section->Get_int("frameskip");
render.frameskip.count=0;
#if (C_SSHOT)