From d3f0cb48b7fb63b1a8c2baaba23389a5ab31ffb4 Mon Sep 17 00:00:00 2001 From: ansstuff Date: Sun, 3 Feb 2013 16:03:25 +0000 Subject: [PATCH] * win32: speed up screen blitting --- src/drivers/win/video.cpp | 249 ++++++++++++++++++------------------- src/drivers/win/video.h | 3 +- src/drivers/win/window.cpp | 18 +-- 3 files changed, 132 insertions(+), 138 deletions(-) diff --git a/src/drivers/win/video.cpp b/src/drivers/win/video.cpp index cbcc0bbd..c93220e8 100644 --- a/src/drivers/win/video.cpp +++ b/src/drivers/win/video.cpp @@ -40,7 +40,7 @@ static int bpp; static int vflags; static int veflags; -int disvaccel = 1; //Disable video hardware acceleration. 1 by default (meaning disable in windowed but not Fullscreen) +int disvaccel = 1; // Disable video hardware acceleration. By default it's disabled in windowed, but enabled in Fullscreen mode int fssync=0; int winsync=0; @@ -77,16 +77,14 @@ LPDIRECTDRAWPALETTE lpddpal = 0; DDSURFACEDESC2 ddsd; DDSURFACEDESC2 ddsdback; -DDSURFACEDESC2 ddsd_Resizable; LPDIRECTDRAWSURFACE7 lpDDSPrimary=0; LPDIRECTDRAWSURFACE7 lpDDSDBack=0; LPDIRECTDRAWSURFACE7 lpDDSBack=0; -LPDIRECTDRAWSURFACE7 lpDDSResizable=0; DDBLTFX blitfx = { sizeof(DDBLTFX) }; -RECT resizable_surface_rect = {0}; +RECT bestfitRect = {0}; #define RELEASE(x) if(x) { x->Release(); x = 0; } @@ -99,11 +97,7 @@ static void ShowDDErr(char *s) int RestoreDD(int w) { - if (w == 2) // lpDDSResizable - { - if(!lpDDSResizable) return 0; - if(IDirectDrawSurface7_Restore(lpDDSResizable)!=DD_OK) return 0; - } else if (w == 1) // lpDDSBack + if (w == 1) // lpDDSBack { if(!lpDDSBack) return 0; if(IDirectDrawSurface7_Restore(lpDDSBack)!=DD_OK) return 0; @@ -250,73 +244,39 @@ static int InitBPPStuff(int fs) return 1; } -void RecreateResizableSurface(int width, int height) +void recalculateBestFitRect(int width, int height) { if (!lpDD7) return; // DirectDraw isn't initialized yet - // delete old surface - RELEASE(lpDDSResizable); - // create new surface - memset(&ddsd_Resizable, 0, sizeof(ddsd_Resizable)); - ddsd_Resizable.dwSize = sizeof(ddsd_Resizable); - ddsd_Resizable.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; - ddsd_Resizable.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - ddsd_Resizable.dwWidth = width; - ddsd_Resizable.dwHeight = height; - ddrval = IDirectDraw7_CreateSurface(lpDD7, &ddsd_Resizable, &lpDDSResizable, (IUnknown FAR*)NULL); - if (ddrval != DD_OK) - { - //ShowDDErr("Error creating resizable surface."); - FCEU_printf("Error creating resizable surface.\n"); - return; - } - RecolorResizableSurface(); - // calculate resizable_surface_rect + // calculate bestfitRect double current_aspectratio = (double)width / (double)height; double needed_aspectratio = (double)(VNSWID) / (double)(FSettings.TotalScanlines()); if (eoptions & EO_TVASPECT) needed_aspectratio = ((double)VNSWID / 256) * ((double)4 / 3); if (current_aspectratio == needed_aspectratio) { - resizable_surface_rect.left = 0; - resizable_surface_rect.right = width; - resizable_surface_rect.top = 0; - resizable_surface_rect.bottom = height; + bestfitRect.left = 0; + bestfitRect.right = width; + bestfitRect.top = 0; + bestfitRect.bottom = height; } else if (current_aspectratio > needed_aspectratio) { // the window is wider than emulated screen - resizable_surface_rect.top = 0; - resizable_surface_rect.bottom = height; + bestfitRect.top = 0; + bestfitRect.bottom = height; int center_x = width / 2; double new_width = ((double)height * needed_aspectratio); - resizable_surface_rect.left = center_x - (new_width / 2); - resizable_surface_rect.right = resizable_surface_rect.left + new_width; + bestfitRect.left = center_x - (new_width / 2); + bestfitRect.right = bestfitRect.left + new_width; } else { // the window is taller than emulated screen - resizable_surface_rect.left = 0; - resizable_surface_rect.right = width; + bestfitRect.left = 0; + bestfitRect.right = width; int center_y = height / 2; double new_height = ((double)width / needed_aspectratio); - resizable_surface_rect.top = center_y - (new_height / 2); - resizable_surface_rect.bottom = resizable_surface_rect.top + new_height; - } -} - -void RecolorResizableSurface() -{ - if (eoptions & EO_BGCOLOR) - { - // fill the surface using BG color from PPU - unsigned char r, g, b; - FCEUD_GetPalette(0x80 | PALRAM[0], &r, &g, &b); - blitfx.dwFillColor = (r << 16) + (g << 8) + b; - ddrval = IDirectDrawSurface7_Blt(lpDDSResizable, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); - } else - { - // fill the surface with black color - blitfx.dwFillColor = 0; - ddrval = IDirectDrawSurface7_Blt(lpDDSResizable, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); + bestfitRect.top = center_y - (new_height / 2); + bestfitRect.bottom = bestfitRect.top + new_height; } } @@ -487,11 +447,8 @@ int SetVideoMode(int fs) } } - if ((vmodes[vmod].flags & VMDF_STRFS) && (eoptions & EO_BESTFIT)) - { - RecreateResizableSurface(vmodes[vmod].x, vmodes[vmod].y); - } - + if (eoptions & EO_BESTFIT) + recalculateBestFitRect(vmodes[vmod].x, vmodes[vmod].y); // create foreground surface @@ -601,8 +558,7 @@ static void BlitScreenWindow(unsigned char *XBuf) { int pitch; unsigned char *ScreenLoc; - static RECT srect; - RECT wrect; + static RECT srect, wrect, blitRect; int specialmul; if (!lpDDSBack) return; @@ -627,9 +583,10 @@ static void BlitScreenWindow(unsigned char *XBuf) if(!GetClientAbsRect(&wrect)) return; ddrval=IDirectDrawSurface7_Lock(lpDDSBack,NULL,&ddsdback, 0, NULL); - if(ddrval!=DD_OK) + if (ddrval != DD_OK) { - if(ddrval==DDERR_SURFACELOST) RestoreDD(1); + if (ddrval == DDERR_SURFACELOST) + RestoreDD(1); return; } @@ -645,44 +602,66 @@ static void BlitScreenWindow(unsigned char *XBuf) IDirectDrawSurface7_Unlock(lpDDSBack, NULL); - if (eoptions & EO_BESTFIT && (resizable_surface_rect.top || resizable_surface_rect.left)) + FCEUD_VerticalSync(); // aquanull 2011-11-28 fix tearing + if (eoptions & EO_BESTFIT && (bestfitRect.top || bestfitRect.left)) { - // clear lpDDSResizable surface - if (eoptions & EO_BGCOLOR) - RecolorResizableSurface(); - // blit from lpDDSBack to lpDDSResizable using best fit - if (IDirectDrawSurface7_Blt(lpDDSResizable, &resizable_surface_rect, lpDDSBack, &srect, DDBLT_ASYNC, 0) != DD_OK) + // blit with resizing + blitRect.top = wrect.top + bestfitRect.top; + blitRect.bottom = blitRect.top + bestfitRect.bottom - bestfitRect.top; + blitRect.left = wrect.left + bestfitRect.left; + blitRect.right = blitRect.left + bestfitRect.right - bestfitRect.left; + if (IDirectDrawSurface7_Blt(lpDDSPrimary, &blitRect, lpDDSBack, &srect, DDBLT_ASYNC, 0) != DD_OK) { - ddrval = IDirectDrawSurface7_Blt(lpDDSResizable, &resizable_surface_rect, lpDDSBack, &srect, DDBLT_WAIT, 0); + ddrval = IDirectDrawSurface7_Blt(lpDDSPrimary, &blitRect, lpDDSBack, &srect, DDBLT_WAIT, 0); if(ddrval != DD_OK) { if(ddrval == DDERR_SURFACELOST) { - RestoreDD(2); RestoreDD(1); - } - return; - } - } - // blit from lpDDSResizable to screen (lpDDSPrimary) - FCEUD_VerticalSync(); // aquanull 2011-11-28 fix tearing - if (IDirectDrawSurface7_Blt(lpDDSPrimary, &wrect, lpDDSResizable, NULL, DDBLT_ASYNC, 0) != DD_OK) - { - ddrval = IDirectDrawSurface7_Blt(lpDDSPrimary, &wrect, lpDDSResizable, NULL, DDBLT_WAIT, 0); - if(ddrval != DD_OK) - { - if(ddrval == DDERR_SURFACELOST) - { - RestoreDD(2); RestoreDD(0); } return; } } + // clear borders + if (eoptions & EO_BGCOLOR) + { + // fill the surface using BG color from PPU + unsigned char r, g, b; + FCEUD_GetPalette(0x80 | PALRAM[0], &r, &g, &b); + blitfx.dwFillColor = (r << 16) + (g << 8) + b; + } else + { + blitfx.dwFillColor = 0; + } + if (bestfitRect.top) + { + // upper border + blitRect.top = wrect.top; + blitRect.bottom = wrect.top + bestfitRect.top; + blitRect.left = wrect.left; + blitRect.right = wrect.right; + IDirectDrawSurface7_Blt(lpDDSPrimary, &blitRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + // lower border + blitRect.top += bestfitRect.bottom; + blitRect.bottom = wrect.bottom; + IDirectDrawSurface7_Blt(lpDDSPrimary, &blitRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + } else + { + // left border + blitRect.top = wrect.top; + blitRect.bottom = wrect.bottom; + blitRect.left = wrect.left; + blitRect.right = wrect.left + bestfitRect.left; + IDirectDrawSurface7_Blt(lpDDSPrimary, &blitRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + // right border + blitRect.left += bestfitRect.right; + blitRect.right = wrect.right; + IDirectDrawSurface7_Blt(lpDDSPrimary, &blitRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + } } else { - // blit directly from lpDDSBack to screen (lpDDSPrimary) - FCEUD_VerticalSync(); // aquanull 2011-11-28 fix tearing + // blit without resizing if(IDirectDrawSurface7_Blt(lpDDSPrimary, &wrect, lpDDSBack, &srect, DDBLT_ASYNC, 0) != DD_OK) { ddrval = IDirectDrawSurface7_Blt(lpDDSPrimary, &wrect, lpDDSBack, &srect, DDBLT_WAIT, 0); @@ -769,12 +748,13 @@ static void BlitScreenFull(uint8 *XBuf) srect.right=VNSWID * specmul; srect.bottom=FSettings.TotalScanlines() * specmul; - if(vmodes[vmod].flags&VMDF_STRFS) - { + //if(vmodes[vmod].flags&VMDF_STRFS) + //{ drect.top=0; drect.left=0; drect.right=vmodes[vmod].x; drect.bottom=vmodes[vmod].y; + /* } else { @@ -782,8 +762,6 @@ static void BlitScreenFull(uint8 *XBuf) drect.bottom=drect.top+(FSettings.TotalScanlines()*vmodes[vmod].yscale); drect.left=(vmodes[vmod].x-VNSWID*vmodes[vmod].xscale)>>1; drect.right=drect.left+VNSWID*vmodes[vmod].xscale; - - RECT fullScreen; fullScreen.left = fullScreen.top = 0; fullScreen.right = vmodes[vmod].x; @@ -803,6 +781,7 @@ static void BlitScreenFull(uint8 *XBuf) DD_FillRect(lpDDSVPrimary,left,bottom,right,fullScreen.bottom,RGB(255,0,255)); //bottomcenter DD_FillRect(lpDDSVPrimary,right,bottom,fullScreen.right,fullScreen.bottom,RGB(0,255,255)); //bottomright } + */ } else { // start rendering directly to screen @@ -964,67 +943,84 @@ static void BlitScreenFull(uint8 *XBuf) if(vmodes[vmod].flags&VMDF_DXBLT) { IDirectDrawSurface7_Unlock(lpDDSBack, NULL); - - if (eoptions & EO_BESTFIT && (resizable_surface_rect.top || resizable_surface_rect.left) && !vmod) + FCEUD_VerticalSync(); + if (eoptions & EO_BESTFIT && (bestfitRect.top || bestfitRect.left) && !vmod) { - // clear lpDDSResizable surface - RecolorResizableSurface(); - // blit from lpDDSBack to lpDDSResizable using best fit - if (IDirectDrawSurface7_Blt(lpDDSResizable, &resizable_surface_rect, lpDDSBack, &srect, DDBLT_ASYNC, 0) != DD_OK) + // blit with resizing + if (IDirectDrawSurface7_Blt(lpDDSVPrimary, &bestfitRect, lpDDSBack, &srect, DDBLT_ASYNC, 0) != DD_OK) { - ddrval = IDirectDrawSurface7_Blt(lpDDSResizable, &resizable_surface_rect, lpDDSBack, &srect, DDBLT_WAIT, 0); + ddrval = IDirectDrawSurface7_Blt(lpDDSVPrimary, &bestfitRect, lpDDSBack, &srect, DDBLT_WAIT, 0); if(ddrval != DD_OK) { if(ddrval == DDERR_SURFACELOST) { - RestoreDD(2); RestoreDD(1); - } - return; - } - } - // blit from lpDDSResizable to screen - RECT fullScreen; - fullScreen.left = fullScreen.top = 0; - fullScreen.right = vmodes[vmod].x; - fullScreen.bottom = vmodes[vmod].y; - FCEUD_VerticalSync(); - if (IDirectDrawSurface7_Blt(lpDDSVPrimary, &fullScreen, lpDDSResizable, &fullScreen, DDBLT_ASYNC, 0) != DD_OK) - { - ddrval = IDirectDrawSurface7_Blt(lpDDSVPrimary, &fullScreen, lpDDSResizable, &fullScreen, DDBLT_WAIT, 0); - if(ddrval != DD_OK) - { - if(ddrval == DDERR_SURFACELOST) - { - RestoreDD(2); RestoreDD(0); } return; } } + // clear borders + if (eoptions & EO_BGCOLOR) + { + // fill the surface using BG color from PPU + unsigned char r, g, b; + FCEUD_GetPalette(0x80 | PALRAM[0], &r, &g, &b); + blitfx.dwFillColor = (r << 16) + (g << 8) + b; + } else + { + blitfx.dwFillColor = 0; + } + static RECT borderRect; + if (bestfitRect.top) + { + // upper border + borderRect.top = drect.top; + borderRect.bottom = drect.top + bestfitRect.top; + borderRect.left = drect.left; + borderRect.right = drect.right; + IDirectDrawSurface7_Blt(lpDDSPrimary, &borderRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + // lower border + borderRect.top += bestfitRect.bottom; + borderRect.bottom = drect.bottom; + IDirectDrawSurface7_Blt(lpDDSPrimary, &borderRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + } else + { + // left border + borderRect.top = drect.top; + borderRect.bottom = drect.bottom; + borderRect.left = drect.left; + borderRect.right = drect.left + bestfitRect.left; + IDirectDrawSurface7_Blt(lpDDSPrimary, &borderRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + // right border + borderRect.left += bestfitRect.right; + borderRect.right = drect.right; + IDirectDrawSurface7_Blt(lpDDSPrimary, &borderRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + } } else { - // blit directly from lpDDSBack to screen - FCEUD_VerticalSync(); + /* if(veflags&2) { // clear screen surface (is that really necessary?) - if(IDirectDrawSurface7_Lock(lpDDSVPrimary,NULL,&ddsd, 0, NULL)==DD_OK) + if(IDirectDrawSurface7_Lock(lpDDSVPrimary, NULL, &ddsd, 0, NULL)==DD_OK) { memset(ddsd.lpSurface,0,ddsd.lPitch*vmodes[vmod].y); //mbg merge 7/17/06 removing dummyunion stuff IDirectDrawSurface7_Unlock(lpDDSVPrimary, NULL); veflags&=~2; } } - if(IDirectDrawSurface7_Blt(lpDDSVPrimary, &drect,lpDDSBack,&srect,DDBLT_ASYNC,0)!=DD_OK) + */ + // blit without resizing + if(IDirectDrawSurface7_Blt(lpDDSVPrimary, NULL, lpDDSBack, &srect, DDBLT_ASYNC,0)!=DD_OK) { - ddrval=IDirectDrawSurface7_Blt(lpDDSVPrimary, &drect,lpDDSBack,&srect,DDBLT_WAIT,0); + ddrval=IDirectDrawSurface7_Blt(lpDDSVPrimary, NULL, lpDDSBack, &srect, DDBLT_WAIT,0); if(ddrval!=DD_OK) { if(ddrval==DDERR_SURFACELOST) { - RestoreDD(0); RestoreDD(1); + RestoreDD(0); } return; } @@ -1055,7 +1051,6 @@ void ResetVideo(void) RELEASE(lpddpal); RELEASE(lpDDSBack); RELEASE(lpDDSPrimary); - RELEASE(lpDDSResizable); RELEASE(lpClipper); RELEASE(lpDD7); } diff --git a/src/drivers/win/video.h b/src/drivers/win/video.h index e2b77d75..642e9f14 100644 --- a/src/drivers/win/video.h +++ b/src/drivers/win/video.h @@ -49,8 +49,7 @@ extern int winsync; void SetFSVideoMode(); void FCEUD_BlitScreen(uint8 *XBuf); void ConfigVideo(); -void RecreateResizableSurface(int width, int height); -void RecolorResizableSurface(); +void recalculateBestFitRect(int width, int height); int SetVideoMode(int fs); void DoVideoConfigFix(); void FCEUD_BlitScreen(uint8 *XBuf); diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index 8b389b41..42fdefe1 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -1121,29 +1121,29 @@ void LoadNewGamey(HWND hParent, const char *initialdir) void GetMouseData(uint32 (&md)[3]) { - extern RECT resizable_surface_rect; + extern RECT bestfitRect; - if (eoptions & EO_BESTFIT && (resizable_surface_rect.top || resizable_surface_rect.left)) + if (eoptions & EO_BESTFIT && (bestfitRect.top || bestfitRect.left)) { - if ((int)mousex <= resizable_surface_rect.left) + if ((int)mousex <= bestfitRect.left) { md[0] = 0; - } else if ((int)mousex >= resizable_surface_rect.right) + } else if ((int)mousex >= bestfitRect.right) { md[0] = VNSWID; } else { - md[0] = VNSWID * (mousex - resizable_surface_rect.left) / (resizable_surface_rect.right - resizable_surface_rect.left); + md[0] = VNSWID * (mousex - bestfitRect.left) / (bestfitRect.right - bestfitRect.left); } - if ((int)mousey <= resizable_surface_rect.top) + if ((int)mousey <= bestfitRect.top) { md[1] = 0; - } else if ((int)mousey >= resizable_surface_rect.bottom) + } else if ((int)mousey >= bestfitRect.bottom) { md[1] = FSettings.TotalScanlines(); } else { - md[1] = FSettings.TotalScanlines() * (mousey - resizable_surface_rect.top) / (resizable_surface_rect.bottom - resizable_surface_rect.top); + md[1] = FSettings.TotalScanlines() * (mousey - bestfitRect.top) / (bestfitRect.bottom - bestfitRect.top); } } else { @@ -2620,7 +2620,7 @@ void SetMainWindowStuff() { RECT client_recr; GetClientRect(hAppWnd, &client_recr); - RecreateResizableSurface(client_recr.right - client_recr.left, client_recr.bottom - client_recr.top); + recalculateBestFitRect(client_recr.right - client_recr.left, client_recr.bottom - client_recr.top); } }