diff --git a/panda/src/cocoadisplay/cocoaGraphicsBuffer.I b/panda/src/cocoadisplay/cocoaGraphicsBuffer.I new file mode 100644 index 0000000000..1611af94d1 --- /dev/null +++ b/panda/src/cocoadisplay/cocoaGraphicsBuffer.I @@ -0,0 +1,12 @@ +/** + * 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." + * + * @file cocoaGraphicsBuffer.I + * @author rdb + * @date 2017-12-19 + */ diff --git a/panda/src/cocoadisplay/cocoaGraphicsBuffer.h b/panda/src/cocoadisplay/cocoaGraphicsBuffer.h new file mode 100644 index 0000000000..ab666b6f75 --- /dev/null +++ b/panda/src/cocoadisplay/cocoaGraphicsBuffer.h @@ -0,0 +1,61 @@ +/** + * 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." + * + * @file cocoaGraphicsBuffer.h + * @author rdb + * @date 2017-12-19 + */ + +#ifndef COCOAGRAPHICSBUFFER_H +#define COCOAGRAPHICSBUFFER_H + +#include "pandabase.h" +#include "glgsg.h" + +/** + * This is a light wrapper around GLGraphicsBuffer (ie. FBOs) to interface + * with Cocoa contexts, so that it can be used without a host window. + */ +class CocoaGraphicsBuffer : public GLGraphicsBuffer { +public: + CocoaGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe, + const string &name, + const FrameBufferProperties &fb_prop, + const WindowProperties &win_prop, + int flags, + GraphicsStateGuardian *gsg, + GraphicsOutput *host); + + 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(); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + GLGraphicsBuffer::init_type(); + register_type(_type_handle, "CocoaGraphicsBuffer", + GLGraphicsBuffer::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 "cocoaGraphicsBuffer.I" + +#endif diff --git a/panda/src/cocoadisplay/cocoaGraphicsBuffer.mm b/panda/src/cocoadisplay/cocoaGraphicsBuffer.mm new file mode 100644 index 0000000000..ea6fb61e4e --- /dev/null +++ b/panda/src/cocoadisplay/cocoaGraphicsBuffer.mm @@ -0,0 +1,165 @@ +/** + * 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." + * + * @file cocoaGraphicsBuffer.mm + * @author rdb + * @date 2017-12-19 + */ + +#include "cocoaGraphicsBuffer.h" +#include "cocoaGraphicsStateGuardian.h" +#include "config_cocoadisplay.h" +#include "cocoaGraphicsPipe.h" + +#import + +TypeHandle CocoaGraphicsBuffer::_type_handle; + +/** + * + */ +CocoaGraphicsBuffer:: +CocoaGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe, + const string &name, + const FrameBufferProperties &fb_prop, + const WindowProperties &win_prop, + int flags, + GraphicsStateGuardian *gsg, + GraphicsOutput *host) : // Ignore the host. + GLGraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, nullptr) +{ +} + +/** + * 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 CocoaGraphicsBuffer:: +begin_frame(FrameMode mode, Thread *current_thread) { + if (_gsg == nullptr) { + return false; + } + + CocoaGraphicsStateGuardian *cocoagsg; + DCAST_INTO_R(cocoagsg, _gsg, false); + nassertr(cocoagsg->_context != nil, false); + + // Lock the context and make it current. + { + PStatTimer timer(_make_current_pcollector, current_thread); + cocoagsg->lock_context(); + [cocoagsg->_context makeCurrentContext]; + } + + return GLGraphicsBuffer::begin_frame(mode, current_thread); +} + +/** + * 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 CocoaGraphicsBuffer:: +end_frame(FrameMode mode, Thread *current_thread) { + nassertv(_gsg != nullptr); + + GLGraphicsBuffer::end_frame(mode, current_thread); + + // Release the context. + CocoaGraphicsStateGuardian *cocoagsg; + DCAST_INTO_V(cocoagsg, _gsg); + cocoagsg->unlock_context(); +} + +/** + * 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 CocoaGraphicsBuffer:: +open_buffer() { + CocoaGraphicsPipe *cocoa_pipe; + DCAST_INTO_R(cocoa_pipe, _pipe, false); + + // GSG CreationInitialization + CocoaGraphicsStateGuardian *cocoagsg; + if (_gsg == nullptr) { + // There is no old gsg. Create a new one. + cocoagsg = new CocoaGraphicsStateGuardian(_engine, _pipe, nullptr); + cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->get_display_id(), false); + _gsg = cocoagsg; + } else { + // If the old gsg has the wrong pixel format, create a new one that shares + // with the old gsg. + DCAST_INTO_R(cocoagsg, _gsg, false); + if (!cocoagsg->get_fb_properties().subsumes(_fb_properties)) { + cocoagsg = new CocoaGraphicsStateGuardian(_engine, _pipe, cocoagsg); + cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->get_display_id(), false); + _gsg = cocoagsg; + } + } + + FrameBufferProperties desired_props(_fb_properties); + + // Lock the context, so we can safely operate on it. + cocoagsg->lock_context(); + + // Make the context current and initialize what we need. + [cocoagsg->_context makeCurrentContext]; + [cocoagsg->_context update]; + cocoagsg->reset_if_new(); + + // These properties are determined by choose_pixel_format. + _fb_properties.set_force_hardware(cocoagsg->_fbprops.get_force_hardware()); + _fb_properties.set_force_software(cocoagsg->_fbprops.get_force_software()); + + bool success = GLGraphicsBuffer::open_buffer(); + if (success) { + rebuild_bitplanes(); + if (_needs_rebuild) { + // If it still needs rebuild, then something must have gone wrong. + success = false; + } + } + + if (success && !_fb_properties.verify_hardware_software + (desired_props, cocoagsg->get_gl_renderer())) { + GLGraphicsBuffer::close_buffer(); + success = false; + } + + // Release the context. + cocoagsg->unlock_context(); + + if (!success) { + return false; + } + + return true; +} + +/** + * Closes the buffer right now. Called from the window thread. + */ +void CocoaGraphicsBuffer:: +close_buffer() { + if (_gsg != nullptr) { + CocoaGraphicsStateGuardian *cocoagsg; + cocoagsg = DCAST(CocoaGraphicsStateGuardian, _gsg); + + if (cocoagsg != nullptr && cocoagsg->_context != nil) { + cocoagsg->lock_context(); + GLGraphicsBuffer::close_buffer(); + cocoagsg->unlock_context(); + } + _gsg.clear(); + } else { + GLGraphicsBuffer::close_buffer(); + } +} diff --git a/panda/src/cocoadisplay/cocoaGraphicsPipe.I b/panda/src/cocoadisplay/cocoaGraphicsPipe.I index 874bf12fea..0ac4a79d83 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsPipe.I +++ b/panda/src/cocoadisplay/cocoaGraphicsPipe.I @@ -18,11 +18,3 @@ INLINE CGDirectDisplayID CocoaGraphicsPipe:: get_display_id() const { return _display; } - -/** - * Returns the Cocoa NSScreen pointer associated with this graphics pipe. - */ -INLINE NSScreen *CocoaGraphicsPipe:: -get_nsscreen() const { - return _screen; -} diff --git a/panda/src/cocoadisplay/cocoaGraphicsPipe.h b/panda/src/cocoadisplay/cocoaGraphicsPipe.h index d53456e332..6f2f863e9c 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsPipe.h +++ b/panda/src/cocoadisplay/cocoaGraphicsPipe.h @@ -35,13 +35,10 @@ class FrameBufferProperties; */ class CocoaGraphicsPipe : public GraphicsPipe { public: - CocoaGraphicsPipe(); - CocoaGraphicsPipe(CGDirectDisplayID display); - CocoaGraphicsPipe(NSScreen *screen); + CocoaGraphicsPipe(CGDirectDisplayID display = CGMainDisplayID()); virtual ~CocoaGraphicsPipe(); INLINE CGDirectDisplayID get_display_id() const; - INLINE NSScreen *get_nsscreen() const; virtual string get_interface_name() const; static PT(GraphicsPipe) pipe_constructor(); @@ -64,11 +61,8 @@ protected: 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. + // This is the Quartz display identifier. CGDirectDisplayID _display; - NSScreen *_screen; friend class CocoaGraphicsWindow; diff --git a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm index 10bef93e2e..0baa94f8ed 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm @@ -12,7 +12,7 @@ */ #include "cocoaGraphicsPipe.h" -// #include "cocoaGraphicsBuffer.h" +#include "cocoaGraphicsBuffer.h" #include "cocoaGraphicsWindow.h" #include "cocoaGraphicsStateGuardian.h" #include "cocoaPandaApp.h" @@ -30,104 +30,32 @@ TypeHandle CocoaGraphicsPipe::_type_handle; -static void init_app() { - if (NSApp == nil) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [CocoaPandaApp sharedApplication]; - -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; -#endif - [NSApp finishLaunching]; - [NSApp activateIgnoringOtherApps:YES]; - - // Put Cocoa into thread-safe mode by spawning a thread which immediately - // exits. - NSThread* thread = [[NSThread alloc] init]; - [thread start]; - [thread autorelease]; - } -} - /** - * Uses the main screen (the one the user is most likely to be working in at - * the moment). + * Takes a CoreGraphics display ID, which defaults to the main display. */ CocoaGraphicsPipe:: -CocoaGraphicsPipe() { +CocoaGraphicsPipe(CGDirectDisplayID display) : _display(display) { _supported_types = OT_window | OT_buffer | OT_texture_buffer; _is_valid = true; - init_app(); + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - _screen = [NSScreen mainScreen]; - NSNumber *num = [[_screen deviceDescription] objectForKey: @"NSScreenNumber"]; - _display = (CGDirectDisplayID) [num longValue]; + // Put Cocoa into thread-safe mode by spawning a thread which immediately + // exits. + NSThread* thread = [[NSThread alloc] init]; + [thread start]; + [thread autorelease]; + + // We used to also obtain the corresponding NSScreen here, but this causes + // the application icon to start bouncing, which may be undesirable for + // apps that will never open a window. _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"; -} - -/** - * 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 longValue]) { - _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"; -} - -/** - * 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 longValue]; - - _display_width = CGDisplayPixelsWide(_display); - _display_height = CGDisplayPixelsHigh(_display); - load_display_information(); - - cocoadisplay_cat.debug() - << "Creating CocoaGraphicsPipe for screen " - << _screen << " with display ID " << _display << "\n"; + << "Creating CocoaGraphicsPipe for display ID " << _display << "\n"; } /** @@ -308,10 +236,12 @@ make_output(const string &name, flags, gsg, host); } - // Second thing to try: a GLGraphicsBuffer + // Second thing to try: a GLGraphicsBuffer. This requires a context, so if + // we don't have a host window, we instead create a CocoaGraphicsBuffer, + // which wraps around GLGraphicsBuffer and manages a context. if (retry == 1) { - if (!gl_support_fbo || host == NULL || + if (!gl_support_fbo || (flags & (BF_require_parasite | BF_require_window)) != 0) { return NULL; } @@ -334,33 +264,14 @@ make_output(const string &name, 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)|| - ((flags&BF_can_bind_layered)!=0)) { - return NULL; + if (host != NULL) { + return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop, + flags, gsg, host); + } else { + return new CocoaGraphicsBuffer(engine, this, name, fb_prop, win_prop, + flags, gsg, host); } - - 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; diff --git a/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.I b/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.I index d593a3fe86..586df26850 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.I +++ b/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.I @@ -19,3 +19,21 @@ INLINE const FrameBufferProperties &CocoaGraphicsStateGuardian:: get_fb_properties() const { return _fbprops; } + +/** + * Locks the context. + */ +INLINE void CocoaGraphicsStateGuardian:: +lock_context() { + nassertv(_context != nil); + CGLLockContext((CGLContextObj) [_context CGLContextObj]); +} + +/** + * Unlocks the context. + */ +INLINE void CocoaGraphicsStateGuardian:: +unlock_context() { + nassertv(_context != nil); + CGLUnlockContext((CGLContextObj) [_context CGLContextObj]); +} diff --git a/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h b/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h index a2420e55c2..2e83e60c34 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h +++ b/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h @@ -19,6 +19,7 @@ #include "glgsg.h" #import +#import /** * A tiny specialization on GLGraphicsStateGuardian to add some Cocoa-specific @@ -38,6 +39,9 @@ public: virtual ~CocoaGraphicsStateGuardian(); + INLINE void lock_context(); + INLINE void unlock_context(); + NSOpenGLContext *_share_context; NSOpenGLContext *_context; FrameBufferProperties _fbprops; diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm index ebc9255d63..426c06cc78 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm @@ -65,6 +65,16 @@ CocoaGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, _fullscreen_mode = NULL; _windowed_mode = NULL; + // Now that we know for sure we want a window, we can create the Cocoa app. + // This will cause the application icon to appear and start bouncing. + if (NSApp == nil) { +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; +#endif + [NSApp finishLaunching]; + [NSApp activateIgnoringOtherApps:YES]; + } + GraphicsWindowInputDevice device = GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse"); add_input_device(device); @@ -144,7 +154,7 @@ begin_frame(FrameMode mode, Thread *current_thread) { nassertr(_view != nil, false); // Place a lock on the context. - CGLLockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); + cocoagsg->lock_context(); // Set the drawable. if (_properties.get_fullscreen()) { @@ -210,7 +220,7 @@ end_frame(FrameMode mode, Thread *current_thread) { CocoaGraphicsStateGuardian *cocoagsg; DCAST_INTO_V(cocoagsg, _gsg); - CGLUnlockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); + cocoagsg->unlock_context(); if (mode == FM_render) { // end_render_texture(); @@ -239,7 +249,7 @@ end_flip() { CocoaGraphicsStateGuardian *cocoagsg; DCAST_INTO_V(cocoagsg, _gsg); - CGLLockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); + cocoagsg->lock_context(); // Swap the front and back buffer. [cocoagsg->_context flushBuffer]; @@ -247,7 +257,7 @@ end_flip() { // Flush the window [[_view window] flushWindow]; - CGLUnlockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); + cocoagsg->unlock_context(); } GraphicsWindow::end_flip(); } @@ -399,6 +409,16 @@ open_window() { } } + // Iterate over the screens to find the one with our display ID. + NSScreen *screen; + NSEnumerator *e = [[NSScreen screens] objectEnumerator]; + while (screen = (NSScreen *) [e nextObject]) { + NSNumber *num = [[screen deviceDescription] objectForKey: @"NSScreenNumber"]; + if (cocoa_pipe->_display == (CGDirectDisplayID) [num longValue]) { + break; + } + } + // Center the window if coordinates were set to -1 or -2 TODO: perhaps in // future, in the case of -1, it should use the origin used in a previous // run of Panda @@ -406,7 +426,7 @@ open_window() { if (parent_nsview != NULL) { container = [parent_nsview bounds]; } else { - container = [cocoa_pipe->_screen frame]; + container = [screen frame]; container.origin = NSMakePoint(0, 0); } int x = _properties.get_x_origin(); @@ -453,7 +473,7 @@ open_window() { _window = [[CocoaPandaWindow alloc] initWithContentRect: rect styleMask:windowStyle - screen:cocoa_pipe->_screen + screen:screen window:this]; if (_window == nil) { @@ -464,7 +484,7 @@ open_window() { } // Lock the context, so we can safely operate on it. - CGLLockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); + cocoagsg->lock_context(); // Create the NSView to render to. NSRect rect = NSMakeRect(0, 0, _properties.get_x_size(), _properties.get_y_size()); @@ -588,7 +608,7 @@ open_window() { cocoagsg->reset_if_new(); // Release the context. - CGLUnlockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); + cocoagsg->unlock_context(); if (!cocoagsg->is_valid()) { close_window(); @@ -637,9 +657,9 @@ close_window() { cocoagsg = DCAST(CocoaGraphicsStateGuardian, _gsg); if (cocoagsg != NULL && cocoagsg->_context != nil) { - CGLLockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); + cocoagsg->lock_context(); [cocoagsg->_context clearDrawable]; - CGLUnlockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); + cocoagsg->unlock_context(); } _gsg.clear(); } @@ -1429,9 +1449,9 @@ handle_close_event() { cocoagsg = DCAST(CocoaGraphicsStateGuardian, _gsg); if (cocoagsg != NULL && cocoagsg->_context != nil) { - CGLLockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); + cocoagsg->lock_context(); [cocoagsg->_context clearDrawable]; - CGLUnlockContext((CGLContextObj) [cocoagsg->_context CGLContextObj]); + cocoagsg->unlock_context(); } _gsg.clear(); } diff --git a/panda/src/cocoadisplay/config_cocoadisplay.mm b/panda/src/cocoadisplay/config_cocoadisplay.mm index 4f67bc1438..42f2f98a8f 100644 --- a/panda/src/cocoadisplay/config_cocoadisplay.mm +++ b/panda/src/cocoadisplay/config_cocoadisplay.mm @@ -12,6 +12,7 @@ */ #include "config_cocoadisplay.h" +#include "cocoaGraphicsBuffer.h" #include "cocoaGraphicsPipe.h" #include "cocoaGraphicsStateGuardian.h" #include "cocoaGraphicsWindow.h" @@ -40,6 +41,7 @@ init_libcocoadisplay() { } initialized = true; + CocoaGraphicsBuffer::init_type(); CocoaGraphicsPipe::init_type(); CocoaGraphicsStateGuardian::init_type(); CocoaGraphicsWindow::init_type(); diff --git a/panda/src/cocoadisplay/p3cocoadisplay_composite1.mm b/panda/src/cocoadisplay/p3cocoadisplay_composite1.mm index 28755a66dd..e85d1e08eb 100644 --- a/panda/src/cocoadisplay/p3cocoadisplay_composite1.mm +++ b/panda/src/cocoadisplay/p3cocoadisplay_composite1.mm @@ -1,4 +1,5 @@ #include "config_cocoadisplay.mm" +#include "cocoaGraphicsBuffer.mm" #include "cocoaGraphicsPipe.mm" #include "cocoaGraphicsStateGuardian.mm" #include "cocoaGraphicsWindow.mm" diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index e76f8fccb9..43f3dbd809 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -213,12 +213,20 @@ begin_frame(FrameMode mode, Thread *current_thread) { return false; } - if (!_host->begin_frame(FM_parasite, current_thread)) { - if (GLCAT.is_debug()) { - GLCAT.debug() - << get_name() << "'s host is not ready\n"; + if (_host != nullptr) { + if (!_host->begin_frame(FM_parasite, current_thread)) { + if (GLCAT.is_debug()) { + GLCAT.debug() + << get_name() << "'s host is not ready\n"; + } + return false; + } + } else { + // We don't have a host window, which is possible for CocoaGraphicsBuffer. + _gsg->set_current_properties(&get_fb_properties()); + if (!_gsg->begin_frame(current_thread)) { + return false; } - return false; } // Figure out the desired size of the buffer. @@ -235,7 +243,7 @@ begin_frame(FrameMode mode, Thread *current_thread) { } } if (_creation_flags & GraphicsPipe::BF_size_track_host) { - if (_host->get_size() != _size) { + if (_host != nullptr && _host->get_size() != _size) { // We also need to rebuild if we need to change size. _needs_rebuild = true; } @@ -356,7 +364,7 @@ rebuild_bitplanes() { // Calculate bitplane size. This can be larger than the buffer. if (_creation_flags & GraphicsPipe::BF_size_track_host) { - if (_host->get_size() != _size) { + if (_host != nullptr && _host->get_size() != _size) { set_size_and_recalc(_host->get_x_size(), _host->get_y_size()); } @@ -1253,7 +1261,11 @@ end_frame(FrameMode mode, Thread *current_thread) { generate_mipmaps(); } - _host->end_frame(FM_parasite, current_thread); + if (_host != nullptr) { + _host->end_frame(FM_parasite, current_thread); + } else { + glgsg->end_frame(current_thread); + } if (mode == FM_render) { trigger_flip(); @@ -1315,8 +1327,11 @@ bool CLP(GraphicsBuffer):: open_buffer() { report_my_gl_errors(); - // Double check that we have a host - nassertr(_host != 0, false); + // Double check that we have a valid gsg + nassertr(_gsg != nullptr, false); + if (!_gsg->is_valid()) { + return false; + } // Count total color buffers. int totalcolor = @@ -1491,8 +1506,10 @@ open_buffer() { _fb_properties.set_back_buffers(0); _fb_properties.set_indexed_color(0); _fb_properties.set_rgb_color(1); - _fb_properties.set_force_hardware(_host->get_fb_properties().get_force_hardware()); - _fb_properties.set_force_software(_host->get_fb_properties().get_force_software()); + if (_host != nullptr) { + _fb_properties.set_force_hardware(_host->get_fb_properties().get_force_hardware()); + _fb_properties.set_force_software(_host->get_fb_properties().get_force_software()); + } _is_valid = true; _needs_rebuild = true; @@ -1508,7 +1525,7 @@ open_buffer() { */ GraphicsOutput *CLP(GraphicsBuffer):: get_host() { - return _host; + return (_host != nullptr) ? _host : this; } /** @@ -1699,7 +1716,7 @@ report_my_errors(int line, const char *file) { */ void CLP(GraphicsBuffer):: check_host_valid() { - if ((_host == 0)||(!_host->is_valid())) { + if (_host != nullptr && !_host->is_valid()) { _rb_data_size_bytes = 0; if (_rb_context != NULL) { // We must delete this object first, because when the GSG destructs, so diff --git a/panda/src/glstuff/glGraphicsBuffer_src.h b/panda/src/glstuff/glGraphicsBuffer_src.h index d119148247..31f7c91912 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.h +++ b/panda/src/glstuff/glGraphicsBuffer_src.h @@ -86,8 +86,6 @@ protected: void report_my_errors(int line, const char *file); -private: - void bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane plane, GLenum attachpoint); void bind_slot_multisample(bool rb_resize, Texture **attach,