Brand new Cocoa display module

This commit is contained in:
rdb 2012-05-25 10:38:47 +00:00
parent d1c9bee195
commit 24cdca64e7
21 changed files with 2985 additions and 0 deletions

View File

@ -0,0 +1,34 @@
#define BUILD_DIRECTORY $[and $[IS_OSX],$[HAVE_GL]]
#define OTHER_LIBS p3interrogatedb:c p3dconfig:c p3dtoolconfig:m \
p3dtoolutil:c p3dtoolbase:c p3dtool:m
#define OSX_SYS_FRAMEWORKS ApplicationServices AppKit
#begin lib_target
#define TARGET p3cocoadisplay
#define LOCAL_LIBS \
p3display p3putil p3glgsg
#define COMBINED_SOURCES $[TARGET]_composite1.mm
#define INSTALL_HEADERS \
config_cocoadisplay.h \
cocoaGraphicsPipe.h cocoaGraphicsPipe.I \
cocoaGraphicsWindow.h cocoaGraphicsWindow.I \
cocoaGraphicsStateGuardian.h cocoaGraphicsStateGuardian.I \
cocoaPandaView.h cocoaPandaWindowDelegate.h
#define INCLUDED_SOURCES \
config_cocoadisplay.mm \
cocoaGraphicsPipe.mm \
cocoaGraphicsStateGuardian.mm \
cocoaGraphicsWindow.mm \
cocoaPandaView.mm \
cocoaPandaWindow.mm \
cocoaPandaWindowDelegate.mm
#define SOURCES \
$[INSTALL_HEADERS]
#end lib_target

View File

@ -0,0 +1,230 @@
// Filename: eglGraphicsBuffer.cxx
// Created by: pro-rsoft (13Jun09)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "eglGraphicsBuffer.h"
#include "eglGraphicsStateGuardian.h"
#include "config_egldisplay.h"
#include "eglGraphicsPipe.h"
#include "graphicsPipe.h"
#include "pStatTimer.h"
TypeHandle eglGraphicsBuffer::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: eglGraphicsBuffer::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
eglGraphicsBuffer::
eglGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
const string &name,
const FrameBufferProperties &fb_prop,
const WindowProperties &win_prop,
int flags,
GraphicsStateGuardian *gsg,
GraphicsOutput *host) :
GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
{
eglGraphicsPipe *egl_pipe;
DCAST_INTO_V(egl_pipe, _pipe);
_pbuffer = EGL_NO_SURFACE;
// Since the pbuffer never gets flipped, we get screenshots from the
// same buffer we draw into.
_screenshot_buffer_type = _draw_buffer_type;
}
////////////////////////////////////////////////////////////////////
// Function: eglGraphicsBuffer::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
eglGraphicsBuffer::
~eglGraphicsBuffer() {
nassertv(_pbuffer == EGL_NO_SURFACE);
}
////////////////////////////////////////////////////////////////////
// Function: eglGraphicsBuffer::begin_frame
// Access: Public, Virtual
// Description: This function will be called within the draw thread
// before beginning rendering for a given frame. It
// should do whatever setup is required, and return true
// if the frame should be rendered, or false if it
// should be skipped.
////////////////////////////////////////////////////////////////////
bool eglGraphicsBuffer::
begin_frame(FrameMode mode, Thread *current_thread) {
PStatTimer timer(_make_current_pcollector, current_thread);
begin_frame_spam(mode);
if (_gsg == (GraphicsStateGuardian *)NULL) {
return false;
}
eglGraphicsStateGuardian *eglgsg;
DCAST_INTO_R(eglgsg, _gsg, false);
if (!eglMakeCurrent(eglgsg->_egl_display, _pbuffer, _pbuffer, eglgsg->_context)) {
egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
<< get_egl_error_string(eglGetError()) << "\n";
}
// Now that we have made the context current to a window, we can
// reset the GSG state if this is the first time it has been used.
// (We can't just call reset() when we construct the GSG, because
// reset() requires having a current context.)
eglgsg->reset_if_new();
if (mode == FM_render) {
CDLockedReader cdata(_cycler);
for (size_t i = 0; i != cdata->_textures.size(); ++i) {
const RenderTexture &rt = cdata->_textures[i];
RenderTextureMode rtm_mode = rt._rtm_mode;
if (rtm_mode == RTM_bind_or_copy) {
CDWriter cdataw(_cycler, cdata, false);
nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
cdataw->_textures[i]._rtm_mode = RTM_copy_texture;
}
}
clear_cube_map_selection();
}
_gsg->set_current_properties(&get_fb_properties());
return _gsg->begin_frame(current_thread);
}
////////////////////////////////////////////////////////////////////
// Function: eglGraphicsBuffer::end_frame
// Access: Public, Virtual
// Description: This function will be called within the draw thread
// after rendering is completed for a given frame. It
// should do whatever finalization is required.
////////////////////////////////////////////////////////////////////
void eglGraphicsBuffer::
end_frame(FrameMode mode, Thread *current_thread) {
end_frame_spam(mode);
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
if (mode == FM_render) {
copy_to_textures();
}
_gsg->end_frame(current_thread);
if (mode == FM_render) {
trigger_flip();
clear_cube_map_selection();
}
}
////////////////////////////////////////////////////////////////////
// Function: eglGraphicsBuffer::close_buffer
// Access: Protected, Virtual
// Description: Closes the buffer right now. Called from the window
// thread.
////////////////////////////////////////////////////////////////////
void eglGraphicsBuffer::
close_buffer() {
if (_gsg != (GraphicsStateGuardian *)NULL) {
eglGraphicsStateGuardian *eglgsg;
DCAST_INTO_V(eglgsg, _gsg);
if (!eglMakeCurrent(eglgsg->_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
<< get_egl_error_string(eglGetError()) << "\n";
}
_gsg.clear();
if (_pbuffer != EGL_NO_SURFACE) {
if (!eglDestroySurface(_egl_display, _pbuffer)) {
egldisplay_cat.error() << "Failed to destroy surface: "
<< get_egl_error_string(eglGetError()) << "\n";
}
_pbuffer = EGL_NO_SURFACE;
}
}
_is_valid = false;
}
////////////////////////////////////////////////////////////////////
// Function: eglGraphicsBuffer::open_buffer
// Access: Protected, Virtual
// Description: Opens the buffer right now. Called from the window
// thread. Returns true if the buffer is successfully
// opened, or false if there was a problem.
////////////////////////////////////////////////////////////////////
bool eglGraphicsBuffer::
open_buffer() {
eglGraphicsPipe *egl_pipe;
DCAST_INTO_R(egl_pipe, _pipe, false);
// GSG Creation/Initialization
eglGraphicsStateGuardian *eglgsg;
if (_gsg == 0) {
// There is no old gsg. Create a new one.
eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, NULL);
eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), true, false);
_gsg = eglgsg;
} else {
// If the old gsg has the wrong pixel format, create a
// new one that shares with the old gsg.
DCAST_INTO_R(eglgsg, _gsg, false);
if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) {
eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg);
eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), true, false);
_gsg = eglgsg;
}
}
if (eglgsg->_fbconfig == None) {
// If we didn't use an fbconfig to create the GSG, we can't create
// a PBuffer.
return false;
}
int attrib_list[] = {
EGL_WIDTH, _x_size,
EGL_HEIGHT, _y_size,
EGL_NONE
};
_pbuffer = eglCreatePbufferSurface(eglgsg->_egl_display, eglgsg->_fbconfig, attrib_list);
if (_pbuffer == EGL_NO_SURFACE) {
egldisplay_cat.error()
<< "Failed to create EGL pbuffer surface: "
<< get_egl_error_string(eglGetError()) << "\n";
return false;
}
if (!eglMakeCurrent(eglgsg->_egl_display, _pbuffer, _pbuffer, eglgsg->_context)) {
egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
<< get_egl_error_string(eglGetError()) << "\n";
}
eglgsg->reset_if_new();
if (!eglgsg->is_valid()) {
close_buffer();
return false;
}
if (!eglgsg->get_fb_properties().verify_hardware_software
(_fb_properties, eglgsg->get_gl_renderer())) {
close_buffer();
return false;
}
_fb_properties = eglgsg->get_fb_properties();
_is_valid = true;
return true;
}

View File

@ -0,0 +1,69 @@
// Filename: eglGraphicsBuffer.h
// Created by: pro-rsoft (13Jun09)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef EGLGRAPHICSBUFFER_H
#define EGLGRAPHICSBUFFER_H
#include "pandabase.h"
#include "eglGraphicsPipe.h"
#include "graphicsBuffer.h"
////////////////////////////////////////////////////////////////////
// Class : eglGraphicsBuffer
// Description : An offscreen buffer in the EGL environment. This
// creates an EGL pbuffer.
////////////////////////////////////////////////////////////////////
class eglGraphicsBuffer : public GraphicsBuffer {
public:
eglGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
const string &name,
const FrameBufferProperties &fb_prop,
const WindowProperties &win_prop,
int flags,
GraphicsStateGuardian *gsg,
GraphicsOutput *host);
virtual ~eglGraphicsBuffer();
virtual bool begin_frame(FrameMode mode, Thread *current_thread);
virtual void end_frame(FrameMode mode, Thread *current_thread);
protected:
virtual void close_buffer();
virtual bool open_buffer();
private:
X11_Display *_display;
EGLSurface _pbuffer;
EGLDisplay _egl_display;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
GraphicsBuffer::init_type();
register_type(_type_handle, "eglGraphicsBuffer",
GraphicsBuffer::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#endif

View File

@ -0,0 +1,36 @@
// Filename: cocoaGraphicsPipe.I
// Created by: rdb (14May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
/*////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsPipe::get_display
// Access: Public
// Description: Returns a pointer to the X display associated with
// the pipe: the display on which to create the windows.
////////////////////////////////////////////////////////////////////
INLINE X11_Display *CocoaGraphicsPipe::
get_display() const {
return _display;
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsPipe::get_screen
// Access: Public
// Description: Returns the X screen number associated with the pipe.
////////////////////////////////////////////////////////////////////
INLINE int CocoaGraphicsPipe::
get_screen() const {
return _screen;
}
*/

View File

@ -0,0 +1,91 @@
// Filename: cocoaGraphicsPipe.h
// Created by: rdb (14May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef COCOAGRAPHICSPIPE_H
#define COCOAGRAPHICSPIPE_H
#include "pandabase.h"
#include "graphicsWindow.h"
#include "graphicsPipe.h"
#include "lightMutex.h"
#include "lightReMutex.h"
#import <AppKit/NSScreen.h>
#import <ApplicationServices/ApplicationServices.h>
class FrameBufferProperties;
////////////////////////////////////////////////////////////////////
// Class : CocoaGraphicsPipe
// Description : This graphics pipe represents the interface for
// creating OpenGL graphics windows on a Cocoa-based
// (e.g. Mac OS X) client.
////////////////////////////////////////////////////////////////////
class CocoaGraphicsPipe : public GraphicsPipe {
public:
CocoaGraphicsPipe();
CocoaGraphicsPipe(CGDirectDisplayID display);
CocoaGraphicsPipe(NSScreen *screen);
virtual ~CocoaGraphicsPipe();
virtual string get_interface_name() const;
static PT(GraphicsPipe) pipe_constructor();
public:
virtual PreferredWindowThread get_preferred_window_thread() const;
protected:
virtual PT(GraphicsOutput) make_output(const string &name,
const FrameBufferProperties &fb_prop,
const WindowProperties &win_prop,
int flags,
GraphicsEngine *engine,
GraphicsStateGuardian *gsg,
GraphicsOutput *host,
int retry,
bool &precertify);
private:
void load_display_information();
// _display and _screen refer to the same thing,
// NSScreen being the tiny Cocoa wrapper around the Quartz
// display ID. NSScreen isn't generally useful, but we need
// it when creating the window.
CGDirectDisplayID _display;
NSScreen *_screen;
friend class CocoaGraphicsWindow;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
GraphicsPipe::init_type();
register_type(_type_handle, "CocoaGraphicsPipe",
GraphicsPipe::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "cocoaGraphicsPipe.I"
#endif

View File

@ -0,0 +1,362 @@
// Filename: cocoaGraphicsPipe.mm
// Created by: rdb (14May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "cocoaGraphicsPipe.h"
//#include "cocoaGraphicsBuffer.h"
#include "cocoaGraphicsWindow.h"
#include "cocoaGraphicsStateGuardian.h"
#include "config_cocoadisplay.h"
#include "frameBufferProperties.h"
#import <Foundation/NSAutoreleasePool.h>
#import <AppKit/NSApplication.h>
TypeHandle CocoaGraphicsPipe::_type_handle;
static void init_app() {
if (NSApp == nil) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
[NSApp setActivationPolicy: nil];
[NSApp finishLaunching];
[NSApp activateIgnoringOtherApps: YES];
//[pool release];
}
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsPipe::Constructor
// Access: Public
// Description: Uses the main screen (the one the user is most
// likely to be working in at the moment).
////////////////////////////////////////////////////////////////////
CocoaGraphicsPipe::
CocoaGraphicsPipe() {
_supported_types = OT_window | OT_buffer | OT_texture_buffer;
_is_valid = true;
init_app();
_screen = [NSScreen mainScreen];
NSNumber *num = [[_screen deviceDescription] objectForKey: @"NSScreenNumber"];
_display = (CGDirectDisplayID) [num pointerValue];
_display_width = CGDisplayPixelsWide(_display);
_display_height = CGDisplayPixelsHigh(_display);
load_display_information();
cocoadisplay_cat.debug()
<< "Creating CocoaGraphicsPipe for main screen "
<< _screen << " with display ID " << _display << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsPipe::Constructor
// Access: Public
// Description: Takes a CoreGraphics display ID.
////////////////////////////////////////////////////////////////////
CocoaGraphicsPipe::
CocoaGraphicsPipe(CGDirectDisplayID display) {
_supported_types = OT_window | OT_buffer | OT_texture_buffer;
_is_valid = true;
_display = display;
init_app();
// Iterate over the screens to find the one with our display ID.
NSEnumerator *e = [[NSScreen screens] objectEnumerator];
while (NSScreen *screen = (NSScreen *) [e nextObject]) {
NSNumber *num = [[screen deviceDescription] objectForKey: @"NSScreenNumber"];
if (display == (CGDirectDisplayID) [num pointerValue]) {
_screen = screen;
break;
}
}
_display_width = CGDisplayPixelsWide(_display);
_display_height = CGDisplayPixelsHigh(_display);
load_display_information();
cocoadisplay_cat.debug()
<< "Creating CocoaGraphicsPipe for screen "
<< _screen << " with display ID " << _display << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsPipe::Constructor
// Access: Public
// Description: Takes an NSScreen pointer.
////////////////////////////////////////////////////////////////////
CocoaGraphicsPipe::
CocoaGraphicsPipe(NSScreen *screen) {
_supported_types = OT_window | OT_buffer | OT_texture_buffer;
_is_valid = true;
init_app();
if (screen == nil) {
_screen = [NSScreen mainScreen];
} else {
_screen = screen;
}
NSNumber *num = [[_screen deviceDescription] objectForKey: @"NSScreenNumber"];
_display = (CGDirectDisplayID) [num pointerValue];
_display_width = CGDisplayPixelsWide(_display);
_display_height = CGDisplayPixelsHigh(_display);
load_display_information();
cocoadisplay_cat.debug()
<< "Creating CocoaGraphicsPipe for screen "
<< _screen << " with display ID " << _display << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsPipe::load_display_information
// Access: Private
// Description: Fills in _display_information.
////////////////////////////////////////////////////////////////////
void CocoaGraphicsPipe::
load_display_information() {
//TODO: read display modes and display information.
_display_information->_vendor_id = CGDisplayVendorNumber(_display);
//_display_information->_device_id = CGDisplayUnitNumber(_display);
//_display_information->_device_id = CGDisplaySerialNumber(_display);
// Display modes
#if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, NULL);
size_t num_modes = CFArrayGetCount(modes);
_display_information->_total_display_modes = num_modes;
_display_information->_display_mode_array = new DisplayMode[num_modes];
for (size_t i = 0; i < num_modes; ++i) {
CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
_display_information->_display_mode_array[i].width = CGDisplayModeGetWidth(mode);
_display_information->_display_mode_array[i].height = CGDisplayModeGetHeight(mode);
_display_information->_display_mode_array[i].refresh_rate = CGDisplayModeGetRefreshRate(mode);
_display_information->_display_mode_array[i].fullscreen_only = false;
// Read number of bits per pixels from the pixel encoding
CFStringRef encoding = CGDisplayModeCopyPixelEncoding(mode);
if (CFStringCompare(encoding, CFSTR(kIO64BitDirectPixels),
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
_display_information->_display_mode_array[i].bits_per_pixel = 64;
} else if (CFStringCompare(encoding, CFSTR(kIO32BitFloatPixels),
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
_display_information->_display_mode_array[i].bits_per_pixel = 32;
} else if (CFStringCompare(encoding, CFSTR(kIO16BitFloatPixels),
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
_display_information->_display_mode_array[i].bits_per_pixel = 16;
} else if (CFStringCompare(encoding, CFSTR(IOYUV422Pixels),
kCFCompareCaseInsensitive) == kCFCompareEqualTo ||
CFStringCompare(encoding, CFSTR(IO8BitOverlayPixels),
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
_display_information->_display_mode_array[i].bits_per_pixel = 8;
} else {
// The other possible pixel formats in IOKit/IOGraphicsTypes.h
// have strings like "PPPP" or "-RRRRRGGGGGBBBBB", so the number
// of bits per pixel can be deduced from the string length. Nifty!
_display_information->_display_mode_array[i].bits_per_pixel = CFStringGetLength(encoding);
}
CFRelease(encoding);
}
CFRelease(modes);
#else
CFArrayRef modes = CGDisplayAvailableModes(_display);
size_t num_modes = CFArrayGetCount(modes);
_display_information->_total_display_modes = num_modes;
_display_information->_display_mode_array = new DisplayMode[num_modes];
for (size_t i = 0; i < num_modes; ++i) {
CFDictionaryRef mode = (CFDictionaryRef) CFArrayGetValueAtIndex(modes, i);
CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(mode, kCGDisplayWidth),
kCFNumberIntType, &_display_information->_display_mode_array[i].width);
CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(mode, kCGDisplayHeight),
kCFNumberIntType, &_display_information->_display_mode_array[i].height);
CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(mode, kCGDisplayBitsPerPixel),
kCFNumberIntType, &_display_information->_display_mode_array[i].bits_per_pixel);
CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(mode, kCGDisplayRefreshRate),
kCFNumberIntType, &_display_information->_display_mode_array[i].refresh_rate);
_display_information->_display_mode_array[i].fullscreen_only = false;
}
#endif
//XXX remove when done
cerr << *_display_information << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsPipe::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CocoaGraphicsPipe::
~CocoaGraphicsPipe() {
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsPipe::get_interface_name
// Access: Published, Virtual
// Description: Returns the name of the rendering interface
// associated with this GraphicsPipe. This is used to
// present to the user to allow him/her to choose
// between several possible GraphicsPipes available on a
// particular platform, so the name should be meaningful
// and unique for a given platform.
////////////////////////////////////////////////////////////////////
string CocoaGraphicsPipe::
get_interface_name() const {
return "OpenGL";
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsPipe::pipe_constructor
// Access: Public, Static
// Description: This function is passed to the GraphicsPipeSelection
// object to allow the user to make a default
// CocoaGraphicsPipe.
////////////////////////////////////////////////////////////////////
PT(GraphicsPipe) CocoaGraphicsPipe::
pipe_constructor() {
return new CocoaGraphicsPipe;
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsPipe::get_preferred_window_thread
// Access: Public, Virtual
// Description: Returns an indication of the thread in which this
// GraphicsPipe requires its window processing to be
// performed: typically either the app thread (e.g. X)
// or the draw thread (Windows).
////////////////////////////////////////////////////////////////////
GraphicsPipe::PreferredWindowThread
CocoaGraphicsPipe::get_preferred_window_thread() const {
// The NSView and NSWindow classes are not thread-safe,
// they can only be called from the main thread!
return PWT_app;
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsPipe::make_output
// Access: Protected, Virtual
// Description: Creates a new window on the pipe, if possible.
////////////////////////////////////////////////////////////////////
PT(GraphicsOutput) CocoaGraphicsPipe::
make_output(const string &name,
const FrameBufferProperties &fb_prop,
const WindowProperties &win_prop,
int flags,
GraphicsEngine *engine,
GraphicsStateGuardian *gsg,
GraphicsOutput *host,
int retry,
bool &precertify) {
if (!_is_valid) {
return NULL;
}
CocoaGraphicsStateGuardian *cocoagsg = 0;
if (gsg != 0) {
DCAST_INTO_R(cocoagsg, gsg, NULL);
}
// First thing to try: a CocoaGraphicsWindow
if (retry == 0) {
if (((flags&BF_require_parasite)!=0)||
((flags&BF_refuse_window)!=0)||
((flags&BF_resizeable)!=0)||
((flags&BF_size_track_host)!=0)||
((flags&BF_rtt_cumulative)!=0)||
((flags&BF_can_bind_color)!=0)||
((flags&BF_can_bind_every)!=0)) {
return NULL;
}
return new CocoaGraphicsWindow(engine, this, name, fb_prop, win_prop,
flags, gsg, host);
}
/*
// Second thing to try: a GLES(2)GraphicsBuffer
if (retry == 1) {
if ((host==0)||
// (!gl_support_fbo)||
((flags&BF_require_parasite)!=0)||
((flags&BF_require_window)!=0)) {
return NULL;
}
// Early failure - if we are sure that this buffer WONT
// meet specs, we can bail out early.
if ((flags & BF_fb_props_optional)==0) {
if ((fb_prop.get_indexed_color() > 0)||
(fb_prop.get_back_buffers() > 0)||
(fb_prop.get_accum_bits() > 0)||
(fb_prop.get_multisamples() > 0)) {
return NULL;
}
}
// Early success - if we are sure that this buffer WILL
// meet specs, we can precertify it.
if ((cocoagsg != 0) &&
(cocoagsg->is_valid()) &&
(!cocoagsg->needs_reset()) &&
(cocoagsg->_supports_framebuffer_object) &&
(cocoagsg->_glDrawBuffers != 0)&&
(fb_prop.is_basic())) {
precertify = true;
}
return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
flags, gsg, host);
}
// Third thing to try: a CocoaGraphicsBuffer
if (retry == 2) {
if (((flags&BF_require_parasite)!=0)||
((flags&BF_require_window)!=0)||
((flags&BF_resizeable)!=0)||
((flags&BF_size_track_host)!=0)) {
return NULL;
}
if (!support_rtt) {
if (((flags&BF_rtt_cumulative)!=0)||
((flags&BF_can_bind_every)!=0)) {
// If we require Render-to-Texture, but can't be sure we
// support it, bail.
return NULL;
}
}
return new CocoaGraphicsBuffer(engine, this, name, fb_prop, win_prop,
flags, gsg, host);
}
*/
// Nothing else left to try.
return NULL;
}

View File

@ -0,0 +1,26 @@
// Filename: cocoaGraphicsStateGuardian.I
// Created by: rdb (14May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsStateGuardian::get_fb_properties
// Access: Private
// Description: Gets the FrameBufferProperties for all windows and
// buffers that use this GSG.
////////////////////////////////////////////////////////////////////
INLINE const FrameBufferProperties &CocoaGraphicsStateGuardian::
get_fb_properties() const {
return _fbprops;
}

View File

@ -0,0 +1,70 @@
// Filename: cocoaGraphicsStateGuardian.h
// Created by: rdb (14May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef COCOAGRAPHICSSTATEGUARDIAN_H
#define COCOAGRAPHICSSTATEGUARDIAN_H
#include "pandabase.h"
#include "cocoaGraphicsPipe.h"
#include "glgsg.h"
#import <AppKit/NSOpenGL.h>
////////////////////////////////////////////////////////////////////
// Class : CocoaGraphicsStateGuardian
// Description : A tiny specialization on GLGraphicsStateGuardian
// to add some Cocoa-specific information.
////////////////////////////////////////////////////////////////////
class CocoaGraphicsStateGuardian : public GLGraphicsStateGuardian {
public:
INLINE const FrameBufferProperties &get_fb_properties() const;
void get_properties(FrameBufferProperties &properties,
NSOpenGLPixelFormat *pixel_format, int virtual_screen);
void choose_pixel_format(const FrameBufferProperties &properties,
CGDirectDisplayID display,
bool need_window, bool need_pbuffer);
CocoaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
CocoaGraphicsStateGuardian *share_with);
virtual ~CocoaGraphicsStateGuardian();
NSOpenGLContext *_share_context;
NSOpenGLContext *_context;
FrameBufferProperties _fbprops;
protected:
virtual void *do_get_extension_func(const char *prefix, const char *name);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
GLGraphicsStateGuardian::init_type();
register_type(_type_handle, "CocoaGraphicsStateGuardian",
GLGraphicsStateGuardian::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "cocoaGraphicsStateGuardian.I"
#endif

View File

@ -0,0 +1,251 @@
// Filename: cocoaGraphicsStateGuardian.mm
// Created by: rdb (14May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "cocoaGraphicsStateGuardian.h"
#include "config_cocoadisplay.h"
#include "lightReMutexHolder.h"
#include <mach-o/dyld.h>
#import <OpenGL/CGLRenderers.h>
TypeHandle CocoaGraphicsStateGuardian::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsStateGuardian::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
CocoaGraphicsStateGuardian::
CocoaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
CocoaGraphicsStateGuardian *share_with) :
GLGraphicsStateGuardian(engine, pipe)
{
_share_context = nil;
_context = nil;
if (share_with != (CocoaGraphicsStateGuardian *)NULL) {
_prepared_objects = share_with->get_prepared_objects();
_share_context = share_with->_context;
}
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsStateGuardian::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
CocoaGraphicsStateGuardian::
~CocoaGraphicsStateGuardian() {
if (_context != nil) {
[_context clearDrawable];
[_context release];
}
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsStateGuardian::get_properties
// Access: Private
// Description: Gets the FrameBufferProperties to match the
// indicated config.
////////////////////////////////////////////////////////////////////
void CocoaGraphicsStateGuardian::
get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_format, int screen) {
properties.clear();
// Now update our framebuffer_mode and bit depth appropriately.
GLint double_buffer, stereo, aux_buffers, color_size, alpha_size,
depth_size, stencil_size, accum_size, sample_buffers, samples,
renderer_id, accelerated, window, pbuffer;
[pixel_format getValues: &double_buffer forAttribute: NSOpenGLPFADoubleBuffer forVirtualScreen: screen];
[pixel_format getValues: &stereo forAttribute: NSOpenGLPFAStereo forVirtualScreen: screen];
[pixel_format getValues: &aux_buffers forAttribute: NSOpenGLPFAAuxBuffers forVirtualScreen: screen];
[pixel_format getValues: &color_size forAttribute: NSOpenGLPFAColorSize forVirtualScreen: screen];
[pixel_format getValues: &alpha_size forAttribute: NSOpenGLPFAAlphaSize forVirtualScreen: screen];
[pixel_format getValues: &depth_size forAttribute: NSOpenGLPFADepthSize forVirtualScreen: screen];
[pixel_format getValues: &stencil_size forAttribute: NSOpenGLPFAStencilSize forVirtualScreen: screen];
[pixel_format getValues: &accum_size forAttribute: NSOpenGLPFAAccumSize forVirtualScreen: screen];
[pixel_format getValues: &sample_buffers forAttribute: NSOpenGLPFASampleBuffers forVirtualScreen: screen];
[pixel_format getValues: &samples forAttribute: NSOpenGLPFASamples forVirtualScreen: screen];
[pixel_format getValues: &renderer_id forAttribute: NSOpenGLPFARendererID forVirtualScreen: screen];
[pixel_format getValues: &accelerated forAttribute: NSOpenGLPFAAccelerated forVirtualScreen: screen];
[pixel_format getValues: &window forAttribute: NSOpenGLPFAWindow forVirtualScreen: screen];
[pixel_format getValues: &pbuffer forAttribute: NSOpenGLPFAPixelBuffer forVirtualScreen: screen];
properties.set_back_buffers(double_buffer);
properties.set_stereo(stereo);
properties.set_rgb_color(1);
properties.set_color_bits(color_size);
properties.set_stencil_bits(stencil_size);
properties.set_depth_bits(depth_size);
properties.set_alpha_bits(alpha_size);
properties.set_accum_bits(accum_size);
if (sample_buffers > 0) {
properties.set_multisamples(samples);
}
//TODO: add aux buffers
if (renderer_id == kCGLRendererGenericID ||
renderer_id == kCGLRendererGenericFloatID ||
renderer_id == kCGLRendererAppleSWID) {
properties.set_force_software(1);
}
if (accelerated) {
properties.set_force_hardware(1);
}
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsStateGuardian::choose_pixel_format
// Access: Private
// Description: Selects a visual or fbconfig for all the windows
// and buffers that use this gsg. Also creates the GL
// context and obtains the visual.
////////////////////////////////////////////////////////////////////
void CocoaGraphicsStateGuardian::
choose_pixel_format(const FrameBufferProperties &properties,
CGDirectDisplayID display,
bool need_window, bool need_pbuffer) {
_context = nil;
_fbprops.clear();
// Neither Cocoa nor CGL seem to have a mechanism to query the available
// pixel formats, unfortunately, so the only thing we can do is ask for one
// with the properties we have requested.
pvector<NSOpenGLPixelFormatAttribute> attribs;
attribs.reserve(13);
// Picked this up from the pyglet source - seems
// to be necessary to support RAGE-II, which is not compliant.
attribs.push_back(NSOpenGLPFAAllRenderers);
// Don't let it fall back to a different renderer.
attribs.push_back(NSOpenGLPFANoRecovery);
// Selection policy.
//attribs.push_back(NSOpenGLPFAMinimumPolicy);
if (!properties.is_single_buffered()) {
attribs.push_back(NSOpenGLPFADoubleBuffer);
}
if (properties.is_stereo()) {
attribs.push_back(NSOpenGLPFAStereo);
}
int aux_buffers = properties.get_aux_rgba() + properties.get_aux_hrgba() + properties.get_aux_float();
attribs.push_back(NSOpenGLPFAAuxBuffers);
attribs.push_back(aux_buffers);
attribs.push_back(NSOpenGLPFAColorSize);
attribs.push_back(properties.get_color_bits());
attribs.push_back(NSOpenGLPFAAlphaSize);
attribs.push_back(properties.get_alpha_bits());
attribs.push_back(NSOpenGLPFADepthSize);
attribs.push_back(properties.get_depth_bits());
attribs.push_back(NSOpenGLPFAStencilSize);
attribs.push_back(properties.get_stencil_bits());
if (properties.get_multisamples() > 0) {
attribs.push_back(NSOpenGLPFASampleBuffers);
attribs.push_back(1);
attribs.push_back(NSOpenGLPFASamples);
attribs.push_back(properties.get_multisamples());
attribs.push_back(NSOpenGLPFAMultisample);
}
if (properties.get_force_software()) {
attribs.push_back(NSOpenGLPFARendererID);
attribs.push_back(kCGLRendererAppleSWID);
}
if (properties.get_force_hardware()) {
attribs.push_back(NSOpenGLPFAAccelerated);
}
if (need_window) {
//TODO: fullscreen != window on OSX
attribs.push_back(NSOpenGLPFAWindow);
//attribs.push_back(NSOpenGLPFAFullScreen);
}
if (need_pbuffer) {
attribs.push_back(NSOpenGLPFAPixelBuffer);
}
// Required when going fullscreen, optional when windowed
attribs.push_back(NSOpenGLPFAScreenMask);
attribs.push_back(CGDisplayIDToOpenGLDisplayMask(display));
attribs.push_back((NSOpenGLPixelFormatAttribute) nil);
// Create the format.
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: &attribs[0]];
if (format == nil) {
cocoadisplay_cat.error() <<
"Could not find a usable pixel format.\n";
return;
}
//XXX not sure what to do with virtual_screen, let's just set it to 0.
get_properties(_fbprops, format, 0);
_context = [[NSOpenGLContext alloc] initWithFormat: format shareContext: _share_context];
[format release];
if (_context == nil) {
cocoadisplay_cat.error() <<
"Failed to create OpenGL context!\n";
return;
}
// Set vsync setting on the context
GLint swap = sync_video ? 1 : 0;
[_context setValues:&swap forParameter:NSOpenGLCPSwapInterval];
cocoadisplay_cat.debug()
<< "Created context " << _context << ": " << _fbprops << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsStateGuardian::do_get_extension_func
// Access: Public, Virtual
// Description: Returns the pointer to the GL extension function with
// the indicated name. It is the responsibility of the
// caller to ensure that the required extension is
// defined in the OpenGL runtime prior to calling this;
// it is an error to call this for a function that is
// not defined.
////////////////////////////////////////////////////////////////////
void *CocoaGraphicsStateGuardian::
do_get_extension_func(const char *prefix, const char *name) {
char* fullname = (char*) malloc(strlen(prefix) + strlen(name) + 2);
strcpy(fullname + 1, prefix);
strcpy(fullname + 1 + strlen(prefix), name);
fullname[0] = '_';
// Believe it or not, but this is actually the
// Apple-recommended way to do it. I know, right?
if (NSIsSymbolNameDefined(fullname)) {
NSSymbol symbol = NSLookupAndBindSymbol(fullname);
free(fullname);
return (void *) NSAddressOfSymbol(symbol);
}
cocoadisplay_cat.error() <<
"do_get_extension_func failed for " << prefix << name << "!\n";
free(fullname);
return NULL;
}

View File

@ -0,0 +1,34 @@
// Filename: cocoaGraphicsWindow.I
// Created by: rdb (14May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsWindow::get_nswindow
// Access: Public
// Description: Returns a pointer to the underlying NSWindow.
////////////////////////////////////////////////////////////////////
INLINE NSWindow *CocoaGraphicsWindow::
get_nswindow() const {
return _window;
}
////////////////////////////////////////////////////////////////////
// Function: CocoaGraphicsWindow::get_nsview
// Access: Public
// Description: Returns a pointer to the underlying NSView.
////////////////////////////////////////////////////////////////////
INLINE NSView *CocoaGraphicsWindow::
get_nsview() const {
return _view;
}

View File

@ -0,0 +1,105 @@
// Filename: cocoaGraphicsWindow.h
// Created by: rdb (14May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef COCOAGRAPHICSWINDOW_H
#define COCOAGRAPHICSWINDOW_H
#include "pandabase.h"
#include "cocoaGraphicsPipe.h"
#include "graphicsWindow.h"
#import <AppKit/NSEvent.h>
#import <AppKit/NSView.h>
#import <AppKit/NSWindow.h>
////////////////////////////////////////////////////////////////////
// Class : CocoaGraphicsWindow
// Description : An interface to the Cocoa system for managing
// OpenGL windows under Mac OS X.
////////////////////////////////////////////////////////////////////
class CocoaGraphicsWindow : public GraphicsWindow {
public:
CocoaGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
const string &name,
const FrameBufferProperties &fb_prop,
const WindowProperties &win_prop,
int flags,
GraphicsStateGuardian *gsg,
GraphicsOutput *host);
virtual ~CocoaGraphicsWindow();
virtual bool move_pointer(int device, int x, int y);
virtual bool begin_frame(FrameMode mode, Thread *current_thread);
virtual void end_frame(FrameMode mode, Thread *current_thread);
virtual void end_flip();
virtual void process_events();
virtual void set_properties_now(WindowProperties &properties);
void handle_move_event();
void handle_resize_event();
void handle_minimize_event(bool minimized);
void handle_foreground_event(bool foreground);
bool handle_close_request();
void handle_close_event();
void handle_key_event(NSEvent *event);
void handle_mouse_button_event(int button, bool down);
void handle_mouse_moved_event(bool in_window, int x, int y, bool absolute);
void handle_wheel_event(double x, double y);
INLINE NSWindow *get_nswindow() const;
INLINE NSView *get_nsview() const;
protected:
virtual void close_window();
virtual bool open_window();
virtual void mouse_mode_absolute();
virtual void mouse_mode_relative();
private:
void set_wm_properties(const WindowProperties &properties,
bool already_mapped);
ButtonHandle map_function_key(unsigned short keycode);
private:
NSWindow *_window;
NSView *_view;
NSUInteger _modifier_keys;
CGDirectDisplayID _display;
bool _mouse_hidden;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
GraphicsWindow::init_type();
register_type(_type_handle, "CocoaGraphicsWindow",
GraphicsWindow::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "cocoaGraphicsWindow.I"
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
// Filename: cocoaPandaView.h
// Created by: rdb (17May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#import <AppKit/NSView.h>
class CocoaGraphicsWindow;
@interface CocoaPandaView : NSView {
@private
NSOpenGLContext *_context;
CocoaGraphicsWindow *_graphicsWindow;
}
- (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window;
- (BOOL) acceptsFirstResponder;
- (BOOL) becomeFirstResponder;
- (BOOL) resignFirstResponder;
- (void) setFrame: (NSRect) frame;
// Keyboard events
- (void) keyDown: (NSEvent *) event;
- (void) keyUp: (NSEvent *) event;
- (void) flagsChanged: (NSEvent *) event;
// Mouse events
- (void) mouseDown: (NSEvent *) event;
- (void) mouseDragged: (NSEvent *) event;
- (void) mouseUp: (NSEvent *) event;
- (void) mouseMoved: (NSEvent *) event;
- (void) rightMouseDown: (NSEvent *) event;
- (void) rightMouseDragged: (NSEvent *) event;
- (void) rightMouseUp: (NSEvent *) event;
- (void) otherMouseDown: (NSEvent *) event;
- (void) otherMouseDragged: (NSEvent *) event;
- (void) otherMouseUp: (NSEvent *) event;
- (void) scrollWheel: (NSEvent *) event;
- (BOOL) isOpaque;
@end

View File

@ -0,0 +1,129 @@
// Filename: cocoaPandaView.mm
// Created by: rdb (17May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#import "cocoaPandaView.h"
#import "cocoaGraphicsWindow.h"
#include <OpenGL/gl.h>
@implementation CocoaPandaView
- (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window {
self = [super initWithFrame: frameRect];
cocoadisplay_cat.debug()
<< "Created CocoaPandaView " << self << " for GraphicsWindow " << window << "\n";
_graphicsWindow = window;
// Make sure that the view automatically resizes with the window
//[self setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
return self;
}
- (BOOL) acceptsFirstResponder {
return YES;
}
- (BOOL) becomeFirstResponder {
return YES;
}
- (BOOL) resignFirstResponder {
return YES;
}
- (void) setFrame: (NSRect) frame {
[super setFrame: frame];
[_context update];
_graphicsWindow->handle_resize_event();
}
- (void) keyDown: (NSEvent *) event {
_graphicsWindow->handle_key_event(event);
}
- (void) keyUp: (NSEvent *) event {
_graphicsWindow->handle_key_event(event);
}
- (void) flagsChanged: (NSEvent *) event {
_graphicsWindow->handle_key_event(event);
}
- (void) mouseDown: (NSEvent *) event {
_graphicsWindow->handle_mouse_button_event(0, true);
}
- (void) mouseDragged: (NSEvent *) event {
[self mouseMoved: event];
}
- (void) mouseUp: (NSEvent *) event {
_graphicsWindow->handle_mouse_button_event(0, false);
}
- (void) mouseMoved: (NSEvent *) event {
NSPoint loc = [self convertPoint: [event locationInWindow] fromView: nil];
BOOL inside = [self mouse: loc inRect: [self bounds]];
if (_graphicsWindow->get_properties().get_mouse_mode() == WindowProperties::M_relative) {
_graphicsWindow->handle_mouse_moved_event(inside, [event deltaX], [event deltaY], false);
} else {
_graphicsWindow->handle_mouse_moved_event(inside, loc.x, [self bounds].size.height - loc.y, true);
}
}
- (void) rightMouseDown: (NSEvent *) event {
_graphicsWindow->handle_mouse_button_event(2, true);
}
- (void) rightMouseDragged: (NSEvent *) event {
[self mouseMoved: event];
}
- (void) rightMouseUp: (NSEvent *) event {
_graphicsWindow->handle_mouse_button_event(2, false);
}
- (void) otherMouseDown: (NSEvent *) event {
// 2 and 3 are swapped, for consistency with X11 implementation
if ([event buttonNumber] == 2) {
_graphicsWindow->handle_mouse_button_event(1, true);
} else {
_graphicsWindow->handle_mouse_button_event([event buttonNumber], true);
}
}
- (void) otherMouseDragged: (NSEvent *) event {
[self mouseMoved: event];
}
- (void) otherMouseUp: (NSEvent *) event {
// 2 and 3 are swapped, for consistency with X11 implementation
if ([event buttonNumber] == 2) {
_graphicsWindow->handle_mouse_button_event(1, false);
} else {
_graphicsWindow->handle_mouse_button_event([event buttonNumber], false);
}
}
- (void) scrollWheel: (NSEvent *) event {
_graphicsWindow->handle_wheel_event([event deltaX], [event deltaY]);
}
- (BOOL) isOpaque {
return YES;
}
@end

View File

@ -0,0 +1,27 @@
// Filename: cocoaPandaWindow.h
// Created by: rdb (25May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#import <AppKit/NSWindow.h>
class CocoaGraphicsWindow;
@interface CocoaPandaWindow : NSWindow {
@private
CocoaGraphicsWindow *_graphicsWindow;
}
- (id) initWithContentRect:(NSRect)rect styleMask:(NSUInteger)styleMask screen:(NSScreen*)screen window:(CocoaGraphicsWindow*)window;
- (BOOL)canBecomeKeyWindow;
@end

View File

@ -0,0 +1,44 @@
// Filename: cocoaPandaWindow.mm
// Created by: rdb (25May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#import "cocoaPandaWindow.h"
#import "cocoaPandaWindowDelegate.h"
@implementation CocoaPandaWindow
- (id) initWithContentRect:(NSRect)rect styleMask:(NSUInteger)styleMask screen:(NSScreen*)screen window:(CocoaGraphicsWindow*)window {
if (self = [super initWithContentRect:rect
styleMask:styleMask
backing:NSBackingStoreBuffered
defer:YES
screen:screen]) {
_graphicsWindow = window;
CocoaPandaWindowDelegate *delegate = [[CocoaPandaWindowDelegate alloc] initWithGraphicsWindow:window];
[self setDelegate:delegate];
[self setOpaque:YES];
// Necessary to be able to accept mouseMoved in the NSView
[self setAcceptsMouseMovedEvents:YES];
}
return self;
}
- (BOOL) canBecomeKeyWindow {
// Otherwise borderless windows won't be able to get keyboard events.
return YES;
}
@end

View File

@ -0,0 +1,36 @@
// Filename: cocoaPandaWindowDelegate.h
// Created by: rdb (24May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#import <AppKit/NSWindow.h>
class CocoaGraphicsWindow;
@interface CocoaPandaWindowDelegate : NSObject<NSWindowDelegate> {
@private
CocoaGraphicsWindow *_graphicsWindow;
}
- (id) initWithGraphicsWindow:(CocoaGraphicsWindow*)window;
- (void)windowDidMove:(NSNotification *)notification;
- (void)windowDidResize:(NSNotification *)notification;
- (void)windowDidMiniaturize:(NSNotification *)notification;
- (void)windowDidDeminiaturize:(NSNotification *)notification;
- (void)windowDidBecomeKey:(NSNotification *)notification;
- (void)windowDidResignKey:(NSNotification *)notification;
- (BOOL)windowShouldClose:(id)sender;
- (void)windowWillClose:(NSNotification *)notification;
//TODO: handle fullscreen on Lion.
@end

View File

@ -0,0 +1,61 @@
// Filename: cocoaPandaWindowDelegate.mm
// Created by: rdb (24May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#import "cocoaPandaWindowDelegate.h"
@implementation CocoaPandaWindowDelegate
- (id) initWithGraphicsWindow:(CocoaGraphicsWindow*)window {
if (self = [super init]) {
_graphicsWindow = window;
}
return self;
}
- (void) windowDidMove:(NSNotification *)notification {
_graphicsWindow->handle_move_event();
}
- (void) windowDidResize:(NSNotification *)notification {
// Forcing a move event is unfortunately necessary because
// Cocoa does not call windowDidMove in case of window zooms.
_graphicsWindow->handle_resize_event();
}
- (void) windowDidMiniaturize:(NSNotification *)notification {
_graphicsWindow->handle_minimize_event(true);
}
- (void) windowDidDeminiaturize:(NSNotification *)notification {
_graphicsWindow->handle_minimize_event(false);
}
- (void) windowDidBecomeKey:(NSNotification *)notification {
_graphicsWindow->handle_foreground_event(true);
}
- (void) windowDidResignKey:(NSNotification *)notification {
_graphicsWindow->handle_foreground_event(false);
}
- (BOOL) windowShouldClose:(id)sender {
return _graphicsWindow->handle_close_request();
}
- (void) windowWillClose:(NSNotification *)notification {
_graphicsWindow->handle_close_event();
}
@end

View File

@ -0,0 +1,25 @@
// Filename: config_cocoadisplay.h
// Created by: rdb (17May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef CONFIG_COCOADISPLAY_H
#define CONFIG_COCOADISPLAY_H
#include "pandabase.h"
#include "notifyCategoryProxy.h"
NotifyCategoryDecl(cocoadisplay, EXPCL_PANDAGL, EXPTP_PANDAGL);
extern EXPCL_PANDAGL void init_libcocoadisplay();
#endif

View File

@ -0,0 +1,56 @@
// Filename: config_cocoadisplay.cxx
// Created by: rdb (17May12)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "config_cocoadisplay.h"
#include "cocoaGraphicsPipe.h"
#include "cocoaGraphicsStateGuardian.h"
#include "cocoaGraphicsWindow.h"
#include "graphicsPipeSelection.h"
#include "dconfig.h"
#include "pandaSystem.h"
Configure(config_cocoadisplay);
NotifyCategoryDef(cocoadisplay, "display");
ConfigureFn(config_cocoadisplay) {
init_libcocoadisplay();
}
////////////////////////////////////////////////////////////////////
// Function: init_libcocoadisplay
// Description: Initializes the library. This must be called at
// least once before any of the functions or classes in
// this library can be used. Normally it will be
// called by the static initializers and need not be
// called explicitly, but special cases exist.
////////////////////////////////////////////////////////////////////
void
init_libcocoadisplay() {
static bool initialized = false;
if (initialized) {
return;
}
initialized = true;
CocoaGraphicsPipe::init_type();
CocoaGraphicsStateGuardian::init_type();
CocoaGraphicsWindow::init_type();
GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
selection->add_pipe_type(CocoaGraphicsPipe::get_class_type(),
CocoaGraphicsPipe::pipe_constructor);
PandaSystem *ps = PandaSystem::get_global_ptr();
ps->set_system_tag("OpenGL", "window_system", "Cocoa");
}

View File

@ -0,0 +1,7 @@
#include "config_cocoadisplay.mm"
#include "cocoaGraphicsPipe.mm"
#include "cocoaGraphicsStateGuardian.mm"
#include "cocoaGraphicsWindow.mm"
#include "cocoaPandaView.mm"
#include "cocoaPandaWindow.mm"
#include "cocoaPandaWindowDelegate.mm"