/* We route all wgl functions from opengl32.dll through gdi32.dll to * the display driver. Various wgl calls have a hDC as one of their parameters. * Using get_dc_ptr we get access to the functions exported by the driver. * Some functions don't receive a hDC. This function creates a global hdc and * if there's already a global hdc, it returns it. */ static DC* OPENGL_GetDefaultDC(void) { if(!default_hdc) default_hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); return get_dc_ptr(default_hdc); }
static void test_dc_values(void) { HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); COLORREF color; ok( hdc != NULL, "CreateDC failed\n" ); color = SetBkColor( hdc, 0x12345678 ); ok( color == 0xffffff, "initial color %08x\n", color ); color = GetBkColor( hdc ); ok( color == 0x12345678, "wrong color %08x\n", color ); color = SetBkColor( hdc, 0xffffffff ); ok( color == 0x12345678, "wrong color %08x\n", color ); color = GetBkColor( hdc ); ok( color == 0xffffffff, "wrong color %08x\n", color ); color = SetBkColor( hdc, 0 ); ok( color == 0xffffffff, "wrong color %08x\n", color ); color = GetBkColor( hdc ); ok( color == 0, "wrong color %08x\n", color ); color = SetTextColor( hdc, 0xffeeddcc ); ok( color == 0, "initial color %08x\n", color ); color = GetTextColor( hdc ); ok( color == 0xffeeddcc, "wrong color %08x\n", color ); color = SetTextColor( hdc, 0xffffffff ); ok( color == 0xffeeddcc, "wrong color %08x\n", color ); color = GetTextColor( hdc ); ok( color == 0xffffffff, "wrong color %08x\n", color ); color = SetTextColor( hdc, 0 ); ok( color == 0xffffffff, "wrong color %08x\n", color ); color = GetTextColor( hdc ); ok( color == 0, "wrong color %08x\n", color ); DeleteDC( hdc ); }
BOOL CreateD3D9DeviceData(IN LPDIRECT3D9_DISPLAYADAPTER pDisplayAdapter, IN LPD3D9_DEVICEDATA pDeviceData) { HDC hDC; /* Test DC creation for the display device */ if (NULL == (hDC = CreateDCA(NULL, pDisplayAdapter->szDeviceName, NULL, NULL))) { DPRINT1("Could not create dc for display adapter: %s", pDisplayAdapter->szDeviceName); return FALSE; } pDeviceData->hDC = hDC; pDeviceData->DisplayGuid = pDisplayAdapter->DisplayGuid; pDeviceData->DeviceType = D3DDEVTYPE_HAL; lstrcpynA(pDeviceData->szDeviceName, pDisplayAdapter->szDeviceName, CCHDEVICENAME); pDeviceData->szDeviceName[CCHDEVICENAME-1] = '\0'; if (pDisplayAdapter->bInUseFlag) { pDeviceData->D3D9Callbacks.DeviceType = D3DDEVTYPE_HAL; } else if (IsGDIDriver(hDC)) { pDeviceData->D3D9Callbacks.DeviceType = D3DDEVTYPE_REF; } if (FALSE == GetDeviceData(pDeviceData)) { DPRINT1("Could not get device data for display adapter: %s", pDisplayAdapter->szDeviceName); return FALSE; } return TRUE; }
static DWORD WINAPI thread_proc(void *param) { LOGPEN lp; DWORD status; struct hgdiobj_event *hgdiobj_event = param; hgdiobj_event->hdc = CreateDCA("display", NULL, NULL, NULL); ok(hgdiobj_event->hdc != NULL, "CreateDC error %u\n", GetLastError()); hgdiobj_event->hgdiobj1 = CreatePen(PS_DASHDOTDOT, 17, RGB(1, 2, 3)); ok(hgdiobj_event->hgdiobj1 != 0, "Failed to create pen\n"); hgdiobj_event->hgdiobj2 = CreateRectRgn(0, 1, 12, 17); ok(hgdiobj_event->hgdiobj2 != 0, "Failed to create pen\n"); SetEvent(hgdiobj_event->ready_event); status = WaitForSingleObject(hgdiobj_event->stop_event, INFINITE); ok(status == WAIT_OBJECT_0, "WaitForSingleObject error %u\n", GetLastError()); ok(!GetObjectA(hgdiobj_event->hgdiobj1, sizeof(lp), &lp), "GetObject should fail\n"); ok(!GetDeviceCaps(hgdiobj_event->hdc, TECHNOLOGY), "GetDeviceCaps(TECHNOLOGY) should fail\n"); return 0; }
static BOOL CALLBACK EnumerationCallback(HMONITOR monitor, HDC hdc_unused, LPRECT rect_unused, LPARAM lparam) { MONITORINFOEXA info; memset(&info, 0, sizeof(MONITORINFOEXA)); info.cbSize = sizeof(MONITORINFOEXA); if (GetMonitorInfoA(monitor, (MONITORINFO*)&info) == FALSE) { return FALSE; } int free_slot = 0; for (; free_slot < MAXIMUM_DISPLAYS; ++free_slot) { if (displays[free_slot].monitor == monitor) { return FALSE; } if (displays[free_slot].monitor == NULL) { break; } } DisplayData *display = &displays[free_slot]; strcpy_s(display->name, 32, info.szDevice); display->index = free_slot; display->monitor = monitor; display->primary = (info.dwFlags & MONITORINFOF_PRIMARY) != 0; display->available = true; display->x = info.rcMonitor.left; display->y = info.rcMonitor.top; display->width = info.rcMonitor.right - info.rcMonitor.left; display->height = info.rcMonitor.bottom - info.rcMonitor.top; HDC hdc = CreateDCA(NULL, display->name, NULL, NULL); display->ppi = GetDeviceCaps(hdc, LOGPIXELSX); int scale = GetDeviceCaps(hdc, SCALINGFACTORX); DeleteDC(hdc); if (MyGetDpiForMonitor != NULL) { unsigned dpiX, dpiY; MyGetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); display->ppi = (int)dpiX; } memset(&original_modes[free_slot], 0, sizeof(DEVMODEA)); original_modes[free_slot].dmSize = sizeof(DEVMODEA); EnumDisplaySettingsA(display->name, ENUM_CURRENT_SETTINGS, &original_modes[free_slot]); display->frequency = original_modes[free_slot].dmDisplayFrequency; display->bpp = original_modes[free_slot].dmBitsPerPel; ++screen_counter; return TRUE; }
static void test_dc_values(void) { HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); COLORREF color; int extra; ok( hdc != NULL, "CreateDC failed\n" ); color = SetBkColor( hdc, 0x12345678 ); ok( color == 0xffffff, "initial color %08x\n", color ); color = GetBkColor( hdc ); ok( color == 0x12345678, "wrong color %08x\n", color ); color = SetBkColor( hdc, 0xffffffff ); ok( color == 0x12345678, "wrong color %08x\n", color ); color = GetBkColor( hdc ); ok( color == 0xffffffff, "wrong color %08x\n", color ); color = SetBkColor( hdc, 0 ); ok( color == 0xffffffff, "wrong color %08x\n", color ); color = GetBkColor( hdc ); ok( color == 0, "wrong color %08x\n", color ); color = SetTextColor( hdc, 0xffeeddcc ); ok( color == 0, "initial color %08x\n", color ); color = GetTextColor( hdc ); ok( color == 0xffeeddcc, "wrong color %08x\n", color ); color = SetTextColor( hdc, 0xffffffff ); ok( color == 0xffeeddcc, "wrong color %08x\n", color ); color = GetTextColor( hdc ); ok( color == 0xffffffff, "wrong color %08x\n", color ); color = SetTextColor( hdc, 0 ); ok( color == 0xffffffff, "wrong color %08x\n", color ); color = GetTextColor( hdc ); ok( color == 0, "wrong color %08x\n", color ); extra = GetTextCharacterExtra( hdc ); ok( extra == 0, "initial extra %d\n", extra ); SetTextCharacterExtra( hdc, 123 ); extra = GetTextCharacterExtra( hdc ); ok( extra == 123, "initial extra %d\n", extra ); SetMapMode( hdc, MM_LOMETRIC ); extra = GetTextCharacterExtra( hdc ); ok( extra == 123, "initial extra %d\n", extra ); SetMapMode( hdc, MM_TEXT ); extra = GetTextCharacterExtra( hdc ); ok( extra == 123, "initial extra %d\n", extra ); DeleteDC( hdc ); }
int winInitScreenCapture(int left, int top, int width, int height) { left_ = left; top_ = top; width_ = width; height_ = height; if(hDesktopWnd_ = GetDesktopWindow()) { if(hDesktopDC_ = CreateDCA("DISPLAY", NULL, NULL, NULL)) { hCaptureDC_ = CreateCompatibleDC(hDesktopDC_); } }; if(hCaptureDC_ && hDesktopDC_ && hDesktopWnd_) return (1 == 1); winShutdownScreenCapture(); return (1 != 1); }
//-------------------------------------------------------------------------- bool WindowsVideoDevice::_SetWindowGammaRamp(VeWindow::Data* pkWindow, const VeUInt16* pu16Ramp) noexcept { VE_ASSERT(pkWindow); VeVideoDisplay* pkDisplay = VeWindow::Cast(pkWindow)->GetDisplayForWindow(); VeDisplayData* pkData = (VeDisplayData*)pkDisplay->m_spDriverData; BOOL bSucceeded = FALSE; HDC hDc = CreateDCA(pkData->DeviceName, nullptr, nullptr, nullptr); if (hDc) { bSucceeded = SetDeviceGammaRamp(hDc, (LPVOID)pu16Ramp); if (!bSucceeded) { VeDebugOutputCore("SetDeviceGammaRamp()"); } DeleteDC(hDc); } return bSucceeded ? true : false; }
/*********************************************************************** * wglGetPbufferDCARB */ static HDC WINAPI wglGetPbufferDCARB(void *pbuffer) { HDC ret = 0; /* Create a device context to associate with the pbuffer */ HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); DC *dc = get_dc_ptr(hdc); TRACE("(%p)\n", pbuffer); if (dc) { PHYSDEV physdev = GET_DC_PHYSDEV( dc, pwglGetPbufferDCARB ); /* The display driver has to do the rest of the work because * we need access to lowlevel datatypes which we can't access here */ ret = physdev->funcs->pwglGetPbufferDCARB( physdev, pbuffer ); release_dc_ptr( dc ); } TRACE("(%p), hdc=%p\n", pbuffer, ret); if (!ret) DeleteDC( hdc ); return ret; }
int fb_PrinterOpen( DEV_LPT_INFO *devInfo, int iPort, const char *pszDevice ) { int result = fb_ErrorSetNum( FB_RTERROR_OK ); const DEV_PRINTER_EMU_MODE *pFoundEmu = NULL; DWORD dwJob = 0; BOOL fResult; HANDLE hPrinter = NULL; HDC hDc = NULL; char *printer_name = NULL; char *doc_title = NULL; DEV_LPT_PROTOCOL *lpt_proto; if ( !fb_DevLptParseProtocol( &lpt_proto, pszDevice, strlen(pszDevice), TRUE ) ) { if( lpt_proto!=NULL ) free(lpt_proto); return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } /* Allow only valid emulation modes */ if( *lpt_proto->emu!=0 ) { int i; for( i=0; i!=sizeof(aEmulationModes)/sizeof(aEmulationModes[0]); ++i ) { const DEV_PRINTER_EMU_MODE *pEmu = aEmulationModes + i; if( strcasecmp( lpt_proto->emu, pEmu->pszId )==0 ) { pFoundEmu = pEmu; break; } } if( !pFoundEmu ) { if( lpt_proto!=NULL ) free(lpt_proto); return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } } if( iPort==0 ) { /* LPT:[PrinterName] */ if( *lpt_proto->name ) { printer_name = strdup( lpt_proto->name ); } else { printer_name = GetDefaultPrinterName(); } } else { /* LPTx: */ FB_LIST dev_printer_devs; DEV_PRINTER_DEVICE* node; fb_hListDevInit( &dev_printer_devs ); fb_hPrinterBuildList( &dev_printer_devs ); /* Find printer attached to specified device */ node = fb_hListDevFindDevice( &dev_printer_devs, lpt_proto->proto ); if( node!=NULL ) { printer_name = strdup( node->printer_name ); } fb_hListDevClear( &dev_printer_devs ); } if( printer_name == NULL ) { result = fb_ErrorSetNum( FB_RTERROR_FILENOTFOUND ); } else { if( *lpt_proto->emu!= '\0' ) { /* When EMULATION is used, we have to use the DC instead of * the PRINTER directly */ hDc = CreateDCA( "WINSPOOL", printer_name, NULL, NULL ); fResult = hDc!=NULL; } else { /* User PRINTER directly */ fResult = OpenPrinter(printer_name, &hPrinter, NULL); } if( !fResult ) { result = fb_ErrorSetNum( FB_RTERROR_FILENOTFOUND ); } } if( lpt_proto->title && *lpt_proto->title ) { doc_title = strdup( lpt_proto->title ); } else { doc_title = strdup( "FreeBASIC document" ); } if( result==FB_RTERROR_OK ) { if( *lpt_proto->emu!= '\0' ) { int iJob; DOCINFO docInfo; memset( &docInfo, 0, sizeof(DOCINFO) ); docInfo.cbSize = sizeof(DOCINFO); docInfo.lpszDocName = doc_title; iJob = StartDoc( hDc, &docInfo ); if( iJob <= 0 ) { result = fb_ErrorSetNum( FB_RTERROR_FILEIO ); } else { dwJob = (DWORD) iJob; } } else { DOC_INFO_1 DocInfo; DocInfo.pDocName = doc_title; DocInfo.pOutputFile = NULL; DocInfo.pDatatype = TEXT("RAW"); dwJob = StartDocPrinter( hPrinter, 1, (BYTE*) &DocInfo ); if( dwJob==0 ) { result = fb_ErrorSetNum( FB_RTERROR_FILEIO ); } } } if( result==FB_RTERROR_OK ) { W32_PRINTER_INFO *pInfo = calloc( 1, sizeof(W32_PRINTER_INFO) ); if( pInfo==NULL ) { result = fb_ErrorSetNum( FB_RTERROR_OUTOFMEM ); } else { devInfo->driver_opaque = pInfo; pInfo->hPrinter = hPrinter; pInfo->dwJob = dwJob; pInfo->hDc = hDc; if( hDc!=NULL ) { LOGFONT lf; pInfo->Emu.dwFullSizeX = GetDeviceCaps( hDc, PHYSICALWIDTH ); pInfo->Emu.dwFullSizeY = GetDeviceCaps( hDc, PHYSICALHEIGHT ); pInfo->Emu.dwSizeX = GetDeviceCaps( hDc, HORZRES ); pInfo->Emu.dwSizeY = GetDeviceCaps( hDc, VERTRES ); pInfo->Emu.dwOffsetX = GetDeviceCaps( hDc, PHYSICALOFFSETX ); pInfo->Emu.dwOffsetY = GetDeviceCaps( hDc, PHYSICALOFFSETY ); pInfo->Emu.dwDPI_X = GetDeviceCaps( hDc, LOGPIXELSX ); pInfo->Emu.dwDPI_Y = GetDeviceCaps( hDc, LOGPIXELSY ); #if 0 pInfo->Emu.dwCurrentX = pInfo->Emu.dwOffsetX; pInfo->Emu.dwCurrentY = pInfo->Emu.dwOffsetY; #else pInfo->Emu.dwCurrentX = 0; pInfo->Emu.dwCurrentY = 0; #endif pInfo->Emu.clFore = RGB(0,0,0); pInfo->Emu.clBack = RGB(255,255,255); /* Start in 12 CPI monospace mode */ EmuBuild_LOGFONT( &lf, pInfo, 12 ); /* Should never fail - except when some default fonts were * removed by hand (which is very unlikely) */ pInfo->Emu.hFont = CreateFontIndirect( &lf ); DBG_ASSERT( pInfo->Emu.hFont!=NULL ); /* Register PRINT function */ pInfo->Emu.pfnPrint = pFoundEmu->pfnPrint; /* Should not be necessary because this is the default */ SetTextAlign( hDc, TA_TOP | TA_LEFT | TA_NOUPDATECP ); EmuUpdateInfo( pInfo ); } } } if( result!=FB_RTERROR_OK ) { if( dwJob!=0 ) { if( *lpt_proto->emu != '\0' ) { EndDoc( hDc ); } else { EndDocPrinter( hPrinter ); } } if( hPrinter!=NULL ) { ClosePrinter( hPrinter ); } if( hDc!=NULL ) { DeleteDC( hDc ); } } if( printer_name!=NULL ) free( printer_name ); if( doc_title!=NULL ) free( doc_title ); if( lpt_proto!=NULL ) free(lpt_proto); return result; }
static void test_savedc(void) { HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); int ret; ok(hdc != NULL, "CreateDC rets %p\n", hdc); ret = SaveDC(hdc); ok(ret == 1, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 2, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 3, "ret = %d\n", ret); ret = RestoreDC(hdc, -1); ok(ret, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 3, "ret = %d\n", ret); ret = RestoreDC(hdc, 1); ok(ret, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 1, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 2, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 3, "ret = %d\n", ret); ret = RestoreDC(hdc, -2); ok(ret, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 2, "ret = %d\n", ret); ret = RestoreDC(hdc, -2); ok(ret, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 1, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 2, "ret = %d\n", ret); ret = RestoreDC(hdc, -4); ok(!ret, "ret = %d\n", ret); ret = RestoreDC(hdc, 3); ok(!ret, "ret = %d\n", ret); /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */ ret = RestoreDC(hdc, -3); ok(!ret || broken(ret), /* Win9x */ "ret = %d\n", ret); /* Trying to clear an empty save stack fails. */ ret = RestoreDC(hdc, -3); ok(!ret, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 3 || broken(ret == 1), /* Win9x */ "ret = %d\n", ret); /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */ ret = RestoreDC(hdc, 0); ok(!ret || broken(ret), /* Win9x */ "ret = %d\n", ret); /* Trying to clear an empty save stack fails. */ ret = RestoreDC(hdc, 0); ok(!ret, "ret = %d\n", ret); ret = RestoreDC(hdc, 1); ok(ret || broken(!ret), /* Win9x */ "ret = %d\n", ret); DeleteDC(hdc); }
static BOOL CALLBACK enum_monitor (HMONITOR hmonitor, HDC hdc, LPRECT rect, LPARAM data) { /* The struct MONITORINFOEX definition is for some reason different * in the winuser.h bundled with mingw64 from that in MSDN and the * official 32-bit mingw (the MONITORINFO part is in a separate "mi" * member). So to keep this easily compileable with either, repeat * the MSDN definition it here. */ typedef struct tagMONITORINFOEXA2 { DWORD cbSize; RECT rcMonitor; RECT rcWork; DWORD dwFlags; CHAR szDevice[CCHDEVICENAME]; } MONITORINFOEXA2; MONITORINFOEXA2 monitor_info; HDC hDC; gint *index = (gint *) data; GdkWin32Monitor *monitor; g_assert (*index < _gdk_num_monitors); monitor = _gdk_monitors + *index; monitor_info.cbSize = sizeof (MONITORINFOEX); GetMonitorInfoA (hmonitor, (MONITORINFO *) &monitor_info); #ifndef MONITORINFOF_PRIMARY #define MONITORINFOF_PRIMARY 1 #endif monitor->name = g_strdup (monitor_info.szDevice); hDC = CreateDCA ("DISPLAY", monitor_info.szDevice, NULL, NULL); monitor->width_mm = GetDeviceCaps (hDC, HORZSIZE); monitor->height_mm = GetDeviceCaps (hDC, VERTSIZE); DeleteDC (hDC); monitor->rect.x = monitor_info.rcMonitor.left; monitor->rect.y = monitor_info.rcMonitor.top; monitor->rect.width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left; monitor->rect.height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top; if (monitor_info.dwFlags & MONITORINFOF_PRIMARY && *index != 0) { /* Put primary monitor at index 0, just in case somebody needs * to know which one is the primary. */ GdkWin32Monitor temp = *monitor; *monitor = _gdk_monitors[0]; _gdk_monitors[0] = temp; } (*index)++; return TRUE; }
/*********************************************************************** * ChangeDisplaySettingsExA (USER32.@) */ LONG WINAPI ChangeDisplaySettingsExA( LPCSTR devname, LPDEVMODEA devmode, HWND hwnd, DWORD flags, LPARAM lparam ) { /* Only the lowest common denominator since that's all that the underlying ChangeDisplaySettings expects */ WINE_WIN31_DEVMODEA *localDevMode = NULL; TRACE_(system)("%s,%p,%08x,0x%08lx,0x%08lx\n", devname, devmode, hwnd, flags, lparam); if (devmode) { localDevMode = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_WIN31_DEVMODEA)); if (!localDevMode) { ERR_(system)("Error allocating memory. Expect problems\n"); return DISP_CHANGE_FAILED; } memcpy(localDevMode, devmode, sizeof(WINE_WIN31_DEVMODEA)); /* Fixup missing values that we intend to use. */ if (!(localDevMode->dmFields & DM_PELSWIDTH)) localDevMode->dmPelsWidth = GetSystemMetrics(SM_CXSCREEN); if (!(localDevMode->dmFields & DM_PELSHEIGHT)) localDevMode->dmPelsHeight = GetSystemMetrics(SM_CYSCREEN); if (!(localDevMode->dmFields & DM_BITSPERPEL)) localDevMode->dmBitsPerPel = GetSystemMetrics(SM_WINE_BPP); } if (USER_Driver.pChangeDisplayMode ((DEVMODEA*)localDevMode) == TRUE) { /* NOTE: the moving of existing windows has been taken out of * the wine premerge tree because of some things that dont exist. */ /* the sysMetrics also needs to be modified */ SYSMETRICS_Set (SM_CXSCREEN, localDevMode->dmPelsWidth); SYSMETRICS_Set (SM_CYSCREEN, localDevMode->dmPelsHeight); SYSMETRICS_Set (SM_WINE_BPP, localDevMode->dmBitsPerPel); } else { /* if the dislpay change mode 'failed' that could mean it was given NULL and hence * was supposed to go back to default mode * so we set it back to the defaults from GetDeviceCaps() */ /* FIXME: * update the res that GetDeviceCaps is storing (do this in ChangeDisplayMode???) * then use this for both cases of failing or succeeding */ HDC hdc = CreateDCA ("DISPLAY", NULL, NULL, NULL); SYSMETRICS_Set (SM_CXSCREEN, GetDeviceCaps(hdc, HORZRES)); SYSMETRICS_Set (SM_CYSCREEN, GetDeviceCaps(hdc, VERTRES)); SYSMETRICS_Set (SM_WINE_BPP, GetDeviceCaps(hdc, BITSPIXEL)); DeleteDC (hdc); } SendNotifyMessageA(HWND_BROADCAST, WM_DISPLAYCHANGE, GetSystemMetrics(SM_WINE_BPP), MAKELONG(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN))); if (localDevMode) HeapFree (GetProcessHeap(), 0, localDevMode); /* But, always return successfull anyway. */ return DISP_CHANGE_SUCCESSFUL; }
//-------------------------------------------------------------------------- static bool GetDisplayMode(LPCSTR deviceName, DWORD index, VeDisplayMode* mode) noexcept { VeDisplayModeData* data; DEVMODEA devmode; HDC hdc; devmode.dmSize = sizeof(devmode); devmode.dmDriverExtra = 0; if (!EnumDisplaySettingsA(deviceName, index, &devmode)) { return false; } data = VE_NEW VeDisplayModeData; VE_ASSERT(data); data->DeviceMode = devmode; data->DeviceMode.dmFields = (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS); data->ScaleX = 1.0f; data->ScaleY = 1.0f; mode->m_u32Format = VE_PIXELFORMAT_UNKNOWN; mode->m_i32Width = devmode.dmPelsWidth; mode->m_i32Height = devmode.dmPelsHeight; mode->m_i32RefreshRate = devmode.dmDisplayFrequency; mode->m_spDriverData = data; if (index == ENUM_CURRENT_SETTINGS && (hdc = CreateDCA(deviceName, nullptr, nullptr, nullptr)) != nullptr) { char bmi_data[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)]; LPBITMAPINFO bmi; HBITMAP hbm; int logical_width = GetDeviceCaps(hdc, HORZRES); int logical_height = GetDeviceCaps(hdc, VERTRES); data->ScaleX = (float)logical_width / devmode.dmPelsWidth; data->ScaleY = (float)logical_height / devmode.dmPelsHeight; mode->m_i32Width = logical_width; mode->m_i32Height = logical_height; VeZeroMemory(bmi_data, sizeof(bmi_data)); bmi = (LPBITMAPINFO)bmi_data; bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); hbm = CreateCompatibleBitmap(hdc, 1, 1); GetDIBits(hdc, hbm, 0, 1, nullptr, bmi, DIB_RGB_COLORS); GetDIBits(hdc, hbm, 0, 1, nullptr, bmi, DIB_RGB_COLORS); DeleteObject(hbm); DeleteDC(hdc); if (bmi->bmiHeader.biCompression == BI_BITFIELDS) { switch (*(VeUInt32 *)bmi->bmiColors) { case 0x00FF0000: mode->m_u32Format = VE_PIXELFORMAT_RGB888; break; case 0x000000FF: mode->m_u32Format = VE_PIXELFORMAT_BGR888; break; case 0xF800: mode->m_u32Format = VE_PIXELFORMAT_RGB565; break; case 0x7C00: mode->m_u32Format = VE_PIXELFORMAT_RGB555; break; } } else if (bmi->bmiHeader.biBitCount == 8) { mode->m_u32Format = VE_PIXELFORMAT_INDEX8; } else if (bmi->bmiHeader.biBitCount == 4) { mode->m_u32Format = VE_PIXELFORMAT_INDEX4LSB; } } else { if ((devmode.dmFields & DM_BITSPERPEL) == DM_BITSPERPEL) { switch (devmode.dmBitsPerPel) { case 32: mode->m_u32Format = VE_PIXELFORMAT_RGB888; break; case 24: mode->m_u32Format = VE_PIXELFORMAT_RGB24; break; case 16: mode->m_u32Format = VE_PIXELFORMAT_RGB565; break; case 15: mode->m_u32Format = VE_PIXELFORMAT_RGB555; break; case 8: mode->m_u32Format = VE_PIXELFORMAT_INDEX8; break; case 4: mode->m_u32Format = VE_PIXELFORMAT_INDEX4LSB; break; } } } return true; }
int DxVsyncSource::vsyncThread(void* context) { DxVsyncSource* me = reinterpret_cast<DxVsyncSource*>(context); SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); D3DKMT_OPENADAPTERFROMHDC openAdapterParams = {}; HMONITOR lastMonitor = nullptr; DEVMODEA monitorMode; monitorMode.dmSize = sizeof(monitorMode); while (SDL_AtomicGet(&me->m_Stopping) == 0) { D3DKMT_WAITFORVERTICALBLANKEVENT waitForVblankEventParams; NTSTATUS status; // If the monitor has changed from last time, open the new adapter HMONITOR currentMonitor = MonitorFromWindow(me->m_Window, MONITOR_DEFAULTTONEAREST); if (currentMonitor != lastMonitor) { MONITORINFOEXA monitorInfo = {}; monitorInfo.cbSize = sizeof(monitorInfo); if (!GetMonitorInfoA(currentMonitor, &monitorInfo)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "GetMonitorInfo() failed: %d", GetLastError()); SDL_Delay(10); continue; } if (!EnumDisplaySettingsA(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &monitorMode)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "EnumDisplaySettings() failed: %d", GetLastError()); SDL_Delay(10); continue; } SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Monitor changed: %s %d Hz", monitorInfo.szDevice, monitorMode.dmDisplayFrequency); if (openAdapterParams.hAdapter != 0) { D3DKMT_CLOSEADAPTER closeAdapterParams = {}; closeAdapterParams.hAdapter = openAdapterParams.hAdapter; me->m_D3DKMTCloseAdapter(&closeAdapterParams); } openAdapterParams.hDc = CreateDCA(nullptr, monitorInfo.szDevice, nullptr, nullptr); if (!openAdapterParams.hDc) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "CreateDC() failed: %d", GetLastError()); SDL_Delay(10); continue; } status = me->m_D3DKMTOpenAdapterFromHdc(&openAdapterParams); DeleteDC(openAdapterParams.hDc); if (status != STATUS_SUCCESS) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "D3DKMTOpenAdapterFromHdc() failed: %x", status); SDL_Delay(10); continue; } lastMonitor = currentMonitor; } waitForVblankEventParams.hAdapter = openAdapterParams.hAdapter; waitForVblankEventParams.hDevice = 0; waitForVblankEventParams.VidPnSourceId = openAdapterParams.VidPnSourceId; status = me->m_D3DKMTWaitForVerticalBlankEvent(&waitForVblankEventParams); if (status != STATUS_SUCCESS) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "D3DKMTWaitForVerticalBlankEvent() failed: %x", status); SDL_Delay(10); continue; } me->m_Pacer->vsyncCallback(1000 / me->m_DisplayFps); } if (openAdapterParams.hAdapter != 0) { D3DKMT_CLOSEADAPTER closeAdapterParams = {}; closeAdapterParams.hAdapter = openAdapterParams.hAdapter; me->m_D3DKMTCloseAdapter(&closeAdapterParams); } return 0; }