1
0
Fork 0

Fixes to hercules emulation, better detection and bank switching

Fixes to tandy emulation, 640x200x16 mode and different sizes bank.
EGA/VGA memory changes detection for faster rendering added
Renderer does initial pass to check for needing to lock buffer


Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2781
This commit is contained in:
Sjoerd van der Berg 2007-01-24 16:29:09 +00:00
parent 667c756775
commit 5660ee1856
16 changed files with 1132 additions and 565 deletions

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: render.cpp,v 1.49 2007-01-08 19:45:39 qbix79 Exp $ */
/* $Id: render.cpp,v 1.50 2007-01-24 16:29:09 harekiet Exp $ */
#include <sys/types.h>
#include <dirent.h>
@ -37,6 +37,8 @@
Render_t render;
ScalerLineHandler_t RENDER_DrawLine;
static void RENDER_CallBack( GFX_CallBackFunctions_t function );
static void Check_Palette(void) {
/* Clean up any previous changed palette data */
if (render.pal.changed) {
@ -95,6 +97,30 @@ void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue) {
static void RENDER_EmptyLineHandler(const void * src) {
}
static void RENDER_StartLineHandler(const void * s) {
if (s) {
const Bitu *src = (Bitu*)s;
Bitu *cache = (Bitu*)(render.scale.cacheRead);
for (Bits x=render.src.start;x>0;) {
if (GCC_UNLIKELY(src[0] != cache[0])) {
if (!GFX_StartUpdate( render.scale.outWrite, render.scale.outPitch )) {
RENDER_DrawLine = RENDER_EmptyLineHandler;
return;
}
render.scale.outWrite += render.scale.outPitch * Scaler_ChangedLines[0];
RENDER_DrawLine = render.scale.lineHandler;
RENDER_DrawLine( s );
return;
}
x--; src++; cache++;
}
}
render.scale.cacheRead += render.scale.cachePitch;
Scaler_ChangedLines[0] += Scaler_Aspect[ render.scale.inLine ];
render.scale.inLine++;
render.scale.outLine++;
}
static void RENDER_ClearCacheHandler(const void * src) {
Bitu x, width;
Bit32u *srcLine, *cacheLine;
@ -119,33 +145,54 @@ bool RENDER_StartUpdate(void) {
if (render.scale.inMode == scalerMode8) {
Check_Palette();
}
if (GCC_UNLIKELY(!GFX_StartUpdate(render.scale.outWrite,render.scale.outPitch)))
return false;
render.scale.inLine = 0;
render.scale.outLine = 0;
render.scale.cacheRead = (Bit8u*)&scalerSourceCache;
render.scale.outWrite = 0;
render.scale.outPitch = 0;
Scaler_ChangedLines[0] = 0;
Scaler_ChangedLineIndex = 0;
/* Clearing the cache will first process the line to make sure it's never the same */
if (GCC_UNLIKELY( render.scale.clearCache) ) {
// LOG_MSG("Clearing cache");
//Will always have to update the screen with this one anyway, so let's update already
if (GCC_UNLIKELY(!GFX_StartUpdate( render.scale.outWrite, render.scale.outPitch )))
return false;
render.fullFrame = true;
render.scale.clearCache = false;
RENDER_DrawLine = RENDER_ClearCacheHandler;
} else {
if (render.pal.changed)
if (render.pal.changed) {
/* Assume pal changes always do a full screen update anyway */
if (GCC_UNLIKELY(!GFX_StartUpdate( render.scale.outWrite, render.scale.outPitch )))
return false;
RENDER_DrawLine = render.scale.linePalHandler;
else
RENDER_DrawLine = render.scale.lineHandler;
render.fullFrame = true;
} else {
RENDER_DrawLine = RENDER_StartLineHandler;
if (GCC_UNLIKELY(CaptureState & (CAPTURE_IMAGE|CAPTURE_VIDEO)))
render.fullFrame = true;
else
render.fullFrame = false;
}
}
render.updating=true;
render.updating = true;
return true;
}
void RENDER_EndUpdate( bool fullUpdate ) {
if (!render.updating)
static void RENDER_Halt( void ) {
RENDER_DrawLine = RENDER_EmptyLineHandler;
GFX_EndUpdate( 0 );
render.updating=false;
render.active=false;
}
extern Bitu PIC_Ticks;
void RENDER_EndUpdate( void ) {
if (GCC_UNLIKELY(!render.updating))
return;
RENDER_DrawLine = RENDER_EmptyLineHandler;
if (CaptureState & (CAPTURE_IMAGE|CAPTURE_VIDEO)) {
if (GCC_UNLIKELY(CaptureState & (CAPTURE_IMAGE|CAPTURE_VIDEO))) {
Bitu pitch, flags;
flags = 0;
if (render.src.dblw != render.src.dblh) {
@ -159,40 +206,46 @@ void RENDER_EndUpdate( bool fullUpdate ) {
CAPTURE_AddImage( render.src.width, render.src.height, render.src.bpp, pitch,
flags, fps, (Bit8u *)&scalerSourceCache, (Bit8u*)&render.pal.rgb );
}
GFX_EndUpdate( fullUpdate ? Scaler_ChangedLines : 0);
if ( render.scale.outWrite ) {
GFX_EndUpdate( Scaler_ChangedLines );
render.frameskip.hadSkip[render.frameskip.index] = 0;
} else {
#if 0
Bitu total = 0, i;
render.frameskip.hadSkip[render.frameskip.index] = 1;
for (i = 0;i<RENDER_SKIP_CACHE;i++)
total += render.frameskip.hadSkip[i];
LOG_MSG( "Skipped frame %d %d", PIC_Ticks, (total * 100) / RENDER_SKIP_CACHE );
#endif
}
render.frameskip.index = (render.frameskip.index + 1) & (RENDER_SKIP_CACHE - 1);
render.updating=false;
}
static Bitu MakeAspectTable(Bitu height,double scaley,Bitu miny) {
static Bitu MakeAspectTable(Bitu skip,Bitu height,double scaley,Bitu miny) {
Bitu i;
double lines=0;
Bitu linesadded=0;
for (Bitu i=0;i<height;i++) {
lines+=scaley;
if (lines>=miny) {
Bitu templines=(Bitu)lines;
lines-=templines;
linesadded+=templines;
Scaler_Aspect[1+i]=templines-miny;
} else Scaler_Aspect[1+i]=0;
for (i=0;i<skip;i++)
Scaler_Aspect[i] = 0;
height += skip;
for (i=skip;i<height;i++) {
lines += scaley;
if (lines >= miny) {
Bitu templines = (Bitu)lines;
lines -= templines;
linesadded += templines;
Scaler_Aspect[i] = templines;
} else {
Scaler_Aspect[i] = 0;
}
}
return linesadded;
}
void RENDER_CallBack( GFX_CallBackFunctions_t function ) {
if (render.updating) {
/* Still updating the current screen, shut it down correctly */
RENDER_EndUpdate( false );
}
if (function == GFX_CallBackStop)
return;
if (function == GFX_CallBackRedraw) {
//LOG_MSG("redraw");
render.scale.clearCache = true;
return;
}
static void RENDER_Reset( void ) {
Bitu width=render.src.width;
Bitu height=render.src.height;
bool dblw=render.src.dblw;
@ -301,20 +354,24 @@ forcenormal:
}
switch (render.src.bpp) {
case 8:
render.src.start = ( render.src.width * 1) / sizeof(Bitu);
if (gfx_flags & GFX_CAN_8)
gfx_flags |= GFX_LOVE_8;
else
gfx_flags |= GFX_LOVE_32;
break;
case 15:
render.src.start = ( render.src.width * 2) / sizeof(Bitu);
gfx_flags |= GFX_LOVE_15;
gfx_flags = (gfx_flags & ~GFX_CAN_8) | GFX_RGBONLY;
break;
case 16:
render.src.start = ( render.src.width * 2) / sizeof(Bitu);
gfx_flags |= GFX_LOVE_16;
gfx_flags = (gfx_flags & ~GFX_CAN_8) | GFX_RGBONLY;
break;
case 32:
render.src.start = ( render.src.width * 4) / sizeof(Bitu);
gfx_flags |= GFX_LOVE_32;
gfx_flags = (gfx_flags & ~GFX_CAN_8) | GFX_RGBONLY;
break;
@ -327,15 +384,16 @@ forcenormal:
goto forcenormal;
}
width *= xscale;
Bitu skip = complexBlock ? 1 : 0;
if (gfx_flags & GFX_SCALING) {
height = MakeAspectTable(render.src.height, yscale, yscale );
height = MakeAspectTable(skip, render.src.height, yscale, yscale );
} else {
if ((gfx_flags & GFX_CAN_RANDOM) && gfx_scaleh > 1) {
gfx_scaleh *= yscale;
height = MakeAspectTable(render.src.height, gfx_scaleh, yscale );
height = MakeAspectTable( skip, render.src.height, gfx_scaleh, yscale );
} else {
gfx_flags &= ~GFX_CAN_RANDOM; //Hardware surface when possible
height = MakeAspectTable(render.src.height, yscale, yscale);
height = MakeAspectTable( skip, render.src.height, yscale, yscale);
}
}
/* Setup the scaler variables */
@ -409,12 +467,26 @@ forcenormal:
render.active=true;
}
static void RENDER_CallBack( GFX_CallBackFunctions_t function ) {
if (function == GFX_CallBackStop) {
RENDER_Halt( );
return;
} else if (function == GFX_CallBackRedraw) {
render.scale.clearCache = true;
return;
} else if ( function == GFX_CallBackReset) {
GFX_EndUpdate( 0 );
RENDER_Reset();
} else {
E_Exit("Unhandled GFX_CallBackReset %d", function );
}
}
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,float fps,double ratio,bool dblw,bool dblh) {
RENDER_Halt( );
if (!width || !height || width > SCALER_MAXWIDTH || height > SCALER_MAXHEIGHT) {
render.active=false;
return;
}
RENDER_EndUpdate( false );
render.src.width=width;
render.src.height=height;
render.src.bpp=bpp;
@ -422,7 +494,7 @@ void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,float fps,double ratio,bool
render.src.dblh=dblh;
render.src.fps=fps;
render.src.ratio=ratio;
RENDER_CallBack( GFX_CallBackReset );
RENDER_Reset( );
}
extern void GFX_SetTitle(Bit32s cycles, Bits frameskip,bool paused);
@ -499,6 +571,7 @@ void RENDER_Init(Section * sec) {
//If something changed that needs a ReInit
if(running && (render.aspect != aspect || render.scale.op != scaleOp))
RENDER_CallBack( GFX_CallBackReset );
if(!running) render.updating=true;
running = true;