在代码中增加了很多对代码的注释。
同时,对在不同平台(Telechips,MStar)的测试效果也做了说明。
虽然代码是 Overlay 示例,但还是增加了一些东东,如注释或者说明,对 Overlay 有兴趣的童鞋可以看看。
1 // mosquito.cpp : Defines the entry point for the application. 2 // 3 4 #include "stdafx.h" 5 #include <windows.h> 6 #include <commctrl.h> 7 #include "Resource.h" 8 //----------------------------------------------------------------------------- 9 // Include files 10 //----------------------------------------------------------------------------- 11 #include <ddraw.h> 12 13 //----------------------------------------------------------------------------- 14 // Local definitions 15 //----------------------------------------------------------------------------- 16 #define NAME TEXT("MosquitoWndClass") 17 #define TITLE TEXT("Mosquito") 18 19 #define BUG_WIDTH 320 20 #define BUG_HEIGHT 200 21 22 #ifdef UNDER_CE 23 #define RAND_INT(x) (Random() % x) 24 #else 25 #define RAND_INT(x) (rand()*x/RAND_MAX) 26 #endif 27 #define RANDOM_VELOCITY() (int)(((RAND_INT(5)+3)*2)) 28 29 //----------------------------------------------------------------------------- 30 // Default settings 31 //----------------------------------------------------------------------------- 32 #define TIMER_ID 1 33 #define TIMER_RATE 200 34 35 //----------------------------------------------------------------------------- 36 // Global data 37 //----------------------------------------------------------------------------- 38 LPDIRECTDRAW g_pDD = NULL; // DirectDraw object 39 LPDIRECTDRAWSURFACE g_pDDSPrimary = NULL; // Primary Surface. 40 LPDIRECTDRAWSURFACE g_pDDSOverlay = NULL; // The overlay primary. 41 BOOL g_bActive = FALSE; // Is application active? 42 int g_RotationAngles = 0; // Supported rotation angles. 43 int g_CurrentAngle = 0; // Current rotation angle. 44 45 // Overlay position and velocity data. 46 47 int g_nOverlayXPos, g_nOverlayYPos; 48 int g_nOverlayXVel, g_nOverlayYVel; 49 int g_nOverlayWidth, g_nOverlayHeight; 50 DWORD g_dwOverlayXPositionAlignment; 51 52 // Our instance handle. 53 54 HINSTANCE g_hInstance; 55 56 //----------------------------------------------------------------------------- 57 // Local data 58 //----------------------------------------------------------------------------- 59 static TCHAR szImg1[] = TEXT("IDB_BUGIMAGE1");//TEXT("IDB_BUGIMAGE1"); 60 static TCHAR szImg2[] = TEXT("IDB_BUGIMAGE2"); 61 static TCHAR szImg3[] = TEXT("IDB_BUGIMAGE3"); 62 63 // These are the pixel formats this app supports. Most display adapters 64 // with overlay support will recognize one or more of these formats. 65 // We start with YUV format, then work down to RGB. (All 16 bpp.) 66 67 /* 68 * Telechips 8902 支持 2 层 overlay 69 * 只能创建一层 YUV 的 overlay (可以再创建一层 RGB overlay) 70 * RGB 模式可以创建多个,模式与顺序没有不影响创建 71 */ 72 static DDPIXELFORMAT ddpfOverlayFormats[] = { 73 //{sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y','U','Y','V'),0,0,0,0,0}, // YUYV - Leo.Zheng Telechips 8902 可以支持 74 //{sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0}, // UYVY - Leo.Zheng Telechips 8902:Create No.1 surface return: 0x88760218 75 // {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x7C00, 0x03e0, 0x001F, 0}, // 16-bit RGB 5:5:5 76 {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0xF800, 0x07e0, 0x001F, 0}, // 16-bit RGB 5:6:5 77 }; 78 79 #define PF_TABLE_SIZE (sizeof(ddpfOverlayFormats) / sizeof(ddpfOverlayFormats[0])) 80 81 static RECT rs; 82 static RECT rd; 83 84 //----------------------------------------------------------------------------- 85 // Prototypes 86 //----------------------------------------------------------------------------- 87 void ReleaseAllObjects(void); 88 HRESULT InitFail(HWND, HRESULT, LPCTSTR, ...); 89 HRESULT RestoreAllSurfaces(); 90 void MoveOverlay(); 91 long FAR PASCAL WindowProc(HWND, UINT, WPARAM, LPARAM); 92 BOOL CopyBitmapToYUVSurface(LPDIRECTDRAWSURFACE, HBITMAP); 93 BOOL LoadImageOntoSurface(LPDIRECTDRAWSURFACE, UINT); 94 HRESULT WINAPI EnumSurfacesCallback(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, LPVOID); 95 HRESULT LoadBugImages(); 96 HRESULT InitApp(HINSTANCE hInstance, int nCmdShow); 97 98 //----------------------------------------------------------------------------- 99 // Name: ReleaseAllObjects() 100 // Desc: Finished with all objects we use; release them 101 //----------------------------------------------------------------------------- 102 static void ReleaseAllObjects(void) 103 { 104 if(g_pDDSOverlay != NULL) 105 { 106 // 如果不再需要一个覆盖表面或只想不让覆盖可见, 就可以设定适当的标志调用 UpdateOverlay 方法来隐藏该覆盖表面 107 // Use UpdateOverlay() with the DDOVER_HIDE flag to remove an overlay from the display. 108 // g_pDDSOverlay->UpdateOverlay(NULL, g_pDDSPrimary, NULL, DDOVER_HIDE, NULL); 109 g_pDDSOverlay->Release(); 110 g_pDDSOverlay = NULL; 111 } 112 113 if(g_pDDSPrimary != NULL) 114 { 115 g_pDDSPrimary->Release(); 116 g_pDDSPrimary = NULL; 117 } 118 119 if(g_pDD != NULL) 120 { 121 g_pDD->Release(); 122 g_pDD = NULL; 123 } 124 } 125 126 //----------------------------------------------------------------------------- 127 // Name: InitFail() 128 // Desc: This function is called if an initialization function fails 129 //----------------------------------------------------------------------------- 130 #define PREFIX TEXT("MOSQUITO: ") 131 #define PREFIX_LEN 10 132 133 static HRESULT InitFail(HWND hWnd, HRESULT hRet, LPCTSTR szError,...) 134 { 135 TCHAR szBuff[128] = PREFIX; 136 va_list vl; 137 138 va_start(vl, szError); 139 StringCchVPrintf(szBuff + PREFIX_LEN, (128-PREFIX_LEN), szError, vl); 140 size_t len = wcslen(szBuff); 141 StringCchPrintf(szBuff + len, 128 - len, TEXT("\r\n")); 142 ReleaseAllObjects(); 143 OutputDebugString(szBuff); 144 DestroyWindow(hWnd); 145 va_end(vl); 146 return hRet; 147 } 148 149 #undef PREFIX_LEN 150 #undef PREFIX 151 152 //----------------------------------------------------------------------------- 153 // Name: RestoreAllSurfaces 154 // Desc: Called in case we lose our surface's vram. 155 //----------------------------------------------------------------------------- 156 static HRESULT RestoreAllSurfaces() 157 { 158 HRESULT hRet = 0; 159 160 // Try Restoring the primary surface. 161 hRet = g_pDDSPrimary->Restore(); 162 if(hRet != DD_OK) 163 return hRet; 164 165 // Try Restoring the overlay surface. 166 hRet = g_pDDSOverlay->Restore(); 167 if(hRet != DD_OK) 168 return hRet; 169 170 // Reload the images. 171 hRet = LoadBugImages(); 172 if(hRet != DD_OK) 173 return hRet; 174 175 // Show the overlay. 176 hRet = g_pDDSOverlay->UpdateOverlay(&rs, g_pDDSPrimary, &rd, DDOVER_SHOW, NULL); 177 178 return hRet; 179 } 180 181 //----------------------------------------------------------------------------- 182 // Name: MoveOverlay() 183 // Desc: Called on the timer, this function moves the overlay around the 184 // screen, periodically calling flip to animate the mosquito. 185 //----------------------------------------------------------------------------- 186 static void MoveOverlay() 187 { 188 HRESULT hRet = 0; 189 DWORD dwXAligned = 0; 190 191 // Add the current velocity vectors to the position. 192 g_nOverlayXPos += g_nOverlayXVel; 193 g_nOverlayYPos += g_nOverlayYVel; 194 195 // Check to see if this new position puts the overlay off the edge of the screen. 196 // SetOverlayPosition() won't like that. 197 // Have we gone off the left edge? 198 if(g_nOverlayXPos < 0) 199 { 200 g_nOverlayXPos = 0; 201 g_nOverlayXVel = RANDOM_VELOCITY(); 202 } 203 204 // Have we gone off the right edge? 205 206 if((g_nOverlayXPos + g_nOverlayWidth) > GetSystemMetrics(SM_CXSCREEN)) 207 { 208 g_nOverlayXPos = GetSystemMetrics(SM_CXSCREEN) - g_nOverlayWidth; 209 g_nOverlayXVel = -RANDOM_VELOCITY(); 210 } 211 212 // Have we gone off the top edge? 213 if(g_nOverlayYPos < 0) 214 { 215 g_nOverlayYPos = 0; 216 g_nOverlayYVel = RANDOM_VELOCITY(); 217 } 218 219 // Have we gone off the bottom edge? 220 if((g_nOverlayYPos + g_nOverlayHeight) > GetSystemMetrics(SM_CYSCREEN)) 221 { 222 g_nOverlayYPos = GetSystemMetrics(SM_CYSCREEN) - g_nOverlayHeight; 223 g_nOverlayYVel = -RANDOM_VELOCITY(); 224 } 225 226 // We need to check for any alignment restrictions on the X position. 227 if(g_dwOverlayXPositionAlignment) 228 dwXAligned = g_nOverlayXPos - g_nOverlayXPos % g_dwOverlayXPositionAlignment; 229 else 230 dwXAligned = g_nOverlayXPos; 231 232 // Set the overlay to it's new position. 重新放置覆盖 233 hRet = g_pDDSOverlay->SetOverlayPosition(dwXAligned, g_nOverlayYPos); 234 if(hRet == DDERR_SURFACELOST) 235 { 236 if(FAILED(RestoreAllSurfaces())) 237 return; 238 } 239 240 // 注意, 不要使用太靠近目标表面的右/下边界的坐标. 因为 SetOverlayPosition 方法并不执行剪切功能, 241 // 所以使用那些可能导致覆盖超出目标表面边界的坐标会引起调用的失败, 并返回 DDERR_INVALIDPOSITION. 242 243 // Flip. 244 while(TRUE) 245 { 246 hRet = g_pDDSOverlay->Flip(NULL, 0); 247 if(hRet == DD_OK) 248 break; 249 if(hRet == DDERR_SURFACELOST) // 正常情况下,不执行此 if 语句 250 { 251 hRet = RestoreAllSurfaces(); 252 if(hRet != DD_OK) 253 break; 254 } 255 if(hRet != DDERR_WASSTILLDRAWING) 256 break; 257 } 258 } 259 260 261 //----------------------------------------------------------------------------- 262 // Name: WindowProc() 263 // Desc: The Main Window Procedure 264 //----------------------------------------------------------------------------- 265 long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 266 { 267 int NewAngle; 268 DEVMODE DevMode; 269 270 switch (message) 271 { 272 #ifdef UNDER_CE 273 case WM_ACTIVATE: 274 #else 275 case WM_ACTIVATEAPP: 276 #endif 277 // Pause if minimized or not the top window 278 g_bActive = (wParam == WA_ACTIVE) || (wParam == WA_CLICKACTIVE); 279 return 0L; 280 281 case WM_KILLFOCUS: 282 // We do not allow anyone else to have the keyboard focus until 283 // we are done. 284 SetFocus(hWnd); 285 return 0L; 286 287 case WM_DESTROY: 288 // Clean up and close the app 289 RETAILMSG(1,(L"[mosquito]overlay test - release overlay objects.\r\n")); 290 ReleaseAllObjects(); 291 PostQuitMessage(0); 292 return 0L; 293 294 case WM_LBUTTONDOWN: // Leo.Zheng 没有窗体,无法响应 MOUSE 消息 295 PostMessage(hWnd, WM_CLOSE, 0, 0); 296 break; 297 298 case WM_KEYDOWN: 299 // Handle any non-accelerated key commands 300 switch (wParam) 301 { 302 case VK_ESCAPE: 303 case VK_F12: 304 PostMessage(hWnd, WM_CLOSE, 0, 0); 305 return 0L; 306 307 case VK_SPACE: 308 // Rotate to the "next" angle. 309 if (g_CurrentAngle >= 0 && g_RotationAngles >= 0) 310 { 311 NewAngle = g_CurrentAngle; 312 do 313 { 314 NewAngle <<= 1; 315 if (NewAngle == DMDO_0) 316 { 317 NewAngle = DMDO_90; 318 } 319 if (NewAngle > DMDO_270) 320 { 321 NewAngle = DMDO_0; 322 } 323 }while (!(NewAngle & g_RotationAngles) && (NewAngle != DMDO_0)); 324 325 memset(&DevMode, 0, sizeof (DevMode)); 326 DevMode.dmSize = sizeof (DevMode); 327 DevMode.dmFields = DM_DISPLAYORIENTATION; 328 DevMode.dmDisplayOrientation = NewAngle; 329 330 if (DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(NULL, &DevMode, NULL, CDS_RESET, NULL)) 331 { 332 g_CurrentAngle = NewAngle; 333 RestoreAllSurfaces(); 334 } 335 } 336 return 0L; 337 } 338 break; 339 340 case WM_TIMER: 341 // Update and flip surfaces 342 if (g_bActive && TIMER_ID == wParam) 343 { 344 MoveOverlay(); 345 Sleep(100); 346 LoadBugImages(); 347 } 348 break; 349 } 350 return DefWindowProc(hWnd, message, wParam, lParam); 351 } 352 353 //----------------------------------------------------------------------------- 354 // Function: CopyBitmapToYUVSurface 355 // Description: 356 // Copies an RGB GDI bitmap to a YUV surface. Both bitmap and surface 357 // must be a multiple of 2 pixels in width for the supported YUV formats. 358 // The following formats are supported: 359 // YUYV 360 // UYVY 361 // 362 // The "YUYV" YUV pixel format looks like this: 363 // As a series of BYTES: [Y0][U][Y1][V] (reverse it for a DWORD) 364 // 365 // The "UYVY" YUV pixel format looks like this: 366 // As a series of BYTES: [U][Y0][V][Y1] (reverse it for a DWORD) 367 // 368 // As you can see, both formats pack two pixels into a single DWORD. The 369 // pixels share U and V components and have separate Y components. 370 // 371 // Returns: TRUE if successful, otherwise FALSE. 372 //----------------------------------------------------------------------------- 373 static BOOL CopyBitmapToYUVSurface(LPDIRECTDRAWSURFACE lpDDSurf, HBITMAP hbm) 374 { 375 HDC hdcImage; 376 HRESULT ddrval; 377 DDSURFACEDESC ddsd; 378 DWORD x, y, dwWidth, dwHeight; 379 DWORD dwPitch; 380 LPBYTE pSurf; 381 DWORD dwBytesInRow; 382 COLORREF color; 383 BYTE R,G,B, Y0,Y1,U,V; 384 BOOL bRet = FALSE; 385 386 if (hbm == NULL || lpDDSurf == NULL) 387 return FALSE; 388 389 // 390 // select bitmap into a memoryDC so we can use it. 391 // 392 hdcImage = CreateCompatibleDC(NULL); 393 SelectObject(hdcImage, hbm); 394 395 memset(&ddsd, 0, sizeof(ddsd)); 396 ddsd.dwSize = sizeof(ddsd); 397 // Lock down the surface so we can modify it's contents. 398 ddrval=lpDDSurf->Lock( NULL, &ddsd, DDLOCK_WAITNOTBUSY, NULL); 399 if (FAILED(ddrval)) 400 goto CleanUp; 401 402 dwWidth=ddsd.dwWidth; 403 dwHeight=ddsd.dwHeight; 404 dwPitch=ddsd.lPitch; 405 pSurf=(LPBYTE)ddsd.lpSurface; 406 dwBytesInRow=ddsd.dwWidth*2; 407 408 // Go through the image 2 pixels at a time and convert to YUV 409 for(y=0; y<dwHeight; y++) 410 { 411 for(x=0; x<dwWidth; x+=2) 412 { 413 // The equations for color conversion used here, probably aren't 414 // exact, but they seem to do an OK job. 415 color=GetPixel(hdcImage, x,y); 416 R=GetRValue(color); 417 G=GetGValue(color); 418 B=GetBValue(color); 419 Y0= (BYTE)(0.29*R + 0.59*G + 0.14*B); 420 U= (BYTE)(128.0 - 0.14*R - 0.29*G + 0.43*B); 421 422 color=GetPixel(hdcImage, x+1,y); 423 R=GetRValue(color); 424 G=GetGValue(color); 425 B=GetBValue(color); 426 Y1= (BYTE)(0.29*R + 0.57*G + 0.14*B); 427 V= (BYTE)(128.0 + 0.36*R - 0.29*G - 0.07*B); 428 429 switch (ddsd.ddpfPixelFormat.dwFourCC) 430 { 431 case MAKEFOURCC('Y','U','Y','V'): 432 *(pSurf++) = Y0; 433 *(pSurf++) = U; 434 *(pSurf++) = Y1; 435 *(pSurf++) = V; 436 break; 437 case MAKEFOURCC('U','Y','V','Y'): 438 *(pSurf++) = U; 439 *(pSurf++) = Y0; 440 *(pSurf++) = V; 441 *(pSurf++) = Y1; 442 break; 443 } 444 } 445 pSurf+=(dwPitch-dwBytesInRow); 446 } 447 448 lpDDSurf->Unlock(NULL); 449 450 CleanUp: 451 if(hdcImage) 452 DeleteDC(hdcImage); 453 454 return TRUE; 455 } 456 457 //----------------------------------------------------------------------------- 458 // Function: LoadImageOnToSurface 459 // Description: 460 // Loads a resource based bitmap image onto a DirectDraw surface. Can 461 // covert the bitmap to all RGB formats, plus a couple YUV formats. 462 //----------------------------------------------------------------------------- 463 static BOOL LoadImageOntoSurface(LPDIRECTDRAWSURFACE lpdds, UINT lpstrResID) 464 { 465 HBITMAP hbm = NULL; 466 HDC hdcImage = NULL; 467 HDC hdcSurf = NULL; 468 BOOL bRetVal = FALSE; 469 HRESULT ddrval; 470 DDSURFACEDESC ddsd; 471 472 if(!lpdds) 473 return FALSE; 474 475 // get surface size and format. 476 memset(&ddsd, 0, sizeof(ddsd)); 477 ddsd.dwSize = sizeof(ddsd); 478 ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH; 479 ddrval = lpdds->GetSurfaceDesc(&ddsd); 480 if(FAILED(ddrval)) 481 goto Exit; 482 483 // Load the bitmap resource. We'll use LoadImage() since it'll scale the 484 // image to fit our surface, and maintain the color information in the bitmap. 485 hbm = (HBITMAP)LoadImage(g_hInstance, MAKEINTRESOURCE(lpstrResID), IMAGE_BITMAP, 0, 0, 0); 486 if(hbm == NULL) 487 goto Exit; 488 489 // If our surface is a FOURCC YUV format, we need to do a little work to convert 490 // our RGB resource bitmap into the appropriate YUV format. 491 if(ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC) 492 { 493 if(!CopyBitmapToYUVSurface(lpdds, hbm)) 494 goto Exit; 495 } 496 else //Looks like we're just using a standard RGB surface format, let GDI do the work. 497 { 498 // Create a DC and associate the bitmap with it. 499 hdcImage = CreateCompatibleDC(NULL); 500 SelectObject(hdcImage, hbm); 501 502 ddrval = lpdds->GetDC(&hdcSurf); 503 if(FAILED(ddrval)) 504 goto Exit; 505 506 if(BitBlt(hdcSurf, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, 0, 0, SRCCOPY) == FALSE) 507 goto Exit; 508 509 ::SetBkMode(hdcSurf,TRANSPARENT); 510 ::SetTextColor(hdcSurf,RGB(255,0,0)); 511 RECT Rect={0,0,100,50}; 512 ::DrawText(hdcSurf,_T("ABCD"),4,&Rect,DT_SINGLELINE|DT_LEFT); 513 } 514 515 bRetVal = TRUE; 516 517 Exit: 518 if(hdcSurf) 519 lpdds->ReleaseDC(hdcSurf); 520 if(hdcImage) 521 DeleteDC(hdcImage); 522 if(hbm) 523 DeleteObject(hbm); 524 525 return bRetVal; 526 } 527 528 //----------------------------------------------------------------------------- 529 // Name: EnumSurfacesCallback() 530 // Desc: Used by LoadBugImages to aid it loading all three bug images. 531 //----------------------------------------------------------------------------- 532 static HRESULT WINAPI EnumSurfacesCallback(LPDIRECTDRAWSURFACE lpDDSurface, 533 LPDDSURFACEDESC lpDDSurfaceDesc, 534 LPVOID lpContext) 535 { 536 int *CallCount = (int *)lpContext; 537 HRESULT hr = (HRESULT)DDENUMRET_OK; 538 UINT ResName; 539 540 // Load the Bug Image appropriate... 541 if(*CallCount == 0) 542 { 543 ResName = IDB_BUGIMAGE2; 544 } 545 else if(*CallCount == 1) 546 { 547 ResName = IDB_BUGIMAGE3; 548 } 549 else 550 { 551 hr = (HRESULT)DDENUMRET_CANCEL; 552 goto exit; 553 } 554 555 if(!LoadImageOntoSurface(lpDDSurface, ResName)) 556 { 557 hr = (HRESULT)DDENUMRET_CANCEL; 558 goto exit; 559 } 560 561 // Bump the count. 562 (*CallCount)++; 563 if(*CallCount >= 2) 564 { 565 *CallCount = 0; 566 } 567 568 exit: 569 lpDDSurface->Release(); 570 return hr; 571 } 572 573 //----------------------------------------------------------------------------- 574 // Name: LoadBugImages() 575 // Desc: Load the bug resource images into our various flipping surfaces. 576 //----------------------------------------------------------------------------- 577 static HRESULT LoadBugImages() 578 { 579 HRESULT hRet; 580 static int CallCount = 0; 581 582 // Put the first bug image onto the first buffer of our complex surface. 583 if(0 == CallCount) 584 { 585 if(!LoadImageOntoSurface(g_pDDSOverlay, IDB_BUGIMAGE1)) 586 return (E_FAIL); 587 } 588 589 // Use the enumeration attachment function to load the other images. 590 hRet = g_pDDSOverlay->EnumAttachedSurfaces((LPVOID)&CallCount,EnumSurfacesCallback); 591 592 return (hRet); 593 } 594 595 //----------------------------------------------------------------------------- 596 // Name: InitApp() 597 // Desc: Do work required for every instance of the application: 598 // Create the window, initialize data 599 //----------------------------------------------------------------------------- 600 static HRESULT InitApp(HINSTANCE hInstance, int nCmdShow) 601 { 602 HWND hWnd; 603 WNDCLASS wc; 604 DDSURFACEDESC ddsd; 605 DDCAPS ddcaps; 606 HRESULT hRet; 607 DWORD dwUpdateFlags = 0; 608 DDOVERLAYFX ovfx; 609 DEVMODE DevMode; 610 611 // Check for rotation support by getting the rotation angles supported. 612 memset(&DevMode, 0, sizeof(DevMode)); 613 DevMode.dmSize = sizeof(DevMode); 614 DevMode.dmFields = DM_DISPLAYQUERYORIENTATION; 615 if(DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(NULL, &DevMode, NULL, CDS_TEST, NULL)) 616 { 617 g_RotationAngles = DevMode.dmDisplayOrientation; 618 } 619 else 620 { 621 OutputDebugString(L"MOSQUITO: Device does not support any rotation modes. Rotation disabled."); 622 g_RotationAngles = -1; 623 } 624 625 // Get the current rotation angle. 626 memset(&DevMode, 0, sizeof (DevMode)); 627 DevMode.dmSize = sizeof (DevMode); 628 DevMode.dmFields = DM_DISPLAYORIENTATION; 629 if(DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(NULL, &DevMode, NULL, CDS_TEST, NULL)) 630 { 631 g_CurrentAngle = DevMode.dmDisplayOrientation; 632 } 633 else 634 { 635 OutputDebugString(L"MOSQUITO: Unable to read current rotation. Rotation disabled."); 636 g_CurrentAngle = -1; 637 } 638 639 // Set up and register window class. 640 wc.style = CS_HREDRAW | CS_VREDRAW; 641 wc.lpfnWndProc = WindowProc; 642 wc.cbClsExtra = 0; 643 wc.cbWndExtra = 0; 644 wc.hInstance = hInstance; 645 wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MOSQUITO)); 646 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 647 wc.hbrBackground = (HBRUSH )GetStockObject(BLACK_BRUSH); 648 wc.lpszMenuName = NULL; 649 wc.lpszClassName = NAME; 650 RegisterClass(&wc); 651 652 // Create a window. 653 hWnd = CreateWindowEx(WS_EX_TOPMOST, 654 NAME, 655 TITLE, 656 WS_POPUP, 657 0, 658 0, 659 GetSystemMetrics(SM_CXSCREEN), 660 GetSystemMetrics(SM_CYSCREEN), 661 NULL, 662 NULL, 663 hInstance, 664 NULL); 665 if(!hWnd) 666 return FALSE; 667 // We never show the window, only set focus to it. 668 SetFocus(hWnd); 669 670 // Create the main DirectDraw object 671 hRet = DirectDrawCreate(NULL, &g_pDD, NULL); 672 if(hRet != DD_OK) 673 return InitFail(hWnd, hRet, TEXT("DirectDrawCreate FAILED")); 674 675 // Get normal mode. 676 hRet = g_pDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL); 677 if(hRet != DD_OK) 678 return InitFail(hWnd, hRet, TEXT("SetCooperativeLevel FAILED")); 679 680 // Get a primary surface interface pointer (only needed for init.) 681 // 要使用覆盖表面, 必须先要初始化一个主表面, 覆盖表面将显示在该主表面上 682 memset(&ddsd, 0, sizeof(ddsd)); 683 ddsd.dwSize = sizeof(ddsd); 684 ddsd.dwFlags = DDSD_CAPS; 685 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; 686 hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL); 687 if(hRet != DD_OK) 688 return InitFail(hWnd, hRet, TEXT("CreateSurface FAILED")); 689 690 // See if we can support overlays. 691 // 初始化 DirectDraw 后, 需要检测设备是否支持覆盖表面 692 // 因为 DirectDraw 不能仿真覆盖, 所以如果硬件不支持覆盖, 就不能继续下面的工作 693 memset(&ddcaps, 0, sizeof(ddcaps)); 694 ddcaps.dwSize = sizeof(ddcaps); 695 hRet = g_pDD->GetCaps(&ddcaps, NULL); 696 if(hRet != DD_OK) 697 return InitFail(hWnd, hRet, TEXT("GetCaps FAILED")); 698 699 if(ddcaps.dwOverlayCaps == 0) 700 return InitFail(hWnd, hRet, TEXT("Overlays are not supported in hardware!")); 701 /* // Leo.Zheng Add 702 if(!(capsDrv.dwCaps & DDCAPS_OVERLAY)) 703 return FALSE; 704 */ 705 706 // Get alignment info to compute our overlay surface size. 707 rs.left = 0; 708 rs.top = 0; 709 rs.right = BUG_WIDTH; 710 rs.bottom = BUG_HEIGHT; 711 if(ddcaps.dwAlignSizeSrc != 0) 712 rs.right += rs.right % ddcaps.dwAlignSizeSrc; 713 714 // Create the overlay flipping surface. We will attempt the pixel formats 715 // in our table one at a time until we find one that jives. 716 // 如果知道显示设备支持覆盖表面, 就可以创建一个. 因为没有指明设备怎样支持覆盖表面的标准, 所以不能够期望创建任意大小的像素格式的表面. 717 // 另外, 也不要期望第一次创建覆盖表面就会成功. 因此, 必须作好准备进行多次创建的尝试, 直到有一个能够工作为止. 718 int i = 0; 719 memset(&ddsd, 0, sizeof(ddsd)); 720 ddsd.dwSize = sizeof(ddsd); 721 ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP; 722 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_BACKBUFFERCOUNT | DDSD_PIXELFORMAT; 723 ddsd.dwWidth = rs.right; 724 ddsd.dwHeight = rs.bottom; 725 ddsd.dwBackBufferCount = 1; 726 do 727 { // Leo.Zheng MStar 2521 只创建 16-bit RGB 5:6:5 成功; 创建 16-bit RGB 5:5:5 失败. 728 ddsd.ddpfPixelFormat = ddpfOverlayFormats[i]; 729 hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSOverlay, NULL); // Leo.Zheng 此处调用后引起使用 IOCtrl 显示在 LCD 上的消失 730 RETAILMSG(1,(L"[mosquito]Create No.%d surface return: 0x%X\r\n",i + 1,hRet)); 731 }while(hRet != DD_OK && (++i < PF_TABLE_SIZE)); 732 if(hRet != DD_OK) 733 return InitFail(hWnd, hRet, TEXT("Unable to create overlay surface!")); 734 735 // Load the images. 736 if(LoadBugImages() != DD_OK) 737 return InitFail(hWnd, hRet, TEXT("Unable to load images to overlay surface!")); 738 739 // Finish setting up the overlay. 740 int StretchFactor1000 = ddcaps.dwMinOverlayStretch > 1000 ? ddcaps.dwMinOverlayStretch : 1000; 741 742 rd.left=0; 743 rd.top=0; 744 // Adding 999 takes care of integer truncation problems. 745 rd.right = (rs.right * StretchFactor1000 + 999) / 1000; 746 rd.bottom = rs.bottom * StretchFactor1000 / 1000; 747 if (ddcaps.dwAlignSizeDest != 0) 748 rd.right = (int)((rd.right + ddcaps.dwAlignSizeDest - 1)/ ddcaps.dwAlignSizeDest) * ddcaps.dwAlignSizeDest; 749 750 // 显示覆盖表面: 在设置了源矩形和目的矩形后, 就可以显示覆盖了. 751 // 程序开始在临时变量 dwUpdateFlags 中设定了 DDOVER_SHOW 和 DDOVER_DDFX 标志, 指明该覆盖是第一次显示, 752 // 硬件应该使用包含在 DDOVERLAYFX 结构中的效果信息完成这一工作. 753 // UpdateOverlay 用于重新定位一个覆盖页面, 或修改其视觉属性. 754 // Set the flags we'll send to UpdateOverlay 755 dwUpdateFlags = DDOVER_SHOW; 756 // dwUpdateFlags = DDOVER_SHOW | DDOVER_DDFX; // Leo.Zheng DDOVER_DDFX WinCE 不支持 757 758 // 检查 DDCAPS 结构确定覆盖是否支持源 Color Key 759 // Does the overlay hardware support source color keying? 760 // If so, we can hide the black background around the image. 761 // This probably won't work with YUV formats 762 memset(&ovfx, 0, sizeof(ovfx)); 763 ovfx.dwSize = sizeof(ovfx); 764 if(ddcaps.dwOverlayCaps & DDOVERLAYCAPS_CKEYSRC) // MStar2521 不支持 color key 765 { 766 dwUpdateFlags |= DDOVER_KEYSRCOVERRIDE; 767 768 // Create an overlay FX structure so we can specify a source color key. 769 // This information is ignored if the DDOVER_SRCKEYOVERRIDE flag 770 // isn't set. 771 ovfx.dckSrcColorkey.dwColorSpaceLowValue=0; // black as the color key 772 ovfx.dckSrcColorkey.dwColorSpaceHighValue=0; 773 } 774 else 775 { 776 RETAILMSG(1,(L"[mosquito]cannot support color key: 0x%X(0x%x)\r\n",ddcaps.dwOverlayCaps,DDOVERLAYCAPS_CKEYSRC)); 777 } 778 779 // Update the overlay parameters. 780 // 调用 IDirectDrawSurface::UpdateOverlay 方法来显示覆盖 781 hRet = g_pDDSOverlay->UpdateOverlay(&rs, g_pDDSPrimary, &rd, dwUpdateFlags, &ovfx); 782 if(hRet != DD_OK) 783 { 784 // 在 MStar 2521 设备上运行第二个此程序实例时出错。 785 // 在 TeleChips 8902 设备上运行第三个此程序实例时出错。 786 return InitFail(hWnd, hRet, TEXT("Unable to show overlay surface: 0x%x!"),hRet); 787 } 788 789 // Set a bunch of position and velocity module vars. 790 g_nOverlayXPos = 0; 791 g_nOverlayYPos = 0; 792 g_nOverlayXVel = RANDOM_VELOCITY(); 793 g_nOverlayYVel = RANDOM_VELOCITY(); 794 g_nOverlayWidth = rd.right - rd.left; 795 g_nOverlayHeight = rd.bottom - rd.top; 796 797 // Set the "destination position alignment" global so we won't have to 798 // keep calling GetCaps() everytime we move the overlay surface. 799 g_dwOverlayXPositionAlignment = ddcaps.dwAlignBoundaryDest; 800 801 // Create a timer to flip the pages. 802 if(TIMER_ID != SetTimer(hWnd, TIMER_ID, TIMER_RATE, NULL)) 803 return InitFail(hWnd, hRet, TEXT("SetTimer FAILED")); 804 805 return DD_OK; 806 } 807 808 //----------------------------------------------------------------------------- 809 // Name: WinMain() 810 // Desc: Initialization, message loop 811 //----------------------------------------------------------------------------- 812 int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, 813 #ifdef UNDER_CE 814 LPWSTR lpCmdLine, 815 #else 816 LPSTR lpCmdLine, 817 #endif 818 int nCmdShow) 819 { 820 MSG msg; 821 822 g_hInstance = hInstance; 823 if(InitApp(hInstance, nCmdShow) != DD_OK) 824 return FALSE; 825 826 while(GetMessage(&msg, NULL, 0, 0)) 827 { 828 TranslateMessage(&msg); 829 DispatchMessage(&msg); 830 } 831 832 return msg.wParam; 833 }