diff --git a/src/gui/midi.cpp b/src/gui/midi.cpp index 524ab956..9c303bb1 100644 --- a/src/gui/midi.cpp +++ b/src/gui/midi.cpp @@ -107,86 +107,8 @@ static struct { } sysex; bool available; MidiHandler * handler; - struct { - FILE * handle; - Bit8u buffer[RAWBUF+SYSEX_SIZE]; - bool capturing; - Bitu used,done; - Bit32u last; - } raw; } midi; -static Bit8u midi_header[]={ - 'M','T','h','d', /* Bit32u, Header Chunk */ - 0x0,0x0,0x0,0x6, /* Bit32u, Chunk Length */ - 0x0,0x0, /* Bit16u, Format, 0=single track */ - 0x0,0x1, /* Bit16u, Track Count, 1 track */ - 0x01,0xf4, /* Bit16u, Timing, 2 beats/second with 500 frames */ - 'M','T','r','k', /* Bit32u, Track Chunk */ - 0x0,0x0,0x0,0x0, /* Bit32u, Chunk Length */ - //Track data -}; - -#define ADDBUF(_VAL_) midi.raw.buffer[midi.raw.used++]=(Bit8u)(_VAL_); -static INLINE void RawAddNumber(Bit32u val) { - if (val & 0xfe00000) ADDBUF(0x80|((val >> 21) & 0x7f)); - if (val & 0xfffc000) ADDBUF(0x80|((val >> 14) & 0x7f)); - if (val & 0xfffff80) ADDBUF(0x80|((val >> 7) & 0x7f)); - ADDBUF(val & 0x7f); -} -static INLINE void RawAddDelta(void) { - if (!midi.raw.handle) { - midi.raw.handle=OpenCaptureFile("Raw Midi",".mid"); - if (!midi.raw.handle) { - midi.raw.capturing=false; - return; - } - fwrite(midi_header,1,sizeof(midi_header),midi.raw.handle); - midi.raw.last=PIC_Ticks; - } - Bit32u delta=PIC_Ticks-midi.raw.last; - midi.raw.last=PIC_Ticks; - RawAddNumber(delta); -} - -static INLINE void RawAddData(Bit8u * data,Bitu len) { - for (Bitu i=0;i=RAWBUF) { - fwrite(midi.raw.buffer,1,midi.raw.used,midi.raw.handle); - midi.raw.done+=midi.raw.used; - midi.raw.used=0; - } -} - -static void MIDI_SaveRawEvent(void) { - /* Check for previously opened wave file */ - if (midi.raw.capturing) { - LOG_MSG("Stopping raw midi saving."); - midi.raw.capturing=false; - if (!midi.raw.handle) return; - ADDBUF(0x00);//Delta time - ADDBUF(0xff);ADDBUF(0x2F);ADDBUF(0x00); //End of track event - fwrite(midi.raw.buffer,1,midi.raw.used,midi.raw.handle); - midi.raw.done+=midi.raw.used; - fseek(midi.raw.handle,18, SEEK_SET); - Bit8u size[4]; - size[0]=(Bit8u)(midi.raw.done >> 24); - size[1]=(Bit8u)(midi.raw.done >> 16); - size[2]=(Bit8u)(midi.raw.done >> 8); - size[3]=(Bit8u)(midi.raw.done >> 0); - fwrite(&size,1,4,midi.raw.handle); - fclose(midi.raw.handle); - midi.raw.handle=0; - } else { - LOG_MSG("Preparing for raw midi capture, will start with first data."); - midi.raw.used=0; - midi.raw.done=0; - midi.raw.handle=0; - midi.raw.capturing=true; - } -} - - void MIDI_RawOutByte(Bit8u data) { /* Test for a active sysex tranfer */ if (midi.status==0xf0) { @@ -197,11 +119,8 @@ void MIDI_RawOutByte(Bit8u data) { midi.sysex.buf[midi.sysex.used++]=0xf7; midi.handler->PlaySysex(midi.sysex.buf,midi.sysex.used); LOG(LOG_ALL,LOG_NORMAL)("Sysex message size %d",midi.sysex.used); - if (midi.raw.capturing) { - RawAddDelta(); - ADDBUF(0xf0); - RawAddNumber(midi.sysex.used-1); - RawAddData(&midi.sysex.buf[1],midi.sysex.used-1); + if (CaptureState & CAPTURE_MIDI) { + CAPTURE_AddMidi( true, midi.sysex.used-1, &midi.sysex.buf[1]); } } } @@ -217,9 +136,8 @@ void MIDI_RawOutByte(Bit8u data) { if (midi.cmd_len) { midi.cmd_buf[midi.cmd_pos++]=data; if (midi.cmd_pos >= midi.cmd_len) { - if (midi.raw.capturing) { - RawAddDelta(); - RawAddData(midi.cmd_buf,midi.cmd_len); + if (CaptureState & CAPTURE_MIDI) { + CAPTURE_AddMidi(false, midi.cmd_len, midi.cmd_buf); } midi.handler->PlayMsg(midi.cmd_buf); midi.cmd_pos=1; //Use Running status @@ -231,7 +149,6 @@ bool MIDI_Available(void) { return midi.available; } - class MIDI:public Module_base{ public: MIDI(Section* configuration):Module_base(configuration){ @@ -240,12 +157,10 @@ public: const char * conf=section->Get_string("config"); /* If device = "default" go for first handler that works */ MidiHandler * handler; - MAPPER_AddHandler(MIDI_SaveRawEvent,MK_f8,MMOD1|MMOD2,"caprawmidi","Cap MIDI"); +// MAPPER_AddHandler(MIDI_SaveRawEvent,MK_f8,MMOD1|MMOD2,"caprawmidi","Cap MIDI"); midi.status=0x00; midi.cmd_pos=0; midi.cmd_len=0; - midi.raw.handle=0; - midi.raw.capturing=false; if (!strcasecmp(dev,"default")) goto getdefault; handler=handler_list; while (handler) { @@ -276,12 +191,13 @@ getdefault: /* This shouldn't be possible */ } ~MIDI(){ - if(midi.raw.handle) MIDI_SaveRawEvent(); if(midi.available) midi.handler->Close(); midi.available = false; midi.handler = 0; } }; + + static MIDI* test; void MIDI_Destroy(Section* sec){ delete test; diff --git a/src/gui/render.cpp b/src/gui/render.cpp index e3cd1381..b6bd4ea8 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: render.cpp,v 1.35 2005-10-25 14:02:11 qbix79 Exp $ */ +/* $Id: render.cpp,v 1.36 2006-01-30 09:58:07 harekiet Exp $ */ #include #include @@ -34,166 +34,45 @@ #include "render_scalers.h" -struct PalData { - struct { - Bit8u red; - Bit8u green; - Bit8u blue; - Bit8u unused; - } rgb[256]; - volatile Bitu first; - volatile Bitu last; -}; - -static struct { - struct { - Bitu width; - Bitu height; - Bitu bpp; - bool dblw,dblh; - double ratio; - } src; - struct { - Bitu width; - Bitu height; - Bitu pitch; - GFX_Modes mode; - RENDER_Operation type; - RENDER_Operation want_type; - RENDER_Line_Handler line_handler; - } op; - struct { - Bitu count; - Bitu max; - } frameskip; - PalData pal; -#if (C_SSHOT) - struct { - Bitu bpp,width,height,rowlen; - Bit8u * buffer,* draw; - bool take,taking; - } shot; -#endif - bool active; - bool aspect; - bool updating; -} render; - -RENDER_Line_Handler RENDER_DrawLine; - -#if (C_SSHOT) -#include - -static void RENDER_ShotDraw(const Bit8u * src) { - memcpy(render.shot.draw,src,render.shot.rowlen); - render.shot.draw+=render.shot.rowlen; - render.op.line_handler(src); -} - -/* Take a screenshot of the data that should be rendered */ -static void TakeScreenShot(Bit8u * bitmap) { - png_structp png_ptr; - png_infop info_ptr; - png_bytep * row_pointers; - png_color palette[256]; - Bitu i; - Bitu fix_double_scale = 1;//variable to compensate for only doubleheight - - /* Remove this if we save rendered screens. instead of pre-rendered */ - if(render.src.dblh && !render.src.dblw) fix_double_scale = 2; - - - /* Open the actual file */ - FILE * fp=OpenCaptureFile("Screenshot",".png"); - if (!fp) return; - /* First try to alloacte the png structures */ - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL); - if (!png_ptr) return; - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_write_struct(&png_ptr,(png_infopp)NULL); - return; - } - - /* Finalize the initing of png library */ - png_init_io(png_ptr, fp); - png_set_compression_level(png_ptr,Z_BEST_COMPRESSION); - - /* set other zlib parameters */ - png_set_compression_mem_level(png_ptr, 8); - png_set_compression_strategy(png_ptr,Z_DEFAULT_STRATEGY); - png_set_compression_window_bits(png_ptr, 15); - png_set_compression_method(png_ptr, 8); - png_set_compression_buffer_size(png_ptr, 8192); - - if (render.shot.bpp==8) { - png_set_IHDR(png_ptr, info_ptr, render.shot.width, (render.shot.height*fix_double_scale), - 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - for (i=0;i<256;i++) { - palette[i].red=render.pal.rgb[i].red; - palette[i].green=render.pal.rgb[i].green; - palette[i].blue=render.pal.rgb[i].blue; - } - png_set_PLTE(png_ptr, info_ptr, palette,256); - } else { - png_set_IHDR(png_ptr, info_ptr, render.shot.width, (render.shot.height*fix_double_scale), - render.shot.bpp, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - } - - /*Allocate an array of scanline pointers*/ - row_pointers=(png_bytep*)malloc(render.shot.height*fix_double_scale*sizeof(png_bytep)); - for (i = 0;i < render.shot.height;i++) { - row_pointers[fix_double_scale*i] = (bitmap+i*render.shot.rowlen); - if(fix_double_scale == 2) row_pointers[fix_double_scale*i+1] = (bitmap+i*render.shot.rowlen); - } - - /*tell the png library what to encode.*/ - png_set_rows(png_ptr, info_ptr, row_pointers); - - /*Write image to file*/ - png_write_png(png_ptr, info_ptr, 0, NULL); - - /*close file*/ - fclose(fp); - - /*Destroy PNG structs*/ - png_destroy_write_struct(&png_ptr, &info_ptr); - - /*clean up dynamically allocated RAM.*/ - free(row_pointers); -} - -static void EnableScreenShot(void) { - render.shot.take=true; -} - -#endif - +Render_t render; static void Check_Palette(void) { - if (render.pal.first>render.pal.last) return; + /* Clean up any previous changed palette data */ + if (render.pal.changed) { + memset(render.pal.modified, 0, sizeof(render.pal.modified)); + render.pal.changed = false; + } + if (render.pal.first>render.pal.last) + return; Bitu i; - switch (render.op.mode) { - case GFX_8: + switch (render.scale.outMode) { + case scalerMode8: GFX_SetPalette(render.pal.first,render.pal.last-render.pal.first+1,(GFX_PalEntry *)&render.pal.rgb[render.pal.first]); break; - case GFX_15: - case GFX_16: + case scalerMode15: + case scalerMode16: 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; - Scaler_PaletteLut.b16[i]=GFX_GetRGB(r,g,b); + Bit16u newPal = GFX_GetRGB(r,g,b); + if (newPal != render.pal.lut.b16[i]) { + render.pal.changed = true; + render.pal.lut.b16[i] = newPal; + } } break; - case GFX_32: + case scalerMode32: + default: 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; - Scaler_PaletteLut.b32[i]=GFX_GetRGB(r,g,b); + Bit32u newPal = GFX_GetRGB(r,g,b); + if (newPal != render.pal.lut.b32[i]) { + render.pal.changed = true; + render.pal.lut.b32[i] = newPal; + } } break; } @@ -215,60 +94,101 @@ void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue) { if (render.pal.last=render.frameskip.max) { - if (render.src.bpp==8) Check_Palette(); - render.frameskip.count=0; - Scaler_Line=0; - Scaler_Index=Scaler_Data; - if (GFX_StartUpdate(Scaler_DstWrite,Scaler_DstPitch)) { - RENDER_DrawLine=render.op.line_handler; -#if (C_SSHOT) - if (GCC_UNLIKELY(render.shot.take)) { - render.shot.take=false; - if (render.shot.buffer) free(render.shot.buffer); - render.shot.width=render.src.width; - render.shot.height=render.src.height; - render.shot.bpp=render.src.bpp; - switch (render.shot.bpp) { - case 8:render.shot.rowlen=render.shot.width;break; - case 15: - case 16:render.shot.rowlen=render.shot.width*2;break; - case 32:render.shot.rowlen=render.shot.width*4;break; - } - render.shot.buffer=(Bit8u*)malloc(render.shot.rowlen*render.shot.height); - render.shot.draw=render.shot.buffer; - RENDER_DrawLine=RENDER_ShotDraw; - render.shot.taking=true; - } -#endif - render.updating=true; - return true; - } - } else render.frameskip.count++; - } - return false; + if (GCC_UNLIKELY(render.updating)) + return false; + if (GCC_UNLIKELY(!render.active)) + return false; + if (GCC_UNLIKELY(render.frameskip.countsimple[render.scale.outMode]; + } else { + render.scale.cacheHandler = cacheBlock->complex[render.scale.outMode]; + } + } + render.scale.lineHandler = render.scale.currentHandler; + render.updating=true; + return true; } void RENDER_EndUpdate(void) { - if (render.updating) { -#if (C_SSHOT) - if (GCC_UNLIKELY(render.shot.taking)) { - render.shot.taking=false; - TakeScreenShot(render.shot.buffer); - free(render.shot.buffer); - render.shot.buffer=0; + if (!render.updating) + return; + render.scale.cacheHandler = RENDER_EmptyCacheHandler; + render.scale.lineHandler = RENDER_EmptyLineHandler; + if (CaptureState & (CAPTURE_IMAGE|CAPTURE_VIDEO)) { + Bitu pitch, flags; + switch (render.scale.inMode) { + case scalerMode8: + pitch = sizeof(scalerSourceCache.b8[0]); + break; + case scalerMode15: + case scalerMode16: + pitch = sizeof(scalerSourceCache.b16[0]); + break; + case scalerMode32: + pitch = sizeof(scalerSourceCache.b32[0]); + break; + } + flags = 0; + if (render.src.dblw != render.src.dblh) { + if (render.src.dblw) flags|=CAPTURE_FLAG_DBLW; + if (render.src.dblh) flags|=CAPTURE_FLAG_DBLH; + } + CAPTURE_AddImage( render.src.width, render.src.height, render.src.bpp, pitch, + flags, render.src.fps, scalerSourceCache.b8[0], (Bit8u*)&render.pal.rgb ); } -#endif /* If Things are added to please check the define */ - GFX_EndUpdate(); - RENDER_DrawLine=RENDER_EmptyLineHandler; + GFX_EndUpdate( Scaler_ChangedLines ); render.updating=false; - } +} + +void RENDER_DrawLine( const void *src ) { + render.scale.cacheHandler( src ); + render.scale.lineHandler(); } static Bitu MakeAspectTable(Bitu height,double scaley,Bitu miny) { @@ -280,90 +200,191 @@ static Bitu MakeAspectTable(Bitu height,double scaley,Bitu miny) { Bitu templines=(Bitu)lines; lines-=templines; linesadded+=templines; - Scaler_Data[i]=templines-miny; - } else Scaler_Data[i]=0; + Scaler_Aspect[1+i]=templines-miny; + } else Scaler_Aspect[1+i]=0; } return linesadded; } -void RENDER_ReInit(void) { - if (render.updating) RENDER_EndUpdate(); +void RENDER_ReInit( bool stopIt ) { + if (render.updating) + RENDER_EndUpdate(); + + if (stopIt) + return; + Bitu width=render.src.width; Bitu height=render.src.height; bool dblw=render.src.dblw; bool dblh=render.src.dblh; - double gfx_scalew=1.0; - double gfx_scaleh=1.0; + double gfx_scalew; + double gfx_scaleh; - if (render.src.ratio>1.0) gfx_scaleh*=render.src.ratio; - else gfx_scalew*=(1/render.src.ratio); - Bitu gfx_flags; - ScalerBlock * block; + ScalerLineBlock_t *lineBlock; + if (render.aspect) { + if (render.src.ratio>1.0) { + gfx_scalew = 1; + gfx_scaleh = render.src.ratio; + } else { + gfx_scalew = (1/render.src.ratio); + gfx_scaleh = 1; + } + } else { + gfx_scalew = 1; + gfx_scaleh = 1; + } + lineBlock = &ScaleNormal; if (dblh && dblw) { - render.op.type=render.op.want_type; + /* Initialize always working defaults */ + if (render.scale.size == 2) + lineBlock = &ScaleNormal2x; + else if (render.scale.size == 3) + lineBlock = &ScaleNormal3x; + else + lineBlock = &ScaleNormal; + /* Maybe override them */ + switch (render.scale.op) { + case scalerOpAdvInterp: + if (render.scale.size == 2) + lineBlock = &ScaleAdvInterp2x; + break; + case scalerOpAdvMame: + if (render.scale.size == 2) + lineBlock = &ScaleAdvMame2x; + else if (render.scale.size == 3) + lineBlock = &ScaleAdvMame3x; + break; + case scalerOpTV: + if (render.scale.size == 2) + lineBlock = &ScaleTV2x; + else if (render.scale.size == 3) + lineBlock = &ScaleTV3x; + break; + case scalerOpRGB: + if (render.scale.size == 2) + lineBlock = &ScaleRGB2x; + else if (render.scale.size == 3) + lineBlock = &ScaleRGB3x; + break; + case scalerOpScan: + if (render.scale.size == 2) + lineBlock = &ScaleScan2x; + else if (render.scale.size == 3) + lineBlock = &ScaleScan3x; + break; + } } else if (dblw) { - render.op.type=OP_Normal2x; + lineBlock = &ScaleNormalDw; } else if (dblh) { - render.op.type=OP_Normal; - gfx_scaleh*=2; + lineBlock = &ScaleNormalDh; } else { forcenormal: - render.op.type=OP_Normal; + lineBlock = &ScaleNormal; } - switch (render.op.type) { - case OP_Normal:block=&Normal_8;break; - case OP_Normal2x:block=(dblh) ? &Normal2x_8 : &NormalDbl_8;break; - case OP_AdvMame2x:block=&AdvMame2x_8;break; - case OP_AdvMame3x:block=&AdvMame3x_8;break; - case OP_Interp2x:block=&Interp2x_8;break; - case OP_AdvInterp2x:block=&AdvInterp2x_8;break; - case OP_TV2x:block=&TV2x_8;break; - } - gfx_flags=GFX_GetBestMode(block->flags); + gfx_flags = lineBlock->gfxFlags; + if (render.src.bpp != 8) + gfx_flags |= GFX_RGBONLY; + gfx_flags=GFX_GetBestMode(gfx_flags); if (!gfx_flags) { - if (render.op.type==OP_Normal) E_Exit("Failed to create a rendering output"); - else goto forcenormal; + if (lineBlock == &ScaleNormal) + E_Exit("Failed to create a rendering output"); + else + goto forcenormal; } /* Special test for normal2x to switch to normal with hardware scaling */ - if (gfx_flags & HAVE_SCALING && render.op.type==OP_Normal2x) { - if (dblw) gfx_scalew*=2; - if (dblh) gfx_scaleh*=2; - block=&Normal_8; - render.op.type=OP_Normal; - } - width*=block->xscale; - if (gfx_flags & HAVE_SCALING) { - height=MakeAspectTable(render.src.height,block->yscale,block->miny); + width *= lineBlock->xscale; + if (gfx_flags & GFX_SCALING) { + height = MakeAspectTable(render.src.height, lineBlock->yscale, lineBlock->yscale ); } else { - gfx_scaleh*=block->yscale; - height=MakeAspectTable(render.src.height,gfx_scaleh,block->miny); + if ((gfx_flags & GFX_CAN_RANDOM) && gfx_scaleh > 1) { + gfx_scaleh *= lineBlock->yscale; + height = MakeAspectTable(render.src.height, gfx_scaleh, lineBlock->yscale ); + } else { + gfx_flags &= ~GFX_CAN_RANDOM; //Hardware surface when possible + height = MakeAspectTable(render.src.height, lineBlock->yscale, lineBlock->yscale); + } } /* Setup the scaler variables */ - render.op.mode=GFX_SetSize(width,height,gfx_flags,gfx_scalew,gfx_scaleh,&RENDER_ReInit);; - if (render.op.mode==GFX_NONE) E_Exit("Failed to create a rendering output"); - render.op.line_handler=block->handlers[render.op.mode]; - render.op.width=width; - render.op.height=height; - Scaler_SrcWidth=render.src.width; - Scaler_SrcHeight=render.src.height; + gfx_flags=GFX_SetSize(width,height,gfx_flags,gfx_scalew,gfx_scaleh,&RENDER_ReInit);; + if (gfx_flags & GFX_CAN_8) + render.scale.outMode = scalerMode8; + else if (gfx_flags & GFX_CAN_15) + render.scale.outMode = scalerMode15; + else if (gfx_flags & GFX_CAN_16) + render.scale.outMode = scalerMode16; + else if (gfx_flags & GFX_CAN_32) + render.scale.outMode = scalerMode32; + else + E_Exit("Failed to create a rendering output"); + if (gfx_flags & GFX_HARDWARE) { + render.scale.currentHandler = lineBlock->Linear[ render.scale.outMode ]; + } else { + render.scale.currentHandler = lineBlock->Random[ render.scale.outMode ]; + } + switch (render.src.bpp) { + case 8: + render.scale.inMode = scalerMode8; + break; + case 15: + render.scale.inMode = scalerMode15; + break; + case 16: + render.scale.inMode = scalerMode16; + break; + case 32: + render.scale.inMode = scalerMode32; + break; + default: + E_Exit("RENDER:Wrong source bpp %d", render.src.bpp ); + } + render.scale.lineFlags = lineBlock->scaleFlags; + render.scale.blocks = render.src.width / SCALER_BLOCKSIZE; + render.scale.lastBlock = render.src.width % SCALER_BLOCKSIZE; + render.scale.inHeight = render.src.height; RENDER_ResetPal(); + /* Not exactltly the best way to clean the cache, but seems to do the trick */ + for (Bitu y=0;y0;x--) + cacheLine[x] = ~cacheLine[x]; + } + //Maybe do it again through a special passthrough cache check handler + render.scale.clearCache = true; render.active=true; } -void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,double ratio,bool dblw,bool dblh) { +void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,float fps,double ratio,bool dblw,bool dblh) { if (!width || !height) { render.active=false; return; } + RENDER_EndUpdate(); render.src.width=width; render.src.height=height; render.src.bpp=bpp; render.src.dblw=dblw; render.src.dblh=dblh; - render.src.ratio=render.aspect ? ratio : 1.0; - RENDER_ReInit(); + render.src.fps=fps; + render.src.ratio=ratio; + RENDER_ReInit( false ); } extern void GFX_SetTitle(Bits cycles, Bits frameskip,bool paused); @@ -385,42 +406,43 @@ void RENDER_Init(Section * sec) { //For restarting the renderer. static bool running = false; bool aspect = render.aspect; - RENDER_Operation type = render.op.want_type; + scalerOperation_t scaleOp = render.scale.op; 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; + render.active=false; const char * scaler;std::string cline; if (control->cmdline->FindString("-scaler",cline,false)) { scaler=cline.c_str(); } else { scaler=section->Get_string("scaler"); } - if (!strcasecmp(scaler,"none")) render.op.want_type=OP_Normal; - else if (!strcasecmp(scaler,"normal2x")) render.op.want_type=OP_Normal2x; - else if (!strcasecmp(scaler,"advmame2x")) render.op.want_type=OP_AdvMame2x; - else if (!strcasecmp(scaler,"advmame3x")) render.op.want_type=OP_AdvMame3x; - else if (!strcasecmp(scaler,"advinterp2x")) render.op.want_type=OP_AdvInterp2x; - else if (!strcasecmp(scaler,"interp2x")) render.op.want_type=OP_Interp2x; - else if (!strcasecmp(scaler,"tv2x")) render.op.want_type=OP_TV2x; + if (!strcasecmp(scaler,"none")) { render.scale.op = scalerOpNormal;render.scale.size = 1; } + else if (!strcasecmp(scaler,"normal2x")) { render.scale.op = scalerOpNormal;render.scale.size = 2; } + else if (!strcasecmp(scaler,"normal3x")) { render.scale.op = scalerOpNormal;render.scale.size = 3; } + else if (!strcasecmp(scaler,"advmame2x")) { render.scale.op = scalerOpAdvMame;render.scale.size = 2; } + else if (!strcasecmp(scaler,"advmame3x")) { render.scale.op = scalerOpAdvMame;render.scale.size = 3; } + else if (!strcasecmp(scaler,"advinterp2x")) { render.scale.op = scalerOpAdvMame;render.scale.size = 2; } + else if (!strcasecmp(scaler,"tv2x")) { render.scale.op = scalerOpTV;render.scale.size = 2; } + else if (!strcasecmp(scaler,"tv3x")) { render.scale.op = scalerOpTV;render.scale.size = 3; } + else if (!strcasecmp(scaler,"rgb2x")){ render.scale.op = scalerOpRGB;render.scale.size = 2; } + else if (!strcasecmp(scaler,"rgb3x")){ render.scale.op = scalerOpRGB;render.scale.size = 3; } + else if (!strcasecmp(scaler,"scan2x")){ render.scale.op = scalerOpScan;render.scale.size = 2; } + else if (!strcasecmp(scaler,"scan3x")){ render.scale.op = scalerOpScan;render.scale.size = 3; } else { - render.op.want_type=OP_Normal; + render.scale.op = scalerOpNormal;render.scale.size = 1; LOG_MSG("Illegal scaler type %s,falling back to normal.",scaler); } //If something changed that needs a ReInit - if(running && (render.aspect != aspect || render.op.want_type != type)) - RENDER_ReInit(); + if(running && (render.aspect != aspect || render.scale.op != scaleOp)) + RENDER_ReInit( false ); if(!running) render.updating=true; running = true; - - -#if (C_SSHOT) - MAPPER_AddHandler(EnableScreenShot,MK_f5,MMOD1,"scrshot","Screenshot"); -#endif MAPPER_AddHandler(DecreaseFrameSkip,MK_f7,MMOD1,"decfskip","Dec Fskip"); MAPPER_AddHandler(IncreaseFrameSkip,MK_f8,MMOD1,"incfskip","Inc Fskip"); GFX_SetTitle(-1,render.frameskip.max,false); diff --git a/src/gui/render_loops.h b/src/gui/render_loops.h new file mode 100644 index 00000000..291b7cb2 --- /dev/null +++ b/src/gui/render_loops.h @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2002-2005 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if defined (SCALERLINEAR) +void conc3d(SCALERNAME,SBPP,L)(void) { +#else +void conc3d(SCALERNAME,SBPP,R)(void) { +#endif + if (!render.scale.outLine) { + render.scale.outLine++; + return; + } +lastagain: + if (!CC[render.scale.outLine][0]) { +#if defined(SCALERLINEAR) + Bitu scaleLines = SCALERHEIGHT; +#else + Bitu scaleLines = SCALERHEIGHT + Scaler_Aspect[ render.scale.outLine ]; +#endif + render.scale.outWrite += render.scale.outPitch * scaleLines; + if (!(Scaler_ChangedLineIndex & 1)) { + Scaler_ChangedLines[Scaler_ChangedLineIndex] += scaleLines; + } else { + Scaler_ChangedLines[++Scaler_ChangedLineIndex] = scaleLines; + } + if (++render.scale.outLine == render.scale.inHeight) + goto lastagain; + return; + } + /* Clear the complete line marker */ + CC[render.scale.outLine][0] = 0; + const PTYPE * fc = &FC[render.scale.outLine][1]; + PTYPE * line0=(PTYPE *)(render.scale.outWrite); + Bit8u * changed = &CC[render.scale.outLine][1]; + Bitu b; + for (b=0;b 1) + PTYPE * line1; +#endif +#if (SCALERHEIGHT > 2) + PTYPE * line2; +#endif + +#if defined ( SCALERSIMPLE ) + if (!changed[b]) { + line0 += SCALERWIDTH * SCALER_BLOCKSIZE; + fc += SCALER_BLOCKSIZE; + continue; + } +#else + switch (changed[b]) { + case 0: + line0 += SCALERWIDTH * SCALER_BLOCKSIZE; + fc += SCALER_BLOCKSIZE; + continue; + case SCALE_LEFT: +#if (SCALERHEIGHT > 1) + line1 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch); +#endif +#if (SCALERHEIGHT > 2) + line2 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch * 2); +#endif + SCALERFUNC; + line0 += SCALERWIDTH * SCALER_BLOCKSIZE; + fc += SCALER_BLOCKSIZE; + break; + case SCALE_LEFT | SCALE_RIGHT: +#if (SCALERHEIGHT > 1) + line1 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch); +#endif +#if (SCALERHEIGHT > 2) + line2 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch * 2); +#endif + SCALERFUNC; + case SCALE_RIGHT: +#if (SCALERHEIGHT > 1) + line1 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch); +#endif +#if (SCALERHEIGHT > 2) + line2 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch * 2); +#endif + line0 += SCALERWIDTH * (SCALER_BLOCKSIZE -1); +#if (SCALERHEIGHT > 1) + line1 += SCALERWIDTH * (SCALER_BLOCKSIZE -1); +#endif +#if (SCALERHEIGHT > 2) + line2 += SCALERWIDTH * (SCALER_BLOCKSIZE -1); +#endif + fc += SCALER_BLOCKSIZE -1; + SCALERFUNC; + line0 += SCALERWIDTH; + fc++; + break; + default: +#endif //SCALERSIMPLE + +#if defined(SCALERLINEAR) +#if (SCALERHEIGHT > 1) + line1 = WC[0]; +#endif +#if (SCALERHEIGHT > 2) + line2 = WC[1]; +#endif +#else +#if (SCALERHEIGHT > 1) + line1 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch); +#endif +#if (SCALERHEIGHT > 2) + line2 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch * 2); +#endif +#endif //defined(SCALERLINEAR) + for (Bitu i = 0; i 1) + line1 += SCALERWIDTH; +#endif +#if (SCALERHEIGHT > 2) + line2 += SCALERWIDTH; +#endif + fc++; + } +#if defined(SCALERLINEAR) +#if (SCALERHEIGHT > 1) + BituMove((Bit8u*)(&line0[-SCALER_BLOCKSIZE*SCALERWIDTH])+render.scale.outPitch ,WC[0], SCALER_BLOCKSIZE *SCALERWIDTH*PSIZE); +#endif +#if (SCALERHEIGHT > 2) + BituMove((Bit8u*)(&line0[-SCALER_BLOCKSIZE*SCALERWIDTH])+render.scale.outPitch*2,WC[1], SCALER_BLOCKSIZE *SCALERWIDTH*PSIZE); +#endif +#endif //defined(SCALERLINEAR) +#if !defined (SCALERSIMPLE) + break; + } +#endif + /* Clear this block being dirty marker */ + changed[b] = 0; + } +#if defined(SCALERLINEAR) + Bitu scaleLines = SCALERHEIGHT; + render.scale.outWrite += render.scale.outPitch * scaleLines; +#else + Bitu scaleLines = SCALERHEIGHT; + if ( Scaler_Aspect[ render.scale.outLine ] ) { + scaleLines++; + BituMove( render.scale.outWrite + render.scale.outPitch * SCALERHEIGHT, + render.scale.outWrite + render.scale.outPitch * (SCALERHEIGHT-1), + render.src.width * SCALERWIDTH * PSIZE); + render.scale.outWrite += render.scale.outPitch * (SCALERHEIGHT + 1); + } else { + render.scale.outWrite += render.scale.outPitch * SCALERHEIGHT; + } +#endif + /* Keep track of changed lines */ + if (Scaler_ChangedLineIndex & 1) { + Scaler_ChangedLines[Scaler_ChangedLineIndex] += scaleLines; + } else { + Scaler_ChangedLines[++Scaler_ChangedLineIndex] = scaleLines; + } + if (++render.scale.outLine == render.scale.inHeight) + goto lastagain; +} + +#if !defined(SCALERLINEAR) +#define SCALERLINEAR 1 +#include "render_loops.h" +#undef SCALERLINEAR +#endif diff --git a/src/gui/render_scalers.cpp b/src/gui/render_scalers.cpp index 6a723b54..c67c7a39 100644 --- a/src/gui/render_scalers.cpp +++ b/src/gui/render_scalers.cpp @@ -16,30 +16,28 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +//TODO: +//Maybe just do the cache checking back into the simple scalers so they can +//just handle it all in one go, but this seems to work well enough for now + #include "dosbox.h" -#include "render_scalers.h" +#include "render.h" +#include -Bitu Scaler_Line; -Bitu Scaler_SrcWidth; -Bitu Scaler_SrcHeight; -Bitu Scaler_DstPitch; -Bit8u * Scaler_DstWrite; -Bit8u * Scaler_Index; -Bit8u Scaler_Data[SCALER_MAXHEIGHT*5]; //5cmds/line -PaletteLut Scaler_PaletteLut; +Bit8u Scaler_Aspect[SCALER_MAXHEIGHT]; +Bit16u Scaler_ChangedLines[SCALER_MAXHEIGHT]; +Bitu Scaler_ChangedLineIndex; -static union { - Bit32u b32 [4][SCALER_MAXWIDTH]; - Bit16u b16 [4][SCALER_MAXWIDTH]; - Bit8u b8 [4][SCALER_MAXWIDTH]; -} line_cache; -static union { +union { Bit32u b32 [4][SCALER_MAXWIDTH*3]; Bit16u b16 [4][SCALER_MAXWIDTH*3]; Bit8u b8 [4][SCALER_MAXWIDTH*3]; -} write_cache; +} scalerWriteCache; +scalerFrameCache_t scalerFrameCache; +scalerSourceCache_t scalerSourceCache; -static Bit8u * ln[3]; +Bit8u scalerChangeCache [SCALER_MAXHEIGHT][SCALER_MAXWIDTH / SCALER_BLOCKSIZE]; #define _conc2(A,B) A ## B #define _conc3(A,B,C) A ## B ## C @@ -52,7 +50,15 @@ static Bit8u * ln[3]; #define conc2d(A,B) _conc3(A,_,B) #define conc3d(A,B,C) _conc5(A,_,B,_,C) -#define BituMove(_DST,_SRC,_SIZE) \ +static INLINE void BituMove( void *_dst, const void * _src, Bitu size) { + Bitu * dst=(Bitu *)(_dst); + const Bitu * src=(Bitu *)(_src); + size/=sizeof(Bitu); + for (Bitu x=0; x -#define SCALER_MAXWIDTH 1280 -#define SCALER_MAXHEIGHT 1024 +#define SCALER_MAXWIDTH 1024 +#define SCALER_MAXHEIGHT 768 +#define SCALER_BLOCKSIZE 16 -extern Bitu Scaler_Line; -extern Bitu Scaler_SrcWidth; -extern Bitu Scaler_SrcHeight; -extern Bitu Scaler_DstPitch; -extern Bit8u * Scaler_DstWrite; -extern Bit8u Scaler_Data[]; -extern Bit8u * Scaler_Index; +typedef enum { + scalerMode8, scalerMode15, scalerMode16, scalerMode32 +} scalerMode_t; -union PaletteLut { - Bit16u b16[256]; - Bit32u b32[256]; -}; +typedef enum { + scalerOpNormal, + scalerOpAdvMame, + scalerOpAdvInterp, + scalerOpTV, + scalerOpRGB, + scalerOpScan, +} scalerOperation_t; -extern PaletteLut Scaler_PaletteLut; +typedef void (*ScalerCacheHandler_t)(const void *src); +typedef void (*ScalerLineHandler_t)(void); -enum RENDER_Operation { - OP_Normal, - OP_Normal2x, - OP_AdvMame2x, - OP_AdvMame3x, - OP_AdvInterp2x, - OP_Interp2x, - OP_TV2x, -}; +extern Bit8u Scaler_Aspect[]; +extern Bit8u diff_table[]; +extern Bitu Scaler_ChangedLineIndex; +extern Bit16u Scaler_ChangedLines[]; +extern Bit8u scalerChangeCache [SCALER_MAXHEIGHT][SCALER_MAXWIDTH / SCALER_BLOCKSIZE]; +typedef union { + Bit32u b32 [(SCALER_MAXHEIGHT+2)] [(SCALER_MAXWIDTH+2)]; + Bit16u b16 [(SCALER_MAXHEIGHT+2)] [(SCALER_MAXWIDTH+2)]; + Bit8u b8 [(SCALER_MAXHEIGHT+2)] [(SCALER_MAXWIDTH+2)]; +} scalerFrameCache_t; +typedef union { + Bit32u b32 [SCALER_MAXHEIGHT] [SCALER_MAXWIDTH]; + Bit16u b16 [SCALER_MAXHEIGHT] [SCALER_MAXWIDTH]; + Bit8u b8 [SCALER_MAXHEIGHT] [SCALER_MAXWIDTH]; +} scalerSourceCache_t; -struct ScalerBlock { - Bitu flags; - Bitu xscale,yscale,miny; - RENDER_Line_Handler handlers[4]; -}; +extern scalerFrameCache_t scalerFrameCache; +extern scalerSourceCache_t scalerSourceCache; -extern ScalerBlock Normal_8; -extern ScalerBlock NormalDbl_8; -extern ScalerBlock Normal2x_8; -extern ScalerBlock AdvMame2x_8; -extern ScalerBlock AdvMame3x_8; -extern ScalerBlock AdvInterp2x_8; -extern ScalerBlock Interp2x_8; -extern ScalerBlock TV2x_8; +#define ScaleFlagSimple 0x001 +typedef struct { + Bitu gfxFlags; + Bitu scaleFlags; + Bitu xscale,yscale; + ScalerLineHandler_t Linear[4]; + ScalerLineHandler_t Random[4]; +} ScalerLineBlock_t; + +typedef struct { + Bitu gfxFlags; + Bitu scaleFlags; + Bitu xscale,yscale; + ScalerLineHandler_t Linear[4][4]; + ScalerLineHandler_t Random[4][4]; +} ScalerFullLineBlock_t; + + +typedef struct { + ScalerCacheHandler_t simple[4]; + ScalerCacheHandler_t complex[4]; +} ScalerCacheBlock_t; + +extern ScalerLineBlock_t ScaleNormal; +extern ScalerLineBlock_t ScaleNormalDw; +extern ScalerLineBlock_t ScaleNormalDh; + +#define SCALE_LEFT 0x1 +#define SCALE_RIGHT 0x2 +#define SCALE_FULL 0x4 + +extern ScalerLineBlock_t ScaleNormal2x; +extern ScalerLineBlock_t ScaleNormal3x; +extern ScalerLineBlock_t ScaleAdvMame2x; +extern ScalerLineBlock_t ScaleAdvMame3x; +extern ScalerLineBlock_t ScaleAdvInterp2x; + +extern ScalerLineBlock_t ScaleTV2x; +extern ScalerLineBlock_t ScaleTV3x; +extern ScalerLineBlock_t ScaleRGB2x; +extern ScalerLineBlock_t ScaleRGB3x; +extern ScalerLineBlock_t ScaleScan2x; +extern ScalerLineBlock_t ScaleScan3x; + +extern ScalerCacheBlock_t ScalerCache_8; +extern ScalerCacheBlock_t ScalerCache_8Pal; +extern ScalerCacheBlock_t ScalerCache_15; +extern ScalerCacheBlock_t ScalerCache_16; +extern ScalerCacheBlock_t ScalerCache_32; #endif diff --git a/src/gui/render_templates.h b/src/gui/render_templates.h index 9a129328..18c11083 100644 --- a/src/gui/render_templates.h +++ b/src/gui/render_templates.h @@ -19,294 +19,502 @@ #if DBPP == 8 #define PSIZE 1 #define PTYPE Bit8u -#define WC write_cache.b8 -#define LC line_cache.b8 -#define redblueMask 0 -#define greenMask 0 +#define WC scalerWriteCache.b8 +#define FC scalerFrameCache.b8 +#define redMask 0 +#define greenMask 0 +#define blueMask 0 #elif DBPP == 15 || DBPP == 16 #define PSIZE 2 #define PTYPE Bit16u -#define WC write_cache.b16 -#define LC line_cache.b16 +#define WC scalerWriteCache.b16 +#define FC scalerFrameCache.b16 #if DBPP == 15 -#define redblueMask 0x7C1F -#define greenMask 0x03E0 +#define redMask 0x7C00 +#define greenMask 0x03E0 +#define blueMask 0x001F #elif DBPP == 16 -#define redblueMask 0xF81F -#define greenMask 0x07E0 +#define redMask 0xF800 +#define greenMask 0x07E0 +#define blueMask 0x001F #endif #elif DBPP == 32 #define PSIZE 4 #define PTYPE Bit32u -#define WC write_cache.b32 -#define LC line_cache.b32 -#define redblueMask 0xff00ff -#define greenMask 0xff00 +#define WC scalerWriteCache.b32 +#define FC scalerFrameCache.b32 +#define redMask 0xff0000 +#define greenMask 0x00ff00 +#define blueMask 0x0000ff #endif +#define redblueMask (redMask | blueMask) + + #if SBPP == 8 +#define SC scalerSourceCache.b8 #if DBPP == 8 -#define PMAKE(_VAL) _VAL +#define PMAKE(_VAL) (_VAL) #elif DBPP == 15 -#define PMAKE(_VAL) Scaler_PaletteLut.b16[_VAL] +#define PMAKE(_VAL) render.pal.lut.b16[_VAL] #elif DBPP == 16 -#define PMAKE(_VAL) Scaler_PaletteLut.b16[_VAL] +#define PMAKE(_VAL) render.pal.lut.b16[_VAL] #elif DBPP == 32 -#define PMAKE(_VAL) Scaler_PaletteLut.b32[_VAL] +#define PMAKE(_VAL) render.pal.lut.b32[_VAL] #endif +#define SRCTYPE Bit8u #endif -#define C0 LC[0][x-1] -#define C1 LC[0][x+0] -#define C2 LC[0][x+1] -#define C3 LC[1][x-1] -#define C4 LC[1][x+0] -#define C5 LC[1][x+1] -#define C6 LC[2][x-1] -#define C7 LC[2][x+0] -#define C8 LC[2][x+1] +#if SBPP == 15 +#define SC scalerSourceCache.b16 +#if DBPP == 15 +#define PMAKE(_VAL) (_VAL) +#elif DBPP == 16 +#define PMAKE(_VAL) (((_VAL) & 31) | ((_VAL) & ~31) << 1) +#elif DBPP == 32 +#define PMAKE(_VAL) (((_VAL&(31<<10))<<9)|((_VAL&(31<<5))<<6)|((_VAL&31)<<3)) +#endif +#define SRCTYPE Bit16u +#endif -static void conc3d(Normal,SBPP,DBPP) (const Bit8u * src) { - const Bit8u * line; -#if SBPP == DBPP - line=src; - BituMove(Scaler_DstWrite,line,Scaler_SrcWidth*PSIZE); +#if SBPP == 16 +#define SC scalerSourceCache.b16 +#if DBPP == 15 +#define PMAKE(_VAL) (((_VAL&~31)>>1)|(_VAL&31)) +#elif DBPP == 16 +#define PMAKE(_VAL) (_VAL) +#elif DBPP == 32 +#define PMAKE(_VAL) (((_VAL&(31<<11))<<8)|((_VAL&(63<<5))<<5)|((_VAL&31)<<3)) +#endif +#define SRCTYPE Bit16u +#endif + +#if SBPP == 32 +#define SC scalerSourceCache.b32 +#if DBPP == 15 +#define PMAKE(_VAL) (PTYPE)(((_VAL&(31<<19))>>9)|((_VAL&(31<<11))>>6)|((_VAL&(31<<3))>>3)) +#elif DBPP == 16 +#define PMAKE(_VAL) (PTYPE)(((_VAL&(31<<19))>>8)|((_VAL&(63<<10))>>4)|((_VAL&(31<<3))>>3)) +#elif DBPP == 32 +#define PMAKE(_VAL) (_VAL) +#endif +#define SRCTYPE Bit32u +#endif + +#define C0 fc[-1 - SCALER_MAXWIDTH -2] +#define C1 fc[+0 - SCALER_MAXWIDTH -2] +#define C2 fc[+1 - SCALER_MAXWIDTH -2] +#define C3 fc[-1 ] +#define C4 fc[+0 ] +#define C5 fc[+1 ] +#define C6 fc[-1 + SCALER_MAXWIDTH +2] +#define C7 fc[+0 + SCALER_MAXWIDTH +2] +#define C8 fc[+1 + SCALER_MAXWIDTH +2] + +#if defined (CACHEWITHPAL) +static void conc3d(CacheComplexPal,SBPP,DBPP) (const void * s) { #else - PTYPE * dst=(PTYPE *)Scaler_DstWrite; - line=line_cache.b8[0]; - for (Bitu x=0;x 8) -static void conc3d(TV2x,SBPP,DBPP) (const Bit8u * src) { - PTYPE * dst=(PTYPE *)Scaler_DstWrite; - for (Bitu x=0;x> 3) & redblueMask; - halfpixel|=(((pixel & greenMask) * 7) >> 3) & greenMask; - dst[x*2+0]=dst[x*2+1]=halfpixel; - LC[0][x*2+0]=LC[0][x*2+1]=pixel; - } - Scaler_DstWrite+=Scaler_DstPitch; - for (Bitu lines=*Scaler_Index++;lines;lines--) { - BituMove(Scaler_DstWrite,LC[0],Scaler_SrcWidth*2*PSIZE); - Scaler_DstWrite+=Scaler_DstPitch; - } -} -static void conc3d(Interp2x,SBPP,DBPP) (const Bit8u * src) { - if (!Scaler_Line) { - Scaler_Line++; - for (Bitu tempx=Scaler_SrcWidth;tempx>0;tempx--) { - LC[1][tempx] = LC[2][tempx] = PMAKE(src[tempx]); - } - return; - } -lastagain: - Bitu x=0; - PTYPE * dst=(PTYPE *)Scaler_DstWrite; - C1=C4;C4=C7;C7=PMAKE(src[x]); - C2=C5;C5=C8;C8=PMAKE(src[x+1]); - dst[0] = interp_w2(C4,C1,3,1); - dst[1] = interp_w4(C4,C1,C2,C5,5,1,1,1); - WC[1][0] = interp_w2(C4,C7,3,1); - WC[1][1] = interp_w4(C4,C5,C8,C7,5,1,1,1); - for (x=1;x> 3) & redblueMask; \ + halfpixel|=(((C4 & greenMask) * 5) >> 3) & greenMask; \ + line0[0]=C4; \ + line0[1]=C4; \ + line1[0]=halfpixel; \ + line1[1]=halfpixel; \ } +#include "render_loops.h" +#undef SCALERNAME +#undef SCALERWIDTH +#undef SCALERHEIGHT +#undef SCALERFUNC +#undef SCALERSIMPLE -static void conc3d(AdvInterp2x,SBPP,DBPP) (const Bit8u * src) { - if (!Scaler_Line) { - Scaler_Line++; - for (Bitu tempx=Scaler_SrcWidth;tempx>0;tempx--) { - LC[1][tempx]=LC[2][tempx]=PMAKE(src[tempx]); - } - return; - } -lastagain: - Bitu x=0; - PTYPE * dst=(PTYPE *)Scaler_DstWrite; - C1=C4;C4=C7;C7=PMAKE(src[x]); - C2=C5;C5=C8;C8=PMAKE(src[x+1]); - dst[0]=C4; - WC[1][0]=C4; - dst[1] = C5 == C1 && C7 != C1 ? C2 : C4; - WC[1][1]= C5 == C7 && C1 != C7 ? C7 : C4; - for (x=1;x0;lines--) { - BituMove(Scaler_DstWrite,&WC[1],2*Scaler_SrcWidth*PSIZE); - Scaler_DstWrite+=Scaler_DstPitch; - } - if (++Scaler_Line==Scaler_SrcHeight) goto lastagain; + +#define SCALERSIMPLE 1 +#define SCALERNAME TV3x +#define SCALERWIDTH 3 +#define SCALERHEIGHT 3 +#define SCALERFUNC \ +{ \ + Bitu halfpixel=(((C4 & redblueMask) * 5) >> 3) & redblueMask; \ + halfpixel|=(((C4 & greenMask) * 5) >> 3) & greenMask; \ + line0[0]=C4; \ + line0[1]=C4; \ + line0[2]=C4; \ + line1[0]=halfpixel; \ + line1[1]=halfpixel; \ + line1[2]=halfpixel; \ + halfpixel=(((C4 & redblueMask) * 5) >> 4) & redblueMask; \ + halfpixel|=(((C4 & greenMask) * 5) >> 4) & greenMask; \ + line2[0]=halfpixel; \ + line2[1]=halfpixel; \ + line2[2]=halfpixel; \ } +#include "render_loops.h" +#undef SCALERNAME +#undef SCALERWIDTH +#undef SCALERHEIGHT +#undef SCALERFUNC +#undef SCALERSIMPLE + +#define SCALERSIMPLE 1 +#define SCALERNAME RGB2x +#define SCALERWIDTH 2 +#define SCALERHEIGHT 2 +#define SCALERFUNC \ + line0[0]=C4 & redMask; \ + line0[1]=C4 & greenMask; \ + line1[0]=C4 & blueMask; \ + line1[1]=C4; +#include "render_loops.h" +#undef SCALERNAME +#undef SCALERWIDTH +#undef SCALERHEIGHT +#undef SCALERFUNC +#undef SCALERSIMPLE + + +#define SCALERSIMPLE 1 +#define SCALERNAME RGB3x +#define SCALERWIDTH 3 +#define SCALERHEIGHT 3 +#define SCALERFUNC \ + line0[0]=C4; \ + line0[1]=C4 & greenMask; \ + line0[2]=C4 & blueMask; \ + line1[0]=C4 & blueMask; \ + line1[1]=C4; \ + line1[2]=C4 & redMask; \ + line2[0]=C4 & redMask; \ + line2[1]=C4 & greenMask; \ + line2[2]=C4; +#include "render_loops.h" +#undef SCALERNAME +#undef SCALERWIDTH +#undef SCALERHEIGHT +#undef SCALERFUNC +#undef SCALERSIMPLE + + +#define SCALERSIMPLE 1 +#define SCALERNAME Scan2x +#define SCALERWIDTH 2 +#define SCALERHEIGHT 2 +#define SCALERFUNC \ + line0[0]=C4; \ + line0[1]=C4; \ + line1[0]=0; \ + line1[1]=0; +#include "render_loops.h" +#undef SCALERNAME +#undef SCALERWIDTH +#undef SCALERHEIGHT +#undef SCALERFUNC +#undef SCALERSIMPLE + + +#define SCALERSIMPLE 1 +#define SCALERNAME Scan3x +#define SCALERWIDTH 3 +#define SCALERHEIGHT 3 +#define SCALERFUNC \ + line0[0]=C4; \ + line0[1]=C4; \ + line0[2]=C4; \ + line1[0]=0; \ + line1[1]=0; \ + line1[2]=0; \ + line2[0]=0; \ + line2[1]=0; \ + line2[2]=0; +#include "render_loops.h" +#undef SCALERNAME +#undef SCALERWIDTH +#undef SCALERHEIGHT +#undef SCALERFUNC +#undef SCALERSIMPLE + + + +#define SCALERNAME AdvInterp2x +#define SCALERWIDTH 2 +#define SCALERHEIGHT 2 +#define SCALERFUNC \ + if (C1 != C7 && C3 != C5) { \ + line0[0] = C3 == C1 ? interp_w2(C3,C4,5,3) : C4; \ + line0[1] = C1 == C5 ? interp_w2(C5,C4,5,3) : C4; \ + line1[0] = C3 == C7 ? interp_w2(C3,C4,5,3) : C4; \ + line1[1] = C7 == C5 ? interp_w2(C5,C4,5,3) : C4; \ + } else { \ + line0[0] = line0[1] = C4; \ + line1[0] = line1[1] = C4; \ + } +#include "render_loops.h" +#undef SCALERNAME +#undef SCALERWIDTH +#undef SCALERHEIGHT +#undef SCALERFUNC + +#define SCALERNAME AdvInterp3x +#define SCALERWIDTH 3 +#define SCALERHEIGHT 3 +#define SCALERFUNC \ + if (C1 != C7 && C3 != C5) { \ + line0[0] = C3 == C1 ? interp_w2(C3,C4,5,3) : C4; \ + line0[1] = C1 == C5 ? interp_w2(C5,C4,5,3) : C4; \ + line1[0] = C3 == C7 ? interp_w2(C3,C4,5,3) : C4; \ + line1[1] = C7 == C5 ? interp_w2(C5,C4,5,3) : C4; \ + } else { \ + line0[0] = line0[1] = C4; \ + line1[0] = line1[1] = C4; \ + } +#include "render_loops.h" +#undef SCALERNAME +#undef SCALERWIDTH +#undef SCALERHEIGHT +#undef SCALERFUNC #endif //DBPP > 8 -static void conc3d(AdvMame2x,SBPP,DBPP) (const Bit8u * src) { - if (!Scaler_Line) { - Scaler_Line++; - for (Bitu tempx=Scaler_SrcWidth;tempx>0;tempx--) { - LC[1][tempx]=LC[2][tempx]=PMAKE(src[tempx]); - } - return; +#define SCALERNAME AdvMame2x +#define SCALERWIDTH 2 +#define SCALERHEIGHT 2 +#define SCALERFUNC \ + if (C1 != C7 && C3 != C5) { \ + line0[0] = C3 == C1 ? C3 : C4; \ + line0[1] = C1 == C5 ? C5 : C4; \ + line1[0] = C3 == C7 ? C3 : C4; \ + line1[1] = C7 == C5 ? C5 : C4; \ + } else { \ + line0[0] = line0[1] = C4; \ + line1[0] = line1[1] = C4; \ } -lastagain: - Bitu x=0; - PTYPE * dst=(PTYPE *)Scaler_DstWrite; - C1=C4;C4=C7;C7=PMAKE(src[x]); - C2=C5;C5=C8;C8=PMAKE(src[x+1]); - dst[0]=C4; - WC[1][0]=C4; - dst[1] = C5 == C1 && C7 != C1 ? C2 : C4; - WC[1][1]= C5 == C7 && C1 != C7 ? C7 : C4; - for (x=1;x0;lines--) { - BituMove(Scaler_DstWrite,&WC[1],2*Scaler_SrcWidth*PSIZE); - Scaler_DstWrite+=Scaler_DstPitch; - } - if (++Scaler_Line==Scaler_SrcHeight) goto lastagain; -} +#include "render_loops.h" +#undef SCALERNAME +#undef SCALERWIDTH +#undef SCALERHEIGHT +#undef SCALERFUNC -static void conc3d(AdvMame3x,SBPP,DBPP) (const Bit8u * src) { - if (!Scaler_Line) { - Scaler_Line++; - for (Bitu tempx=Scaler_SrcWidth;tempx>0;tempx--) { - LC[1][tempx]=LC[2][tempx]=PMAKE(src[tempx]); - } - return; +#define SCALERNAME AdvMame3x +#define SCALERWIDTH 3 +#define SCALERHEIGHT 3 +#define SCALERFUNC \ + if ((C1 != C7) && (C3 != C5)) { \ + line0[0] = C3 == C1 ? C3 : C4; \ + line0[1] = (C3 == C1 && C4 != C2) || (C5 == C1 && C4 != C0) ? C1 : C4; \ + line0[2] = C5 == C1 ? C5 : C4; \ + line1[0] = (C3 == C1 && C4 != C6) || (C3 == C7 && C4 != C0) ? C3 : C4; \ + line1[1] = C4; \ + line1[2] = (C5 == C1 && C4 != C8) || (C5 == C7 && C4 != C2) ? C5 : C4; \ + line2[0] = C3 == C7 ? C3 : C4; \ + line2[1] = (C3 == C7 && C4 != C8) || (C5 == C7 && C4 != C6) ? C7 : C4; \ + line2[2] = C5 == C7 ? C5 : C4; \ + } else { \ + line0[0] = line0[1] = line0[2] = C4; \ + line1[0] = line1[1] = line1[2] = C4; \ + line2[0] = line2[1] = line2[2] = C4; \ } -lastagain: - PTYPE * dst=(PTYPE *)Scaler_DstWrite; - LC[0][0]=LC[1][0];LC[1][0]=LC[2][0];LC[2][0]=PMAKE(src[0]); - LC[0][1]=LC[1][1];LC[1][1]=LC[2][1];LC[2][1]=PMAKE(src[1]); - /* first pixel */ - dst[0] = LC[1][0]; - dst[1] = LC[1][0]; - dst[2] = (LC[1][1] == LC[0][0] && LC[2][0] != LC[0][0]) ? LC[0][0] : LC[1][0]; - WC[1][0] = LC[1][0]; - WC[1][1] = LC[1][0]; - WC[1][2] = (LC[0][0] != LC[2][0]) ? (((LC[1][1] == LC[0][0] && LC[1][0] != LC[2][1]) || (LC[1][1] == LC[2][0] && LC[1][0] != LC[0][1])) ? LC[1][1] : LC[1][0]) : LC[1][0]; - WC[2][0] = LC[1][0]; - WC[2][1] = LC[1][0]; - WC[2][2] = (LC[1][1] == LC[2][0] && LC[0][0] != LC[2][0]) ? LC[2][0] : LC[1][0]; - Bitu x; - for (x=1;x0;lines--) { - BituMove(Scaler_DstWrite,&WC[2],3*Scaler_SrcWidth*PSIZE); - Scaler_DstWrite+=Scaler_DstPitch; - } - if (++Scaler_Line==Scaler_SrcHeight) goto lastagain; -} + +#include "render_loops.h" +#undef SCALERNAME +#undef SCALERWIDTH +#undef SCALERHEIGHT +#undef SCALERFUNC + + +#endif // (SBPP == DBPP) && !defined (CACHEWITHPAL) #undef PSIZE #undef PTYPE #undef PMAKE #undef WC #undef LC +#undef FC +#undef SC +#undef redMask #undef greenMask +#undef blueMask #undef redblueMask +#undef SRCTYPE - +#if (SBPP == 8) && (DBPP > 8) && !defined (CACHEWITHPAL) +#define CACHEWITHPAL 1 +#include "render_templates.h" +#undef CACHEWITHPAL +#endif diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 8b7790e0..e37efa6d 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: sdlmain.cpp,v 1.95 2006-01-22 14:13:00 qbix79 Exp $ */ +/* $Id: sdlmain.cpp,v 1.96 2006-01-30 09:58:07 harekiet Exp $ */ #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -144,20 +144,25 @@ struct SDL_Block { struct { Bit32u width; Bit32u height; + Bit32u bpp; Bitu flags; - GFX_Modes mode; double scalex,scaley; GFX_ResetCallBack reset; } draw; bool wait_on_error; struct { - Bit32u width,height,bpp; - bool fixed; + struct { + Bit16u width, height; + bool fixed; + } full; + struct { + Bit16u width, height; + } window; + Bit8u bpp; bool fullscreen; bool doublebuf; SCREEN_TYPES type; SCREEN_TYPES want_type; - double hwscale; } desktop; #if C_OPENGL struct { @@ -196,6 +201,7 @@ struct SDL_Block { bool locked; Bitu sensitivity; } mouse; + SDL_Rect updateRects[1024]; }; static SDL_Block sdl; @@ -249,47 +255,51 @@ Bitu GFX_GetBestMode(Bitu flags) { case SCREEN_SURFACE: check_surface: /* Check if we can satisfy the depth it loves */ - if (flags & LOVE_8) testbpp=8; - else if (flags & LOVE_16) testbpp=16; - else if (flags & LOVE_32) testbpp=32; + if (flags & GFX_LOVE_8) testbpp=8; + else if (flags & GFX_LOVE_15) testbpp=15; + else if (flags & GFX_LOVE_16) testbpp=16; + else if (flags & GFX_LOVE_32) testbpp=32; check_gotbpp: if (sdl.desktop.fullscreen) gotbpp=SDL_VideoModeOK(640,480,testbpp,SDL_FULLSCREEN|SDL_HWSURFACE|SDL_HWPALETTE); else gotbpp=sdl.desktop.bpp; /* If we can't get our favorite mode check for another working one */ switch (gotbpp) { case 8: - if (flags & CAN_8) flags&=~(CAN_16|CAN_32); + if (flags & GFX_CAN_8) flags&=~(GFX_CAN_15|GFX_CAN_16|GFX_CAN_32); break; case 15: + if (flags & GFX_CAN_15) flags&=~(GFX_CAN_8|GFX_CAN_16|GFX_CAN_32); + break; case 16: - if (flags & CAN_16) flags&=~(CAN_8|CAN_32); + if (flags & GFX_CAN_16) flags&=~(GFX_CAN_8|GFX_CAN_15|GFX_CAN_32); break; case 24: case 32: - if (flags & CAN_32) flags&=~(CAN_8|CAN_16); + if (flags & GFX_CAN_32) flags&=~(GFX_CAN_8|GFX_CAN_15|GFX_CAN_16); break; } - /* Not a valid display depth found? Let's just hope sdl provides conversions */ + flags |= GFX_CAN_RANDOM; break; #if (HAVE_DDRAW_H) && defined(WIN32) case SCREEN_SURFACE_DDRAW: - if (!(flags&(CAN_32|CAN_16))) goto check_surface; - if (flags & LOVE_16) testbpp=16; - else if (flags & LOVE_32) testbpp=32; + if (!(flags&(GFX_CAN_15|GFX_CAN_16|GFX_CAN_32))) goto check_surface; + if (flags & GFX_LOVE_15) testbpp=15; + else if (flags & GFX_LOVE_16) testbpp=16; + else if (flags & GFX_LOVE_32) testbpp=32; else testbpp=0; - flags|=HAVE_SCALING; + flags|=GFX_SCALING; goto check_gotbpp; #endif case SCREEN_OVERLAY: - if (flags & NEED_RGB || !(flags&CAN_32)) goto check_surface; - flags|=HAVE_SCALING; - flags&=~(CAN_8|CAN_16); + if (flags & GFX_RGBONLY || !(flags&GFX_CAN_32)) goto check_surface; + flags|=GFX_SCALING; + flags&=~(GFX_CAN_8|GFX_CAN_15|GFX_CAN_16); break; #if C_OPENGL case SCREEN_OPENGL: - if (flags & NEED_RGB || !(flags&CAN_32)) goto check_surface; - flags|=HAVE_SCALING; - flags&=~(CAN_8|CAN_16); + if (flags & GFX_RGBONLY || !(flags&GFX_CAN_32)) goto check_surface; + flags|=GFX_SCALING; + flags&=~(GFX_CAN_8|GFX_CAN_15|GFX_CAN_16); break; #endif } @@ -299,7 +309,7 @@ check_gotbpp: void GFX_ResetScreen(void) { GFX_Stop(); - if (sdl.draw.reset) (sdl.draw.reset)(); + if (sdl.draw.reset) (sdl.draw.reset)( false ); GFX_Start(); } @@ -311,86 +321,91 @@ static int int_log2 (int val) { } -static SDL_Surface * GFX_SetupSurfaceScaled(Bit32u sdl_flags,Bit32u bpp) { +static SDL_Surface * GFX_SetupSurfaceScaled(Bit32u sdl_flags, Bit32u bpp) { + Bit16u fixedWidth; + Bit16u fixedHeight; + if (sdl.desktop.fullscreen) { - if (sdl.desktop.fixed) { - double ratio_w=(double)sdl.desktop.width/(sdl.draw.width*sdl.draw.scalex); - double ratio_h=(double)sdl.desktop.height/(sdl.draw.height*sdl.draw.scaley); - if ( ratio_w < ratio_h) { - sdl.clip.w=(Bit16u)sdl.desktop.width; - sdl.clip.h=(Bit16u)(sdl.draw.height*sdl.draw.scaley*ratio_w); - } else { - sdl.clip.w=(Bit16u)(sdl.draw.width*sdl.draw.scalex*ratio_h); - sdl.clip.h=(Bit16u)sdl.desktop.height; - } - sdl.clip.x=(Sint16)((sdl.desktop.width-sdl.clip.w)/2); - sdl.clip.y=(Sint16)((sdl.desktop.height-sdl.clip.h)/2); - sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,bpp,sdl_flags|SDL_FULLSCREEN|SDL_HWSURFACE); - if (sdl.surface == NULL) E_Exit("Could not set fullscreen video mode %ix%i-%i: %s",sdl.desktop.width,sdl.desktop.height,bpp,SDL_GetError()); - return sdl.surface; + fixedWidth = sdl.desktop.full.fixed ? sdl.desktop.full.width : 0; + fixedHeight = sdl.desktop.full.fixed ? sdl.desktop.full.height : 0; + sdl_flags |= SDL_FULLSCREEN|SDL_HWSURFACE; + } else { + fixedWidth = sdl.desktop.window.width; + fixedHeight = sdl.desktop.window.height; + sdl_flags |= SDL_HWSURFACE; + } + if (fixedWidth && fixedHeight) { + double ratio_w=(double)fixedWidth/(sdl.draw.width*sdl.draw.scalex); + double ratio_h=(double)fixedHeight/(sdl.draw.height*sdl.draw.scaley); + if ( ratio_w < ratio_h) { + sdl.clip.w=fixedWidth; + sdl.clip.h=(Bit16u)(sdl.draw.height*sdl.draw.scaley*ratio_w); } else { - sdl.clip.x=0;sdl.clip.y=0; - sdl.clip.w=(Bit16u)(sdl.draw.width*sdl.draw.scalex); - sdl.clip.h=(Bit16u)(sdl.draw.height*sdl.draw.scaley); - sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,bpp,sdl_flags|SDL_FULLSCREEN|SDL_HWSURFACE); - if (sdl.surface == NULL) E_Exit("Could not set fullscreen video mode %ix%i-%i: %s",sdl.clip.w,sdl.clip.h,bpp,SDL_GetError()); - return sdl.surface; + sdl.clip.w=(Bit16u)(sdl.draw.width*sdl.draw.scalex*ratio_h); + sdl.clip.h=(Bit16u)fixedHeight; } + if (sdl.desktop.fullscreen) + sdl.surface = SDL_SetVideoMode(fixedWidth,fixedHeight,bpp,sdl_flags); + else + sdl.surface = SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,bpp,sdl_flags); + if (sdl.surface && sdl.surface->flags & SDL_FULLSCREEN) { + sdl.clip.x=(Sint16)((sdl.surface->w-sdl.clip.w)/2); + sdl.clip.y=(Sint16)((sdl.surface->h-sdl.clip.h)/2); + } else { + sdl.clip.x = 0; + sdl.clip.y = 0; + } + return sdl.surface; } else { sdl.clip.x=0;sdl.clip.y=0; - sdl.clip.w=(Bit16u)(sdl.draw.width*sdl.draw.scalex*sdl.desktop.hwscale); - sdl.clip.h=(Bit16u)(sdl.draw.height*sdl.draw.scaley*sdl.desktop.hwscale); - sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,bpp,sdl_flags|SDL_HWSURFACE); -#ifdef WIN32 - if (sdl.surface == NULL) { - LOG_MSG("Failed to create hardware surface.\nRestarting video subsystem with windib enabled."); - SDL_QuitSubSystem(SDL_INIT_VIDEO); - putenv("SDL_VIDEODRIVER=windib"); - SDL_InitSubSystem(SDL_INIT_VIDEO); - sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,bpp,sdl_flags|SDL_HWSURFACE); - } -#endif - if (sdl.surface == NULL) E_Exit("Could not set windowed video mode %ix%i-%i: %s",sdl.clip.w,sdl.clip.h,bpp,SDL_GetError()); + sdl.clip.w=(Bit16u)(sdl.draw.width*sdl.draw.scalex); + sdl.clip.h=(Bit16u)(sdl.draw.height*sdl.draw.scaley); + sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,bpp,sdl_flags); return sdl.surface; } } -GFX_Modes GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_ResetCallBack reset) { - if (sdl.updating) GFX_EndUpdate(); +Bitu GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_ResetCallBack reset) { + if (sdl.updating) + GFX_EndUpdate( 0 ); + sdl.draw.width=width; sdl.draw.height=height; - sdl.draw.flags=flags; - sdl.draw.mode=GFX_NONE; sdl.draw.reset=reset; sdl.draw.scalex=scalex; sdl.draw.scaley=scaley; Bitu bpp; + Bitu retFlags; switch (sdl.desktop.want_type) { case SCREEN_SURFACE: dosurface: - if (flags & CAN_8) bpp=8; - if (flags & CAN_16) bpp=16; - if (flags & CAN_32) bpp=32; + if (flags & GFX_CAN_8) bpp=8; + if (flags & GFX_CAN_15) bpp=15; + if (flags & GFX_CAN_16) bpp=16; + if (flags & GFX_CAN_32) bpp=32; sdl.desktop.type=SCREEN_SURFACE; sdl.clip.w=width; sdl.clip.h=height; if (sdl.desktop.fullscreen) { - if (sdl.desktop.fixed) { - sdl.clip.x=(Sint16)((sdl.desktop.width-width)/2); - sdl.clip.y=(Sint16)((sdl.desktop.height-height)/2); - sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,bpp, - SDL_FULLSCREEN|SDL_HWSURFACE|(sdl.desktop.doublebuf ? SDL_DOUBLEBUF|SDL_ASYNCBLIT : 0)|SDL_HWPALETTE); - if (sdl.surface == NULL) E_Exit("Could not set fullscreen video mode %ix%i-%i: %s",sdl.desktop.width,sdl.desktop.height,bpp,SDL_GetError()); + if (sdl.desktop.full.fixed) { + sdl.clip.x=(Sint16)((sdl.desktop.full.width-width)/2); + sdl.clip.y=(Sint16)((sdl.desktop.full.height-height)/2); + sdl.surface=SDL_SetVideoMode(sdl.desktop.full.width,sdl.desktop.full.height,bpp, + SDL_FULLSCREEN | ((flags & GFX_CAN_RANDOM) ? SDL_SWSURFACE : SDL_HWSURFACE) | + (sdl.desktop.doublebuf ? SDL_DOUBLEBUF|SDL_ASYNCBLIT : 0) | SDL_HWPALETTE); + if (sdl.surface == NULL) E_Exit("Could not set fullscreen video mode %ix%i-%i: %s",sdl.desktop.full.width,sdl.desktop.full.height,bpp,SDL_GetError()); } else { sdl.clip.x=0;sdl.clip.y=0; sdl.surface=SDL_SetVideoMode(width,height,bpp, - SDL_FULLSCREEN|SDL_HWSURFACE|(sdl.desktop.doublebuf ? SDL_DOUBLEBUF|SDL_ASYNCBLIT : 0)|SDL_HWPALETTE); - if (sdl.surface == NULL) E_Exit("Could not set fullscreen video mode %ix%i-%i: %s",width,height,bpp,SDL_GetError()); + SDL_FULLSCREEN | ((flags & GFX_CAN_RANDOM) ? SDL_SWSURFACE : SDL_HWSURFACE) | + (sdl.desktop.doublebuf ? SDL_DOUBLEBUF|SDL_ASYNCBLIT : 0)|SDL_HWPALETTE); + if (sdl.surface == NULL) + E_Exit("Could not set fullscreen video mode %ix%i-%i: %s",width,height,bpp,SDL_GetError()); } } else { sdl.clip.x=0;sdl.clip.y=0; - sdl.surface = SDL_SetVideoMode(width,height,bpp,SDL_HWSURFACE); + sdl.surface=SDL_SetVideoMode(width,height,bpp,(flags & GFX_CAN_RANDOM) ? SDL_SWSURFACE : SDL_HWSURFACE); #ifdef WIN32 if (sdl.surface == NULL) { LOG_MSG("Failed to create hardware surface.\nRestarting video subsystem with windib enabled."); @@ -400,21 +415,33 @@ dosurface: sdl.surface = SDL_SetVideoMode(width,height,bpp,SDL_HWSURFACE); } #endif - if (sdl.surface == NULL) E_Exit("Could not set windowed video mode %ix%i-%i: %s",width,height,bpp,SDL_GetError()); + if (sdl.surface == NULL) + E_Exit("Could not set windowed video mode %ix%i-%i: %s",width,height,bpp,SDL_GetError()); } - if (sdl.surface) switch (sdl.surface->format->BitsPerPixel) { - case 8:sdl.draw.mode=GFX_8;break; - case 15:sdl.draw.mode=GFX_15;break; - case 16:sdl.draw.mode=GFX_16;break; - case 32:sdl.draw.mode=GFX_32;break; - default: + if (sdl.surface) { + switch (sdl.surface->format->BitsPerPixel) { + case 8: + retFlags = GFX_CAN_8; + break; + case 15: + retFlags = GFX_CAN_15; break; + case 16: + retFlags = GFX_CAN_16; + break; + case 32: + retFlags = GFX_CAN_32; + break; + } + if (retFlags && sdl.surface->flags & SDL_HWSURFACE) + retFlags |= GFX_HARDWARE; } break; #if (HAVE_DDRAW_H) && defined(WIN32) case SCREEN_SURFACE_DDRAW: - if (flags & CAN_16) bpp=16; - if (flags & CAN_32) bpp=32; + if (flags & GFX_CAN_15) bpp=15; + if (flags & GFX_CAN_16) bpp=16; + if (flags & GFX_CAN_32) bpp=32; if (sdl.blit.surface) { SDL_FreeSurface(sdl.blit.surface); sdl.blit.surface=0; @@ -437,11 +464,15 @@ dosurface: goto dosurface; } switch (sdl.surface->format->BitsPerPixel) { - case 15:sdl.draw.mode=GFX_15;break; - case 16:sdl.draw.mode=GFX_16;break; - case 32:sdl.draw.mode=GFX_32;break; - default: - break; + case 15: + retFlags = GFX_CAN_15 | GFX_SCALING | GFX_HARDWARE; + break; + case 16: + retFlags = GFX_CAN_16 | GFX_SCALING | GFX_HARDWARE; + break; + case 32: + retFlags = GFX_CAN_32 | GFX_SCALING | GFX_HARDWARE; + break; } sdl.desktop.type=SCREEN_SURFACE_DDRAW; break; @@ -451,7 +482,7 @@ dosurface: SDL_FreeYUVOverlay(sdl.overlay); sdl.overlay=0; } - if (!(flags&CAN_32) || (flags & NEED_RGB)) goto dosurface; + if (!(flags&GFX_CAN_32) || (flags & GFX_RGBONLY)) goto dosurface; if (!GFX_SetupSurfaceScaled(0,0)) goto dosurface; sdl.overlay=SDL_CreateYUVOverlay(width*2,height,SDL_UYVY_OVERLAY,sdl.surface); if (!sdl.overlay) { @@ -459,7 +490,7 @@ dosurface: goto dosurface; } sdl.desktop.type=SCREEN_OVERLAY; - sdl.draw.mode=GFX_32; + retFlags = GFX_CAN_32 | GFX_SCALING | GFX_HARDWARE; break; #if C_OPENGL case SCREEN_OPENGL: @@ -472,7 +503,7 @@ dosurface: free(sdl.opengl.framebuf); } sdl.opengl.framebuf=0; - if (!(flags&CAN_32) || (flags & NEED_RGB)) goto dosurface; + if (!(flags&GFX_CAN_32) || (flags & GFX_RGBONLY)) goto dosurface; int texsize=2 << int_log2(width > height ? width : height); if (texsize>sdl.opengl.max_texsize) { LOG_MSG("SDL:OPENGL:No support for texturesize of %d, falling back to surface",texsize); @@ -546,13 +577,18 @@ dosurface: glEnd(); glEndList(); sdl.desktop.type=SCREEN_OPENGL; - sdl.draw.mode=GFX_32; - break; + retFlags = GFX_CAN_32 | GFX_SCALING; +#if defined(NVIDIA_PixelDataRange) + if (sdl.opengl.pixel_data_range) + retFlags |= GFX_HARDWARE; +#endif + break; }//OPENGL #endif //C_OPENGL }//CASE - if (sdl.draw.mode!=GFX_NONE) GFX_Start(); - return sdl.draw.mode; + if (retFlags) + GFX_Start(); + return retFlags; } bool mouselocked; //Global variable for mapper @@ -629,7 +665,8 @@ bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch) { return false; } -void GFX_EndUpdate(void) { + +void GFX_EndUpdate( const Bit16u *changedLines ) { int ret; if (!sdl.updating) return; sdl.updating=false; @@ -637,8 +674,27 @@ void GFX_EndUpdate(void) { case SCREEN_SURFACE: if (SDL_MUSTLOCK(sdl.surface)) { SDL_UnlockSurface(sdl.surface); + SDL_Flip(sdl.surface); + } else if (changedLines) { + Bitu y = 0, index = 0, rectCount = 0; + while (y < sdl.draw.height) { + if (!(index & 1)) { + y += changedLines[index]; + } else { + SDL_Rect *rect = &sdl.updateRects[rectCount++]; + rect->x = sdl.clip.x; + rect->y = sdl.clip.y + y; + rect->w = (Bit16u)sdl.draw.width; + rect->h = changedLines[index]; + y += changedLines[index]; + } + index++; + } + if (rectCount) + SDL_UpdateRects( sdl.surface, rectCount, sdl.updateRects ); + } else { + SDL_Flip(sdl.surface); } - SDL_Flip(sdl.surface); break; #if (HAVE_DDRAW_H) && defined(WIN32) case SCREEN_SURFACE_DDRAW: @@ -668,12 +724,35 @@ void GFX_EndUpdate(void) { break; #if C_OPENGL case SCREEN_OPENGL: - glBindTexture(GL_TEXTURE_2D, sdl.opengl.texture); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, - sdl.draw.width, sdl.draw.height, GL_BGRA_EXT, - GL_UNSIGNED_INT_8_8_8_8_REV, sdl.opengl.framebuf); - glCallList(sdl.opengl.displaylist); - SDL_GL_SwapBuffers(); +#if defined(NVIDIA_PixelDataRange) + if (sdl.opengl.pixel_data_range) { + glBindTexture(GL_TEXTURE_2D, sdl.opengl.texture); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, + sdl.draw.width, sdl.draw.height, GL_BGRA_EXT, + GL_UNSIGNED_INT_8_8_8_8_REV, sdl.opengl.framebuf); + glCallList(sdl.opengl.displaylist); + SDL_GL_SwapBuffers(); + } else +#endif + if (changedLines) { + Bitu y = 0, index = 0; + glBindTexture(GL_TEXTURE_2D, sdl.opengl.texture); + while (y < sdl.draw.height) { + if (!(index & 1)) { + y += changedLines[index]; + } else { + Bit8u *pixels = (Bit8u *)sdl.opengl.framebuf + y * sdl.opengl.pitch; + Bitu height = changedLines[index]; + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, + sdl.draw.width, height, GL_BGRA_EXT, + GL_UNSIGNED_INT_8_8_8_8_REV, pixels ); + y += height; + } + index++; + } + glCallList(sdl.opengl.displaylist); + SDL_GL_SwapBuffers(); + } break; #endif @@ -719,7 +798,8 @@ Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue) { } void GFX_Stop() { - if (sdl.updating) GFX_EndUpdate(); + if (sdl.updating) + GFX_EndUpdate( 0 ); sdl.active=false; } @@ -729,6 +809,7 @@ void GFX_Start() { static void GUI_ShutDown(Section * sec) { GFX_Stop(); + if (sdl.draw.reset) (sdl.draw.reset)( true ); if (sdl.mouse.locked) CaptureMouse(); if (sdl.desktop.fullscreen) SwitchFullScreen(); } @@ -825,44 +906,58 @@ static void GUI_StartUp(Section * sec) { sdl.mouse.locked=false; mouselocked=false; //Global for mapper sdl.mouse.requestlock=false; - sdl.desktop.fixed=section->Get_bool("fullfixed"); + sdl.desktop.full.fixed=section->Get_bool("fullfixed"); const char* fullresolution=section->Get_string("fullresolution"); if(fullresolution && *fullresolution) { - char res[100]= { 0 }; - strcpy(res,fullresolution); + char res[100]; + strncpy( res, fullresolution, sizeof( res )); fullresolution = lowcase (res);//so x and X are allowed char* height = const_cast(strchr(fullresolution,'x')); if(height && * height) { *height = 0; - sdl.desktop.height = atoi(height+1); - sdl.desktop.width = atoi(res); + sdl.desktop.full.height = atoi(height+1); + sdl.desktop.full.width = atoi(res); } else { - sdl.desktop.width = 0; - sdl.desktop.height = 0; + sdl.desktop.full.width = 0; + sdl.desktop.full.height = 0; } } else { - sdl.desktop.width = 0; - sdl.desktop.height = 0; + sdl.desktop.full.width = 0; + sdl.desktop.full.height = 0; + } + const char* windowresolution=section->Get_string("windowresolution"); + if(windowresolution && *windowresolution) { + char res[100]; + strncpy( res,windowresolution, sizeof( res )); + windowresolution = lowcase (res);//so x and X are allowed + + char* height = const_cast(strchr(windowresolution,'x')); + if(height && *height) { + *height = 0; + sdl.desktop.window.height = atoi(height+1); + sdl.desktop.window.width = atoi(res); + } else { + sdl.desktop.window.width = 0; + sdl.desktop.window.height = 0; + } + } else { + sdl.desktop.window.width = 0; + sdl.desktop.window.height = 0; } sdl.desktop.doublebuf=section->Get_bool("fulldouble"); - sdl.desktop.hwscale=section->Get_float("hwscale"); - if (sdl.desktop.hwscale<0.1f) { - LOG_MSG("SDL:Can't hwscale lower than 0.1"); - sdl.desktop.hwscale=0.1f; - } - if (!sdl.desktop.width) { + if (!sdl.desktop.full.width) { #ifdef WIN32 - sdl.desktop.width=GetSystemMetrics(SM_CXSCREEN); + sdl.desktop.full.width=GetSystemMetrics(SM_CXSCREEN); #else - sdl.desktop.width=1024; + sdl.desktop.full.width=1024; #endif } - if (!sdl.desktop.height) { + if (!sdl.desktop.full.height) { #ifdef WIN32 - sdl.desktop.height=GetSystemMetrics(SM_CYSCREEN); + sdl.desktop.full.height=GetSystemMetrics(SM_CYSCREEN); #else - sdl.desktop.height=768; + sdl.desktop.full.height=768; #endif } sdl.mouse.autoenable=section->Get_bool("autolock"); @@ -914,6 +1009,7 @@ static void GUI_StartUp(Section * sec) { #if defined(NVIDIA_PixelDataRange) sdl.opengl.pixel_data_range=(strstr(gl_ext,"GL_NV_pixel_data_range") >0 ) && glPixelDataRangeNV && db_glAllocateMemoryNV && db_glFreeMemoryNV; + sdl.opengl.pixel_data_range = 0; #endif } else { sdl.opengl.packed_pixel=sdl.opengl.paletted_texture=false; @@ -1018,6 +1114,7 @@ void GFX_Events() { CaptureMouse(); } SetPriority(sdl.priority.nofocus); + MAPPER_LosingFocus(); } } break; @@ -1112,9 +1209,9 @@ int main(int argc, char* argv[]) { #endif if ( SDL_Init( SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_CDROM + |SDL_INIT_NOPARACHUTE #ifndef DISABLE_JOYSTICK |SDL_INIT_JOYSTICK - #endif ) < 0 ) E_Exit("Can't init SDL %s",SDL_GetError()); Section_prop * sdl_sec=control->AddSection_prop("sdl",&GUI_StartUp); @@ -1123,8 +1220,8 @@ int main(int argc, char* argv[]) { sdl_sec->Add_bool("fulldouble",false); sdl_sec->Add_bool("fullfixed",false); sdl_sec->Add_string("fullresolution","1024x768"); + sdl_sec->Add_string("windowresolution","0x0"); sdl_sec->Add_string("output","surface"); - sdl_sec->Add_float("hwscale",1.0); sdl_sec->Add_bool("autolock",true); sdl_sec->Add_int("sensitivity",100); sdl_sec->Add_bool("waitonerror",true);