size_t modeBitsPerPixel(CGDisplayModeRef mode) { size_t bpp = 0; // no match // Compare encoding. CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode); if(CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { bpp = 32; } else if(CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { bpp = 16; } else if(CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { bpp = 8; } // Clean up memory. CFRelease(pixEnc); return bpp; }
// Returns depth of screen int wxDisplayDepth() { int theDepth = 0; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 if ( UMAGetSystemVersion() >= 0x1060 ) { CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay); CFStringRef encoding = CGDisplayModeCopyPixelEncoding(currentMode); if(CFStringCompare(encoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) theDepth = 32; else if(CFStringCompare(encoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) theDepth = 16; else if(CFStringCompare(encoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) theDepth = 8; else theDepth = 32; // some reasonable default CFRelease(encoding); CGDisplayModeRelease(currentMode); } else #endif { #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 theDepth = (int) CGDisplayBitsPerPixel(CGMainDisplayID()); #endif } return theDepth; }
void TorcQMLDisplayOSX::RefreshScreenModes(void) { if (!m_window) return; // release existing modes if (m_displayModes) CFRelease(m_displayModes); m_displayModes = NULL; m_modes.clear(); // retrieve new list of modes CGDirectDisplayID display = GetOSXDisplay(m_window->winId()); if (!display) return; CGDisplayModeRef current = CGDisplayCopyDisplayMode(display); m_displayModes = CGDisplayCopyAllDisplayModes(display, NULL); if (m_displayModes) { for (int i = 0; i < CFArrayGetCount(m_displayModes); ++i) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(m_displayModes, i); int modewidth = CGDisplayModeGetWidth(mode); int modeheight = CGDisplayModeGetHeight(mode); double moderate = CGDisplayModeGetRefreshRate(mode); // internal OSX displays have 'flexible' refresh rates, with a max of 60Hz - but report 0hz if (moderate < 0.1f) moderate = 60.0f; int32_t flags = CGDisplayModeGetIOFlags(mode); bool interlaced = flags & kDisplayModeInterlacedFlag; CFStringRef fmt = CGDisplayModeCopyPixelEncoding(mode); int depth = DepthFromStringRef(fmt); CFRelease(fmt); bool ignore = modewidth != screenPixelSize.width() || modeheight != screenPixelSize.height() || (flags & kDisplayModeNotGraphicsQualityFlag) || !(flags & kDisplayModeSafetyFlags) || depth < 32 || moderate < 10.0f || moderate > 121.0f; LOG(VB_GENERAL, LOG_INFO, QString("Mode %1x%2@%3Hz %4bpp%5%6%7") .arg(modewidth).arg(modeheight).arg(moderate).arg(depth) .arg(interlaced ? QString(" Interlaced") : "") .arg(ignore ? QString(" Ignoring") : "") .arg(mode == current ? QString(" CURRENT"): "")); if (!ignore) { if (mode == current) { setScreenInterlaced(interlaced); setScreenRefreshRate(moderate); } m_modes.append(TorcDisplayMode(modewidth, modeheight, depth, moderate, interlaced, i)); } } } }
static int display_mode_bits_per_pixel(CGDisplayModeRef display_mode) { CFStringRef pixel_encoding; int bits_per_pixel = 0; pixel_encoding = CGDisplayModeCopyPixelEncoding(display_mode); if (pixel_encoding) { if (CFEqual(pixel_encoding, CFSTR(kIO32BitFloatPixels))) bits_per_pixel = 128; else if (CFEqual(pixel_encoding, CFSTR(kIO16BitFloatPixels))) bits_per_pixel = 64; else if (CFEqual(pixel_encoding, CFSTR(kIO64BitDirectPixels))) bits_per_pixel = 64; else if (CFEqual(pixel_encoding, CFSTR(kIO30BitDirectPixels))) bits_per_pixel = 30; else if (CFEqual(pixel_encoding, CFSTR(IO32BitDirectPixels))) bits_per_pixel = 32; else if (CFEqual(pixel_encoding, CFSTR(IO16BitDirectPixels))) bits_per_pixel = 16; else if (CFEqual(pixel_encoding, CFSTR(IO8BitIndexedPixels))) bits_per_pixel = 8; else if (CFEqual(pixel_encoding, CFSTR(IO4BitIndexedPixels))) bits_per_pixel = 4; else if (CFEqual(pixel_encoding, CFSTR(IO2BitIndexedPixels))) bits_per_pixel = 2; else if (CFEqual(pixel_encoding, CFSTR(IO1BitIndexedPixels))) bits_per_pixel = 1; CFRelease(pixel_encoding); } return bits_per_pixel; }
// Search for available resolutions - TODO: Move to Common? static wxArrayString GetListOfResolutions() { wxArrayString retlist; retlist.Add(_("Auto")); #ifdef _WIN32 DWORD iModeNum = 0; DEVMODE dmi; ZeroMemory(&dmi, sizeof(dmi)); dmi.dmSize = sizeof(dmi); std::vector<std::string> resos; while (EnumDisplaySettings(nullptr, iModeNum++, &dmi) != 0) { char res[100]; sprintf(res, "%dx%d", dmi.dmPelsWidth, dmi.dmPelsHeight); std::string strRes(res); // Only add unique resolutions if (std::find(resos.begin(), resos.end(), strRes) == resos.end()) { resos.push_back(strRes); retlist.Add(StrToWxStr(res)); } ZeroMemory(&dmi, sizeof(dmi)); } #elif defined(HAVE_XRANDR) && HAVE_XRANDR std::vector<std::string> resos; main_frame->m_XRRConfig->AddResolutions(resos); for (auto res : resos) retlist.Add(StrToWxStr(res)); #elif defined(__APPLE__) CFArrayRef modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), nullptr); for (CFIndex i = 0; i < CFArrayGetCount(modes); i++) { std::stringstream res; CGDisplayModeRef mode; CFStringRef encoding; size_t w, h; bool is32; mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); w = CGDisplayModeGetWidth(mode); h = CGDisplayModeGetHeight(mode); encoding = CGDisplayModeCopyPixelEncoding(mode); is32 = CFEqual(encoding, CFSTR(IO32BitDirectPixels)); CFRelease(encoding); if (!is32) continue; if (CGDisplayModeGetIOFlags(mode) & kDisplayModeStretchedFlag) continue; res << w << "x" << h; retlist.Add(res.str()); } CFRelease(modes); #endif return retlist; }
Status GetVideoMode(int* xres, int* yres, int* bpp, int* freq) { #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay); #else CFDictionaryRef currentMode = CGDisplayCurrentMode(kCGDirectMainDisplay); #endif if(xres) *xres = (int)CGDisplayPixelsWide(kCGDirectMainDisplay); if(yres) *yres = (int)CGDisplayPixelsHigh(kCGDirectMainDisplay); if(bpp) { #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 // CGDisplayBitsPerPixel was deprecated in OS X 10.6 CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(currentMode); if (CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) *bpp = 32; else if (CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) *bpp = 16; else if (CFStringCompare(pixelEncoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) *bpp = 8; else // error *bpp = 0; // We're responsible for this CFRelease(pixelEncoding); #else CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(currentMode, kCGDisplayBitsPerPixel); CFNumberGetValue(num, kCFNumberIntType, bpp); #endif } if(freq) { #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 *freq = (int)CGDisplayModeGetRefreshRate(currentMode); #else CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(currentMode, kCGDisplayRefreshRate); CFNumberGetValue(num, kCFNumberIntType, freq); #endif } #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 // We're responsible for this CGDisplayModeRelease(currentMode); #endif return INFO::OK; }
uint32 OSXWindow::bitDepthFromDisplayMode(CGDisplayModeRef mode) { uint32 depth = 0; CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode); if(CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) depth = 32; else if(CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) depth = 16; else if(CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) depth = 8; return depth; }
static CFDictionaryRef create_mode_dict(CGDisplayModeRef display_mode, BOOL is_original) { CFDictionaryRef ret; SInt32 io_flags = CGDisplayModeGetIOFlags(display_mode); SInt64 width = CGDisplayModeGetWidth(display_mode); SInt64 height = CGDisplayModeGetHeight(display_mode); double refresh_rate = CGDisplayModeGetRefreshRate(display_mode); CFStringRef pixel_encoding = CGDisplayModeCopyPixelEncoding(display_mode); CFNumberRef cf_io_flags, cf_width, cf_height, cf_refresh; if (retina_enabled && is_original) { width *= 2; height *= 2; } io_flags &= kDisplayModeValidFlag | kDisplayModeSafeFlag | kDisplayModeInterlacedFlag | kDisplayModeStretchedFlag | kDisplayModeTelevisionFlag; cf_io_flags = CFNumberCreate(NULL, kCFNumberSInt32Type, &io_flags); cf_width = CFNumberCreate(NULL, kCFNumberSInt64Type, &width); cf_height = CFNumberCreate(NULL, kCFNumberSInt64Type, &height); cf_refresh = CFNumberCreate(NULL, kCFNumberDoubleType, &refresh_rate); { static const CFStringRef keys[] = { CFSTR("io_flags"), CFSTR("width"), CFSTR("height"), CFSTR("pixel_encoding"), CFSTR("refresh_rate"), }; const void* values[sizeof(keys) / sizeof(keys[0])] = { cf_io_flags, cf_width, cf_height, pixel_encoding, cf_refresh, }; ret = CFDictionaryCreate(NULL, (const void**)keys, (const void**)values, sizeof(keys) / sizeof(keys[0]), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } CFRelease(pixel_encoding); CFRelease(cf_io_flags); CFRelease(cf_width); CFRelease(cf_height); CFRelease(cf_refresh); return ret; }
/********************************************************************** * device_init * * Perform initializations needed upon creation of the first device. */ static void device_init(void) { CGDirectDisplayID mainDisplay = CGMainDisplayID(); CGSize size_mm = CGDisplayScreenSize(mainDisplay); CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay); check_retina_status(); /* Initialize device caps */ horz_size = size_mm.width; vert_size = size_mm.height; bits_per_pixel = 32; if (mode) { CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); horz_res = CGDisplayModeGetWidth(mode); vert_res = CGDisplayModeGetHeight(mode); if (pixelEncoding) { if (CFEqual(pixelEncoding, CFSTR(IO32BitDirectPixels))) bits_per_pixel = 32; else if (CFEqual(pixelEncoding, CFSTR(IO16BitDirectPixels))) bits_per_pixel = 16; else if (CFEqual(pixelEncoding, CFSTR(IO8BitIndexedPixels))) bits_per_pixel = 8; CFRelease(pixelEncoding); } CGDisplayModeRelease(mode); } else { horz_res = CGDisplayPixelsWide(mainDisplay); vert_res = CGDisplayPixelsHigh(mainDisplay); } if (retina_on) { horz_res *= 2; vert_res *= 2; } compute_desktop_rect(); desktop_horz_res = desktop_rect.size.width; desktop_vert_res = desktop_rect.size.height; device_data_valid = TRUE; }
static BOOL display_mode_matches_descriptor(CGDisplayModeRef mode, const struct display_mode_descriptor* desc) { DWORD mode_io_flags; double mode_refresh; CFStringRef mode_pixel_encoding; if (!desc) return FALSE; if (CGDisplayModeGetWidth(mode) != desc->width || CGDisplayModeGetHeight(mode) != desc->height) return FALSE; mode_io_flags = CGDisplayModeGetIOFlags(mode); if ((desc->io_flags ^ mode_io_flags) & (kDisplayModeValidFlag | kDisplayModeSafeFlag | kDisplayModeStretchedFlag | kDisplayModeInterlacedFlag | kDisplayModeTelevisionFlag)) return FALSE; mode_refresh = CGDisplayModeGetRefreshRate(mode); if (!mode_refresh) mode_refresh = 60; if (fabs(desc->refresh - mode_refresh) > 0.1) return FALSE; #if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 if (CGDisplayModeGetPixelWidth != NULL && CGDisplayModeGetPixelHeight != NULL) { if (CGDisplayModeGetPixelWidth(mode) != desc->pixel_width || CGDisplayModeGetPixelHeight(mode) != desc->pixel_height) return FALSE; } else #endif if (CGDisplayModeGetWidth(mode) != desc->pixel_width || CGDisplayModeGetHeight(mode) != desc->pixel_height) return FALSE; mode_pixel_encoding = CGDisplayModeCopyPixelEncoding(mode); if (!CFEqual(mode_pixel_encoding, desc->pixel_encoding)) { CFRelease(mode_pixel_encoding); return FALSE; } CFRelease(mode_pixel_encoding); return TRUE; }
// Returns depth of screen int wxDisplayDepth() { int theDepth = 0; CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay); CFStringRef encoding = CGDisplayModeCopyPixelEncoding(currentMode); if(CFStringCompare(encoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) theDepth = 32; else if(CFStringCompare(encoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) theDepth = 16; else if(CFStringCompare(encoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) theDepth = 8; else theDepth = 32; // some reasonable default CFRelease(encoding); CGDisplayModeRelease(currentMode); return theDepth; }
size_t bitDepth(CGDisplayModeRef mode) { size_t depth = 0; CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); // my numerical representation for kIO16BitFloatPixels and kIO32bitFloatPixels // are made up and possibly non-sensical if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO32BitFloatPixels), kCFCompareCaseInsensitive)) { depth = 96; } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO64BitDirectPixels), kCFCompareCaseInsensitive)) { depth = 64; } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO16BitFloatPixels), kCFCompareCaseInsensitive)) { depth = 48; } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive)) { depth = 32; } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive)) { depth = 30; } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive)) { depth = 16; } else if (kCFCompareEqualTo == CFStringCompare(pixelEncoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive)) { depth = 8; } CFRelease(pixelEncoding); return depth; }
/*********************************************************************** * copy_display_modes * * Wrapper around CGDisplayCopyAllDisplayModes() to include additional * modes on Retina-capable systems, but filter those which would confuse * Windows apps (basically duplicates at different DPIs). * * For example, some Retina Macs support a 1920x1200 mode, but it's not * returned from CGDisplayCopyAllDisplayModes() without special options. * This is especially bad if that's the user's default mode, since then * no "available" mode matches the initial settings. */ static CFArrayRef copy_display_modes(CGDirectDisplayID display) { CFArrayRef modes = NULL; #if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 if (&kCGDisplayShowDuplicateLowResolutionModes != NULL && CGDisplayModeGetPixelWidth != NULL && CGDisplayModeGetPixelHeight != NULL) { CFDictionaryRef options; struct display_mode_descriptor* desc; CFMutableDictionaryRef modes_by_size; CFIndex i, count; CGDisplayModeRef* mode_array; options = CFDictionaryCreate(NULL, (const void**)&kCGDisplayShowDuplicateLowResolutionModes, (const void**)&kCFBooleanTrue, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); modes = CGDisplayCopyAllDisplayModes(display, options); if (options) CFRelease(options); if (!modes) return NULL; desc = create_original_display_mode_descriptor(display); modes_by_size = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); count = CFArrayGetCount(modes); for (i = 0; i < count; i++) { BOOL better = TRUE; CGDisplayModeRef new_mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); BOOL new_is_original = display_mode_matches_descriptor(new_mode, desc); CFDictionaryRef key = create_mode_dict(new_mode); /* If a given mode is the user's default, then always list it in preference to any similar modes that may exist. */ if (new_is_original) better = TRUE; else { CFStringRef pixel_encoding = CGDisplayModeCopyPixelEncoding(new_mode); CGDisplayModeRef old_mode; if (pixel_encoding) { BOOL bpp30 = CFEqual(pixel_encoding, CFSTR(kIO30BitDirectPixels)); CFRelease(pixel_encoding); if (bpp30) { /* This is an odd pixel encoding. It seems it's only returned when using kCGDisplayShowDuplicateLowResolutionModes. It's 32bpp in terms of the actual raster layout, but it's 10 bits per component. I think that no Windows program is likely to need it and they will probably be confused by it. Skip it. */ CFRelease(key); continue; } } old_mode = (CGDisplayModeRef)CFDictionaryGetValue(modes_by_size, key); if (old_mode) { BOOL old_is_original = display_mode_matches_descriptor(old_mode, desc); if (old_is_original) better = FALSE; else { /* Otherwise, prefer a mode whose pixel size equals its point size over one which is scaled. */ size_t width_points = CGDisplayModeGetWidth(new_mode); size_t height_points = CGDisplayModeGetHeight(new_mode); size_t new_width_pixels = CGDisplayModeGetPixelWidth(new_mode); size_t new_height_pixels = CGDisplayModeGetPixelHeight(new_mode); size_t old_width_pixels = CGDisplayModeGetPixelWidth(old_mode); size_t old_height_pixels = CGDisplayModeGetPixelHeight(old_mode); BOOL new_size_same = (new_width_pixels == width_points && new_height_pixels == height_points); BOOL old_size_same = (old_width_pixels == width_points && old_height_pixels == height_points); if (new_size_same && !old_size_same) better = TRUE; else if (!new_size_same && old_size_same) better = FALSE; else { /* Otherwise, prefer the mode with the smaller pixel size. */ if (old_width_pixels < new_width_pixels || old_height_pixels < new_height_pixels) better = FALSE; } } } } if (better) CFDictionarySetValue(modes_by_size, key, new_mode); CFRelease(key); } free_display_mode_descriptor(desc); CFRelease(modes); count = CFDictionaryGetCount(modes_by_size); mode_array = HeapAlloc(GetProcessHeap(), 0, count * sizeof(mode_array[0])); CFDictionaryGetKeysAndValues(modes_by_size, NULL, (const void **)mode_array); modes = CFArrayCreate(NULL, (const void **)mode_array, count, &kCFTypeArrayCallBacks); HeapFree(GetProcessHeap(), 0, mode_array); CFRelease(modes_by_size); } else #endif modes = CGDisplayCopyAllDisplayModes(display, NULL); return modes; }
/* * xprAddScreen * Init the framebuffer and record pixmap parameters for the screen. */ static Bool xprAddScreen(int index, ScreenPtr pScreen) { DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); int depth = darwinDesiredDepth; DEBUG_LOG("index=%d depth=%d\n", index, depth); if(depth == -1) { #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 depth = CGDisplaySamplesPerPixel(kCGDirectMainDisplay) * CGDisplayBitsPerSample(kCGDirectMainDisplay); #else CGDisplayModeRef modeRef; CFStringRef encStrRef; modeRef = CGDisplayCopyDisplayMode(kCGDirectMainDisplay); if(!modeRef) goto have_depth; encStrRef = CGDisplayModeCopyPixelEncoding(modeRef); CFRelease(modeRef); if(!encStrRef) goto have_depth; if(CFStringCompare(encStrRef, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { depth = 24; } else if(CFStringCompare(encStrRef, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { depth = 15; } else if(CFStringCompare(encStrRef, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { depth = 8; } CFRelease(encStrRef); #endif } have_depth: switch(depth) { case 8: // pseudo-working dfb->visuals = PseudoColorMask; dfb->preferredCVC = PseudoColor; dfb->depth = 8; dfb->bitsPerRGB = 8; dfb->bitsPerPixel = 8; dfb->redMask = 0; dfb->greenMask = 0; dfb->blueMask = 0; break; case 15: dfb->visuals = TrueColorMask; //LARGE_VISUALS; dfb->preferredCVC = TrueColor; dfb->depth = 15; dfb->bitsPerRGB = 5; dfb->bitsPerPixel = 16; dfb->redMask = RM_ARGB(0,5,5,5); dfb->greenMask = GM_ARGB(0,5,5,5); dfb->blueMask = BM_ARGB(0,5,5,5); break; // case 24: default: if(depth != 24) ErrorF("Unsupported color depth requested. Defaulting to 24bit. (depth=%d darwinDesiredDepth=%d)\n", depth, darwinDesiredDepth); dfb->visuals = TrueColorMask; //LARGE_VISUALS; dfb->preferredCVC = TrueColor; dfb->depth = 24; dfb->bitsPerRGB = 8; dfb->bitsPerPixel = 32; dfb->redMask = RM_ARGB(0,8,8,8); dfb->greenMask = GM_ARGB(0,8,8,8); dfb->blueMask = BM_ARGB(0,8,8,8); break; } if (noPseudoramiXExtension) { CGDirectDisplayID dpy; CGRect frame; ErrorF("Warning: noPseudoramiXExtension!\n"); dpy = displayAtIndex(index); QuartzCopyDisplayIDs(pScreen, 1, &dpy); frame = displayScreenBounds(dpy); dfb->x = frame.origin.x; dfb->y = frame.origin.y; dfb->width = frame.size.width; dfb->height = frame.size.height; } else { xprAddPseudoramiXScreens(&dfb->x, &dfb->y, &dfb->width, &dfb->height, pScreen); } /* Passing zero width (pitch) makes miCreateScreenResources set the screen pixmap to the framebuffer pointer, i.e. NULL. The generic rootless code takes care of making this work. */ dfb->pitch = 0; dfb->framebuffer = NULL; DRIScreenInit(pScreen); return TRUE; }
bool DisplayManagerOSX::initialize() { int totalModes = 0; m_displays.clear(); for (int i = 0; i < m_osxDisplayModes.size(); i++) { if (m_osxDisplayModes[i]) CFRelease(m_osxDisplayModes[i]); } m_osxDisplayModes.clear(); CGError err = CGGetActiveDisplayList(MAX_DISPLAYS, m_osxDisplays, &m_osxnumDisplays); if (err) { m_osxnumDisplays = 0; QLOG_ERROR() << "CGGetActiveDisplayList returned failure:" << err; return false; } for (int displayid = 0; displayid < m_osxnumDisplays; displayid++) { // add the display to the list DMDisplayPtr display = DMDisplayPtr(new DMDisplay); display->m_id = displayid; display->m_name = QString("Display %1").arg(displayid); m_displays[display->m_id] = display; m_osxDisplayModes[displayid] = CGDisplayCopyAllDisplayModes(m_osxDisplays[displayid], nullptr); if (!m_osxDisplayModes[displayid]) continue; int numModes = (int)CFArrayGetCount(m_osxDisplayModes[displayid]); for (int modeid = 0; modeid < numModes; modeid++) { totalModes++; // add the videomode to the display DMVideoModePtr mode = DMVideoModePtr(new DMVideoMode); mode->m_id = modeid; display->m_videoModes[modeid] = mode; // grab videomode info CGDisplayModeRef displayMode = (CGDisplayModeRef)CFArrayGetValueAtIndex(m_osxDisplayModes[displayid], modeid); mode->m_height = CGDisplayModeGetHeight(displayMode); mode->m_width = CGDisplayModeGetWidth(displayMode); mode->m_refreshRate = CGDisplayModeGetRefreshRate(displayMode); CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(displayMode); if (CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) mode->m_bitsPerPixel = 32; else if (CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) mode->m_bitsPerPixel = 16; else if (CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) mode->m_bitsPerPixel = 8; CFRelease(pixEnc); mode->m_interlaced = (CGDisplayModeGetIOFlags(displayMode) & kDisplayModeInterlacedFlag) > 0; if (mode->m_refreshRate == 0) mode->m_refreshRate = 60; } } if (totalModes == 0) return false; else return DisplayManager::initialize(); }
/********************************************************************** * device_init * * Perform initializations needed upon creation of the first device. */ static void device_init(void) { CGDirectDisplayID mainDisplay = CGMainDisplayID(); CGSize size_mm = CGDisplayScreenSize(mainDisplay); CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay); CGDirectPaletteRef palette; /* Initialize device caps */ log_pixels_x = log_pixels_y = get_dpi(); if (!log_pixels_x) { size_t width = CGDisplayPixelsWide(mainDisplay); size_t height = CGDisplayPixelsHigh(mainDisplay); log_pixels_x = MulDiv(width, 254, size_mm.width * 10); log_pixels_y = MulDiv(height, 254, size_mm.height * 10); } horz_size = size_mm.width; vert_size = size_mm.height; bits_per_pixel = 32; if (mode) { CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); horz_res = CGDisplayModeGetWidth(mode); vert_res = CGDisplayModeGetHeight(mode); if (pixelEncoding) { if (CFEqual(pixelEncoding, CFSTR(IO32BitDirectPixels))) bits_per_pixel = 32; else if (CFEqual(pixelEncoding, CFSTR(IO16BitDirectPixels))) bits_per_pixel = 16; else if (CFEqual(pixelEncoding, CFSTR(IO8BitIndexedPixels))) bits_per_pixel = 8; CFRelease(pixelEncoding); } CGDisplayModeRelease(mode); } else { horz_res = CGDisplayPixelsWide(mainDisplay); vert_res = CGDisplayPixelsHigh(mainDisplay); } macdrv_get_desktop_rect(); desktop_horz_res = desktop_rect.size.width; desktop_vert_res = desktop_rect.size.height; palette = CGPaletteCreateWithDisplay(mainDisplay); if (palette) { palette_size = CGPaletteGetNumberOfSamples(palette); CGPaletteRelease(palette); } else palette_size = 0; device_data_valid = TRUE; }
bool macosxSetScreenResolution(QSize resolution, QPoint screenPoint) { CGDirectDisplayID display = displayAtPoint(screenPoint); if (display == kCGNullDirectDisplay) { return false; } #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 if (CGDisplayCopyAllDisplayModes != NULL) { bool ok = false; CGDisplayModeRef currentMainDisplayMode = CGDisplayCopyDisplayMode(display); CFStringRef currentPixelEncoding = CGDisplayModeCopyPixelEncoding(currentMainDisplayMode); CFArrayRef displayModes = CGDisplayCopyAllDisplayModes(display, NULL); for (CFIndex i = 0, c = CFArrayGetCount(displayModes); i < c; i++) { bool isEqual = false; CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(displayModes, i); CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode); if (CFStringCompare(pixelEncoding, currentPixelEncoding, 0) == kCFCompareEqualTo && CGDisplayModeGetWidth(mode) == (size_t)resolution.width() && CGDisplayModeGetHeight(mode) == (size_t)resolution.height()) { isEqual = true; } CFRelease(pixelEncoding); if (isEqual) { CGDisplaySetDisplayMode(display, mode, NULL); ok = true; break; } } CFRelease(currentPixelEncoding); CFRelease(displayModes); return ok; } else #endif { CFDictionaryRef currentMainDisplayMode = CGDisplayCurrentMode(display); int bpp; dictget(currentMainDisplayMode, Int, kCGDisplayBitsPerPixel, &bpp); boolean_t exactMatch = false; CFDictionaryRef bestMode = CGDisplayBestModeForParameters(display, bpp, resolution.width(), resolution.height(), &exactMatch); if (bestMode != NULL) { if (!exactMatch) { qWarning("No optimal display mode for requested parameters."); } CGDisplaySwitchToMode(display, bestMode); return true; } else { qWarning("Bad resolution change: Invalid display."); return false; } } }
bool macosxAppendAvailableScreenResolutions(QList<QSize> &resolutions, QSize minSize, QPoint screenPoint) { CGDirectDisplayID display = displayAtPoint(screenPoint); if (display == kCGNullDirectDisplay) { return false; } #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 bool modern = (CGDisplayCopyAllDisplayModes != NULL); // where 'modern' means >= 10.6 #endif CFArrayRef displayModes; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 if (modern) { displayModes = CGDisplayCopyAllDisplayModes(display, NULL); } else #endif { displayModes = CGDisplayAvailableModes(display); } #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 CFStringRef currentPixelEncoding = NULL; #endif double currentRefreshRate; int curBPP, curBPS, curSPP; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 if (modern) { CGDisplayModeRef currentDisplayMode = CGDisplayCopyDisplayMode(display); currentRefreshRate = CGDisplayModeGetRefreshRate(currentDisplayMode); currentPixelEncoding = CGDisplayModeCopyPixelEncoding(currentDisplayMode); CFRelease(currentDisplayMode); } else #endif { CFDictionaryRef currentDisplayMode = CGDisplayCurrentMode(display); dictget(currentDisplayMode, Double, kCGDisplayRefreshRate, ¤tRefreshRate); dictget(currentDisplayMode, Int, kCGDisplayBitsPerPixel, &curBPP); dictget(currentDisplayMode, Int, kCGDisplayBitsPerSample, &curBPS); dictget(currentDisplayMode, Int, kCGDisplaySamplesPerPixel, &curSPP); } for (CFIndex j = 0, c = CFArrayGetCount(displayModes); j < c; j++) { int width, height; double refreshRate; bool pixelEncodingsEqual; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 if (modern) { CGDisplayModeRef displayMode = (CGDisplayModeRef)CFArrayGetValueAtIndex(displayModes, j); width = (int)CGDisplayModeGetWidth(displayMode); height = (int)CGDisplayModeGetHeight(displayMode); refreshRate = CGDisplayModeGetRefreshRate(displayMode); CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(displayMode); pixelEncodingsEqual = (CFStringCompare(pixelEncoding, currentPixelEncoding, 0) == kCFCompareEqualTo); CFRelease(pixelEncoding); } else #endif { CFDictionaryRef displayMode = (CFDictionaryRef)CFArrayGetValueAtIndex(displayModes, j); dictget(displayMode, Int, kCGDisplayWidth, &width); dictget(displayMode, Int, kCGDisplayHeight, &height); dictget(displayMode, Double, kCGDisplayRefreshRate, &refreshRate); int bpp, bps, spp; dictget(displayMode, Int, kCGDisplayBitsPerPixel, &bpp); dictget(displayMode, Int, kCGDisplayBitsPerSample, &bps); dictget(displayMode, Int, kCGDisplaySamplesPerPixel, &spp); pixelEncodingsEqual = (bpp == curBPP && bps == curBPS && spp == curSPP); } QSize res(width, height); if (!resolutions.contains(res) && width >= minSize.width() && height >= minSize.height() && refreshRate == currentRefreshRate && pixelEncodingsEqual) { resolutions += res; } } #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 if (modern) { CFRelease(currentPixelEncoding); CFRelease(displayModes); } #endif return true; }
static BOOL write_display_settings(HKEY parent_hkey, CGDirectDisplayID displayID) { BOOL ret = FALSE; char display_key_name[19]; HKEY display_hkey; CGDisplayModeRef display_mode; DWORD val; CFStringRef pixel_encoding; size_t len; WCHAR* buf = NULL; snprintf(display_key_name, sizeof(display_key_name), "Display 0x%08x", CGDisplayUnitNumber(displayID)); /* @@ Wine registry key: HKLM\Software\Wine\Mac Driver\Initial Display Mode\Display 0xnnnnnnnn */ if (RegCreateKeyExA(parent_hkey, display_key_name, 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &display_hkey, NULL)) return FALSE; display_mode = CGDisplayCopyDisplayMode(displayID); if (!display_mode) goto fail; val = CGDisplayModeGetWidth(display_mode); if (RegSetValueExA(display_hkey, "Width", 0, REG_DWORD, (const BYTE*)&val, sizeof(val))) goto fail; val = CGDisplayModeGetHeight(display_mode); if (RegSetValueExA(display_hkey, "Height", 0, REG_DWORD, (const BYTE*)&val, sizeof(val))) goto fail; val = CGDisplayModeGetRefreshRate(display_mode) * 100; if (RegSetValueExA(display_hkey, "RefreshRateTimes100", 0, REG_DWORD, (const BYTE*)&val, sizeof(val))) goto fail; val = CGDisplayModeGetIOFlags(display_mode); if (RegSetValueExA(display_hkey, "IOFlags", 0, REG_DWORD, (const BYTE*)&val, sizeof(val))) goto fail; #if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 if (CGDisplayModeGetPixelWidth != NULL && CGDisplayModeGetPixelHeight != NULL) { val = CGDisplayModeGetPixelWidth(display_mode); if (RegSetValueExA(display_hkey, "PixelWidth", 0, REG_DWORD, (const BYTE*)&val, sizeof(val))) goto fail; val = CGDisplayModeGetPixelHeight(display_mode); if (RegSetValueExA(display_hkey, "PixelHeight", 0, REG_DWORD, (const BYTE*)&val, sizeof(val))) goto fail; } #endif pixel_encoding = CGDisplayModeCopyPixelEncoding(display_mode); len = CFStringGetLength(pixel_encoding); buf = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); CFStringGetCharacters(pixel_encoding, CFRangeMake(0, len), (UniChar*)buf); buf[len] = 0; CFRelease(pixel_encoding); if (RegSetValueExW(display_hkey, pixelencodingW, 0, REG_SZ, (const BYTE*)buf, (len + 1) * sizeof(WCHAR))) goto fail; ret = TRUE; fail: HeapFree(GetProcessHeap(), 0, buf); if (display_mode) CGDisplayModeRelease(display_mode); RegCloseKey(display_hkey); if (!ret) RegDeleteKeyA(parent_hkey, display_key_name); return ret; }
static Bool QuartzRandREnumerateModes(ScreenPtr pScreen, QuartzModeCallback callback, void *data) { Bool retval = FALSE; QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); /* Just an 800x600 fallback if we have no attached heads */ if (pQuartzScreen->displayIDs) { CGDisplayModeRef curModeRef, modeRef; CFStringRef curPixelEnc, pixelEnc; CFComparisonResult pixelEncEqual; CFArrayRef modes; QuartzModeInfo modeInfo; int i; CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0]; curModeRef = CGDisplayCopyDisplayMode(screenId); if (!curModeRef) return FALSE; curPixelEnc = CGDisplayModeCopyPixelEncoding(curModeRef); CGDisplayModeRelease(curModeRef); modes = CGDisplayCopyAllDisplayModes(screenId, NULL); if (!modes) { CFRelease(curPixelEnc); return FALSE; } for (i = 0; i < CFArrayGetCount(modes); i++) { int cb; modeRef = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); /* Skip modes that are not usable on the current display or have a different pixel encoding than the current mode. */ if ((CGDisplayModeGetIOFlags(modeRef) & kDisplayModeUsableFlags) != kDisplayModeUsableFlags) continue; pixelEnc = CGDisplayModeCopyPixelEncoding(modeRef); pixelEncEqual = CFStringCompare(pixelEnc, curPixelEnc, 0); CFRelease(pixelEnc); if (pixelEncEqual != kCFCompareEqualTo) continue; QuartzRandRGetModeInfo(modeRef, &modeInfo); modeInfo.ref = modeRef; cb = callback(pScreen, &modeInfo, data); if (cb == CALLBACK_CONTINUE) { retval = TRUE; } else if (cb == CALLBACK_SUCCESS) { CFRelease(modes); CFRelease(curPixelEnc); return TRUE; } else if (cb == CALLBACK_ERROR) { CFRelease(modes); CFRelease(curPixelEnc); return FALSE; } } CFRelease(modes); CFRelease(curPixelEnc); } switch (callback(pScreen, &pQuartzScreen->rootlessMode, data)) { case CALLBACK_SUCCESS: return TRUE; case CALLBACK_ERROR: return FALSE; case CALLBACK_CONTINUE: retval = TRUE; default: break; } switch (callback(pScreen, &pQuartzScreen->fullscreenMode, data)) { case CALLBACK_SUCCESS: return TRUE; case CALLBACK_ERROR: return FALSE; case CALLBACK_CONTINUE: retval = TRUE; default: break; } return retval; }
double UIDisplay::GetRefreshRatePriv(void) { CocoaAutoReleasePool pool; double rate = 0.0f; CGDirectDisplayID disp = GetOSXDisplay(m_widget->winId()); if (!disp) { LOG(VB_GENERAL, LOG_WARNING, "Failed to get OS X display"); return rate; } CGDisplayModeRef current = CGDisplayCopyDisplayMode(disp); if (current) { rate = CGDisplayModeGetRefreshRate(current); if (qFuzzyCompare((double)1.0f, rate + 1.0f)) m_variableRefreshRate = true; } else { LOG(VB_GENERAL, LOG_WARNING, "Failed to get current display mode"); return rate; } if (m_variableRefreshRate) { CGDisplayModeRelease(current); return rate; } // if we've run this already, release the modes m_modes.clear(); m_originalModeIndex = -1; if (gDisplayModes) CFRelease(gDisplayModes); gDisplayModes = CGDisplayCopyAllDisplayModes(disp, NULL); if (gDisplayModes) { for (int i = 0; i < CFArrayGetCount(gDisplayModes); ++i) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(gDisplayModes, i); int modewidth = CGDisplayModeGetWidth(mode); int modeheight = CGDisplayModeGetHeight(mode); double moderate = CGDisplayModeGetRefreshRate(mode); int32_t flags = CGDisplayModeGetIOFlags(mode); bool interlaced = flags & kDisplayModeInterlacedFlag; CFStringRef fmt = CGDisplayModeCopyPixelEncoding(mode); int depth = DepthFromStringRef(fmt); CFRelease(fmt); bool ignore = modewidth != m_pixelSize.width() || modeheight != m_pixelSize.height() || (flags & kDisplayModeNotGraphicsQualityFlag) || !(flags & kDisplayModeSafetyFlags) || depth < 32 || moderate < 10.0f || moderate > 121.0f; LOG(VB_GUI, LOG_INFO, QString("Mode %1x%2@%3Hz %4bpp%5%6%7") .arg(modewidth).arg(modeheight).arg(moderate).arg(depth) .arg(interlaced ? QString(" Interlaced") : "") .arg(ignore ? QString(" Ignoring") : "") .arg(mode == current ? QString(" CURRENT"): "")); if (!ignore) { m_modes.append(UIDisplayMode(modewidth, modeheight, depth, moderate, interlaced, i)); if (mode == current) m_originalModeIndex = m_modes.size() - 1; } } } CGDisplayModeRelease(current); return rate; }
MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect) { #if defined(IS_MACOSX) size_t bytewidth; uint8_t bitsPerPixel, bytesPerPixel; uint8_t *buffer; CGDirectDisplayID displayID = CGMainDisplayID(); //Replacement for CGDisplayBitsPerPixel. CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayID); size_t depth = 0; CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode); if(CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) depth = 32; else if(CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) depth = 16; else if(CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) depth = 8; bitsPerPixel = (uint8_t) depth; bytesPerPixel = bitsPerPixel / 8; /* Align width to padding. */ bytewidth = ADD_PADDING(rect.size.width * bytesPerPixel); /* Convert Quartz point to postscript point. */ rect.origin.y = CGDisplayPixelsHigh(displayID) - rect.origin.y - rect.size.height; CGImageRef image = CGDisplayCreateImageForRect(displayID, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)); // Request access to the raw pixel data via the image's DataProvider. CGDataProviderRef provider = CGImageGetDataProvider(image); CFDataRef data = CGDataProviderCopyData(provider); size_t width, height; width = CGImageGetWidth(image); height = CGImageGetHeight(image); size_t bpp = CGImageGetBitsPerPixel(image) / 8; uint8 *pixels = malloc(width * height * bpp); memcpy(pixels, CFDataGetBytePtr(data), width * height * bpp); CFRelease(data); CGImageRelease(image); return createMMBitmap(pixels, rect.size.width, rect.size.height, bytewidth, bitsPerPixel, bytesPerPixel); #elif defined(USE_X11) MMBitmapRef bitmap; Display *display = XOpenDisplay(NULL); XImage *image = XGetImage(display, XDefaultRootWindow(display), (int)rect.origin.x, (int)rect.origin.y, (unsigned int)rect.size.width, (unsigned int)rect.size.height, AllPlanes, ZPixmap); XCloseDisplay(display); if (image == NULL) return NULL; bitmap = createMMBitmap((uint8_t *)image->data, rect.size.width, rect.size.height, (size_t)image->bytes_per_line, (uint8_t)image->bits_per_pixel, (uint8_t)image->bits_per_pixel / 8); image->data = NULL; /* Steal ownership of bitmap data so we don't have to * copy it. */ XDestroyImage(image); return bitmap; #elif defined(IS_WINDOWS) MMBitmapRef bitmap; void *data; HDC screen = NULL, screenMem = NULL; HBITMAP dib; BITMAPINFO bi; /* Initialize bitmap info. */ bi.bmiHeader.biSize = sizeof(bi.bmiHeader); bi.bmiHeader.biWidth = (long)rect.size.width; bi.bmiHeader.biHeight = -(long)rect.size.height; /* Non-cartesian, please */ bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = (DWORD)(4 * rect.size.width * rect.size.height); bi.bmiHeader.biXPelsPerMeter = 0; bi.bmiHeader.biYPelsPerMeter = 0; bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; screen = GetDC(NULL); /* Get entire screen */ if (screen == NULL) return NULL; /* Get screen data in display device context. */ dib = CreateDIBSection(screen, &bi, DIB_RGB_COLORS, &data, NULL, 0); /* Copy the data into a bitmap struct. */ if ((screenMem = CreateCompatibleDC(screen)) == NULL || SelectObject(screenMem, dib) == NULL || !BitBlt(screenMem, (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height, screen, 0, 0, SRCCOPY)) { /* Error copying data. */ ReleaseDC(NULL, screen); DeleteObject(dib); if (screenMem != NULL) DeleteDC(screenMem); return NULL; } bitmap = createMMBitmap(NULL, rect.size.width, rect.size.height, 4 * rect.size.width, (uint8_t)bi.bmiHeader.biBitCount, 4); /* Copy the data to our pixel buffer. */ if (bitmap != NULL) { bitmap->imageBuffer = malloc(bitmap->bytewidth * bitmap->height); memcpy(bitmap->imageBuffer, data, bitmap->bytewidth * bitmap->height); } ReleaseDC(NULL, screen); DeleteObject(dib); DeleteDC(screenMem); return bitmap; #endif }