diff options
Diffstat (limited to 'Src/Plugins/Visualization/vis_avs/draw.cpp')
-rw-r--r-- | Src/Plugins/Visualization/vis_avs/draw.cpp | 1476 |
1 files changed, 1476 insertions, 0 deletions
diff --git a/Src/Plugins/Visualization/vis_avs/draw.cpp b/Src/Plugins/Visualization/vis_avs/draw.cpp new file mode 100644 index 00000000..5eddc451 --- /dev/null +++ b/Src/Plugins/Visualization/vis_avs/draw.cpp @@ -0,0 +1,1476 @@ +/* + LICENSE + ------- +Copyright 2005 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +#include <windows.h> +#include <ddraw.h> +#include "draw.h" +#include <stdio.h> +#include <process.h> +#include "r_defs.h" +#include "resource.h" +#include "vis.h" +#include "../Agave/Language/api_language.h" + +extern HINSTANCE g_hInstance; + +#define RESIZE_ONRESIZE +int draw_title_p=0; +int cfg_cancelfs_on_deactivate=1; +extern int g_dlg_fps,g_dlg_w,g_dlg_h; +extern int cfg_fs_fps,cfg_fs_flip,cfg_fs_height,cfg_fs_use_overlay; +extern int cfg_bkgnd_render, cfg_bkgnd_render_color; +static LPDIRECTDRAW g_lpDD; +static LPDIRECTDRAWSURFACE g_lpRenderSurf[2], g_lpPrimSurf, g_lpPrimSurfBack; +static int g_bpp, g_fs, g_noshoww; +int g_w, g_h, g_dsw, g_dsh; +extern HWND g_hwnd; +static CRITICAL_SECTION g_cs; +static int g_windowed_dsize; +static int g_initted, g_fs_flip, g_fs_height, g_fs_w, g_fs_h; +static int nodraw=0; +extern int inWharf; +#ifdef RESIZE_ONRESIZE +static int last_used; +#endif +static LPDIRECTDRAWSURFACE g_lpddsOverlay = NULL; +static LPDIRECTDRAWSURFACE g_lpddsPrimary = NULL; +static int g_overlay_init_ok=0; +typedef enum { + UYVY, + YUY2 +} fourcc_enum; +static fourcc_enum g_overlay_fourcc=UYVY; +static int g_saved_desktop_values=0; + +static char g_saved_desktop_wallpaper[256]; +static char g_saved_reg_bkgnd_color[64]; +static DWORD g_saved_bkgnd_color; + +extern void Wnd_GoWindowed(HWND hwnd); + +#define INIT_DIRECTDRAW_STRUCT(x) (ZeroMemory(&x, sizeof(x)), x.dwSize=sizeof(x)) +DDPIXELFORMAT g_ddpfOverlayFormats[] = +{ {sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0}, // UYVY + {sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('Y','U','Y','2'),0,0,0,0,0}}; // YUY2 + +#define NUM_OVERLAY_FORMATS (sizeof(g_ddpfOverlayFormats) / sizeof(g_ddpfOverlayFormats[0])) + +static HWND hwndOverlayWnd; + +static LRESULT CALLBACK FSOverlayWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static unsigned int start_t; + + if ( + + (((message == WM_KEYDOWN && (wParam == VK_ESCAPE || wParam == VK_RETURN)) || + message == WM_LBUTTONUP) && GetTickCount()-start_t > 1000) + + || + + (cfg_cancelfs_on_deactivate && ((message == WM_NCACTIVATE && !wParam) || + message == WM_KILLFOCUS)) + ) + { + DestroyWindow(hwnd); + Wnd_GoWindowed(g_hwnd); + return 0; + } + switch(message) + { + case WM_CREATE: + start_t=GetTickCount(); + return 0; + case WM_SETCURSOR: + SetCursor(NULL); + return TRUE; + case WM_DESTROY: + hwndOverlayWnd=0; + return 0; + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc=BeginPaint(hwnd,&ps); + RECT r; + GetClientRect(hwnd,&r); + int rv=0xff&(cfg_bkgnd_render_color>>16), gv=0xff&(cfg_bkgnd_render_color>>8), bv=0xff&cfg_bkgnd_render_color; + HBRUSH b=CreateSolidBrush(RGB(rv,gv,bv)); + SelectObject(ps.hdc, b); + Rectangle(ps.hdc, r.left, r.top, r.right, r.bottom); + DeleteObject(b); + EndPaint(hwnd,&ps); + } + return 0; + case WM_KEYDOWN: + return SendMessage(g_hwnd, message, wParam, lParam); + } + return DefWindowProc(hwnd, message, wParam, lParam); +} + +static void DD_CreateFullscreenOverlayWindow() +{ + static int inited=0; + if(!inited) + { + WNDCLASSW wc={0,}; + wc.style = CS_DBLCLKS|CS_VREDRAW|CS_HREDRAW; + wc.lpfnWndProc = FSOverlayWndProc; + wc.hInstance = g_hInstance; + wc.hbrBackground = NULL; + wc.lpszClassName = L"avsfsoverlaywnd"; + wc.hCursor=NULL; + if(!RegisterClassW(&wc)) return; + inited=1; + } + hwndOverlayWnd=CreateWindowExW(WS_EX_TOPMOST|WS_EX_TOOLWINDOW,L"avsfsoverlaywnd",L"",WS_VISIBLE|WS_POPUP,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),NULL,NULL,g_hInstance,0); +} + +static void DD_RestoreBkgndSettings() +{ + if (g_saved_desktop_values) + { + int e=COLOR_DESKTOP; + unsigned long c=g_saved_bkgnd_color; + SetSysColors(1, &e, &c); // FUCKING MESSAGE PUMP AND SETSYSCOLORS + SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, g_saved_desktop_wallpaper, NULL); + g_saved_desktop_values=0; + } +} + +void DD_CreateSurfaces(int w, int h, int fsh, int fs, int fsbpp, int flip, int dbl, int fsovl) // fsh is the height to use (not screen res) +{ + int resize_h=8, resize_w=8; +#ifdef RESIZE_ONRESIZE + int fb_save[64*65+1]; + int fb_save_use=0; +#endif + EnterCriticalSection(&g_cs); + nodraw=0; + if (g_lpDD) + { + extern int config_reuseonresize; +#ifdef RESIZE_ONRESIZE + HRESULT han; + int ll=!!last_used; + DDSURFACEDESC d={sizeof(d),}; + if (config_reuseonresize && g_w && g_h && g_lpRenderSurf[ll] && + (han = g_lpRenderSurf[ll]->Lock(NULL,&d,DDLOCK_WAIT,NULL)) == DD_OK) + { + if (d.lpSurface) + { + int x,y; + int dxpos=(g_w<<16)/64; + int ypos=0; + int dypos=(g_h<<16)/64; + int *pp=((int *)d.lpSurface); + + if (g_fs && g_fs_height < g_h) // adjust to use partial screen when + { + int fsy=g_h/2-g_fs_height/2; + dypos=(g_fs_height<<16)/64; + pp+=fsy * g_w; + } + + for (y = 0; y < 64; y++) + { + int *p=pp + g_w * (ypos>>16); + int xpos=0; + for (x = 0; x < 64; x ++) + { + fb_save[(y<<6)+x]=p[xpos>>16]; + xpos+=dxpos; + } + ypos+=dypos; + } + memset(fb_save+64*64,0,sizeof(int)*65); + fb_save_use=1; + } + g_lpRenderSurf[ll]->Unlock(d.lpSurface); + } +#endif + + if (g_lpPrimSurf) + { + g_lpPrimSurf->Release(); + g_lpPrimSurfBack=g_lpPrimSurf=NULL; + } + if (g_lpRenderSurf[0]) g_lpRenderSurf[0]->Release(); + if (g_lpRenderSurf[1]) g_lpRenderSurf[1]->Release(); + g_lpRenderSurf[0]=0; + g_lpRenderSurf[1]=0; + if (g_lpddsOverlay) g_lpddsOverlay->Release(); + if (g_lpddsPrimary) g_lpddsPrimary->Release(); + g_lpddsOverlay=g_lpddsPrimary=NULL; + g_lpDD->Release(); + g_lpDD=NULL; + } + + if (DirectDrawCreate(NULL,&g_lpDD,NULL) != DD_OK) + { + g_lpDD=NULL; + MessageBox(g_hwnd,WASABI_API_LNGSTRING(IDS_ERROR_CREATING_DDRAW_OBJECT),"DDraw",0); + LeaveCriticalSection(&g_cs); + return; + } + if (fs && !fsovl) + { + g_fs_w=w; + g_fs_h=h; + g_fs_height=fsh>>dbl; + g_fs_flip=flip; + resize_w=w>>dbl; + resize_h=h>>dbl; + if (g_lpDD->SetCooperativeLevel(g_hwnd,DDSCL_NOWINDOWCHANGES|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN) != DD_OK) + { + fs=0; + } + else + { + if (g_lpDD->SetDisplayMode(w,h,fsbpp) != DD_OK) + { + fs=0; + } + else + { + DDSURFACEDESC DDsd={sizeof(DDsd),}; + DDsd.dwFlags = DDSD_CAPS; + DDsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + if (g_fs_flip&1) + { + DDsd.ddsCaps.dwCaps |= DDSCAPS_COMPLEX|DDSCAPS_FLIP; + DDsd.dwFlags|=DDSD_BACKBUFFERCOUNT; + DDsd.dwBackBufferCount = 1; + } + if (g_lpDD->CreateSurface(&DDsd, &g_lpPrimSurf, NULL) != DD_OK) + { + fs=0; + } + else + { + DDBLTFX ddbfx={sizeof(ddbfx),}; + g_lpPrimSurf->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx); + if (g_fs_flip&1) + { + DDSCAPS ddscaps; + ddscaps.dwCaps = DDSCAPS_BACKBUFFER; + if (g_lpPrimSurf->GetAttachedSurface(&ddscaps, &g_lpPrimSurfBack) != DD_OK) + { + g_lpPrimSurf->Release(); + fs=0; + } + else g_lpPrimSurfBack->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx); + } + else + g_lpPrimSurfBack=g_lpPrimSurf; + } + } + } + SetForegroundWindow(g_hwnd); + } else { + g_lpDD->SetCooperativeLevel(g_hwnd,DDSCL_NOWINDOWCHANGES|DDSCL_NORMAL); + resize_w=(((w>>dbl)+3)&~3); + g_noshoww=resize_w-(w>>dbl); + resize_h=h>>dbl; + } + g_fs=fs; + + int wh; + for (wh = 0; wh < 2; wh ++) + { + DDSURFACEDESC DDsd={sizeof(DDsd),}; + DDsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_PIXELFORMAT; + DDsd.dwWidth=resize_w; + DDsd.dwHeight=resize_h; + DDsd.lPitch=resize_w*sizeof(int); + DDsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY; + DDsd.ddpfPixelFormat.dwSize = sizeof(DDsd.ddpfPixelFormat); + DDsd.ddpfPixelFormat.dwFlags=DDPF_RGB; + DDsd.ddpfPixelFormat.dwRGBBitCount = 32; + DDsd.ddpfPixelFormat.dwRBitMask=0xff0000; + DDsd.ddpfPixelFormat.dwGBitMask=0x00ff00; + DDsd.ddpfPixelFormat.dwBBitMask=0x0000ff; + if (g_lpDD->CreateSurface(&DDsd, &g_lpRenderSurf[wh], NULL) != DD_OK) + { + if (wh) + { + g_lpRenderSurf[0]->Release(); + g_lpRenderSurf[0]=0; + } + g_lpRenderSurf[wh]=0; + LeaveCriticalSection(&g_cs); + return; + } + +#ifdef RESIZE_ONRESIZE + DDSURFACEDESC d={sizeof(d),}; + HRESULT han; + if (fb_save_use && g_lpRenderSurf[wh] && + (han = g_lpRenderSurf[wh]->Lock(NULL,&d,DDLOCK_WAIT,NULL)) == DD_OK) + { + if (d.lpSurface) + { + int x,y; + int dxpos=(64<<16)/resize_w; + int ypos=0; + int *p=(int *)d.lpSurface; + int h=resize_h; + + if (fs && (fsh>>dbl) < resize_h) + { + int fsy=resize_h/2-(((fsh>>dbl)/2)); + p+=fsy * resize_w; + h -= fsy*2; + } + int dypos=(64<<16)/h; + + for (y = 0; y < h; y ++) + { + int xpos=0; + for (x = 0; x < resize_w; x ++) + { + *p++ = BLEND4_16((unsigned int *)fb_save + ((ypos>>10)&~63) + (xpos>>16),64,xpos,ypos); + xpos+=dxpos; + } + ypos+=dypos; + } +#ifndef NO_MMX + __asm emms; +#endif + } + g_lpRenderSurf[wh]->Unlock(d.lpSurface); + } +#endif + } + g_w=resize_w; + g_h=resize_h; + g_dsh=g_h<<dbl; + g_dsw=g_w<<dbl; + g_bpp=fs?fsbpp:32; + g_windowed_dsize=dbl; + + g_overlay_init_ok=0; + if(!(cfg_bkgnd_render&1)) DD_RestoreBkgndSettings(); + if((cfg_bkgnd_render&1) || (g_fs && fsovl)) { + // init overlay stuff + DDSURFACEDESC ddsdOverlay; + HRESULT ddrval; + int i; + + // It's currently not possible to query for pixel formats supported by the + // overlay hardware (though GetFourCCCodes() usually provides a partial + // list). Instead you need to call CreateSurface() to try a variety of + // formats till one works. + INIT_DIRECTDRAW_STRUCT(ddsdOverlay); + ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY; + ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH; + ddsdOverlay.dwWidth=resize_w; + ddsdOverlay.dwHeight=resize_h; + ddsdOverlay.lPitch=resize_w*sizeof(int); + ddsdOverlay.dwBackBufferCount=0; + + // Try to create an overlay surface using one of the pixel formats in our + // global list. + i=0; + do + { + ddsdOverlay.ddpfPixelFormat=g_ddpfOverlayFormats[i]; + // Try to create the overlay surface + ddrval = g_lpDD->CreateSurface(&ddsdOverlay, &g_lpddsOverlay, NULL); + } while( FAILED(ddrval) && (++i < NUM_OVERLAY_FORMATS) ); + + if(!FAILED(ddrval)) + { + g_overlay_fourcc=(fourcc_enum)i; + + HRESULT ddrval; + DDSURFACEDESC ddsd; + INIT_DIRECTDRAW_STRUCT(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + ddrval = g_lpDD->CreateSurface(&ddsd, &g_lpddsPrimary, NULL ); + + RECT rs, rd; + DDOVERLAYFX ovfx; + DDCAPS capsDrv; + unsigned int uDestSizeAlign, uSrcSizeAlign; + DWORD dwUpdateFlags; + + INIT_DIRECTDRAW_STRUCT(capsDrv); + ddrval = g_lpDD->GetCaps(&capsDrv, NULL); + + uDestSizeAlign = capsDrv.dwAlignSizeDest; + uSrcSizeAlign = capsDrv.dwAlignSizeSrc; + + dwUpdateFlags = DDOVER_SHOW | DDOVER_DDFX | DDOVER_KEYDESTOVERRIDE; + + DEVMODE d; + d.dmSize=sizeof(d); + d.dmDriverExtra=0; + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &d); + + int rv=0xff&(cfg_bkgnd_render_color>>16), gv=0xff&(cfg_bkgnd_render_color>>8), bv=0xff&cfg_bkgnd_render_color; + + if(!fsovl) + { + if (cfg_bkgnd_render&2) + { + if (!g_saved_desktop_values) + { + HKEY key; + g_saved_desktop_wallpaper[0]=0; + g_saved_reg_bkgnd_color[0]=0; + + // get wallpaper + if(RegOpenKey(HKEY_CURRENT_USER, "Control Panel\\Desktop",&key)==ERROR_SUCCESS) + { + unsigned long s=sizeof(g_saved_desktop_wallpaper),vt; + RegQueryValueEx(key,"Wallpaper", 0, &vt, (unsigned char *)g_saved_desktop_wallpaper, &s); + } + + // get registry bkgnd color + if(RegOpenKey(HKEY_CURRENT_USER, "Control Panel\\Colors",&key)==ERROR_SUCCESS) + { + unsigned long s=sizeof(g_saved_reg_bkgnd_color),vt; + RegQueryValueEx(key,"Background", 0, &vt, (unsigned char *)g_saved_reg_bkgnd_color, &s); + } + + g_saved_bkgnd_color=GetSysColor(COLOR_DESKTOP); + g_saved_desktop_values=1; + } + int e=COLOR_DESKTOP; + unsigned long c=RGB(rv,gv,bv); + SetSysColors(1, &e, &c); + SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, "", NULL); + + // rewrite registry settings right now so we don't fuck the user desktop if avs crashes + { + HKEY key; + if(RegOpenKey(HKEY_CURRENT_USER, "Control Panel\\Desktop",&key)==ERROR_SUCCESS) + RegSetValueEx(key,"Wallpaper", 0, REG_SZ, (unsigned char *)g_saved_desktop_wallpaper, strlen(g_saved_desktop_wallpaper)+1); + if(RegOpenKey(HKEY_CURRENT_USER, "Control Panel\\Colors",&key)==ERROR_SUCCESS) + RegSetValueEx(key,"Background", 0, REG_SZ, (unsigned char *)g_saved_reg_bkgnd_color, strlen(g_saved_reg_bkgnd_color)+1); + } + } + else DD_RestoreBkgndSettings(); + } + + INIT_DIRECTDRAW_STRUCT(ovfx); + switch(d.dmBitsPerPel) + { + case 16: + ovfx.dckDestColorkey.dwColorSpaceLowValue=((rv>>3) << 11) | ((gv>>2) << 5) | (bv>>3); + break; + case 15: + ovfx.dckDestColorkey.dwColorSpaceLowValue=((rv>>3) << 10) | ((gv>>3) << 5) | (bv>>3); + break; + case 24: case 32: + ovfx.dckDestColorkey.dwColorSpaceLowValue=(rv << 16) | (gv << 8) | bv; + break; + } + ovfx.dckDestColorkey.dwColorSpaceHighValue=ovfx.dckDestColorkey.dwColorSpaceLowValue; + + rs.left=0; rs.top=0; + rs.right = resize_w; + rs.bottom = resize_h; + if (capsDrv.dwCaps & DDCAPS_ALIGNSIZESRC && uSrcSizeAlign) + rs.right -= rs.right % uSrcSizeAlign; + rd.left=0; rd.top=0; + rd.right=GetSystemMetrics(SM_CXSCREEN); rd.bottom=GetSystemMetrics(SM_CYSCREEN); + if (capsDrv.dwCaps & DDCAPS_ALIGNSIZEDEST && uDestSizeAlign) + rd.right = (int)((rd.right+uDestSizeAlign-1)/uDestSizeAlign)*uDestSizeAlign; + // Make the call to UpdateOverlay() which actually displays the overlay on + // the screen. + ddrval = g_lpddsOverlay->UpdateOverlay(&rs, g_lpddsPrimary, &rd, dwUpdateFlags, &ovfx); + if(!FAILED(ddrval)) g_overlay_init_ok=1; + } + } + + if(g_fs && fsovl) + { + g_fs_height=fsh>>dbl; + DD_CreateFullscreenOverlayWindow(); + } + + LeaveCriticalSection(&g_cs); +} + +#ifndef NO_MMX +bool CopyRGBSurfaceToYUVSurfaceMMX( + LPDDSURFACEDESC pddsd1, + LPDDSURFACEDESC pddsd2, + fourcc_enum eOverlayFormat) +{ + if (pddsd1->dwWidth != pddsd2->dwWidth) + return false; + if (pddsd1->dwHeight != pddsd2->dwHeight) + return false; + + DWORD w = pddsd1->dwWidth; + DWORD h = pddsd1->dwHeight; + LONG pitch1 = pddsd1->lPitch; + LONG pitch2 = pddsd2->lPitch; + unsigned __int32 *pPixels1 = (unsigned __int32 *)pddsd1->lpSurface; + unsigned __int32 *pPixels2 = (unsigned __int32 *)pddsd2->lpSurface; + signed __int16 cm1[4]; + signed __int16 cm2[4]; + signed __int16 cm3[4]; + signed __int16 cm4[4]; + int loops_per_scanline = w/2; + int extra_bytes_per_scanline_src = pitch1 - w*4; + int extra_bytes_per_scanline_dest = pitch2 - w*2; + + if (eOverlayFormat == UYVY) // U Y V Y + { + // swap 0<->1, and 2<->3 + cm1[1] = 77/2; cm1[0] = -38/2; cm1[3] = 77/2; cm1[2] = 110/2; + cm2[1] = 150/2; cm2[0] = -74/2; cm2[3] = 150/2; cm2[2] = -92/2; + cm3[1] = 29/2; cm3[0] = 112/2; cm3[3] = 29/2; cm3[2] = -18/2; + cm4[1] = 0; cm4[0] = 32768/2; cm4[3] = 0; cm4[2] = 32768/2; + } + else // Y U Y 2 + { + // (laptop) + cm1[0] = 77/2; cm1[1] = -38/2; cm1[2] = 77/2; cm1[3] = 110/2; + cm2[0] = 150/2; cm2[1] = -74/2; cm2[2] = 150/2; cm2[3] = -92/2; + cm3[0] = 29/2; cm3[1] = 112/2; cm3[2] = 29/2; cm3[3] = -18/2; + cm4[0] = 0; cm4[1] = 32768/2; cm4[2] = 0; cm4[3] = 32768/2; + } + + __asm + { + mov edx, h + + mov esi, pPixels1 + mov edi, pPixels2 + sub edi, 4 // pre-subtract + movq mm4, cm4 + movq mm5, cm1 + movq mm6, cm2 + movq mm7, cm3 + + ALIGN 8 + yuvscanlineloop: + + mov ecx, loops_per_scanline + + ALIGN 8 + yuvloop: + + /* + // prefetch + test ecx, 0x000001ff + jnz PROCESS_PIXEL_MMX32 // every 256th pixel do some prefetches + + mov ebx, 2*256 // need to prefetch 256*6 bytes + ALIGN 8 + LOAD_ESI_ARRAY_MMX32: + mov eax, [ebx+esi] + mov eax, [ebx+esi+32] + sub ebx, 64 + jnz LOAD_ESI_ARRAY_MMX32 + + ALIGN 8 + PROCESS_PIXEL_MMX32: + */ + + // read in 2 pixels + movq mm0, qword ptr [esi] // -- b1 g1 r1 -- b2 g2 r2 + movq mm1, qword ptr [esi] // -- b1 g1 r1 -- b2 g2 r2 + movq mm2, qword ptr [esi] // -- b1 g1 r1 -- b2 g2 r2 + + // quick reference: + // punpcklbw mm7, mm7 // abcdefgh -> eeffgghh + // punpcklbw mm7, mm0 // abcdefgh -> 0e0f0g0h (if mm0 is zero) + // packuswb mm7, mm7 // 0a0b0g0r -> abgrabgr ? + + // step 1: get to this state: + // mm0: r1 r1 r2 r2 + // mm1: g1 g1 g2 g2 + // mm2: b1 b1 b2 b2 + // mm3: junk + // mm4: 0 32k 0 32k + // mm5: c1r1 c1r2 c2r1 c2r2 + // mm6: c1g1 c1g2 c2g1 c2g2 + // mm7: c1b1 c1b2 c2b1 c2b2 + + // NOTE: the shifts of 8, 16, and 24 below are + // correct (vs. 0-8-16) but might be in + // backwards order! + + pslld mm0, 8 + pslld mm1, 16 + pslld mm2, 24 + psrld mm0, 24 // 00 00 00 r1 00 00 00 r2 + psrld mm1, 24 // 00 00 00 g1 00 00 00 g2 + psrld mm2, 24 // 00 00 00 b1 00 00 00 b2 + + movq mm3, mm0 + pslld mm0, 16 + por mm0, mm3 // 00 r1 00 r1 00 r2 00 r2 + + movq mm3, mm1 + pslld mm1, 16 + por mm1, mm3 // 00 g1 00 g1 00 g2 00 g2 + + movq mm3, mm2 + pslld mm2, 16 + por mm2, mm3 // 00 b1 00 b1 00 b2 00 b2 + + // step 2: multiply to get to this state: + // mm0: r1*c1r1 r1*c1r2 r2*c2r1 r2*c2r2 + // mm1: g1*c1g1 g1*c1g2 g2*c2g1 g2*c2g2 + // mm2: b1*c1b1 b1*c1b2 b2*c2b1 b2*c2b2 + // mm4: 0 32k 0 32k + pmullw mm0, mm5 + add edi, 4 + pmullw mm1, mm6 + add esi, 8 + pmullw mm2, mm7 + + // step 3: add to get to this state: + // mm0: d1*256 d2*256 d3*256 d4*256 + paddsw mm0, mm4 + paddsw mm0, mm1 + paddsw mm0, mm2 + + psrlw mm0, 7 + packuswb mm0, mm0 // bytes: abgrabgr + movd dword ptr [edi], mm0 // store + + loop yuvloop + + // scanline complete + add esi, extra_bytes_per_scanline_src + add edi, extra_bytes_per_scanline_dest + + dec edx + jnz yuvscanlineloop + + emms + } + + return true; +} +#else +bool CopyRGBSurfaceToYUVSurface( + LPDDSURFACEDESC pddsd1, + LPDDSURFACEDESC pddsd2, + fourcc_enum eOverlayFormat) +{ + if (pddsd1->dwWidth != pddsd2->dwWidth) + return false; + if (pddsd1->dwHeight != pddsd2->dwHeight) + return false; + + DWORD w = pddsd1->dwWidth; + DWORD h = pddsd1->dwHeight; + LONG pitch1 = pddsd1->lPitch; + LONG pitch2 = pddsd2->lPitch; + unsigned __int32 *pPixels1 = (unsigned __int32 *)pddsd1->lpSurface; + unsigned __int32 *pPixels2 = (unsigned __int32 *)pddsd2->lpSurface; + unsigned __int32 color1; + LONG offset1 = 0; + LONG offset2 = 0; + unsigned int R, G, B, i1, i2, i3, i4; + BYTE yuv[4]; + + if (eOverlayFormat == UYVY) // U Y V Y + { + i1 = 1; + i2 = 0; + i3 = 3; + i4 = 2; + } + else // Y U Y 2 + { + i1 = 0; + i2 = 1; + i3 = 2; + i4 = 3; + } + + // Go through the image 2 pixels at a time and convert to YUV + for (unsigned int y=0; y<h; y++) + { + offset1 = y*pitch1/4; + offset2 = y*pitch2/4; + + for (unsigned int x=0; x<w; x+=2) + { + color1 = pPixels1[offset1++]; + B = (color1) & 0xFF; + G = (color1 >> 8) & 0xFF; + R = (color1 >> 16) & 0xFF; + yuv[i1] = (77*R + 150*G + 29*B) >> 8; + yuv[i2] = (32768 - 38*R - 74*G + 112*B) >> 8; + + color1 = pPixels1[offset1++]; + B = (color1) & 0xFF; + G = (color1 >> 8) & 0xFF; + R = (color1 >> 16) & 0xFF; + yuv[i3] = (77*R + 150*G + 29*B) >> 8; + yuv[i4] = (32768 + 110*R - 92*G - 18*B) >> 8; + + pPixels2[offset2++] = *((unsigned __int32 *)yuv); + } + } + return true; +} +#endif + +int DDraw_Init() +{ + InitializeCriticalSection(&g_cs); + return 0; + +} +void DDraw_Quit(void) +{ + if (g_lpDD) + { + if (g_lpPrimSurf) + { + g_lpPrimSurf->Release(); + g_lpPrimSurfBack=g_lpPrimSurf=NULL; + } + if (g_lpRenderSurf[0]) g_lpRenderSurf[0]->Release(); + if (g_lpRenderSurf[1]) g_lpRenderSurf[1]->Release(); + g_lpRenderSurf[0]=0; + g_lpRenderSurf[1]=0; + if (g_lpddsOverlay) g_lpddsOverlay->Release(); + if (g_lpddsPrimary) g_lpddsPrimary->Release(); + g_lpddsOverlay=g_lpddsPrimary=NULL; + g_lpDD->Release(); + g_lpDD=NULL; + DD_RestoreBkgndSettings(); + } + DeleteCriticalSection(&g_cs); +} + + +void DDraw_BeginResize(void) +{ + if (!g_fs) nodraw=1; +} +void DDraw_Resize(int w, int h, int dsize) +{ + if (!g_fs) DD_CreateSurfaces(w, h, 0, 0, 0, 0, !!dsize, 0); +} + +static void *g_lpsurf[2]; + +static DDSURFACEDESC d={sizeof(d),}; +static DDSURFACEDESC d2={sizeof(d),}; + +void DDraw_Enter(int *w, int *h, int **fb1, int **fb2) +{ + HRESULT han; + if (nodraw) + { + *fb1=*fb2=0; + return; + } + EnterCriticalSection(&g_cs); + *w=g_w; + *h=g_h; + if (!g_lpDD || !g_lpRenderSurf[0] || !g_lpRenderSurf[1]) + { + *fb1=*fb2=0; + LeaveCriticalSection(&g_cs); + return; + } + if ((han = g_lpRenderSurf[0]->Lock(NULL,&d,DDLOCK_WAIT,NULL)) != DD_OK) + { + *fb1=*fb2=0; + LeaveCriticalSection(&g_cs); + return; + } + if ((han = g_lpRenderSurf[1]->Lock(NULL,&d2,DDLOCK_WAIT,NULL)) != DD_OK) + { + g_lpRenderSurf[0]->Unlock(d.lpSurface); + *fb1=*fb2=0; + LeaveCriticalSection(&g_cs); + return; + } + *fb1=(int*)(g_lpsurf[0]=d.lpSurface); + *fb2=(int*)(g_lpsurf[1]=d2.lpSurface); + + if (g_fs && g_fs_height!=g_h)// && !cfg_fs_use_overlay) + { + int y=g_h/2-((g_fs_height/2)); + *h-=y*2; + *fb1 += y*g_w; + *fb2 += y*g_w; + } +} + +static unsigned int draw_title_time; +static char last_title[1024]; + +extern HWND hwnd_WinampParent; + +static void do_gettitle() +{ + if (draw_title_p < 1 && --draw_title_p < -7) + { + char this_title[2048]={0,}; + char *p; + if (IsWindow(hwnd_WinampParent)) + { + DWORD id; + if (!SendMessageTimeout( hwnd_WinampParent,WM_GETTEXT,(WPARAM)sizeof(this_title),(LPARAM)this_title,SMTO_BLOCK,50,&id) || !id) return; + } + p = this_title+strlen(this_title); + while (p >= this_title) + { + char buf[9]; + memcpy(buf,p,8); + buf[8]=0; + if (!lstrcmpi(buf,"- Winamp")) break; + p--; + } + if (p >= this_title) p--; + while (p >= this_title && *p == ' ') p--; + *++p=0; + if (lstrcmpi(this_title,last_title)) + { + strcpy(last_title,this_title); + draw_title_p=1; + draw_title_time=GetTickCount()+1000; + } + else draw_title_p=0; + } + if (draw_title_p == 2) + { + draw_title_p=1; + draw_title_time=GetTickCount()+1000; + } +} + + +char statustext[256]; +DWORD statustext_life; +int statustext_len; + +void DDraw_SetStatusText(char *text, int life) +{ + strcpy(statustext,text); + statustext_len=life?life:2000; + statustext_life=1; + +} + + + +#ifndef NO_X86ASM +void homemadeBlitFrom32bpp(DDSURFACEDESC *out, void *in, int w, int h, int sy, int ey) +{ + int mh=min(h,(int)out->dwHeight); + if (sy < 0) sy=0; + if (ey > mh) ey=mh; + if (out->ddpfPixelFormat.dwRGBBitCount == 15) + { + int y; + int mw; + mw=min(w,out->lPitch/2); + unsigned int *inptr=(unsigned int *)in + w*sy; + for (y = sy; y < ey; y ++) + { + unsigned char *optr = (unsigned char *)out->lpSurface + (y * out->lPitch); + __asm + { + mov edi, optr + mov esi, inptr + mov ecx, mw + mov ebx, 00000000111110001111100011111000b + shr ecx, 1 + conv15_loop: + mov eax,[esi] + + mov edx,[esi+4] + + and eax, ebx + and edx, ebx + + // 00000000RRRRR000GGGGG000BBBBB000 + shr ah,3 // 00000000RRRRR000000GGGGGBBBBB000 + shr dh,3 + + shr ax,3 // 00000000RRRRR000000000GGGGGBBBBB + shr dx,3 + + // ----------------HHHHHHHHLLLLLLLL + ror eax,10// GGGGGBBBBB00000000RRRRR000000000 + ror edx,10 + + shr ah,1 + shr dh,1 + + mov al,ah + mov dl,dh + + rol eax,10 + + rol edx,10 + + shl edx, 16 + + and eax, 0x0000ffff + add esi,8 + + or eax, edx + + mov [edi], eax + + add edi, 4 + dec ecx + jnz conv15_loop + } + inptr += w; + } + + } + else if (out->ddpfPixelFormat.dwRGBBitCount == 16) + { + int y; + int mw; + mw=min(w,out->lPitch/2); + unsigned int *inptr=(unsigned int *)in + w*sy; + for (y = sy; y < ey; y ++) + { + unsigned char *optr = (unsigned char *)out->lpSurface + (y * out->lPitch); + __asm + { + mov edi, optr + mov esi, inptr + mov ecx, mw + mov ebx, 00000000111110001111110011111000b + shr ecx, 1 + conv16_loop: + mov eax,[esi] + + mov edx,[esi+4] + + and eax, ebx + and edx, ebx + + // RRRRR000GGGGGG00BBBBB000 + + shr ah,2 // RRRRR00000GGGGGGBBBBB000 + shr dh,2 + + shr ax,3 // RRRRR00000000GGGGGGBBBBB + shr dx,3 + + ror eax,8 // GGGBBBBBRRRRR00000000GGG + ror edx,8 + + add al,ah // GGGBBBBBRRRRR000RRRRRGGG + add dl,dh + + rol eax,8 // RRRRR000RRRRRGGGGGGBBBBB + + rol edx,8 + + shl edx, 16 + + and eax, 0x0000ffff + add esi,8 + + or eax, edx + + mov [edi], eax + + add edi, 4 + dec ecx + jnz conv16_loop + } + inptr += w; + } + + } + else if (out->ddpfPixelFormat.dwRGBBitCount == 24) + { // very unoptimized + int y,x; + int mw; + unsigned int *inptr=(unsigned int *)in+sy; + mw=min(w,out->lPitch/3); + for (y = sy; y < ey; y ++) + { + unsigned char *optr = (unsigned char *)out->lpSurface + (y * out->lPitch); + x=mw/2; + while (x--) + { + int a=inptr[0]; + int b=inptr[1]; + optr[0]=(unsigned char) a; + optr[3]=(unsigned char) b; + optr[1]=(unsigned char) (a>>8); + optr[4]=(unsigned char) (b>>8); + optr[2]=(unsigned char) (a>>16); + optr[5]=(unsigned char) (b>>16); + + optr+=6; + inptr+=2; + } + inptr += (w-mw); + } + } + else + { + unsigned char *outptr; + unsigned int *inptr; + int mw=min(w*4,out->lPitch); + int y; + inptr=(unsigned int*)in + (sy*w); + outptr=(unsigned char *)out->lpSurface + (sy*out->lPitch); + for (y = sy; y < ey; y ++) + { + memcpy(outptr,inptr,mw); + inptr+=w; + outptr+=out->lPitch; + } + } +} +#endif + +static int unlocksurfaces() +{ + int a=0; + if (g_lpRenderSurf[0] && g_lpRenderSurf[0]->Unlock(g_lpsurf[0]) != DD_OK) a=1; + if (g_lpRenderSurf[1] && g_lpRenderSurf[1]->Unlock(g_lpsurf[1]) != DD_OK) a=1; + return a; +} + +void DDraw_Exit(int which) +{ + if (!g_lpRenderSurf[0] || !g_lpRenderSurf[1]) + { + unlocksurfaces(); + goto endfunc; + } +#ifdef RESIZE_ONRESIZE + last_used=which; +#endif + + if (g_fs && !cfg_fs_use_overlay) + { + int fsy=g_h/2-((g_fs_height/2)); + RECT r={0,0,g_w,g_h}; + if (g_bpp != 32) // non-32bpp mode + { + if (fsy>0 && ((cfg_fs_fps&1) || (statustext_life&&!(cfg_fs_fps&8)))) // clear portions of backbuffer if necessary + { + DDBLTFX ddbfx={sizeof(ddbfx),}; + int ty=min(fsy,16); + RECT r2={0,0,g_w,ty}; + g_lpPrimSurfBack->Blt(&r2,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx); + r2.top=g_h-ty; + r2.bottom=g_h-1; + g_lpPrimSurfBack->Blt(&r2,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx); + } +#ifndef NO_X86ASM + if (!(g_fs_flip&8) && !g_windowed_dsize) // homemade bltshit + { + DDSURFACEDESC d={sizeof(d),}; + HRESULT han; + han = g_lpPrimSurfBack->Lock(NULL,&d,DDLOCK_WAIT,NULL); + if (han == DDERR_SURFACELOST) + { + DDBLTFX ddbfx={sizeof(ddbfx),}; + g_lpPrimSurfBack->Restore(); + g_lpPrimSurfBack->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx); + han = g_lpPrimSurfBack->Lock(NULL,&d,DDLOCK_WAIT,NULL); + } + if (han != DD_OK) goto slow_fs_non32bpp; + + homemadeBlitFrom32bpp(&d,g_lpsurf[which],g_w,g_h,fsy,g_h-fsy); + + int a=0; + if (g_lpPrimSurfBack->Unlock(d.lpSurface) != DD_OK ) a=1; + if (unlocksurfaces()||a) + { + goto endfunc; + } + } + else // slow (stretchblt) +#endif + { + HDC in, out; +#ifndef NO_X86ASM +slow_fs_non32bpp: +#endif + if (unlocksurfaces() || g_lpPrimSurfBack->GetDC(&out) != DD_OK) + { + goto endfunc; + } + if (g_lpRenderSurf[which]->GetDC(&in) != DD_OK) + { + g_lpPrimSurfBack->ReleaseDC(out); + goto endfunc; + } + if (g_windowed_dsize) StretchBlt(out,0,fsy*2,g_dsw,g_dsh-fsy*4,in,0,fsy,g_w,g_h-fsy*2,SRCCOPY); + else BitBlt(out,0,fsy,g_w,g_h-fsy*2,in,0,fsy,SRCCOPY); + g_lpRenderSurf[which]->ReleaseDC(in); + g_lpPrimSurfBack->ReleaseDC(out); + } + } + else // 32bpp - always just use Blt() - will scale if necessary (yay Blt!) + { + //RECT or={0,g_go_fs_h/2-g_go_fs_height/2,g_go_fs_w,g_go_fs_h/2+g_go_fs_height/2}; + //RECT ir={0,g_h/2-g_go_fs_height/2,g_w,g_h/2+g_go_fs_height/2}; + if (unlocksurfaces()) + { + goto endfunc; + } + if (g_lpPrimSurfBack->Blt(NULL,g_lpRenderSurf[which],&r,DDBLT_WAIT,NULL) == DDERR_SURFACELOST) + { + DDBLTFX ddbfx={sizeof(ddbfx),}; + if (g_fs_flip&1) + { + g_lpPrimSurfBack->Restore(); + g_lpPrimSurfBack->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx); + } + g_lpPrimSurf->Restore(); + g_lpPrimSurf->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx); + goto endfunc; + } + } + do_gettitle(); + if ((cfg_fs_fps&1) || (draw_title_p>0&&!(cfg_fs_fps&16)) || (statustext_life&&!(cfg_fs_fps&8))) + { + HDC out; + if (g_lpPrimSurfBack->GetDC(&out) == DD_OK) + { + char str[2048]; + SetBkMode(out,TRANSPARENT); + if (cfg_fs_fps&1) + { + RECT r={2,2,g_fs_w,g_fs_h}; + wsprintf(str,"%d.%d",g_dlg_fps/10,g_dlg_fps%10); + SetTextColor(out,RGB(0,0,0)); + DrawText(out,str,-1,&r,DT_TOP|DT_LEFT|DT_SINGLELINE|DT_NOCLIP|DT_NOPREFIX); + r.left=r.top=0; + SetTextColor(out,RGB(255,255,255)); + DrawText(out,str,-1,&r,DT_TOP|DT_LEFT|DT_SINGLELINE|DT_NOCLIP|DT_NOPREFIX); + } + if (statustext_life&&!(cfg_fs_fps&8)) + { + if (statustext_life==1) statustext_life=GetTickCount()+statustext_len; + RECT r={0,0,g_fs_w,g_fs_h}; + if (GetTickCount() > statustext_life) + { + if (statustext_life==2) statustext_life=0; + else statustext_life=2; + } + else + { + SetTextColor(out,RGB(0,0,0)); + DrawText(out,statustext,-1,&r,DT_BOTTOM|DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX); + SetTextColor(out,RGB(255,255,255)); + r.right-=2; + r.bottom-=2; + DrawText(out,statustext,-1,&r,DT_BOTTOM|DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX); + } + } + if (draw_title_p>0&&!(cfg_fs_fps&16)) + { + RECT r={4,4,g_fs_w,g_fs_h}; + SetTextColor(out,RGB(0,0,0)); + DrawText(out,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX); + r.left=r.top=0; + SetTextColor(out,RGB(255,255,255)); + DrawText(out,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX); + } + g_lpPrimSurfBack->ReleaseDC(out); + } + if (draw_title_p>0 && draw_title_time < GetTickCount() && !(cfg_fs_fps&16)) + { + if (g_lpRenderSurf[which]->GetDC(&out) == DD_OK) + { + RECT r={4,4,g_w,g_h}; + SetBkMode(out,TRANSPARENT); + SetTextColor(out,RGB(0,0,0)); + DrawText(out,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX); + r.left=r.top=0; + SetTextColor(out,RGB(255,255,255)); + DrawText(out,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX); + g_lpRenderSurf[which]->ReleaseDC(out); + } + draw_title_p=0; + } + } + if (g_fs_flip&1) g_lpPrimSurf->Flip(NULL, DDFLIP_WAIT); + else if (!(g_fs_flip&2)) g_lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0); + } + else + { + if(g_overlay_init_ok) + { + LPDDSURFACEDESC pd=(which==0?&d:&d2); + DDSURFACEDESC dd={sizeof(dd),}; + if (g_fs) if (!(cfg_fs_flip&2)) g_lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0); + + if (g_lpddsOverlay->Lock(NULL,&dd,DDLOCK_WAIT,NULL) != DD_OK) + { + g_overlay_init_ok=0; + goto endfunc; + } +#ifndef NO_MMX + CopyRGBSurfaceToYUVSurfaceMMX(pd,&dd,g_overlay_fourcc); +#else + CopyRGBSurfaceToYUVSurface(pd,&dd,g_overlay_fourcc); +#endif + g_lpddsOverlay->Unlock(&dd); + if (g_fs) + { + unlocksurfaces(); + goto endfunc; + } + } + + HDC in1, out, in2=NULL; + if (unlocksurfaces() || g_lpRenderSurf[which]->GetDC(&in1) != DD_OK) + { + goto endfunc; + } + do_gettitle(); + if (draw_title_p>0&&!(cfg_fs_fps&4) && draw_title_time < GetTickCount()) + { + RECT r={4,4,g_w,g_h}; + SetBkMode(in1,TRANSPARENT); + SetTextColor(in1,RGB(0,0,0)); + DrawText(in1,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX); + r.left=r.top=0; + SetTextColor(in1,RGB(255,255,255)); + DrawText(in1,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX); + draw_title_p=0; + } + if ((draw_title_p > 0&&!(cfg_fs_fps&4)) || (statustext_life&&!(cfg_fs_fps&2))) + { + // draw perframe + RECT r={4,4,g_w,g_h}; + if (g_lpRenderSurf[which^1]->GetDC(&in2) != DD_OK) + { + in2=NULL; + goto abort_thingy; + } + BitBlt(in2,0,0,g_w,g_h,in1,0,0,SRCCOPY); + SetBkMode(in2,TRANSPARENT); + if (draw_title_p > 0&&!(cfg_fs_fps&4)) + { + SetTextColor(in2,RGB(0,0,0)); + DrawText(in2,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX); + r.left=r.top=0; + SetTextColor(in2,RGB(255,255,255)); + DrawText(in2,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX); + } + if (statustext_life&&!(cfg_fs_fps&2)) + { + if (statustext_life==1) statustext_life=GetTickCount()+statustext_len; + if (GetTickCount() > statustext_life) statustext_life=0; + SetTextColor(in2,RGB(0,0,0)); + DrawText(in2,statustext,-1,&r,DT_BOTTOM|DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX); + r.right-=2; + r.bottom-=2; + SetTextColor(in2,RGB(255,255,255)); + DrawText(in2,statustext,-1,&r,DT_BOTTOM|DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX); + } + } +abort_thingy: + if (!(cfg_fs_flip&4)) g_lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0); + out=GetDC(g_hwnd); + if (out) + { + if (!g_windowed_dsize) + { +#ifndef WA2_EMBED + BitBlt(out,inWharf?0:7,inWharf?0:15,g_w-g_noshoww,g_h,in2?in2:in1,0,0,SRCCOPY); +#else + BitBlt(out,0,0,g_w-g_noshoww,g_h,in2?in2:in1,0,0,SRCCOPY); +#endif + } + else + { +#ifndef WA2_EMBED + StretchBlt(out,inWharf?0:7,inWharf?0:15,g_dsw,g_dsh,in2?in2:in1,0,0,g_w,g_h,SRCCOPY); +#else + StretchBlt(out,0,0,g_dsw,g_dsh,in2?in2:in1,0,0,g_w,g_h,SRCCOPY); +#endif + } + ReleaseDC(g_hwnd,out); + } + g_lpRenderSurf[which]->ReleaseDC(in1); + if (in2) + g_lpRenderSurf[which^1]->ReleaseDC(in2); + } +endfunc: + LeaveCriticalSection(&g_cs); +} + + +void DDraw_SetFullScreen(int fs, int w, int h, int dbl, int bpp) +{ + if (!fs) DD_CreateSurfaces(w, h, 0, 0, 0, 0, !!dbl, 0); + else + { + DD_CreateSurfaces(w, h, (min(max(1,cfg_fs_height),100)*h)/100, 1, bpp, cfg_fs_flip, !!dbl, cfg_fs_use_overlay); + } +} + +int DDraw_IsFullScreen(void) +{ + return g_fs; +} + +HRESULT WINAPI _cb( + LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext) +{ + HWND h=(HWND)lpContext; + if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) && + (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==32 || + lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==24 || + lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==16 || + lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==15)) + { + char s[256]; + wsprintf(s,"%dx%d@%dBPP",lpDDSurfaceDesc->dwWidth,lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount); + SendMessage(h,CB_ADDSTRING,0,(long)s); + } + + return DDENUMRET_OK; +} + + +void DDraw_EnumDispModes(HWND hwnd) +{ + if (g_lpDD) + g_lpDD->EnumDisplayModes(0,NULL,hwnd,_cb); +} + +static int g_st; + +HRESULT WINAPI _cb2( + LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext) +{ + DWORD *x=(DWORD *)lpContext; + if (x[0]==lpDDSurfaceDesc->dwWidth && + x[1]==lpDDSurfaceDesc->dwHeight && + x[2]==lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount) + { + g_st=1; + return DDENUMRET_CANCEL; + } + + return DDENUMRET_OK; +} + +int DDraw_IsMode(int w, int h, int bpp) +{ + int x[3]={w,h,bpp}; + if (!x[0] || !x[1] || !x[2]) return 0; + if (!g_lpDD) return 0; + g_st=0; + g_lpDD->EnumDisplayModes(0,NULL,(LPVOID)x,_cb2); + return g_st; +} + +HRESULT WINAPI _cb3( + LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext) +{ + if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) && + (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==32 || + lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==24 || + lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==16 || + lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==15)) + { + int *(*x)=(int **)lpContext; + if (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount > (DWORD)x[2][0] || + lpDDSurfaceDesc->dwWidth < (DWORD)x[0][0] || + lpDDSurfaceDesc->dwHeight < (DWORD)x[1][0]) + { + x[0][0]=lpDDSurfaceDesc->dwWidth; + x[1][0]=lpDDSurfaceDesc->dwHeight; + x[2][0]=lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount; + } + } + + return DDENUMRET_OK; +} + + +int DDraw_PickMode(int *w, int *h, int *bpp) +{ + int *(x[3])={w,h,bpp}; + *w=0; + *h=0; + *bpp=0; + // return if mode found that is suitable + g_lpDD->EnumDisplayModes(0,NULL,(LPVOID)x,_cb3); + return *w && *h && *bpp; +} + +double DDraw_translatePoint(POINT p, int isY) +{ + double v=0.0; + if(g_fs && g_overlay_init_ok && hwndOverlayWnd && IsWindow(hwndOverlayWnd)) + { + RECT r; + ScreenToClient(hwndOverlayWnd,&p); + GetClientRect(hwndOverlayWnd,&r); + if (isY) + { + if (r.bottom>0) + v=p.y/(double)(r.bottom*0.5) - 1.0; + } + else + { + if (r.right>0) + v=p.x/(double)(r.right*0.5) - 1.0; + } + } + else + { + ScreenToClient(g_hwnd,&p); + + if (isY) + { + if (g_dsh>0) + v=p.y/(double)(g_dsh*0.5) - 1.0; + } + else + { + if (g_dsw>0) + v=p.x/(double)(g_dsw*0.5) - 1.0; + } + } + //if (v > 1.0) v=1.0; + //if (v < -1.0) v=-1.0; + return v; +}
\ No newline at end of file |