12 #include "osxGraphicsPipe.h"
13 #include "config_osxdisplay.h"
14 #include "osxGraphicsWindow.h"
15 #include "osxGraphicsBuffer.h"
16 #include "osxGraphicsStateGuardian.h"
18 #include "subprocessWindow.h"
19 #include "nativeWindowHandle.h"
20 #import <Carbon/Carbon.h>
23 #define GetModeWidth(mode) GetDictionaryLong((mode), kCGDisplayWidth)
24 #define GetModeHeight(mode) GetDictionaryLong((mode), kCGDisplayHeight)
25 #define GetModeRefreshRate(mode) GetDictionaryLong((mode), kCGDisplayRefreshRate)
26 #define GetModeBitsPerPixel(mode) GetDictionaryLong((mode), kCGDisplayBitsPerPixel)
27 #define GetModeSafeForHardware(mode) GetDictionaryBoolean((mode), kCGDisplayModeIsSafeForHardware)
28 #define GetModeStretched(mode) GetDictionaryBoolean((mode), kCGDisplayModeIsStretched)
29 #define MAX_DISPLAYS 32
31 Boolean GetDictionaryBoolean(CFDictionaryRef theDict,
const void* key) {
33 Boolean value =
false;
35 boolRef = (CFBooleanRef)CFDictionaryGetValue(theDict, key);
37 value = CFBooleanGetValue(boolRef);
41 long GetDictionaryLong(CFDictionaryRef theDict,
const void* key) {
45 numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key);
47 CFNumberGetValue(numRef, kCFNumberLongType, &value);
51 static CFComparisonResult CompareModes (
const void *val1,
const void *val2,
void *context) {
53 #pragma unused(context)
54 CFDictionaryRef thisMode = (CFDictionaryRef)val1;
55 CFDictionaryRef otherMode = (CFDictionaryRef)val2;
57 long width = GetModeWidth(thisMode);
58 long otherWidth = GetModeWidth(otherMode);
59 long height = GetModeHeight(thisMode);
60 long otherHeight = GetModeHeight(otherMode);
63 if (width * height < otherWidth * otherHeight) {
64 return kCFCompareLessThan;
65 }
else if (width * height > otherWidth * otherHeight) {
66 return kCFCompareGreaterThan;
70 long bitsPerPixel = GetModeBitsPerPixel(thisMode);
71 long otherBitsPerPixel = GetModeBitsPerPixel(otherMode);
72 if (bitsPerPixel < otherBitsPerPixel) {
73 return kCFCompareLessThan;
74 }
else if (bitsPerPixel > otherBitsPerPixel) {
75 return kCFCompareGreaterThan;
79 long refreshRate = GetModeRefreshRate(thisMode);
80 long otherRefreshRate = GetModeRefreshRate(otherMode);
81 if (refreshRate < otherRefreshRate) {
82 return kCFCompareLessThan;
83 }
else if (refreshRate > otherRefreshRate) {
84 return kCFCompareGreaterThan;
87 return kCFCompareEqualTo;
90 CFArrayRef GSCGDisplayAvailableModesUsefulForOpenGL(CGDirectDisplayID display) {
92 CFArrayRef availableModes = CGDisplayAvailableModes(display);
93 unsigned int numberOfAvailableModes = CFArrayGetCount(availableModes);
96 CFMutableArrayRef usefulModes = CFArrayCreateMutable(kCFAllocatorDefault, numberOfAvailableModes, NULL);
99 long currentModeBitsPerPixel = GetModeBitsPerPixel(CGDisplayCurrentMode(display));
102 for (i= 0; i<numberOfAvailableModes; ++i) {
104 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, NULL);
169 CGRect display_bounds = CGDisplayBounds(kCGDirectMainDisplay);
170 _display_width = CGRectGetWidth(display_bounds);
171 _display_height = CGRectGetHeight(display_bounds);
173 CGDirectDisplayID display, displayArray[MAX_DISPLAYS] ;
174 CGDisplayCount numDisplays;
175 CFDictionaryRef displayMode;
176 CFArrayRef displayModeArray;
178 CGGetActiveDisplayList (MAX_DISPLAYS, displayArray, &numDisplays);
179 display = displayArray [numDisplays - 1];
180 displayModeArray = GSCGDisplayAvailableModesUsefulForOpenGL( display );
181 number = CFArrayGetCount( displayModeArray );
183 for(i = 0; i < number; i++) {
184 displayMode = (CFDictionaryRef) CFArrayGetValueAtIndex (displayModeArray, i);
185 _display_information -> _total_display_modes++;
186 displays[i].width = (
signed int)GetModeWidth (displayMode);
187 displays[i].height = (
signed int)GetModeHeight (displayMode);
188 displays[i].bits_per_pixel = (
signed int)GetModeBitsPerPixel (displayMode);
189 displays[i].refresh_rate = (
signed int)GetModeRefreshRate (displayMode);
191 _display_information -> _display_mode_array = displays;
238 GraphicsPipe::PreferredWindowThread
256 size_t bytes_per_component = 2;
258 size_t bytes_per_component = 1;
260 size_t bits_per_component = bytes_per_component * 8;
263 size_t bits_per_pixel = num_components * bits_per_component;
264 size_t bytes_per_row = num_components * bytes_per_component * width;
266 size_t num_bytes = bytes_per_row * height;
270 CFStringRef color_space_name = NULL;
272 case PNMImage::CT_grayscale:
273 color_space_name = kCGColorSpaceGenericGray;
278 case PNMImage::CT_two_channel:
279 color_space_name = kCGColorSpaceGenericGray;
284 case PNMImage::CT_color:
285 color_space_name = kCGColorSpaceGenericRGB;
287 is_grayscale =
false;
290 case PNMImage::CT_four_channel:
291 color_space_name = kCGColorSpaceGenericRGB;
293 is_grayscale =
false;
296 case PNMImage::CT_invalid:
298 nassertr(
false, NULL);
301 nassertr(color_space_name != NULL, NULL);
303 CGColorSpaceRef color_space = CGColorSpaceCreateWithName(color_space_name);
304 nassertr(color_space != NULL, NULL);
306 CGBitmapInfo bitmap_info = 0;
308 bitmap_info |= kCGBitmapByteOrder16Host;
311 bitmap_info |= kCGImageAlphaLast;
316 char *char_array = (
char *)PANDA_MALLOC_ARRAY(num_bytes);
318 xelval *dp = (xelval *)char_array;
319 for (
size_t yi = 0; yi < height; ++yi) {
320 for (
size_t xi = 0; xi < width; ++xi) {
322 *dp++ = (xelval)(pnm_image.
get_gray(xi, yi) * PGM_MAXMAXVAL);
324 *dp++ = (xelval)(pnm_image.
get_red(xi, yi) * PGM_MAXMAXVAL);
325 *dp++ = (xelval)(pnm_image.
get_green(xi, yi) * PGM_MAXMAXVAL);
326 *dp++ = (xelval)(pnm_image.
get_blue(xi, yi) * PGM_MAXMAXVAL);
329 *dp++ = (xelval)(pnm_image.
get_alpha(xi, yi) * PGM_MAXMAXVAL);
333 nassertr((
void *)dp == (
void *)(char_array + num_bytes), NULL);
335 CGDataProviderRef provider =
336 CGDataProviderCreateWithData(NULL, char_array, num_bytes, release_data);
337 nassertr(provider != NULL, NULL);
339 CGImageRef image = CGImageCreate
340 (width, height, bits_per_component, bits_per_pixel, bytes_per_row,
341 color_space, bitmap_info, provider,
342 NULL,
false, kCGRenderingIntentDefault);
343 nassertr(image != NULL, NULL);
345 CGColorSpaceRelease(color_space);
346 CGDataProviderRelease(provider);
357 void osxGraphicsPipe::
358 release_data(
void *info,
const void *data,
size_t size) {
359 char *char_array = (
char *)data;
360 PANDA_FREE_ARRAY(char_array);
369 make_output(const
string &name,
384 DCAST_INTO_R(osxgsg, gsg, NULL);
390 if (((flags&BF_require_parasite)!=0)||
391 ((flags&BF_refuse_window)!=0)||
392 ((flags&BF_resizeable)!=0)||
393 ((flags&BF_size_track_host)!=0)||
394 ((flags&BF_can_bind_color)!=0)||
395 ((flags&BF_can_bind_every)!=0)||
396 ((flags&BF_can_bind_layered)!=0)) {
399 WindowHandle *window_handle = win_prop.get_parent_window();
400 if (window_handle != NULL) {
401 osxdisplay_cat.info()
402 <<
"Got parent_window " << *window_handle <<
"\n";
403 #ifdef SUPPORT_SUBPROCESS_WINDOW
405 if (os_handle != NULL &&
406 os_handle->
is_of_type(NativeWindowHandle::SubprocessHandle::get_class_type())) {
407 return new SubprocessWindow(engine,
this, name, fb_prop, win_prop,
410 #endif // SUPPORT_SUBPROCESS_WINDOW
419 if (!osx_support_gl_buffer || !gl_support_fbo || host == NULL ||
420 (flags & (BF_require_parasite | BF_require_window)) != 0) {
425 if ((flags & BF_fb_props_optional) == 0) {
426 if (fb_prop.get_indexed_color() ||
427 fb_prop.get_back_buffers() > 0 ||
428 fb_prop.get_accum_bits() > 0) {
432 if (osxgsg != NULL && osxgsg->is_valid() && !osxgsg->needs_reset()) {
433 if (!osxgsg->_supports_framebuffer_object ||
434 osxgsg->_glDrawBuffers == NULL) {
436 }
else if (fb_prop.is_basic()) {
442 return new GLGraphicsBuffer(engine,
this, name, fb_prop, win_prop, flags, gsg, host);
447 if ((!support_render_texture)||
448 ((flags&BF_require_parasite)!=0)||
449 ((flags&BF_require_window)!=0)||
450 ((flags&BF_resizeable)!=0)||
451 ((flags&BF_size_track_host)!=0)||
452 ((flags&BF_can_bind_every)!=0)||
453 ((flags&BF_can_bind_layered)!=0)) {
virtual PreferredWindowThread get_preferred_window_thread() const
Returns an indication of the thread in which this GraphicsPipe requires its window processing to be p...
This object represents a window on the desktop, not necessarily a Panda window.
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
An offscreen buffer in the OSX environment.
float get_red(int x, int y) const
Returns the red component color at the indicated pixel.
virtual string get_interface_name() const
Returns the name of the rendering interface associated with this GraphicsPipe.
static CGImageRef create_cg_image(const PNMImage &pnm_image)
Creates a new Quartz bitmap image with the data in the indicated PNMImage.
float get_blue(int x, int y) const
Returns the blue component color at the indicated pixel.
This graphics pipe represents the interface for creating OpenGL graphics windows on the various OSX's...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
float get_gray(int x, int y) const
Returns the gray component color at the indicated pixel.
A tiny specialization on GLGraphicsStateGuardian to add some wgl-specific information.
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
float get_green(int x, int y) const
Returns the green component color at the indicated pixel.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
An interface to the osx/ system for managing GL windows under X.
An object to create GraphicsOutputs that share a particular 3-D API.
This is a base class for the various different classes that represent the result of a frame of render...
Encapsulates all the communication with a particular instance of a given rendering backend...
This class is the main interface to controlling the render process.
TypeHandle is the identifier used to differentiate C++ class types.
OSHandle * get_os_handle() const
Returns the OS-specific handle stored internally to the WindowHandle wrapper.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...