21 #import <Carbon/Carbon.h>
24 #define GetModeWidth(mode) GetDictionaryLong((mode), kCGDisplayWidth)
25 #define GetModeHeight(mode) GetDictionaryLong((mode), kCGDisplayHeight)
26 #define GetModeRefreshRate(mode) GetDictionaryLong((mode), kCGDisplayRefreshRate)
27 #define GetModeBitsPerPixel(mode) GetDictionaryLong((mode), kCGDisplayBitsPerPixel)
28 #define GetModeSafeForHardware(mode) GetDictionaryBoolean((mode), kCGDisplayModeIsSafeForHardware)
29 #define GetModeStretched(mode) GetDictionaryBoolean((mode), kCGDisplayModeIsStretched)
30 #define MAX_DISPLAYS 32
32 Boolean GetDictionaryBoolean(CFDictionaryRef theDict,
const void* key) {
34 Boolean value =
false;
36 boolRef = (CFBooleanRef)CFDictionaryGetValue(theDict, key);
37 if (boolRef !=
nullptr)
38 value = CFBooleanGetValue(boolRef);
42 long GetDictionaryLong(CFDictionaryRef theDict,
const void* key) {
46 numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key);
47 if (numRef !=
nullptr)
48 CFNumberGetValue(numRef, kCFNumberLongType, &value);
52 static CFComparisonResult CompareModes (
const void *val1,
const void *val2,
void *context) {
54 #pragma unused(context)
55 CFDictionaryRef thisMode = (CFDictionaryRef)val1;
56 CFDictionaryRef otherMode = (CFDictionaryRef)val2;
58 long width = GetModeWidth(thisMode);
59 long otherWidth = GetModeWidth(otherMode);
60 long height = GetModeHeight(thisMode);
61 long otherHeight = GetModeHeight(otherMode);
64 if (width * height < otherWidth * otherHeight) {
65 return kCFCompareLessThan;
66 }
else if (width * height > otherWidth * otherHeight) {
67 return kCFCompareGreaterThan;
71 long bitsPerPixel = GetModeBitsPerPixel(thisMode);
72 long otherBitsPerPixel = GetModeBitsPerPixel(otherMode);
73 if (bitsPerPixel < otherBitsPerPixel) {
74 return kCFCompareLessThan;
75 }
else if (bitsPerPixel > otherBitsPerPixel) {
76 return kCFCompareGreaterThan;
80 long refreshRate = GetModeRefreshRate(thisMode);
81 long otherRefreshRate = GetModeRefreshRate(otherMode);
82 if (refreshRate < otherRefreshRate) {
83 return kCFCompareLessThan;
84 }
else if (refreshRate > otherRefreshRate) {
85 return kCFCompareGreaterThan;
88 return kCFCompareEqualTo;
91 CFArrayRef GSCGDisplayAvailableModesUsefulForOpenGL(CGDirectDisplayID display) {
93 CFArrayRef availableModes = CGDisplayAvailableModes(display);
94 unsigned int numberOfAvailableModes = CFArrayGetCount(availableModes);
97 CFMutableArrayRef usefulModes = CFArrayCreateMutable(kCFAllocatorDefault, numberOfAvailableModes,
nullptr);
100 long currentModeBitsPerPixel = GetModeBitsPerPixel(CGDisplayCurrentMode(display));
103 for (i= 0; i<numberOfAvailableModes; ++i) {
105 CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, i);
110 long bitsPerPixel = GetModeBitsPerPixel(mode);
111 Boolean safeForHardware = GetModeSafeForHardware(mode);
112 Boolean stretched = GetModeStretched(mode);
114 if ((bitsPerPixel != currentModeBitsPerPixel) || (!safeForHardware) || (stretched)) {
118 long width = GetModeWidth(mode);
119 long height = GetModeHeight(mode);
120 long refreshRate = GetModeRefreshRate(mode);
121 Boolean replaced =
false;
122 Boolean skipped =
false;
127 unsigned int currentNumberOfUsefulModes = CFArrayGetCount(usefulModes);
128 for (j = 0; j < currentNumberOfUsefulModes; ++j) {
129 CFDictionaryRef otherMode = (CFDictionaryRef)CFArrayGetValueAtIndex(usefulModes, j);
130 long otherWidth = GetModeWidth(otherMode);
131 long otherHeight = GetModeHeight(otherMode);
132 if ((otherWidth == width) && (otherHeight == height)) {
133 long otherRefreshRate = GetModeRefreshRate(otherMode);
134 if (otherRefreshRate < refreshRate) {
136 const void* value = mode;
137 CFArrayReplaceValues(usefulModes, CFRangeMake(j ,1), &value, 1);
141 else if (otherRefreshRate > refreshRate) {
148 if (!replaced && !skipped) {
149 CFArrayAppendValue(usefulModes, mode);
153 CFArraySortValues( usefulModes,
154 CFRangeMake(0, CFArrayGetCount(usefulModes)),
155 (CFComparatorFunction) CompareModes,
nullptr);
167 CGRect display_bounds = CGDisplayBounds(kCGDirectMainDisplay);
168 _display_width = CGRectGetWidth(display_bounds);
169 _display_height = CGRectGetHeight(display_bounds);
171 CGDirectDisplayID display, displayArray[MAX_DISPLAYS] ;
172 CGDisplayCount numDisplays;
173 CFDictionaryRef displayMode;
174 CFArrayRef displayModeArray;
176 CGGetActiveDisplayList (MAX_DISPLAYS, displayArray, &numDisplays);
177 display = displayArray [numDisplays - 1];
178 displayModeArray = GSCGDisplayAvailableModesUsefulForOpenGL( display );
179 number = CFArrayGetCount( displayModeArray );
181 for(i = 0; i < number; i++) {
182 displayMode = (CFDictionaryRef) CFArrayGetValueAtIndex (displayModeArray, i);
183 _display_information -> _total_display_modes++;
184 displays[i].width = (
signed int)GetModeWidth (displayMode);
185 displays[i].height = (
signed int)GetModeHeight (displayMode);
186 displays[i].bits_per_pixel = (
signed int)GetModeBitsPerPixel (displayMode);
187 displays[i].refresh_rate = (
signed int)GetModeRefreshRate (displayMode);
189 _display_information -> _display_mode_array = displays;
224 GraphicsPipe::PreferredWindowThread
239 size_t bytes_per_component = 2;
241 size_t bytes_per_component = 1;
243 size_t bits_per_component = bytes_per_component * 8;
246 size_t bits_per_pixel = num_components * bits_per_component;
247 size_t bytes_per_row = num_components * bytes_per_component * width;
249 size_t num_bytes = bytes_per_row * height;
253 CFStringRef color_space_name =
nullptr;
255 case PNMImage::CT_grayscale:
256 color_space_name = kCGColorSpaceGenericGray;
261 case PNMImage::CT_two_channel:
262 color_space_name = kCGColorSpaceGenericGray;
267 case PNMImage::CT_color:
268 color_space_name = kCGColorSpaceGenericRGB;
270 is_grayscale =
false;
273 case PNMImage::CT_four_channel:
274 color_space_name = kCGColorSpaceGenericRGB;
276 is_grayscale =
false;
279 case PNMImage::CT_invalid:
281 nassertr(
false,
nullptr);
284 nassertr(color_space_name !=
nullptr,
nullptr);
286 CGColorSpaceRef color_space = CGColorSpaceCreateWithName(color_space_name);
287 nassertr(color_space !=
nullptr,
nullptr);
289 CGBitmapInfo bitmap_info = 0;
291 bitmap_info |= kCGBitmapByteOrder16Host;
294 bitmap_info |= kCGImageAlphaLast;
298 char *char_array = (
char *)PANDA_MALLOC_ARRAY(num_bytes);
300 xelval *dp = (xelval *)char_array;
301 for (
size_t yi = 0; yi < height; ++yi) {
302 for (
size_t xi = 0; xi < width; ++xi) {
304 *dp++ = (xelval)(pnm_image.
get_gray(xi, yi) * PGM_MAXMAXVAL);
306 *dp++ = (xelval)(pnm_image.
get_red(xi, yi) * PGM_MAXMAXVAL);
307 *dp++ = (xelval)(pnm_image.
get_green(xi, yi) * PGM_MAXMAXVAL);
308 *dp++ = (xelval)(pnm_image.
get_blue(xi, yi) * PGM_MAXMAXVAL);
311 *dp++ = (xelval)(pnm_image.
get_alpha(xi, yi) * PGM_MAXMAXVAL);
315 nassertr((
void *)dp == (
void *)(char_array + num_bytes),
nullptr);
317 CGDataProviderRef provider =
318 CGDataProviderCreateWithData(
nullptr, char_array, num_bytes, release_data);
319 nassertr(provider !=
nullptr,
nullptr);
321 CGImageRef image = CGImageCreate
322 (width, height, bits_per_component, bits_per_pixel, bytes_per_row,
323 color_space, bitmap_info, provider,
324 nullptr,
false, kCGRenderingIntentDefault);
325 nassertr(image !=
nullptr,
nullptr);
327 CGColorSpaceRelease(color_space);
328 CGDataProviderRelease(provider);
337 void osxGraphicsPipe::
338 release_data(
void *info,
const void *data,
size_t size) {
339 char *char_array = (
char *)data;
340 PANDA_FREE_ARRAY(char_array);
347 make_output(
const std::string &name,
362 DCAST_INTO_R(osxgsg, gsg,
nullptr);
368 if (((flags&BF_require_parasite)!=0)||
369 ((flags&BF_refuse_window)!=0)||
370 ((flags&BF_resizeable)!=0)||
371 ((flags&BF_size_track_host)!=0)||
372 ((flags&BF_can_bind_color)!=0)||
373 ((flags&BF_can_bind_every)!=0)||
374 ((flags&BF_can_bind_layered)!=0)) {
378 if (window_handle !=
nullptr) {
379 osxdisplay_cat.info()
380 <<
"Got parent_window " << *window_handle <<
"\n";
381 #ifdef SUPPORT_SUBPROCESS_WINDOW
383 if (os_handle !=
nullptr &&
384 os_handle->
is_of_type(NativeWindowHandle::SubprocessHandle::get_class_type())) {
385 return new SubprocessWindow(engine,
this, name, fb_prop, win_prop,
388 #endif // SUPPORT_SUBPROCESS_WINDOW
397 if (!osx_support_gl_buffer || !gl_support_fbo || host ==
nullptr ||
398 (flags & (BF_require_parasite | BF_require_window)) != 0) {
403 if ((flags & BF_fb_props_optional) == 0) {
404 if (fb_prop.get_indexed_color() ||
405 fb_prop.get_back_buffers() > 0 ||
406 fb_prop.get_accum_bits() > 0) {
410 if (osxgsg !=
nullptr && osxgsg->is_valid() && !osxgsg->needs_reset()) {
411 if (!osxgsg->_supports_framebuffer_object ||
412 osxgsg->_glDrawBuffers ==
nullptr) {
420 return new GLGraphicsBuffer(engine,
this, name, fb_prop, win_prop, flags, gsg, host);
425 if ((!support_render_texture)||
426 ((flags&BF_require_parasite)!=0)||
427 ((flags&BF_require_window)!=0)||
428 ((flags&BF_resizeable)!=0)||
429 ((flags&BF_size_track_host)!=0)||
430 ((flags&BF_can_bind_every)!=0)||
431 ((flags&BF_can_bind_layered)!=0)) {