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)) {
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) {
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)) {
bool is_basic() const
Returns true if the properties are extremely basic.
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.
static CGImageRef create_cg_image(const PNMImage &pnm_image)
Creates a new Quartz bitmap image with the data in the indicated PNMImage.
This graphics pipe represents the interface for creating OpenGL graphics windows on the various OSX's...
float get_gray(int x, int y) const
Returns the gray component color at the indicated pixel.
float get_blue(int x, int y) const
Returns the blue component color at the indicated pixel.
A tiny specialization on GLGraphicsStateGuardian to add some wgl-specific information.
virtual string get_interface_name() const
Returns the name of the rendering interface associated with this GraphicsPipe.
float get_red(int x, int y) const
Returns the red 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...
float get_green(int x, int y) const
Returns the green component color at the indicated pixel.
OSHandle * get_os_handle() const
Returns the OS-specific handle stored internally to the WindowHandle wrapper.
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...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
This class is the main interface to controlling the render process.
WindowHandle * get_parent_window() const
Returns the parent window specification, or NULL if there is no parent window specified.
TypeHandle is the identifier used to differentiate C++ class types.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
virtual PreferredWindowThread get_preferred_window_thread() const
Returns an indication of the thread in which this GraphicsPipe requires its window processing to be p...
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.