![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
00001 /* 00002 Copyright 2005-2010 Intel Corporation. All Rights Reserved. 00003 00004 This file is part of Threading Building Blocks. 00005 00006 Threading Building Blocks is free software; you can redistribute it 00007 and/or modify it under the terms of the GNU General Public License 00008 version 2 as published by the Free Software Foundation. 00009 00010 Threading Building Blocks is distributed in the hope that it will be 00011 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00012 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with Threading Building Blocks; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 00019 As a special exception, you may use this file as part of a free software 00020 library without restriction. Specifically, if other files instantiate 00021 templates or use macros or inline functions from this file, or you compile 00022 this file and link it with other files to produce an executable, this 00023 file does not by itself cause the resulting executable to be covered by 00024 the GNU General Public License. This exception does not however 00025 invalidate any other reasons why the executable file might be covered by 00026 the GNU General Public License. 00027 */ 00028 00029 // common Windows parts 00030 #include "winvideo.h" 00031 // and another headers 00032 #include <cassert> 00033 #include <stdio.h> 00034 #include <ddraw.h> 00035 00036 #pragma comment(lib, "ddraw.lib") 00037 #pragma comment(lib, "dxguid.lib") 00038 00039 LPDIRECTDRAW7 g_pDD = NULL; // DirectDraw object 00040 LPDIRECTDRAWSURFACE7 g_pDDSPrimary = NULL;// DirectDraw primary surface 00041 LPDIRECTDRAWSURFACE7 g_pDDSBack = NULL; // DirectDraw back surface 00042 LPDIRECTDRAWSURFACE7 g_pDDSOverlay = NULL;// DirectDraw overlay surface 00043 LPDIRECTDRAWCLIPPER g_pClipper = NULL; // DirectDraw clipping struct 00044 DDOVERLAYFX g_OverlayFX; // DirectDraw overlay effects struct 00045 DDCAPS g_DDCaps; // DirectDraw hardware capabilities struct 00046 DWORD g_OverlayFlags = 0; // DirectDraw overlay flags variable 00047 DWORD g_dwXRatio, 00048 g_dwYRatio; // The ratios between the src and dst rects 00049 RECT g_rcSrc = {0, 0, 0, 0}, 00050 g_rcDst = {0, 0, 0, 0}; 00051 HANDLE g_hVSync; 00052 00053 // check for new DX SDK (8 & 9) 00054 #ifdef DDSCAPS_PRIMARYSURFACELEFT 00055 #include <dxerr8.h> 00056 #pragma comment(lib, "dxerr8.lib") 00057 #else 00058 // old SDK (7) 00059 #include <d3dx.h> 00060 #pragma comment(lib, "d3dx.lib") 00061 #endif 00062 00064 bool DisplayError(LPSTR lpstrErr, HRESULT hres) 00065 { 00066 static bool InError = false; 00067 int retval = 0; 00068 if (!InError) 00069 { 00070 InError = true; 00071 #ifdef DDSCAPS_PRIMARYSURFACELEFT 00072 const char *message = hres?DXGetErrorString8A(hres):0; 00073 #else 00074 char message[256]; if(hres) D3DXGetErrorString(hres, 256, message); 00075 #endif 00076 retval = MessageBoxA(g_hAppWnd, lpstrErr, hres?message:"Error!", MB_OK|MB_ICONERROR); 00077 InError = false; 00078 } 00079 return false; 00080 } 00081 00083 void DestroyOverlay() 00084 { 00085 if (g_pClipper) 00086 g_pClipper->Release(); 00087 if (g_pDDSOverlay) { 00088 g_pImg = 0; LPDIRECTDRAWSURFACE7 pDDSOverlay(g_pDDSOverlay); 00089 g_pDDSOverlay = NULL; 00090 YIELD_TO_THREAD(); 00091 pDDSOverlay->Release(); // be sure nobody uses old value 00092 } 00093 } 00094 00096 void DestroyPrimary() 00097 { 00098 if (g_pDDSPrimary) 00099 { 00100 g_pDDSPrimary->Release(); 00101 g_pDDSPrimary = NULL; 00102 } 00103 } 00104 00106 void DestroyDDraw() 00107 { 00108 DestroyPrimary(); 00109 // Release the DDraw object 00110 if (g_pDD) { 00111 LPDIRECTDRAW7 pDD(g_pDD); // be sure nobody uses old value 00112 g_pDD = NULL; Sleep(1); pDD->Release(); 00113 } 00114 } 00115 00117 void CheckBoundries(void) 00118 { 00119 // Make sure the coordinates fulfill the stretching requirements. Often 00120 // the hardware will require a certain ammount of stretching to do 00121 // overlays. This stretch factor is held in dwMinOverlayStretch as the 00122 // stretch factor multiplied by 1000 (to keep an accuracy of 3 decimal places). 00123 if ((g_DDCaps.dwCaps & DDCAPS_OVERLAYSTRETCH) && (g_DDCaps.dwMinOverlayStretch) 00124 && (g_dwXRatio < g_DDCaps.dwMinOverlayStretch)) 00125 { 00126 g_rcDst.right = 2 * GetSystemMetrics(SM_CXSIZEFRAME) + g_rcDst.left + (g_sizex 00127 * (g_DDCaps.dwMinOverlayStretch + 1)) / 1000; 00128 SetWindowTextA(g_hAppWnd, "Window is too small!"); 00129 } 00130 else if ((g_DDCaps.dwCaps & DDCAPS_OVERLAYSTRETCH) && (g_DDCaps.dwMaxOverlayStretch) 00131 && (g_dwXRatio > g_DDCaps.dwMaxOverlayStretch)) 00132 { 00133 g_rcDst.right = 2 * GetSystemMetrics(SM_CXSIZEFRAME) + g_rcDst.left + (g_sizey 00134 * (g_DDCaps.dwMaxOverlayStretch + 999)) / 1000; 00135 SetWindowTextA(g_hAppWnd, "Window is too large!"); 00136 } 00137 else if(!g_video->calc_fps) SetWindowText(g_hAppWnd, g_video->title); 00138 00139 // Recalculate the ratio's for the upcoming calculations 00140 g_dwXRatio = (g_rcDst.right - g_rcDst.left) * 1000 / (g_rcSrc.right - g_rcSrc.left); 00141 g_dwYRatio = (g_rcDst.bottom - g_rcDst.top) * 1000 / (g_rcSrc.bottom - g_rcSrc.top); 00142 00143 // Check to make sure we're within the screen's boundries, if not then fix 00144 // the problem by adjusting the source rectangle which we draw from. 00145 if (g_rcDst.left < 0) 00146 { 00147 g_rcSrc.left = -g_rcDst.left * 1000 / g_dwXRatio; 00148 g_rcDst.left = 0; 00149 } 00150 if (g_rcDst.right > GetSystemMetrics(SM_CXSCREEN)) 00151 { 00152 g_rcSrc.right = g_sizex - ((g_rcDst.right - GetSystemMetrics(SM_CXSCREEN)) * 1000 / g_dwXRatio); 00153 g_rcDst.right = GetSystemMetrics(SM_CXSCREEN); 00154 } 00155 if (g_rcDst.bottom > GetSystemMetrics(SM_CYSCREEN)) 00156 { 00157 g_rcSrc.bottom = g_sizey - ((g_rcDst.bottom - GetSystemMetrics(SM_CYSCREEN)) * 1000 / g_dwYRatio); 00158 g_rcDst.bottom = GetSystemMetrics(SM_CYSCREEN); 00159 } 00160 // I don't know how useful this is... but just in case someone can do it - here's the check. 00161 if (g_rcDst.top < 0) 00162 { 00163 g_rcSrc.top = -g_rcDst.top * 1000 / g_dwYRatio; 00164 g_rcDst.top = 0; 00165 } 00166 00167 // Make sure the coordinates fulfill the alignment requirements 00168 // these expressions (x & -y) just do alignment by dropping low order bits... 00169 // so to round up, we add first, then truncate. 00170 if ((g_DDCaps.dwCaps & DDCAPS_ALIGNBOUNDARYSRC) && g_DDCaps.dwAlignBoundarySrc) 00171 g_rcSrc.left = (g_rcSrc.left + g_DDCaps.dwAlignBoundarySrc / 2) & -(signed) 00172 (g_DDCaps.dwAlignBoundarySrc); 00173 if ((g_DDCaps.dwCaps & DDCAPS_ALIGNSIZESRC) && g_DDCaps.dwAlignSizeSrc) 00174 g_rcSrc.right = g_rcSrc.left + (g_rcSrc.right - g_rcSrc.left + g_DDCaps.dwAlignSizeSrc 00175 / 2) & -(signed) (g_DDCaps.dwAlignSizeSrc); 00176 if ((g_DDCaps.dwCaps & DDCAPS_ALIGNBOUNDARYDEST) && g_DDCaps.dwAlignBoundaryDest) 00177 g_rcDst.left = (g_rcDst.left + g_DDCaps.dwAlignBoundaryDest / 2) & -(signed) 00178 (g_DDCaps.dwAlignBoundaryDest); 00179 if ((g_DDCaps.dwCaps & DDCAPS_ALIGNSIZEDEST) && g_DDCaps.dwAlignSizeDest) 00180 g_rcDst.right = g_rcDst.left + (g_rcDst.right - g_rcDst.left) & -(signed) (g_DDCaps.dwAlignSizeDest); 00181 } 00182 00184 DWORD DDColorMatch(IDirectDrawSurface7 * pdds, COLORREF rgb) 00185 { 00186 COLORREF rgbT; 00187 HDC hdc; 00188 DWORD dw = CLR_INVALID; 00189 DDSURFACEDESC2 ddsd; 00190 HRESULT hres; 00191 00192 // Use GDI SetPixel to color match for us 00193 if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK) { 00194 rgbT = GetPixel(hdc, 0, 0); // Save current pixel value 00195 SetPixel(hdc, 0, 0, rgb); // Set our value 00196 pdds->ReleaseDC(hdc); 00197 } 00198 // Now lock the surface so we can read back the converted color 00199 ddsd.dwSize = sizeof(ddsd); 00200 while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING) 00201 YIELD_TO_THREAD(); 00202 if (hres == DD_OK) { 00203 dw = *(DWORD *) ddsd.lpSurface; // Get DWORD 00204 if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32) 00205 dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1; // Mask it to bpp 00206 pdds->Unlock(NULL); 00207 } 00208 else return DisplayError("Can't lock primary surface", hres); 00209 // Now put the color that was there back. 00210 if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK) { 00211 SetPixel(hdc, 0, 0, rgbT); 00212 pdds->ReleaseDC(hdc); 00213 } 00214 return dw; 00215 } 00216 00218 bool DrawOverlay() 00219 { 00220 HRESULT hRet; // This is where we put return values from DirectDraw. 00221 DDSURFACEDESC2 surfDesc; 00222 // Setup structure 00223 memset(&surfDesc, 0, sizeof(surfDesc)); surfDesc.dwSize = sizeof(surfDesc); 00224 00225 hRet = g_pDDSOverlay->Lock(NULL, &surfDesc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_NOSYSLOCK | DDLOCK_WRITEONLY, NULL); 00226 if (hRet != DD_OK || surfDesc.lpSurface == NULL) 00227 return DisplayError("Can't lock overlay surface", hRet); 00228 else { 00229 g_pImg = (unsigned int *)surfDesc.lpSurface; 00230 //g_pDDSOverlay->Unlock(NULL); is not needed? 00231 } 00232 // Setup effects structure 00233 memset(&g_OverlayFX, 0, sizeof(g_OverlayFX)); g_OverlayFX.dwSize = sizeof(g_OverlayFX); 00234 // Setup overlay flags. 00235 g_OverlayFlags = DDOVER_SHOW; 00236 // Check for destination color keying capability 00237 if ((g_DDCaps.dwCKeyCaps & DDCKEYCAPS_DESTOVERLAY) && ((g_DDCaps.dwCaps & DDCAPS_OVERLAYCANTCLIP) || (g_DDCaps.dwCKeyCaps & DDCKEYCAPS_NOCOSTOVERLAY) )) 00238 { 00239 // If so, we'll use it to clip the bitmap when other windows go on top 00240 // of us. Just for the record - this color range for color keying (the 00241 // high/low values) are not heavily supported right now, so for almost 00242 // all cards, just use the same color for both. 00243 g_OverlayFX.dckDestColorkey.dwColorSpaceLowValue = 00244 g_OverlayFX.dckDestColorkey.dwColorSpaceHighValue = DDColorMatch(g_pDDSPrimary, RGBKEY); 00245 g_OverlayFlags |= DDOVER_DDFX | DDOVER_KEYDESTOVERRIDE; 00246 } else { 00247 // If not, we'll setup a clipper for the window. This will fix the 00248 // problem on a few video cards - but the ones that don't shouldn't care. 00249 hRet = g_pDD->CreateClipper(0, &g_pClipper, NULL); 00250 if (hRet != DD_OK) 00251 return DisplayError("Can't create clipper", hRet); 00252 hRet = g_pClipper->SetHWnd(0, g_hAppWnd); 00253 if (hRet != DD_OK) 00254 return DisplayError("Can't attach clipper", hRet); 00255 hRet = g_pDDSPrimary->SetClipper(g_pClipper); 00256 if (hRet != DD_OK) 00257 return DisplayError("Can't set clipper", hRet); 00258 } 00259 return true; 00260 } 00261 00263 bool DDPrimaryInit() 00264 { 00265 HRESULT hRet; 00266 DDSURFACEDESC2 ddsd; // A surface description structure 00267 00268 // Create the primary surface. The primary surface is the full screen - 00269 // since we're a windowed app - we'll just write to the portion of the 00270 // screen within our window. 00271 memset(&ddsd, 0, sizeof(ddsd)); // Set all fields of struct to 0 and set .dwSize to 00272 ddsd.dwSize = sizeof(ddsd); // Sizeof the variable - these two steps required for most DDraw structs 00273 ddsd.dwFlags = DDSD_CAPS; // Set flags for variables we're using... 00274 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // Set the variables we said we would in dwFlags 00275 hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL); 00276 if (hRet != DD_OK) 00277 return DisplayError("Can't create primary surface", hRet); 00278 return true; 00279 } 00280 00282 bool DDInit() 00283 { 00284 HRESULT hRet; 00285 g_rcSrc.right = g_sizex; 00286 g_rcSrc.bottom = g_sizey; 00287 00288 hRet = DirectDrawCreateEx(NULL, (VOID**)&g_pDD, IID_IDirectDraw7, NULL); 00289 if (hRet != DD_OK) 00290 return DisplayError("Can't create DirectDraw7 instance", hRet); 00291 00292 // Set cooperation level with other windows to be normal (ie. not full screen) 00293 // You MUST set the cooperation level to be SOMETHING, for windowed apps use 00294 // DDSCL_NORMAL, for full screen use: DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. 00295 hRet = g_pDD->SetCooperativeLevel(g_hAppWnd, DDSCL_NORMAL); 00296 if (hRet != DD_OK) 00297 return DisplayError("Can't set cooperative level", hRet); 00298 return DDPrimaryInit(); 00299 } 00300 00302 bool DDOverlayInit() 00303 { 00304 // Get hardware's CAPabilitieS 00305 memset(&g_DDCaps, 0, sizeof(g_DDCaps)); 00306 g_DDCaps.dwSize = sizeof(g_DDCaps); 00307 if (g_pDD->GetCaps(&g_DDCaps, 0)) 00308 return DisplayError("Can't get capabilities"); 00309 00310 // Make sure it supports overlays 00311 if (!(g_DDCaps.dwCaps & DDCAPS_OVERLAY)) 00312 return DisplayError("Hardware doesn't support overlays"); 00313 00314 //DO NOT Make sure it supports stretching (scaling) 00315 //if (!(g_DDCaps.dwCaps & DDCAPS_OVERLAYSTRETCH)) return false; 00316 00317 DDSURFACEDESC2 ddsd; // DirectDraw surface descriptor 00318 HRESULT hRet; // I'm not even going to try... 00319 // The pixel formats that we want the surface to be in 00320 DDPIXELFORMAT ddpfOverlayFormats[] = { 00321 {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 32, 0xFF0000, 0x0FF00, 0x0000FF, 0}, // 32-bit RGB 00322 {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x007C00, 0x003e0, 0x00001F, 0}, // 16-bit RGB 5:5:5 00323 {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x00F800, 0x007e0, 0x00001F, 0}, // 16-bit RGB 5:6:5 00324 {sizeof(DDPIXELFORMAT), DDPF_FOURCC, mmioFOURCC('U','Y','V','Y'), 16, 0, 0, 0, 0}, // UYVY 00325 {sizeof(DDPIXELFORMAT), DDPF_FOURCC, mmioFOURCC('Y','4','2','2'), 16, 0, 0, 0, 0}, // the same as UYVY 00326 {sizeof(DDPIXELFORMAT), DDPF_FOURCC, mmioFOURCC('Y','U','Y','2'), 16, 0, 0, 0, 0}, // YUY2 is unsupported color-space here 00327 {0}}; 00328 00329 // Setup the overlay surface's attributes in the surface descriptor 00330 memset(&ddsd, 0, sizeof(ddsd)); 00331 ddsd.dwSize = sizeof(ddsd); 00332 ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | g_DDCaps.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY; 00333 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; 00334 ddsd.dwBackBufferCount = 0; 00335 ddsd.dwWidth = g_sizex; 00336 ddsd.dwHeight = g_sizey; 00337 for(int format = 0; ddpfOverlayFormats[format].dwSize; format++) { 00338 ddsd.ddpfPixelFormat = ddpfOverlayFormats[format]; 00339 // Attempt to create the surface with theses settings 00340 hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSOverlay, NULL); 00341 if(hRet == DD_OK) break; 00342 } 00343 if (hRet != DD_OK) 00344 return DisplayError("Can't create appropriate overlay surface", hRet); 00345 return true; 00346 } 00347 00348 inline void mouse(int k, LPARAM lParam) 00349 { 00350 int x = (int)LOWORD(lParam), y = (int)HIWORD(lParam); 00351 g_video->on_mouse( x*g_sizex/(g_rcDst.right - g_rcDst.left), 00352 y*g_sizey/(g_rcDst.bottom - g_rcDst.top), k); 00353 } 00354 00355 LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) 00356 { 00357 PAINTSTRUCT ps; // Structure for the paint message 00358 POINT p = {0, 0}; // Translation point for the window's client region 00359 HRESULT hRet; 00360 00361 switch (iMsg) 00362 { 00363 case WM_MOVE: 00364 // Make sure we're not moving to be minimized - because otherwise 00365 // our ratio varialbes (g_dwXRatio and g_dwYRatio) will end up 00366 // being 0, and once we hit CheckBoundries it divides by 0. 00367 if (!IsIconic(hwnd)) 00368 { 00369 g_rcSrc.left = 0; 00370 g_rcSrc.right = g_sizex; 00371 g_rcSrc.top = 0; 00372 g_rcSrc.bottom = g_sizey; 00373 GetClientRect(hwnd, &g_rcDst); 00374 g_dwXRatio = (g_rcDst.right - g_rcDst.left) * 1000 / 00375 (g_rcSrc.right - g_rcSrc.left); 00376 g_dwYRatio = (g_rcDst.bottom - g_rcDst.top) * 1000 / 00377 (g_rcSrc.bottom - g_rcSrc.top); 00378 ClientToScreen(hwnd, &p); 00379 g_rcDst.left = p.x; 00380 g_rcDst.top = p.y; 00381 g_rcDst.bottom += p.y; 00382 g_rcDst.right += p.x; 00383 CheckBoundries(); 00384 } 00385 else 00386 // Else, hide the overlay... just in case we can't do 00387 // destination color keying, this will pull the overlay 00388 // off of the screen for the user. 00389 if (g_pDDSOverlay && g_pDDSPrimary) 00390 g_pDDSOverlay->UpdateOverlay(NULL, g_pDDSPrimary, NULL, DDOVER_HIDE, NULL); 00391 // Check to make sure our window exists before we tell it to 00392 // repaint. This will fail the first time (while the window is being created). 00393 if (hwnd) 00394 { 00395 InvalidateRect(hwnd, NULL, FALSE); 00396 UpdateWindow(hwnd); 00397 } 00398 return 0L; 00399 00400 case WM_SIZE: 00401 // Another check for the minimization action. This check is 00402 // quicker though... 00403 if (wParam != SIZE_MINIMIZED) 00404 { 00405 GetClientRect(hwnd, &g_rcDst); 00406 ClientToScreen(hwnd, &p); 00407 g_rcDst.left = p.x; 00408 g_rcDst.top = p.y; 00409 g_rcDst.bottom += p.y; 00410 g_rcDst.right += p.x; 00411 g_rcSrc.left = 0; 00412 g_rcSrc.right = g_sizex; 00413 g_rcSrc.top = 0; 00414 g_rcSrc.bottom = g_sizey; 00415 // Here we multiply by 1000 to preserve 3 decimal places in the 00416 // division opperation (we picked 1000 to be on the same order 00417 // of magnitude as the stretch factor for easier comparisons) 00418 g_dwXRatio = (g_rcDst.right - g_rcDst.left) * 1000 / 00419 (g_rcSrc.right - g_rcSrc.left); 00420 g_dwYRatio = (g_rcDst.bottom - g_rcDst.top) * 1000 / 00421 (g_rcSrc.bottom - g_rcSrc.top); 00422 CheckBoundries(); 00423 } 00424 return 0L; 00425 00426 case WM_PAINT: 00427 BeginPaint(hwnd, &ps); 00428 // Check the primary surface to see if it's lost - if so you can 00429 // pretty much bet that the other surfaces are also lost - thus 00430 // restore EVERYTHING! If we got our surfaces stolen by a full 00431 // screen app - then we'll destroy our primary - and won't be able 00432 // to initialize it again. When we get our next paint message (the 00433 // full screen app closed for example) we'll want to try to reinit 00434 // the surfaces again - that's why there is a check for 00435 // g_pDDSPrimary == NULL. The other option, is that our program 00436 // went through this process, could init the primary again, but it 00437 // couldn't init the overlay, that's why there's a third check for 00438 // g_pDDSOverlay == NULL. Make sure that the check for 00439 // !g_pDDSPrimary is BEFORE the IsLost call - that way if the 00440 // pointer is NULL (ie. !g_pDDSPrimary is TRUE) - the compiler 00441 // won't try to evaluate the IsLost function (which, since the 00442 // g_pDDSPrimary surface is NULL, would be bad...). 00443 if (!g_pDDSPrimary || (g_pDDSPrimary->IsLost() != DD_OK) || 00444 (g_pDDSOverlay == NULL)) 00445 { 00446 DestroyOverlay(); 00447 DestroyPrimary(); 00448 if (DDPrimaryInit()) 00449 if (DDOverlayInit()) 00450 if (!DrawOverlay()) 00451 DestroyOverlay(); 00452 } 00453 // UpdateOverlay is how we put the overlay on the screen. 00454 if (g_pDDSOverlay && g_pDDSPrimary && g_video->updating) 00455 { 00456 hRet = g_pDDSOverlay->UpdateOverlay(&g_rcSrc, g_pDDSPrimary, 00457 &g_rcDst, g_OverlayFlags, 00458 &g_OverlayFX); 00459 #ifdef _DEBUG 00460 if(hRet != DD_OK) DisplayError("Can't update overlay", hRet); 00461 #endif 00462 } 00463 EndPaint(hwnd, &ps); 00464 return 0L; 00465 00466 // process mouse and keyboard events 00467 case WM_LBUTTONDOWN: mouse(1, lParam); break; 00468 case WM_LBUTTONUP: mouse(-1, lParam); break; 00469 case WM_RBUTTONDOWN: mouse(2, lParam); break; 00470 case WM_RBUTTONUP: mouse(-2, lParam); break; 00471 case WM_MBUTTONDOWN: mouse(3, lParam); break; 00472 case WM_MBUTTONUP: mouse(-3, lParam); break; 00473 case WM_CHAR: g_video->on_key(wParam); break; 00474 00475 case WM_DISPLAYCHANGE: return 0L; 00476 00477 case WM_DESTROY: 00478 // Now, shut down the window... 00479 PostQuitMessage(0); 00480 return 0L; 00481 } 00482 return g_pUserProc? g_pUserProc(hwnd, iMsg, wParam, lParam) : DefWindowProc(hwnd, iMsg, wParam, lParam); 00483 } 00484 00485 DWORD WINAPI thread_vsync(LPVOID lpParameter) 00486 { 00487 BOOL vblank = false; 00488 while(g_video && g_video->running) { 00489 while(!vblank && g_video && g_video->running) { 00490 YIELD_TO_THREAD(); 00491 LPDIRECTDRAW7 pDD(g_pDD); 00492 if(pDD) pDD->GetVerticalBlankStatus(&vblank); 00493 } 00494 LPDIRECTDRAWSURFACE7 pDDSOverlay(g_pDDSOverlay); 00495 if(pDDSOverlay) pDDSOverlay->UpdateOverlay(&g_rcSrc, g_pDDSPrimary, &g_rcDst, g_OverlayFlags | DDOVER_REFRESHALL, &g_OverlayFX); 00496 do { 00497 Sleep(1); 00498 LPDIRECTDRAW7 pDD(g_pDD); 00499 if(pDD) pDD->GetVerticalBlankStatus(&vblank); 00500 } while(vblank && g_video && g_video->running); 00501 while(g_video && !g_video->updating && g_video->running) Sleep(10); 00502 } 00503 return 0; 00504 } 00505 00507 00508 inline void mask2bits(unsigned int mask, color_t &save, char &shift) 00509 { 00510 save = mask; if(!mask) { shift = 8; return; } 00511 shift = 0; while(!(mask&1)) ++shift, mask >>= 1; 00512 int bits = 0; while(mask&1) ++bits, mask >>= 1; 00513 shift += bits - 8; 00514 } 00515 00516 bool video::init_window(int sizex, int sizey) 00517 { 00518 assert(win_hInstance != 0); 00519 g_sizex = sizex; g_sizey = sizey; 00520 if( !WinInit(win_hInstance, win_iCmdShow, gWndClass, title, false) ) 00521 return DisplayError("Unable to initialize the program's window."); 00522 running = true; 00523 if( !DDInit() ) { 00524 DestroyDDraw(); 00525 goto fail; 00526 } 00527 if( !DDOverlayInit() || !DrawOverlay() ) { 00528 DestroyOverlay(); 00529 DestroyDDraw(); 00530 goto fail; 00531 } 00532 DDPIXELFORMAT PixelFormat; memset(&PixelFormat, 0, sizeof(PixelFormat)); PixelFormat.dwSize = sizeof(PixelFormat); 00533 g_pDDSOverlay->GetPixelFormat(&PixelFormat); 00534 mask2bits(PixelFormat.dwRBitMask, red_mask, red_shift); 00535 mask2bits(PixelFormat.dwGBitMask, green_mask, green_shift); 00536 mask2bits(PixelFormat.dwBBitMask, blue_mask, blue_shift); 00537 if(PixelFormat.dwFlags == DDPF_RGB) 00538 depth = char(PixelFormat.dwRGBBitCount); 00539 else depth = -char(PixelFormat.dwFourCC); 00540 for(int i = 0, e = sizex * sizey * PixelFormat.dwRGBBitCount / 32, c = get_color(0, 0, 0); i < e; i++) 00541 g_pImg[i] = c; // clear surface 00542 ShowWindow(g_hAppWnd, SW_SHOW); 00543 g_hVSync = CreateThread ( 00544 NULL, // LPSECURITY_ATTRIBUTES security_attrs 00545 0, // SIZE_T stacksize 00546 (LPTHREAD_START_ROUTINE) thread_vsync, 00547 this, // argument 00548 0, 0); 00549 SetPriorityClass(g_hVSync, IDLE_PRIORITY_CLASS); // questionable 00550 return true; 00551 fail: 00552 g_pImg = new unsigned int[g_sizex * g_sizey]; 00553 return false; 00554 } 00555 00556 void video::terminate() 00557 { 00558 running = false; 00559 DestroyOverlay(); 00560 if(WaitForSingleObject(g_hVSync, 100) == WAIT_TIMEOUT) TerminateThread(g_hVSync, 0); 00561 CloseHandle(g_hVSync); 00562 DestroyDDraw(); 00563 if(g_pImg) delete[] g_pImg; 00564 g_pImg = 0; g_video = 0; 00565 } 00567 00568 drawing_area::drawing_area(int x, int y, int sizex, int sizey) 00569 : start_x(x), start_y(y), size_x(sizex), size_y(sizey), pixel_depth(g_video->depth), 00570 base_index(y*g_sizex + x), max_index(g_sizex*g_sizey), index_stride(g_sizex), ptr32(g_pImg) 00571 { 00572 assert(ptr32); assert(x < g_sizex); assert(y < g_sizey); 00573 assert(x+sizex <= g_sizex); assert(y+sizey <= g_sizey); 00574 00575 index = base_index; // current index 00576 } 00577 00578 drawing_area::~drawing_area() 00579 { 00580 }
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.