/*****************************Private*Routine******************************\ * DDSurfEnumFunc * \**************************************************************************/ HRESULT WINAPI DDSurfEnumFunc( LPDIRECTDRAWSURFACE7 pdds, DDSURFACEDESC2* pddsd, void* lpContext ) { LPDIRECTDRAWSURFACE7* ppdds = (LPDIRECTDRAWSURFACE7*)lpContext; DDSURFACEDESC2 ddsd; INITDDSTRUCT(ddsd); HRESULT hr = pdds->GetSurfaceDesc(&ddsd); if(SUCCEEDED(hr)) { if(ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { *ppdds = pdds; return DDENUMRET_CANCEL; } } pdds->Release(); return DDENUMRET_OK; }
//------------------------------------------------------------------------- // InitializeEnvironment // creates default allocator-presenter and sets D3D environment //------------------------------------------------------------------------- HRESULT CMultiSAP::InitializeEnvironment() { HRESULT hr; // m_hMonitor = MonitorFromWindow(m_hwndApp, MONITOR_DEFAULTTOPRIMARY); hr = CreateDefaultAllocatorPresenter(); if (hr != S_OK) return hr; BITMAPINFOHEADER bi = { sizeof(BITMAPINFOHEADER), // biSize 640, // biWidth 480, // biHeight 1, // biPlanes 0, // biBitCount BI_RGB, // biCompression 0, // biSizeImage, 0, // biXpelsPerMeter 0, // biYPelsPerMeter 0, // biClrUsed 0 // biClrImportant }; VMRALLOCATIONINFO ai = { AMAP_3D_TARGET, // dwFlags &bi, // lpHdr NULL, // lpPicFmt {4, 3}, // szAspectRatio 1, // dwMinBuffers 1, // dwMaxBuffers 0, // dwInterlaceFlags {640, 480} // szNativeSize }; DWORD dwBuffers = 0; LPDIRECTDRAWSURFACE7 lpDDSurf; hr = m_pAlloc->AllocateSurface(0, &ai, &dwBuffers, &lpDDSurf); if (hr != DD_OK) return hr; DDSURFACEDESC2 ddsd = {sizeof(DDSURFACEDESC2)}; hr = lpDDSurf->GetSurfaceDesc(&ddsd); if (hr != DD_OK) { return hr; } // // Overlay surfaces have these flags set, we need to remove // these flags prior to calling GetAttachedSurface // ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_FRONTBUFFER | DDSCAPS_VISIBLE); hr = lpDDSurf->GetAttachedSurface(&ddsd.ddsCaps, &m_lpBackBuffer); m_lpBackBuffer->GetDDInterface((LPVOID *)&m_lpDDObj); // // get the h/w caps for this device // INITDDSTRUCT(m_ddHWCaps); m_lpDDObj->GetCaps(&m_ddHWCaps, NULL); // // Create the device. The device is created off of our back buffer, which // becomes the render target for the newly created device. Note that the // z-buffer must be created BEFORE the device // m_pD3DHelper = new CD3DHelper(m_lpBackBuffer, &hr); if(m_pD3DHelper == NULL || hr != DD_OK) { if(m_pD3DHelper == NULL) { hr = E_OUTOFMEMORY; } delete m_pD3DHelper; } SetRect(&m_rcDst, 0, 0, 640, 480); #ifdef SPARKLE m_pSparkle = new CSparkle(m_lpDDObj); if (m_pSparkle) m_pSparkle->InitializeSparkle(); #endif return hr; }
/******************************Public*Routine******************************\ * PresentImage * \**************************************************************************/ STDMETHODIMP CMpegMovie::PresentImage( DWORD_PTR dwUserID, VMRPRESENTATIONINFO* lpPresInfo ) { #if 0 LPDIRECTDRAWSURFACE7 lpSurface = lpPresInfo->lpSurf; const REFERENCE_TIME rtNow = lpPresInfo->rtStart; const DWORD dwSurfaceFlags = lpPresInfo->dwFlags; if(m_iDuration > 0) { HRESULT hr; RECT rs, rd; DDSURFACEDESC2 ddsdV; INITDDSTRUCT(ddsdV); hr = lpSurface->GetSurfaceDesc(&ddsdV); DDSURFACEDESC2 ddsdP; INITDDSTRUCT(ddsdP); hr = m_pddsPriText->GetSurfaceDesc(&ddsdP); FLOAT fPos = (FLOAT)m_iDuration / 30.0F; FLOAT fPosInv = 1.0F - fPos; SetRect(&rs, 0, 0, MulDiv((int)ddsdV.dwWidth, 30 - m_iDuration, 30), ddsdV.dwHeight); SetRect(&rd, 0, 0, MulDiv((int)ddsdP.dwWidth, 30 - m_iDuration, 30), ddsdP.dwHeight); hr = m_pddsRenderT->Blt(&rd, lpSurface, &rs, DDBLT_WAIT, NULL); SetRect(&rs, 0, 0, MulDiv((int)ddsdP.dwWidth, m_iDuration, 30), ddsdP.dwHeight); SetRect(&rd, (int)ddsdP.dwWidth - MulDiv((int)ddsdP.dwWidth, m_iDuration, 30), 0, ddsdP.dwWidth, ddsdP.dwHeight); hr = m_pddsRenderT->Blt(&rd, m_pddsPriText, &rs, DDBLT_WAIT, NULL); // // need to wait for VBlank before blt-ing // { LPDIRECTDRAW lpdd; hr = m_pddsPrimary->GetDDInterface((LPVOID*)&lpdd); if(SUCCEEDED(hr)) { DWORD dwScanLine; for(; ;) { hr = lpdd->GetScanLine(&dwScanLine); if(hr == DDERR_VERTICALBLANKINPROGRESS) { break; } if(FAILED(hr)) { break; } if((LONG)dwScanLine>= rd.top) { if((LONG)dwScanLine <= rd.bottom) { continue; } } break; } RELEASE(lpdd); } } hr = m_pddsPrimary->Blt(NULL, m_pddsRenderT, NULL, DDBLT_WAIT, NULL); m_iDuration--; if(m_iDuration == 0 && (ddsdV.ddsCaps.dwCaps & DDSCAPS_OVERLAY)) { // need to get the color key visible again. InvalidateRect(m_hwndApp, NULL, FALSE); } return hr; } else { return m_lpDefIP->PresentImage(dwUserID, lpPresInfo); } #endif return m_lpDefIP->PresentImage(dwUserID, lpPresInfo); }
bool SetupDDraw() { logOutput << CurrentTimeString() << "called SetupDDraw()" << endl; if (!g_ddInterface) { logOutput << CurrentTimeString() << "SetupDDraw: DirectDraw interface not set, returning" << endl; return false; } bool bSuccess = true; bKillThread = false; if (hCopyThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CopyDDrawTextureThread, NULL, 0, NULL)) { if (!(hCopyEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) { logOutput << CurrentTimeString() << "SetupDDraw: CreateEvent failed, GetLastError = " << GetLastError() << endl; bSuccess = false; } } else { logOutput << CurrentTimeString() << "SetupDDraw: CreateThread failed, GetLastError = " << GetLastError() << endl; bSuccess = false; } if (bSuccess) { if (!ddUnlockFctMutex) { ddUnlockFctMutex = CreateMutex(NULL, FALSE, mutexName); if (!ddUnlockFctMutex) { RUNEVERYRESET logOutput << CurrentTimeString() << "SetupDDraw: CreateMutex failed, GetLastError = " << GetLastError() << endl; bSuccess = false; } } } if (bSuccess && !g_frontSurface) { RUNEVERYRESET logOutput << "SetupDDraw: frontSurface and surface descriptor not set, returning" << endl; CleanUpDDraw(); return false; } else if (bSuccess) { LPDIRECTDRAWPALETTE palette = NULL; HRESULT err; if (SUCCEEDED(err = g_frontSurface->GetPalette(&palette))) { if (palette) SetupPalette(palette); } else if (err == DDERR_NOPALETTEATTACHED) { //logOutput << CurrentTimeString() << "No palette attached to primary surface" << endl; } else { logOutput << CurrentTimeString() << "Error retrieving palette" << endl; printDDrawError(err, "getFrontSurface"); } } if (bSuccess && !g_surfaceDesc) { logOutput << CurrentTimeString() << "SetupDDraw: no surface descriptor found, creating a new one (not an error)" << endl; g_surfaceDesc = new DDSURFACEDESC2; g_surfaceDesc->dwSize = sizeof(DDSURFACEDESC); HRESULT hr; if (FAILED(hr = ((LPDIRECTDRAWSURFACE)g_frontSurface)->GetSurfaceDesc((LPDDSURFACEDESC)g_surfaceDesc))) { g_surfaceDesc->dwSize = sizeof(DDSURFACEDESC2); if (FAILED(g_frontSurface->GetSurfaceDesc(g_surfaceDesc))) { logOutput << CurrentTimeString() << "SetupDDraw: error getting surface descriptor" << endl; printDDrawError(hr, "SetupDDraw"); bSuccess = false; } } } if (bSuccess && g_surfaceDesc) { const DDPIXELFORMAT& pf = g_surfaceDesc->ddpfPixelFormat; if (pf.dwFlags & DDPF_RGB) { if (pf.dwRGBBitCount == 16) { logOutput << CurrentTimeString() << "SetupDDraw: found 16bit format (using R5G6B5 conversion)" << endl; g_bConvert16to32 = true; } else if (pf.dwRGBBitCount == 32) { logOutput << CurrentTimeString() << "SetupDDraw: found 32bit format (using plain copy)" << endl; g_bUse32bitCapture = true; } } else if (pf.dwFlags & (DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED2 | DDPF_PALETTEINDEXED1)) { logOutput << CurrentTimeString() << "SetupDDraw: front surface uses palette indices" << endl; } } if (bSuccess) { logOutput << CurrentTimeString() << "SetupDDraw: primary surface width = " << g_surfaceDesc->dwWidth << ", height = " << g_surfaceDesc->dwHeight << endl; g_dwSize = g_surfaceDesc->lPitch*g_surfaceDesc->dwHeight; ddrawCaptureInfo.captureType = CAPTURETYPE_MEMORY; ddrawCaptureInfo.cx = g_surfaceDesc->dwWidth; ddrawCaptureInfo.cy = g_surfaceDesc->dwHeight; ddrawCaptureInfo.pitch = 4 * ddrawCaptureInfo.cx; ddrawCaptureInfo.hwndCapture = (DWORD)hwndSender; ddrawCaptureInfo.format = GS_BGRA; DWORD g_dwCaptureSize = ddrawCaptureInfo.pitch*ddrawCaptureInfo.cy; ddrawCaptureInfo.bFlip = FALSE; ddrawCaptureInfo.mapID = InitializeSharedMemoryCPUCapture(g_dwCaptureSize, &ddrawCaptureInfo.mapSize, ©Data, textureBuffers); memcpy(infoMem, &ddrawCaptureInfo, sizeof(CaptureInfo)); DDSURFACEDESC2 captureDesc; ZeroMemory(&captureDesc, sizeof(captureDesc)); captureDesc.dwSize = sizeof(DDSURFACEDESC2); captureDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_PITCH; captureDesc.dwWidth = g_surfaceDesc->dwWidth; captureDesc.dwHeight = g_surfaceDesc->dwHeight; captureDesc.lPitch = g_surfaceDesc->lPitch; captureDesc.ddpfPixelFormat = g_surfaceDesc->ddpfPixelFormat; captureDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; HRESULT err; ddrawSurfaceCreate.Unhook(); for (int i = 0; i < NUM_BUFFERS && bSuccess; i++) { if (FAILED(err = g_ddInterface->CreateSurface(&captureDesc, &ddCaptures[i], NULL))) { logOutput << CurrentTimeString() << "SetupDDraw: Could not create offscreen capture" << endl; printDDrawError(err, "SetupDDraw"); bSuccess = false; break; } } ddrawSurfaceCreate.Rehook(); if (bSuccess) { bHasTextures = true; SetEvent(hSignalReady); OSInitializeTimer(); } } if (bSuccess) { logOutput << CurrentTimeString() << "SetupDDraw successfull" << endl; HookAll(); return true; } else { logOutput << CurrentTimeString() << "SetupDDraw failed" << endl; CleanUpDDraw(); return false; } }
/** * vdraw_ddraw_init(): Initialize the DirectDraw video subsystem. * @return 0 on success; non-zero on error. */ int vdraw_ddraw_init(void) { DDSURFACEDESC2 ddsd; vdraw_ddraw_end(); mdp_render_t *rendMode = get_mdp_render_t(); const int scale = rendMode->scale; // Determine the window size using the scaling factor. if (scale <= 0) return -1; const int w = 320 * scale; const int h = 240 * scale; if (vdraw_get_fullscreen()) { Res_X = w; Res_Y = h; } // Return value. int rval; // Initialize DirectDraw. // TODO: Initialize DirectDraw on the monitor with most of Gens/GS onscreen. LPDIRECTDRAW lpDD_Init; rval = DirectDrawCreate(NULL, &lpDD_Init, NULL); if (FAILED(rval)) { LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "DirectDrawCreate() failed: 0x%08X", rval); return -2; } rval = lpDD_Init->QueryInterface(IID_IDirectDraw7, (LPVOID*)&lpDD); if (FAILED(rval)) { if (lpDD_Init) lpDD_Init->Release(); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD_Init->QueryInterface(IID_IDirectDraw4) failed: 0x%08X", rval); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "This can usually be fixed by upgrading DirectX."); return -3; } // Free the DirectDraw initialization object. lpDD_Init->Release(); // Set the cooperative level. vdraw_ddraw_set_cooperative_level(); // TODO: 15-bit color override. ("Force 555" or "Force 565" in the config file.) memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); // TODO: Figure out what FS_No_Res_Change is for. // TODO: Figure out if this is correct. if (vdraw_get_fullscreen() /* && !FS_No_Res_Change*/) { // Use the color depth setting. // NOTE: "15-bit" color requires 16-bit to be specified. rval = lpDD->SetDisplayMode(Res_X, Res_Y, (bppOut == 15 ? 16 : bppOut), 0, 0); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD->SetDisplayMode() failed: 0x%08X", rval); // If render mode is set to Normal, try using Double instead. if (rendMode_FS == RenderMgr::begin() && rendMode_FS != RenderMgr::end()) { LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "Renderer is set to Normal; attempting to use Double instead."); rendMode_FS++; vdraw_set_renderer(rendMode_FS); vdraw_text_write("Normal rendering failed. Using Double.", 1500); Sync_Gens_Window_GraphicsMenu(); } return -4; } } #if 0 // Check the current color depth. unsigned char newBpp; lpDD->GetDisplayMode(&ddsd); switch (ddsd.ddpfPixelFormat.dwGBitMask) { case 0x03E0: // 15-bit color. newBpp = 15; break; case 0x07E0: // 16-bit color. newBpp = 16; break; case 0x00FF00: default: // 32-bit color. newBpp = 32; break; } if (newBpp != bppOut) vdraw_set_bpp(newBpp, false); #endif // Clear ddsd. memset(&ddsd, 0x00, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); if (vdraw_get_fullscreen() && Video.VSync_FS) { ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; ddsd.dwBackBufferCount = 2; } else { ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; } // Create the primary surface. rval = lpDD->CreateSurface(&ddsd, &lpDDS_Primary, NULL); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD->CreateSurface(&lpDDS_Primary) failed: 0x%08X", rval); return -5; } if (vdraw_get_fullscreen()) { if (Video.VSync_FS) { ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; rval = lpDDS_Primary->GetAttachedSurface(&ddsd.ddsCaps, &lpDDS_Flip); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDDS_Primary->GetAttachSurface() failed: 0x%08X", rval); return -6; } lpDDS_Blit = lpDDS_Flip; } else { lpDDS_Blit = lpDDS_Primary; } } else { rval = lpDD->CreateClipper(0, &lpDDC_Clipper, NULL); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD->CreateClipper() failed: 0x%08X", rval); return -7; } rval = lpDDC_Clipper->SetHWnd(0, gens_window); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDDC_Clipper->SetHWnd() failed: 0x%08X", rval); return -8; } rval = lpDDS_Primary->SetClipper(lpDDC_Clipper); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDDC_Primary->SetClipper() failed: 0x%08X", rval); return -9; } } // Clear ddsd again. memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; // Determine the width and height. // NOTE: For DirectDraw, the actual 336 width is used. if (vdraw_ddraw_is_hw_render()) { // Normal render mode. 320x240 [336x240] ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; ddsd.dwWidth = 336; ddsd.dwHeight = 240; } else { // Larger than 1x. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; ddsd.dwWidth = w; ddsd.dwHeight = h; } // Set the pixel format. ddsd.dwFlags |= DDSD_PIXELFORMAT; ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; ddsd.ddpfPixelFormat.dwFourCC = 0; // RGB ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0; // Bits per component. switch (bppOut) { case 15: // 15-bit color. (555) ddsd.ddpfPixelFormat.dwRGBBitCount = 16; ddsd.ddpfPixelFormat.dwRBitMask = 0x7C00; ddsd.ddpfPixelFormat.dwGBitMask = 0x03E0; ddsd.ddpfPixelFormat.dwBBitMask = 0x001F; break; case 16: // 16-bit color. (555) ddsd.ddpfPixelFormat.dwRGBBitCount = 16; ddsd.ddpfPixelFormat.dwRBitMask = 0xF800; ddsd.ddpfPixelFormat.dwGBitMask = 0x07E0; ddsd.ddpfPixelFormat.dwBBitMask = 0x001F; break; case 32: default: // 32-bit color. ddsd.ddpfPixelFormat.dwRGBBitCount = 32; ddsd.ddpfPixelFormat.dwRBitMask = 0xFF0000; ddsd.ddpfPixelFormat.dwGBitMask = 0x00FF00; ddsd.ddpfPixelFormat.dwBBitMask = 0x0000FF; break; } // Create the back surface. rval = lpDD->CreateSurface(&ddsd, &lpDDS_Back, NULL); if (FAILED(rval)) { // Failed to create the back surface. // If we attempted to create it in video memory, try system memory instead. if (ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) { LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD->CreateSurface(&lpDDS_Back, DDSCAPS_VIDEOMEMORY) failed: 0x%08X", rval); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "Attempting to use DDSCAPS_SYSTEMMEMORY instead."); ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; rval = lpDD->CreateSurface(&ddsd, &lpDDS_Back, NULL); if (FAILED(rval)) { // Failed to create the back surface in system memory. vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD->CreateSurface(&lpDDS_Back, DDSCAPS_SYSTEMMEMORY) failed: 0x%08X", rval); return -10; } } else { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDD->CreateSurface(&lpDDS_Back, DDSCAPS_SYSTEMMEMORY) failed: 0x%08X", rval); return -11; } } // TODO: Check if this is right. // I think this might be causing the frame counter flicker in full screen mode. //if (!vdraw_get_fullscreen() || (rendMode >= 1 && (/*FS_No_Res_Change ||*/ Res_X != 640 || Res_Y != 480))) if (!vdraw_get_fullscreen() || !vdraw_ddraw_is_hw_render()) lpDDS_Blit = lpDDS_Back; if (vdraw_ddraw_is_hw_render()) { // Normal rendering mode uses MD_Screen directly. memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); // TODO: This causes issues if the selected color depth isn't the // same as the desktop color depth. This only affects windowed mode, // since in fullscreen, the desktop color depth is changed. rval = lpDDS_Back->GetSurfaceDesc(&ddsd); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDDS_Back->GetSurfaceDesc() failed: 0x%08X", rval); return -12; } ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE | DDSD_PIXELFORMAT; ddsd.dwWidth = 336; ddsd.dwHeight = 240; if (ddsd.ddpfPixelFormat.dwRGBBitCount > 16) { // 32-bit color. ddsd.lpSurface = MD_Screen.u32; ddsd.lPitch = 336 * 4; } else { // 15-bit or 16-bit color. ddsd.lpSurface = MD_Screen.u16; ddsd.lPitch = 336 * 2; } rval = lpDDS_Back->SetSurfaceDesc(&ddsd, 0); if (FAILED(rval)) { vdraw_ddraw_free_all(false); LOG_MSG(video, LOG_MSG_LEVEL_ERROR, "lpDDS_Back->SetSurfaceDesc() failed: 0x%08X", rval); return -13; } } // Initialize the destination rectangle. vdraw_ddraw_adjust_RectDest(); // Reset the render mode. vdraw_reset_renderer(false); // Synchronize menus. Sync_Gens_Window(); // vdraw_ddraw initialized. return 0; }