// // Flip the real page with virtual page // - in bAppFullScreen mode, do page flipping // - in windowed mode, copy the hidden surface to the visible surface // // waitflip : if not 0, wait for page flip to end BOOL ScreenFlip(int waitflip) { HRESULT hr; RECT rect; UNREFERENCED_PARAMETER(waitflip); if (bAppFullScreen) { //hr = IDirectDrawSurface_GetFlipStatus (ScreenReal, DDGFS_); // In full-screen exclusive mode, do a hardware flip. hr = IDirectDrawSurface_Flip(ScreenReal, NULL, DDFLIP_WAIT); //return immediately // If the surface was lost, restore it. if (hr == DDERR_SURFACELOST) { IDirectDrawSurface_Restore(ScreenReal); // The restore worked, so try the flip again. hr = IDirectDrawSurface_Flip(ScreenReal, 0, DDFLIP_WAIT); } } else { rect.left = windowPosX; rect.top = windowPosY; rect.right = windowPosX + ScreenWidth - 1; rect.bottom = windowPosY + ScreenHeight - 1; // Copy the back buffer to front. hr = IDirectDrawSurface_Blt(ScreenReal, &rect, ScreenVirtual, 0, DDBLT_WAIT, 0); if (hr != DD_OK) { // If the surfaces were lost, restore them. if (IDirectDrawSurface_IsLost(ScreenReal) == DDERR_SURFACELOST) IDirectDrawSurface_Restore(ScreenReal); if (IDirectDrawSurface_IsLost(ScreenVirtual) == DDERR_SURFACELOST) IDirectDrawSurface_Restore(ScreenVirtual); // Retry the copy. hr = IDirectDrawSurface_Blt(ScreenReal,&rect, ScreenVirtual, 0, DDBLT_WAIT, 0); } } if (hr != DD_OK) I_Error("ScreenFlip() : couldn't Flip surfaces because %s", DXErrorToString(hr)); return FALSE; }
// // Create the DirectDraw object for later // BOOL CreateDirectDrawInstance (VOID) { HRESULT hr; IDirectDraw* DDr; IDirectDraw** rp = &DDr; IDirectDraw2** rp2 = &DDr2; LPVOID *tp = (LPVOID *)rp2; if (!LoadDirectDraw()) return FALSE; // // create an instance of DirectDraw object // if (FAILED(hr = pfnDirectDrawCreate(NULL, rp, NULL))) I_Error("DirectDrawCreate FAILED: %s", DXErrorToString(hr)); // change interface to IDirectDraw2 if (FAILED(hr = IDirectDraw_QueryInterface(DDr, &IID_IDirectDraw2, tp))) I_Error("Failed to query DirectDraw2 interface: %s", DXErrorToString(hr)); // release the interface we don't need IDirectDraw_Release (DDr); return TRUE; }
// // - returns true if DirectDraw was initialized properly // int InitDirectDrawe (HWND appWin, int width, int height, int bpp, int fullScr) { DDSURFACEDESC ddsd; // DirectDraw surface description for allocating DDSCAPS ddscaps; HRESULT ddrval; DWORD dwStyle; RECT rect; // enumerate directdraw devices //if (FAILED(DirectDrawEnumerate (myEnumDDDevicesCallback, NULL))) // I_Error("Error with DirectDrawEnumerate"); if (!DDr2) CreateDirectDrawInstance(); // remember what screen mode we are in bAppFullScreen = fullScr; ScreenHeight = height; ScreenWidth = width; if (bAppFullScreen) { // Change window attributes dwStyle = WS_POPUP | WS_VISIBLE; SetWindowLong (appWin, GWL_STYLE, dwStyle); SetWindowPos(appWin, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); // Get exclusive mode ddrval = IDirectDraw2_SetCooperativeLevel(DDr2, appWin, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT); if (ddrval != DD_OK) I_Error("SetCooperativeLevel FAILED: %s\n", DXErrorToString(ddrval)); // Switch from windows desktop to fullscreen #ifdef NT4COMPAT ddrval = IDirectDraw2_SetDisplayMode(DDr2, width, height, bpp, 0, 0); #else ddrval = IDirectDraw2_SetDisplayMode(DDr2, width, height, bpp, 0, DDSDM_STANDARDVGAMODE); #endif if (ddrval != DD_OK) I_Error("SetDisplayMode FAILED: %s\n", DXErrorToString(ddrval)); // This is not really needed, except in certain cases. One case // is while using MFC. When the desktop is initally at 16bpp, a mode // switch to 8bpp somehow causes the MFC window to not fully initialize // and a CreateSurface will fail with DDERR_NOEXCLUSIVEMODE. This will // ensure that the window is initialized properly after a mode switch. ShowWindow(appWin, SW_SHOW); // Create the primary surface with 1 back buffer. Always zero the // DDSURFACEDESC structure and set the dwSize member! ZeroMemory(&ddsd, sizeof (ddsd)); ddsd.dwSize = sizeof (ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; // for fullscreen we use page flipping, for windowed mode, we blit the hidden surface to // the visible surface, in both cases we have a visible (or 'real') surface, and a hidden // (or 'virtual', or 'backbuffer') surface. ddsd.dwBackBufferCount = 2; ddrval = IDirectDraw2_CreateSurface(DDr2,&ddsd, &ScreenReal, NULL); if (ddrval != DD_OK) I_Error("CreateSurface Primary Screen FAILED"); // Get a pointer to the back buffer ddscaps.dwCaps = DDSCAPS_BACKBUFFER; ddrval = IDirectDrawSurface_GetAttachedSurface(ScreenReal,&ddscaps, &ScreenVirtual); if (ddrval != DD_OK) I_Error("GetAttachedSurface FAILED"); } else { rect.top = 0; rect.left = 0; rect.bottom = height; rect.right = width; // Change window attributes dwStyle = GetWindowStyle(appWin); dwStyle &= ~WS_POPUP; dwStyle |= WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION; SetWindowLong(appWin, GWL_STYLE, dwStyle); // Resize the window so that the client area is the requested width/height AdjustWindowRectEx(&rect, GetWindowStyle(appWin), GetMenu(appWin) != NULL, GetWindowExStyle(appWin)); // Just in case the window was moved off the visible area of the // screen. SetWindowPos(appWin, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); SetWindowPos(appWin, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); // Exclusive mode is normal since it's in windowed mode and needs // to cooperate with GDI ddrval = IDirectDraw2_SetCooperativeLevel(DDr2,appWin, DDSCL_NORMAL); if (ddrval != DD_OK) I_Error("SetCooperativeLevel FAILED"); // Always zero the DDSURFACEDESC structure and set the dwSize member! ZeroMemory(&ddsd, sizeof (ddsd)); ddsd.dwSize = sizeof (ddsd); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // Create the primary surface ddrval = IDirectDraw2_CreateSurface(DDr2,&ddsd, &ScreenReal, NULL); if (ddrval != DD_OK) I_Error("CreateSurface Primary Screen FAILED"); // Create a back buffer for offscreen rendering, this will be used to // blt to the primary ScreenVirtual = CreateNewSurface(width, height, DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY); if (ScreenVirtual == NULL) I_Error("CreateSurface Secondary Screen FAILED"); /// \todo get the desktop bit depth, and build a lookup table /// for quick conversions of 8bit color indexes 0-255 to desktop colors /// eg: 256 entries of equivalent of palette colors 0-255 in 15,16,24,32 bit format /// when blit virtual to real, convert pixels through lookup table.. // Use a clipper object for clipping when in windowed mode // (make sure our drawing doesn't affect other windows) ddrval = IDirectDraw2_CreateClipper (DDr2, 0, &windclip, 0); if (ddrval != DD_OK) I_Error("CreateClipper FAILED"); // Associate the clipper with the window. ddrval = IDirectDrawClipper_SetHWnd (windclip,0, appWin); if (ddrval != DD_OK) I_Error("Clipper -> SetHWnd FAILED"); // Attach the clipper to the surface. ddrval = IDirectDrawSurface_SetClipper (ScreenReal,windclip); if (ddrval != DD_OK) I_Error("PrimaryScreen -> SetClipperClipper FAILED"); } return TRUE; }