/** * Create a clipper that will be used when blitting the RGB surface to the main display. * * This clipper prevents us to modify by mistake anything on the screen * which doesn't belong to our window. For example when a part of our video * window is hidden by another window. */ static void DirectXCreateClipper(vout_display_t *vd) { vout_display_sys_t *sys = vd->sys; HRESULT hr; /* Create the clipper */ hr = IDirectDraw2_CreateClipper(sys->ddobject, 0, &sys->clipper, NULL); if (hr != DD_OK) { msg_Warn(vd, "cannot create clipper (error %li)", hr); goto error; } /* Associate the clipper to the window */ hr = IDirectDrawClipper_SetHWnd(sys->clipper, 0, sys->hvideownd); if (hr != DD_OK) { msg_Warn(vd, "cannot attach clipper to window (error %li)", hr); goto error; } /* associate the clipper with the surface */ hr = IDirectDrawSurface_SetClipper(sys->display, sys->clipper); if (hr != DD_OK) { msg_Warn(vd, "cannot attach clipper to surface (error %li)", hr); goto error; } return; error: if (sys->clipper) IDirectDrawClipper_Release(sys->clipper); sys->clipper = NULL; }
// Clipper FUnctions void DDCreateClipper( LPDIRECTDRAW2 pDirectDraw, UINT32 fFlags, LPDIRECTDRAWCLIPPER *pDDClipper ) { Assert( pDirectDraw != NULL ); Assert( pDDClipper != NULL ); ATTEMPT( IDirectDraw2_CreateClipper( pDirectDraw, 0, pDDClipper, NULL ) ); }
// // - 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; }
int directdraw_init(HWND hwndp) { int width = 320, height = 200; RECT rect; DDPIXELFORMAT format; DDSURFACEDESC descriptor; DIRECTDRAWCREATE DirectDrawCreate; if(lpDDS) return 0; if(!hwndp) return 0; if(video_window) return 0; /* you gotta uninitialize it first */ library = (HMODULE) LoadLibrary(uni("ddraw.dll")); if(!library) return 0; DirectDrawCreate = (DIRECTDRAWCREATE) GetProcAddress(library, "DirectDrawCreate"); if(!DirectDrawCreate) return 0; if(FAILED(DirectDrawCreate(0,&lpDD,0))) return 0; wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = 0; wc.hIcon = 0; wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hbrBackground = 0; wc.lpszMenuName = 0; wc.lpszClassName = window_class_name; RegisterClass(&wc); video_window = CreateWindow(window_class_name, uni("Video"), WS_CHILD, 0, 0, width, height, hwndp, 0, 0, 0); ShowWindow(video_window, SW_NORMAL); if(FAILED(IDirectDraw2_SetCooperativeLevel(lpDD, video_window, DDSCL_NORMAL))) return 0; descriptor.dwSize = sizeof(descriptor); descriptor.dwFlags = DDSD_CAPS; descriptor.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY; if(FAILED(IDirectDraw2_CreateSurface(lpDD, &descriptor, &lpDDS, 0))) return 0; descriptor.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; descriptor.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; descriptor.dwWidth = d_width ; descriptor.dwHeight = d_height; if(FAILED(IDirectDraw2_CreateSurface(lpDD, &descriptor, &lpDDS_secondary, 0))) return 0; if(FAILED(IDirectDraw2_CreateClipper(lpDD, 0, &lpDDC, 0))) return 0; if(FAILED(IDirectDrawClipper_SetHWnd(lpDDC, 0, video_window))) return 0; if(FAILED(IDirectDrawSurface2_SetClipper(lpDDS, lpDDC))) return 0; lpDDS_back = lpDDS_secondary; format.dwSize = sizeof(format); if(FAILED(IDirectDrawSurface2_GetPixelFormat(lpDDS, &format))) return 0; if(!(format.dwFlags & DDPF_RGB)) return 0; IDirectDraw2_EnumDisplayModes(lpDD, DDEDM_STANDARDVGAMODES, 0, 0, EnumDisplayModesCallback); osd_initialize(); osd_created = 0; return 1; }
static int DDCreateSurface(directx_priv *priv, ggi_mode *mode) { HRESULT hr; LPDIRECTDRAWCLIPPER pClipper; DDSURFACEDESC pddsd, bddsd; int i; if (!priv->fullscreen) IDirectDraw2_SetCooperativeLevel(priv->lpddext, priv->hWnd, DDSCL_NORMAL); else { /* Only the thread that has excluse access (Cooperative level) * may restore the surfaces when they are lost. Therefore * let the helper thread get exclusive access so that it can * later do restores. */ directx_fullscreen dxfull; dxfull.priv = priv; dxfull.mode = mode; dxfull.event = CreateEvent(NULL, FALSE, FALSE, NULL); PostThreadMessage(priv->nThreadID, WM_DDFULLSCREEN, 0, (long)&dxfull); WaitForSingleObject(dxfull.event, INFINITE); CloseHandle(dxfull.event); } /* create the primary surface */ memset(&pddsd, 0, sizeof(pddsd)); pddsd.dwSize = sizeof(pddsd); pddsd.dwFlags = DDSD_CAPS; pddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; if (priv->fullscreen) pddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; hr = IDirectDraw2_CreateSurface(priv->lpddext, &pddsd, &priv->lppdds, NULL); if (hr != 0) { fprintf(stderr, "Init Primary Surface Failed RC = %lx. Exiting\n", hr); exit(-1); } IDirectDraw2_CreateClipper(priv->lpddext, 0, &pClipper, NULL); IDirectDrawClipper_SetHWnd(pClipper, 0, priv->hWnd); IDirectDrawSurface_SetClipper(priv->lppdds, pClipper); IDirectDrawClipper_Release(pClipper); pddsd.dwSize = sizeof(pddsd); IDirectDrawSurface_GetSurfaceDesc(priv->lppdds, &pddsd); DPRINT_MISC("DDraw pixel format:\n"); DPRINT_MISC(" Size %u\n", pddsd.ddpfPixelFormat.dwSize); DPRINT_MISC(" Flags %08x\n", pddsd.ddpfPixelFormat.dwFlags); DPRINT_MISC(" FourCC %08x\n", pddsd.ddpfPixelFormat.dwFourCC); DPRINT_MISC(" Count %u\n", pddsd.ddpfPixelFormat.dwRGBBitCount); DPRINT_MISC(" R-Mask(etc) %08x\n", pddsd.ddpfPixelFormat.dwRBitMask); DPRINT_MISC(" G-Mask(etc) %08x\n", pddsd.ddpfPixelFormat.dwGBitMask); DPRINT_MISC(" B-Mask(etc) %08x\n", pddsd.ddpfPixelFormat.dwBBitMask); DPRINT_MISC(" Z-Mask(etc) %08x\n", pddsd.ddpfPixelFormat.dwRGBZBitMask); /* create the back storages */ for (i = 0; i < mode->frames; ++i) { memset(&bddsd, 0, sizeof(bddsd)); bddsd.dwSize = sizeof(bddsd); bddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; bddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; bddsd.dwWidth = mode->virt.x; bddsd.dwHeight = mode->virt.y; /* set up the pixel format */ ZeroMemory(&bddsd.ddpfPixelFormat, sizeof(DDPIXELFORMAT)); bddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); bddsd.ddpfPixelFormat.dwFlags = pddsd.ddpfPixelFormat.dwFlags; bddsd.ddpfPixelFormat.dwFourCC = pddsd.ddpfPixelFormat.dwFourCC; bddsd.ddpfPixelFormat.dwRGBBitCount = pddsd.ddpfPixelFormat.dwRGBBitCount; bddsd.ddpfPixelFormat.dwRBitMask = pddsd.ddpfPixelFormat.dwRBitMask; bddsd.ddpfPixelFormat.dwGBitMask = pddsd.ddpfPixelFormat.dwGBitMask; bddsd.ddpfPixelFormat.dwBBitMask = pddsd.ddpfPixelFormat.dwBBitMask; bddsd.ddpfPixelFormat.dwRGBAlphaBitMask = pddsd.ddpfPixelFormat.dwRGBAlphaBitMask; hr = IDirectDraw2_CreateSurface(priv->lpddext, &bddsd, &priv->lpbdds[i], NULL); if (hr) { fprintf(stderr, "Init Backup Failed RC = %lx. Exiting\n", hr); exit(-1); } IDirectDrawSurface2_Lock(priv->lpbdds[i], NULL, &bddsd, DDLOCK_SURFACEMEMORYPTR, NULL); priv->lpSurfaceAdd[i] = (char *) bddsd.lpSurface; IDirectDrawSurface2_Unlock(priv->lpbdds[i], bddsd.lpSurface); } /* set private mode parameters */ priv->maxX = mode->virt.x; priv->maxY = mode->virt.y; priv->ColorDepth = pddsd.ddpfPixelFormat.dwRGBBitCount; priv->pitch = bddsd.lPitch; if (pddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) { static PALETTEENTRY pal[256]; /* todo fill in pal */ hr = IDirectDraw_CreatePalette(priv->lpddext, DDPCAPS_8BIT|DDPCAPS_ALLOW256, pal, &priv->lpddp, NULL); if (hr) { fprintf(stderr, "Init Palette failed RC = %lx. Exiting\n", hr); exit(-1); } hr = IDirectDrawSurface_SetPalette(priv->lppdds, priv->lpddp); if (hr) { fprintf(stderr, "Install Palette failed RC = %lx. Exiting\n", hr); exit(-1); } } return 1; }