mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-28 15:53:55 -04:00
cocoa: Split out GL-specific code into new cocoagldisplay module
This makes it possible to create subclasses for tinydisplay and vulkandisplay without having to duplicate code
This commit is contained in:
parent
4bb6d8f6d8
commit
545ede9d94
@ -3288,6 +3288,8 @@ if GetTarget() == 'windows':
|
||||
CopyAllHeaders('panda/src/wgldisplay')
|
||||
elif GetTarget() == 'darwin':
|
||||
CopyAllHeaders('panda/src/cocoadisplay')
|
||||
if not PkgSkip('GL'):
|
||||
CopyAllHeaders('panda/src/cocoagldisplay')
|
||||
elif GetTarget() == 'android':
|
||||
CopyAllHeaders('panda/src/android')
|
||||
CopyAllHeaders('panda/src/androiddisplay')
|
||||
@ -4647,15 +4649,24 @@ if GetTarget() not in ['windows', 'darwin'] and not PkgSkip("GL") and not PkgSki
|
||||
# DIRECTORY: panda/src/cocoadisplay/
|
||||
#
|
||||
|
||||
if GetTarget() == 'darwin' and PkgSkip("COCOA")==0 and not PkgSkip("GL"):
|
||||
OPTS=['DIR:panda/src/cocoadisplay', 'BUILDING:PANDAGL', 'GL', 'NVIDIACG', 'CGGL']
|
||||
if GetTarget() == 'darwin' and not PkgSkip("COCOA"):
|
||||
OPTS=['DIR:panda/src/cocoadisplay', 'BUILDING:PANDAGL', 'COCOA']
|
||||
TargetAdd('p3cocoadisplay_composite1.obj', opts=OPTS, input='p3cocoadisplay_composite1.mm')
|
||||
|
||||
#
|
||||
# DIRECTORY: panda/src/cocoagldisplay/
|
||||
#
|
||||
|
||||
if GetTarget() == 'darwin' and not PkgSkip("COCOA") and not PkgSkip("GL"):
|
||||
OPTS=['DIR:panda/src/cocoagldisplay', 'BUILDING:PANDAGL', 'GL', 'NVIDIACG', 'CGGL']
|
||||
TargetAdd('p3cocoagldisplay_composite1.obj', opts=OPTS, input='p3cocoagldisplay_composite1.mm')
|
||||
OPTS=['DIR:panda/metalibs/pandagl', 'BUILDING:PANDAGL', 'GL', 'NVIDIACG', 'CGGL']
|
||||
TargetAdd('pandagl_pandagl.obj', opts=OPTS, input='pandagl.cxx')
|
||||
TargetAdd('libpandagl.dll', input='pandagl_pandagl.obj')
|
||||
TargetAdd('libpandagl.dll', input='p3glgsg_config_glgsg.obj')
|
||||
TargetAdd('libpandagl.dll', input='p3glgsg_glgsg.obj')
|
||||
TargetAdd('libpandagl.dll', input='p3cocoadisplay_composite1.obj')
|
||||
TargetAdd('libpandagl.dll', input='p3cocoagldisplay_composite1.obj')
|
||||
if not PkgSkip('PANDAFX'):
|
||||
TargetAdd('libpandagl.dll', input='libpandafx.dll')
|
||||
TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS)
|
||||
|
@ -8,6 +8,7 @@ add_subdirectory(src/audiotraits)
|
||||
add_subdirectory(src/chan)
|
||||
add_subdirectory(src/char)
|
||||
add_subdirectory(src/cocoadisplay)
|
||||
add_subdirectory(src/cocoagldisplay)
|
||||
add_subdirectory(src/collide)
|
||||
add_subdirectory(src/configfiles)
|
||||
add_subdirectory(src/cull)
|
||||
|
@ -13,9 +13,9 @@ elseif(HAVE_WGL)
|
||||
set(PANDAGL_PIPE_TYPE "wglGraphicsPipe")
|
||||
|
||||
elseif(HAVE_COCOA)
|
||||
list(APPEND PANDAGL_LINK_TARGETS p3cocoadisplay)
|
||||
set(PANDAGL_PIPE_TYPE "CocoaGraphicsPipe")
|
||||
set(PANDAGL_PIPE_INCLUDE "cocoaGraphicsPipe.h")
|
||||
list(APPEND PANDAGL_LINK_TARGETS p3cocoagldisplay p3cocoadisplay)
|
||||
set(PANDAGL_PIPE_TYPE "CocoaGLGraphicsPipe")
|
||||
set(PANDAGL_PIPE_INCLUDE "cocoaGLGraphicsPipe.h")
|
||||
|
||||
else()
|
||||
message("") # Add extra line before error
|
||||
|
@ -13,9 +13,9 @@
|
||||
#include "wglGraphicsPipe.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_COCOA)
|
||||
#include "config_cocoadisplay.h"
|
||||
#include "cocoaGraphicsPipe.h"
|
||||
#ifdef HAVE_COCOA
|
||||
#include "config_cocoagldisplay.h"
|
||||
#include "cocoaGLGraphicsPipe.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLX
|
||||
@ -46,8 +46,8 @@ init_libpandagl() {
|
||||
init_libwgldisplay();
|
||||
#endif // HAVE_GL
|
||||
|
||||
#if defined(HAVE_COCOA)
|
||||
init_libcocoadisplay();
|
||||
#ifdef HAVE_COCOA
|
||||
init_libcocoagldisplay();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLX
|
||||
@ -69,8 +69,8 @@ get_pipe_type_pandagl() {
|
||||
return wglGraphicsPipe::get_class_type().get_index();
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_COCOA)
|
||||
return CocoaGraphicsPipe::get_class_type().get_index();
|
||||
#ifdef HAVE_COCOA
|
||||
return CocoaGLGraphicsPipe::get_class_type().get_index();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLX
|
||||
|
@ -1,13 +1,11 @@
|
||||
if(NOT APPLE OR NOT HAVE_GL OR NOT HAVE_COCOA)
|
||||
if(NOT APPLE OR NOT HAVE_COCOA)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(P3COCOADISPLAY_HEADERS
|
||||
config_cocoadisplay.h
|
||||
cocoaGraphicsBuffer.h cocoaGraphicsBuffer.I
|
||||
cocoaGraphicsPipe.h cocoaGraphicsPipe.I
|
||||
cocoaGraphicsWindow.h cocoaGraphicsWindow.I
|
||||
cocoaGraphicsStateGuardian.h cocoaGraphicsStateGuardian.I
|
||||
cocoaPandaApp.h
|
||||
cocoaPandaView.h
|
||||
cocoaPandaWindow.h
|
||||
@ -17,9 +15,7 @@ set(P3COCOADISPLAY_HEADERS
|
||||
|
||||
set(P3COCOADISPLAY_SOURCES
|
||||
config_cocoadisplay.mm
|
||||
cocoaGraphicsBuffer.mm
|
||||
cocoaGraphicsPipe.mm
|
||||
cocoaGraphicsStateGuardian.mm
|
||||
cocoaGraphicsWindow.mm
|
||||
cocoaPandaApp.mm
|
||||
cocoaPandaView.mm
|
||||
@ -31,7 +27,7 @@ set(P3COCOADISPLAY_SOURCES
|
||||
composite_sources(p3cocoadisplay P3COCOADISPLAY_SOURCES)
|
||||
add_component_library(p3cocoadisplay SYMBOL BUILDING_PANDA_COCOADISPLAY
|
||||
${P3COCOADISPLAY_HEADERS} ${P3COCOADISPLAY_SOURCES})
|
||||
target_link_libraries(p3cocoadisplay p3glgsg panda)
|
||||
target_link_libraries(p3cocoadisplay panda)
|
||||
|
||||
# Frameworks:
|
||||
find_library(APPLICATIONSERVICES_LIBRARY ApplicationServices)
|
||||
@ -46,5 +42,5 @@ mark_as_advanced(
|
||||
APPLICATIONSERVICES_LIBRARY APPKIT_LIBRARY CARBON_LIBRARY CORE_VIDEO_LIBRARY)
|
||||
|
||||
if(NOT BUILD_METALIBS)
|
||||
install(TARGETS p3cocoadisplay EXPORT OpenGL COMPONENT OpenGL DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(TARGETS p3cocoadisplay EXPORT Core COMPONENT Core DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
@ -15,22 +15,12 @@
|
||||
#define COCOAGRAPHICSPIPE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "graphicsPipe.h"
|
||||
#include "lightMutex.h"
|
||||
#include "lightReMutex.h"
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <AppKit/NSScreen.h>
|
||||
#else
|
||||
struct NSScreen;
|
||||
#endif
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
|
||||
class FrameBufferProperties;
|
||||
|
||||
/**
|
||||
* This graphics pipe represents the interface for creating OpenGL graphics
|
||||
* This graphics pipe represents the base class for pipes that create
|
||||
* windows on a Cocoa-based (e.g. Mac OS X) client.
|
||||
*/
|
||||
class EXPCL_PANDA_COCOADISPLAY CocoaGraphicsPipe : public GraphicsPipe {
|
||||
@ -40,32 +30,15 @@ public:
|
||||
|
||||
INLINE CGDirectDisplayID get_display_id() const;
|
||||
|
||||
virtual std::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 std::string &name,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
const WindowProperties &win_prop,
|
||||
int flags,
|
||||
GraphicsEngine *engine,
|
||||
GraphicsStateGuardian *gsg,
|
||||
GraphicsOutput *host,
|
||||
int retry,
|
||||
bool &precertify);
|
||||
virtual PT(GraphicsStateGuardian) make_callback_gsg(GraphicsEngine *engine);
|
||||
|
||||
private:
|
||||
void load_display_information();
|
||||
|
||||
// This is the Quartz display identifier.
|
||||
CGDirectDisplayID _display;
|
||||
|
||||
friend class CocoaGraphicsWindow;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
@ -12,11 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "cocoaGraphicsPipe.h"
|
||||
#include "cocoaGraphicsBuffer.h"
|
||||
#include "cocoaGraphicsWindow.h"
|
||||
#include "cocoaGraphicsStateGuardian.h"
|
||||
#include "config_cocoadisplay.h"
|
||||
#include "frameBufferProperties.h"
|
||||
#include "displayInformation.h"
|
||||
|
||||
#import <Foundation/NSAutoreleasePool.h>
|
||||
@ -32,9 +28,6 @@ TypeHandle CocoaGraphicsPipe::_type_handle;
|
||||
*/
|
||||
CocoaGraphicsPipe::
|
||||
CocoaGraphicsPipe(CGDirectDisplayID display) : _display(display) {
|
||||
_supported_types = OT_window | OT_buffer | OT_texture_buffer;
|
||||
_is_valid = true;
|
||||
|
||||
[[NSAutoreleasePool alloc] init];
|
||||
|
||||
// Put Cocoa into thread-safe mode by spawning a thread which immediately
|
||||
@ -110,7 +103,7 @@ load_display_information() {
|
||||
}
|
||||
CFRelease(encoding);
|
||||
}
|
||||
if (modes != NULL) {
|
||||
if (modes != nullptr) {
|
||||
CFRelease(modes);
|
||||
}
|
||||
|
||||
@ -135,26 +128,6 @@ CocoaGraphicsPipe::
|
||||
~CocoaGraphicsPipe() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
std::string CocoaGraphicsPipe::
|
||||
get_interface_name() const {
|
||||
return "OpenGL";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an indication of the thread in which this GraphicsPipe requires its
|
||||
* window processing to be performed: typically either the app thread (e.g.
|
||||
@ -166,95 +139,3 @@ CocoaGraphicsPipe::get_preferred_window_thread() const {
|
||||
// only be called from the main thread!
|
||||
return PWT_app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new window on the pipe, if possible.
|
||||
*/
|
||||
PT(GraphicsOutput) CocoaGraphicsPipe::
|
||||
make_output(const std::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)||
|
||||
((flags&BF_can_bind_layered)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
return new CocoaGraphicsWindow(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}
|
||||
|
||||
// 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 ||
|
||||
(flags & (BF_require_parasite | 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() ||
|
||||
fb_prop.get_back_buffers() > 0 ||
|
||||
fb_prop.get_accum_bits() > 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (cocoagsg != NULL && cocoagsg->is_valid() && !cocoagsg->needs_reset()) {
|
||||
if (!cocoagsg->_supports_framebuffer_object ||
|
||||
cocoagsg->_glDrawBuffers == NULL) {
|
||||
return NULL;
|
||||
} else if (fb_prop.is_basic()) {
|
||||
// Early success - if we are sure that this buffer WILL meet specs, we
|
||||
// can precertify it.
|
||||
precertify = true;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing else left to try.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when make_output() is used to create a
|
||||
* CallbackGraphicsWindow. If the GraphicsPipe can construct a GSG that's not
|
||||
* associated with any particular window object, do so now, assuming the
|
||||
* correct graphics context has been set up externally.
|
||||
*/
|
||||
PT(GraphicsStateGuardian) CocoaGraphicsPipe::
|
||||
make_callback_gsg(GraphicsEngine *engine) {
|
||||
return new CocoaGraphicsStateGuardian(engine, this, NULL);
|
||||
}
|
||||
|
@ -19,11 +19,21 @@
|
||||
#include "cocoaGraphicsPipe.h"
|
||||
#include "graphicsWindow.h"
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <AppKit/NSEvent.h>
|
||||
#import <AppKit/NSView.h>
|
||||
#import <AppKit/NSWindow.h>
|
||||
|
||||
#import <CoreVideo/CoreVideo.h>
|
||||
#else
|
||||
#include <objc/objc.h>
|
||||
typedef objc_object NSCursor;
|
||||
typedef objc_object NSData;
|
||||
typedef objc_object NSEvent;
|
||||
typedef objc_object NSImage;
|
||||
typedef objc_object NSView;
|
||||
typedef objc_object NSWindow;
|
||||
typedef unsigned long NSUInteger;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* An interface to the Cocoa system for managing OpenGL windows under Mac OS
|
||||
@ -41,13 +51,13 @@ public:
|
||||
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);
|
||||
|
||||
virtual void update_context();
|
||||
virtual void unbind_context();
|
||||
|
||||
void handle_move_event();
|
||||
void handle_resize_event();
|
||||
void handle_minimize_event(bool minimized);
|
||||
@ -81,7 +91,7 @@ private:
|
||||
ButtonHandle map_key(unsigned short c) const;
|
||||
ButtonHandle map_raw_key(unsigned short keycode) const;
|
||||
|
||||
private:
|
||||
protected:
|
||||
NSWindow *_window;
|
||||
NSView *_view;
|
||||
NSUInteger _modifier_keys;
|
||||
@ -90,7 +100,6 @@ private:
|
||||
PT(GraphicsWindowInputDevice) _input;
|
||||
bool _mouse_hidden;
|
||||
bool _context_needs_update;
|
||||
bool _vsync_enabled = false;
|
||||
|
||||
CGDisplayModeRef _fullscreen_mode;
|
||||
CGDisplayModeRef _windowed_mode;
|
||||
|
@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
#include "cocoaGraphicsWindow.h"
|
||||
#include "cocoaGraphicsStateGuardian.h"
|
||||
#include "config_cocoadisplay.h"
|
||||
#include "cocoaGraphicsPipe.h"
|
||||
#include "cocoaPandaApp.h"
|
||||
@ -40,7 +39,6 @@
|
||||
#import <AppKit/NSImage.h>
|
||||
#import <AppKit/NSScreen.h>
|
||||
#import <AppKit/NSText.h>
|
||||
#import <OpenGL/OpenGL.h>
|
||||
#import <Carbon/Carbon.h>
|
||||
|
||||
TypeHandle CocoaGraphicsWindow::_type_handle;
|
||||
@ -108,7 +106,7 @@ CocoaGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
|
||||
CocoaGraphicsPipe *cocoa_pipe;
|
||||
DCAST_INTO_V(cocoa_pipe, _pipe);
|
||||
_display = cocoa_pipe->_display;
|
||||
_display = cocoa_pipe->get_display_id();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,147 +159,6 @@ move_pointer(int device, int x, int y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 CocoaGraphicsWindow::
|
||||
begin_frame(FrameMode mode, Thread *current_thread) {
|
||||
PStatTimer timer(_make_current_pcollector, current_thread);
|
||||
|
||||
begin_frame_spam(mode);
|
||||
if (_gsg == (GraphicsStateGuardian *)NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CocoaGraphicsStateGuardian *cocoagsg;
|
||||
DCAST_INTO_R(cocoagsg, _gsg, false);
|
||||
nassertr(cocoagsg->_context != nil, false);
|
||||
nassertr(_view != nil, false);
|
||||
|
||||
// Place a lock on the context.
|
||||
cocoagsg->lock_context();
|
||||
|
||||
// Set the drawable.
|
||||
// Although not recommended, it is technically possible to use the same
|
||||
// context with multiple different-sized windows. If that happens, the
|
||||
// context needs to be updated accordingly.
|
||||
if ([cocoagsg->_context view] != _view) {
|
||||
// XXX I'm not 100% sure that changing the view requires it to update.
|
||||
_context_needs_update = true;
|
||||
[cocoagsg->_context setView:_view];
|
||||
|
||||
if (cocoadisplay_cat.is_spam()) {
|
||||
cocoadisplay_cat.spam()
|
||||
<< "Switching context to view " << _view << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Update the context if necessary, to make it reallocate buffers etc.
|
||||
if (_context_needs_update) {
|
||||
if ([NSThread isMainThread]) {
|
||||
[cocoagsg->_context update];
|
||||
_context_needs_update = false;
|
||||
} else {
|
||||
cocoagsg->unlock_context();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Lock the view for drawing.
|
||||
if (!_properties.get_fullscreen()) {
|
||||
nassertr_always([_view lockFocusIfCanDraw], false);
|
||||
}
|
||||
|
||||
// Make the context current.
|
||||
[cocoagsg->_context makeCurrentContext];
|
||||
|
||||
// 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.)
|
||||
cocoagsg->reset_if_new();
|
||||
|
||||
if (mode == FM_render) {
|
||||
// begin_render_texture();
|
||||
clear_cube_map_selection();
|
||||
}
|
||||
|
||||
_gsg->set_current_properties(&get_fb_properties());
|
||||
return _gsg->begin_frame(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 CocoaGraphicsWindow::
|
||||
end_frame(FrameMode mode, Thread *current_thread) {
|
||||
end_frame_spam(mode);
|
||||
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
||||
|
||||
if (!_properties.get_fullscreen()) {
|
||||
[_view unlockFocus];
|
||||
}
|
||||
// Release the context.
|
||||
CocoaGraphicsStateGuardian *cocoagsg;
|
||||
DCAST_INTO_V(cocoagsg, _gsg);
|
||||
|
||||
cocoagsg->unlock_context();
|
||||
|
||||
if (mode == FM_render) {
|
||||
// end_render_texture();
|
||||
copy_to_textures();
|
||||
}
|
||||
|
||||
_gsg->end_frame(current_thread);
|
||||
|
||||
if (mode == FM_render) {
|
||||
trigger_flip();
|
||||
clear_cube_map_selection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be called within the draw thread after begin_flip() has
|
||||
* been called on all windows, to finish the exchange of the front and back
|
||||
* buffers.
|
||||
*
|
||||
* This should cause the window to wait for the flip, if necessary.
|
||||
*/
|
||||
void CocoaGraphicsWindow::
|
||||
end_flip() {
|
||||
if (_gsg != (GraphicsStateGuardian *)NULL && _flip_ready) {
|
||||
|
||||
CocoaGraphicsStateGuardian *cocoagsg;
|
||||
DCAST_INTO_V(cocoagsg, _gsg);
|
||||
|
||||
if (_vsync_enabled) {
|
||||
AtomicAdjust::Integer cur_frame = ClockObject::get_global_clock()->get_frame_count();
|
||||
if (AtomicAdjust::set(cocoagsg->_last_wait_frame, cur_frame) != cur_frame) {
|
||||
cocoagsg->_swap_lock.lock();
|
||||
cocoagsg->_swap_condition.wait();
|
||||
cocoagsg->_swap_lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
cocoagsg->lock_context();
|
||||
|
||||
// Swap the front and back buffer.
|
||||
[cocoagsg->_context flushBuffer];
|
||||
|
||||
// Flush the window
|
||||
[[_view window] flushWindow];
|
||||
|
||||
cocoagsg->unlock_context();
|
||||
}
|
||||
GraphicsWindow::end_flip();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do whatever processing is necessary to ensure that the window responds to
|
||||
* user events. Also, honor any requests recently made via
|
||||
@ -351,15 +208,7 @@ process_events() {
|
||||
[pool release];
|
||||
|
||||
if (_context_needs_update && _gsg != nullptr) {
|
||||
CocoaGraphicsStateGuardian *cocoagsg;
|
||||
DCAST_INTO_V(cocoagsg, _gsg);
|
||||
|
||||
if (cocoagsg != nullptr && cocoagsg->_context != nil) {
|
||||
cocoagsg->lock_context();
|
||||
_context_needs_update = false;
|
||||
[cocoagsg->_context update];
|
||||
cocoagsg->unlock_context();
|
||||
}
|
||||
update_context();
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,34 +218,6 @@ process_events() {
|
||||
*/
|
||||
bool CocoaGraphicsWindow::
|
||||
open_window() {
|
||||
CocoaGraphicsPipe *cocoa_pipe;
|
||||
DCAST_INTO_R(cocoa_pipe, _pipe, false);
|
||||
|
||||
// GSG CreationInitialization
|
||||
CocoaGraphicsStateGuardian *cocoagsg;
|
||||
if (_gsg == 0) {
|
||||
// There is no old gsg. Create a new one.
|
||||
cocoagsg = new CocoaGraphicsStateGuardian(_engine, _pipe, NULL);
|
||||
cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->_display, 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->_display, false);
|
||||
_gsg = cocoagsg;
|
||||
}
|
||||
}
|
||||
|
||||
if (cocoagsg->_context == nil) {
|
||||
// Could not obtain a proper context.
|
||||
_gsg.clear();
|
||||
close_window();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fill in the blanks.
|
||||
if (!_properties.has_origin()) {
|
||||
_properties.set_origin(-2, -2);
|
||||
@ -476,7 +297,7 @@ open_window() {
|
||||
NSEnumerator *e = [[NSScreen screens] objectEnumerator];
|
||||
while (screen = (NSScreen *) [e nextObject]) {
|
||||
NSNumber *num = [[screen deviceDescription] objectForKey: @"NSScreenNumber"];
|
||||
if (cocoa_pipe->_display == (CGDirectDisplayID) [num longValue]) {
|
||||
if (_display == (CGDirectDisplayID) [num longValue]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -545,19 +366,16 @@ open_window() {
|
||||
}
|
||||
}
|
||||
|
||||
// Lock the context, so we can safely operate on it.
|
||||
cocoagsg->lock_context();
|
||||
|
||||
// Create the NSView to render to.
|
||||
NSRect rect = NSMakeRect(0, 0, _properties.get_x_size(), _properties.get_y_size());
|
||||
_view = [[CocoaPandaView alloc] initWithFrame:rect context:cocoagsg->_context window:this];
|
||||
if (_parent_window_handle == (WindowHandle *)NULL) {
|
||||
_view = [[CocoaPandaView alloc] initWithFrame:rect window:this];
|
||||
if (_parent_window_handle == nullptr) {
|
||||
[_window setContentView:_view];
|
||||
[_window makeFirstResponder:_view];
|
||||
}
|
||||
|
||||
// Check if we have an NSView to attach our NSView to.
|
||||
if (parent_nsview != NULL) {
|
||||
if (parent_nsview != nullptr) {
|
||||
[parent_nsview addSubview:_view];
|
||||
}
|
||||
|
||||
@ -566,7 +384,7 @@ open_window() {
|
||||
_window_handle = NativeWindowHandle::make_int((size_t) _view);
|
||||
|
||||
// And tell our parent window that we're now its child.
|
||||
if (_parent_window_handle != (WindowHandle *)NULL) {
|
||||
if (_parent_window_handle != nullptr) {
|
||||
_parent_window_handle->attach_child(_window_handle);
|
||||
}
|
||||
|
||||
@ -672,29 +490,6 @@ open_window() {
|
||||
}
|
||||
}
|
||||
|
||||
// Make the context current.
|
||||
_context_needs_update = false;
|
||||
[cocoagsg->_context makeCurrentContext];
|
||||
[cocoagsg->_context setView:_view];
|
||||
[cocoagsg->_context update];
|
||||
|
||||
cocoagsg->reset_if_new();
|
||||
|
||||
// Release the context.
|
||||
cocoagsg->unlock_context();
|
||||
|
||||
if (!cocoagsg->is_valid()) {
|
||||
close_window();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cocoagsg->get_fb_properties().verify_hardware_software
|
||||
(_fb_properties, cocoagsg->get_gl_renderer())) {
|
||||
close_window();
|
||||
return false;
|
||||
}
|
||||
_fb_properties = cocoagsg->get_fb_properties();
|
||||
|
||||
// Reset dead key state.
|
||||
_dead_key_state = 0;
|
||||
|
||||
@ -710,8 +505,6 @@ open_window() {
|
||||
CGAssociateMouseAndMouseCursorPosition(NO);
|
||||
}
|
||||
|
||||
_vsync_enabled = sync_video && cocoagsg->setup_vsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -730,15 +523,8 @@ close_window() {
|
||||
_cursor = nil;
|
||||
}
|
||||
|
||||
if (_gsg != (GraphicsStateGuardian *)NULL) {
|
||||
CocoaGraphicsStateGuardian *cocoagsg;
|
||||
cocoagsg = DCAST(CocoaGraphicsStateGuardian, _gsg);
|
||||
|
||||
if (cocoagsg != NULL && cocoagsg->_context != nil) {
|
||||
cocoagsg->lock_context();
|
||||
[cocoagsg->_context clearDrawable];
|
||||
cocoagsg->unlock_context();
|
||||
}
|
||||
if (_gsg != nullptr) {
|
||||
unbind_context();
|
||||
_gsg.clear();
|
||||
}
|
||||
|
||||
@ -756,8 +542,6 @@ close_window() {
|
||||
_view = nil;
|
||||
}
|
||||
|
||||
_vsync_enabled = false;
|
||||
|
||||
GraphicsWindow::close_window();
|
||||
}
|
||||
|
||||
@ -1148,18 +932,24 @@ set_properties_now(WindowProperties &properties) {
|
||||
}
|
||||
|
||||
if (_context_needs_update && _gsg != nullptr) {
|
||||
CocoaGraphicsStateGuardian *cocoagsg;
|
||||
DCAST_INTO_V(cocoagsg, _gsg);
|
||||
|
||||
if (cocoagsg != nullptr && cocoagsg->_context != nil) {
|
||||
cocoagsg->lock_context();
|
||||
_context_needs_update = false;
|
||||
[cocoagsg->_context update];
|
||||
cocoagsg->unlock_context();
|
||||
}
|
||||
update_context();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void CocoaGraphicsWindow::
|
||||
update_context() {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void CocoaGraphicsWindow::
|
||||
unbind_context() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an appropriate CGDisplayModeRef for the given width and height, or
|
||||
* NULL if none was found.
|
||||
@ -1663,17 +1453,9 @@ handle_close_event() {
|
||||
_window = nil;
|
||||
|
||||
// Get rid of the GSG
|
||||
if (_gsg != (GraphicsStateGuardian *)NULL) {
|
||||
CocoaGraphicsStateGuardian *cocoagsg;
|
||||
cocoagsg = DCAST(CocoaGraphicsStateGuardian, _gsg);
|
||||
|
||||
if (cocoagsg != NULL && cocoagsg->_context != nil) {
|
||||
cocoagsg->lock_context();
|
||||
[cocoagsg->_context clearDrawable];
|
||||
cocoagsg->unlock_context();
|
||||
}
|
||||
if (_gsg != nullptr) {
|
||||
unbind_context();
|
||||
_gsg.clear();
|
||||
_vsync_enabled = false;
|
||||
}
|
||||
|
||||
// Dump the view, too
|
||||
|
154
panda/src/cocoadisplay/cocoaGraphicsWindow.mm.rej
Normal file
154
panda/src/cocoadisplay/cocoaGraphicsWindow.mm.rej
Normal file
@ -0,0 +1,154 @@
|
||||
diff a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm (rejected hunks)
|
||||
@@ -161,152 +159,6 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
-
|
||||
-/**
|
||||
- * 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 CocoaGraphicsWindow::
|
||||
-begin_frame(FrameMode mode, Thread *current_thread) {
|
||||
- PStatTimer timer(_make_current_pcollector, current_thread);
|
||||
-
|
||||
- begin_frame_spam(mode);
|
||||
- if (_gsg == (GraphicsStateGuardian *)NULL) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- CocoaGraphicsStateGuardian *cocoagsg;
|
||||
- DCAST_INTO_R(cocoagsg, _gsg, false);
|
||||
- nassertr(cocoagsg->_context != nil, false);
|
||||
- nassertr(_view != nil, false);
|
||||
-
|
||||
- // Place a lock on the context.
|
||||
- cocoagsg->lock_context();
|
||||
-
|
||||
- // Set the drawable.
|
||||
- // Although not recommended, it is technically possible to use the same
|
||||
- // context with multiple different-sized windows. If that happens, the
|
||||
- // context needs to be updated accordingly.
|
||||
- if ([cocoagsg->_context view] != _view) {
|
||||
- // XXX I'm not 100% sure that changing the view requires it to update.
|
||||
- _context_needs_update = true;
|
||||
- [cocoagsg->_context setView:_view];
|
||||
-
|
||||
- if (cocoadisplay_cat.is_spam()) {
|
||||
- cocoadisplay_cat.spam()
|
||||
- << "Switching context to view " << _view << "\n";
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // Update the context if necessary, to make it reallocate buffers etc.
|
||||
- if (_context_needs_update) {
|
||||
- if ([NSThread isMainThread]) {
|
||||
- [cocoagsg->_context update];
|
||||
- _context_needs_update = false;
|
||||
- } else {
|
||||
- cocoagsg->unlock_context();
|
||||
- return false;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // Lock the view for drawing.
|
||||
- if (!_properties.get_fullscreen()) {
|
||||
- nassertr_always([_view lockFocusIfCanDraw], false);
|
||||
- }
|
||||
-
|
||||
- // Make the context current.
|
||||
- [cocoagsg->_context makeCurrentContext];
|
||||
-
|
||||
- // 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.)
|
||||
- cocoagsg->reset_if_new();
|
||||
-
|
||||
- if (mode == FM_render) {
|
||||
- // begin_render_texture();
|
||||
- clear_cube_map_selection();
|
||||
- }
|
||||
-
|
||||
- _gsg->set_current_properties(&get_fb_properties());
|
||||
- if (_gsg->begin_frame(current_thread)) {
|
||||
- copy_async_screenshot();
|
||||
- return true;
|
||||
- } else {
|
||||
- return false;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-/**
|
||||
- * 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 CocoaGraphicsWindow::
|
||||
-end_frame(FrameMode mode, Thread *current_thread) {
|
||||
- end_frame_spam(mode);
|
||||
- nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
||||
-
|
||||
- if (!_properties.get_fullscreen()) {
|
||||
- [_view unlockFocus];
|
||||
- }
|
||||
- // Release the context.
|
||||
- CocoaGraphicsStateGuardian *cocoagsg;
|
||||
- DCAST_INTO_V(cocoagsg, _gsg);
|
||||
-
|
||||
- cocoagsg->unlock_context();
|
||||
-
|
||||
- if (mode == FM_render) {
|
||||
- // end_render_texture();
|
||||
- copy_to_textures();
|
||||
- }
|
||||
-
|
||||
- _gsg->end_frame(current_thread);
|
||||
-
|
||||
- if (mode == FM_render) {
|
||||
- trigger_flip();
|
||||
- clear_cube_map_selection();
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-/**
|
||||
- * This function will be called within the draw thread after begin_flip() has
|
||||
- * been called on all windows, to finish the exchange of the front and back
|
||||
- * buffers.
|
||||
- *
|
||||
- * This should cause the window to wait for the flip, if necessary.
|
||||
- */
|
||||
-void CocoaGraphicsWindow::
|
||||
-end_flip() {
|
||||
- if (_gsg != (GraphicsStateGuardian *)NULL && _flip_ready) {
|
||||
-
|
||||
- CocoaGraphicsStateGuardian *cocoagsg;
|
||||
- DCAST_INTO_V(cocoagsg, _gsg);
|
||||
-
|
||||
- if (_vsync_enabled) {
|
||||
- AtomicAdjust::Integer cur_frame = ClockObject::get_global_clock()->get_frame_count();
|
||||
- if (AtomicAdjust::set(cocoagsg->_last_wait_frame, cur_frame) != cur_frame) {
|
||||
- cocoagsg->_swap_lock.lock();
|
||||
- cocoagsg->_swap_condition.wait();
|
||||
- cocoagsg->_swap_lock.unlock();
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- cocoagsg->lock_context();
|
||||
-
|
||||
- // Swap the front and back buffer.
|
||||
- [cocoagsg->_context flushBuffer];
|
||||
-
|
||||
- // Flush the window
|
||||
- [[_view window] flushWindow];
|
||||
-
|
||||
- cocoagsg->unlock_context();
|
||||
- }
|
||||
- GraphicsWindow::end_flip();
|
||||
-}
|
||||
-
|
||||
/**
|
||||
* Do whatever processing is necessary to ensure that the window responds to
|
||||
* user events. Also, honor any requests recently made via
|
@ -14,18 +14,15 @@
|
||||
#include "graphicsWindow.h"
|
||||
|
||||
#import <AppKit/NSView.h>
|
||||
#import <AppKit/NSOpenGL.h>
|
||||
|
||||
class CocoaGraphicsWindow;
|
||||
|
||||
@interface CocoaPandaView : NSView {
|
||||
@private
|
||||
NSOpenGLContext *_context;
|
||||
CocoaGraphicsWindow *_graphicsWindow;
|
||||
}
|
||||
|
||||
- (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window;
|
||||
- (NSOpenGLContext*) openGLContext;
|
||||
- (id) initWithFrame:(NSRect)frameRect window:(CocoaGraphicsWindow*)window;
|
||||
- (GraphicsWindow*) graphicsWindow;
|
||||
|
||||
- (void) drawRect:(NSRect)dirtyRect;
|
||||
|
@ -18,10 +18,9 @@
|
||||
#include <OpenGL/gl.h>
|
||||
|
||||
@implementation CocoaPandaView
|
||||
- (id) initWithFrame:(NSRect)frameRect context:(NSOpenGLContext*)context window:(CocoaGraphicsWindow*)window {
|
||||
- (id) initWithFrame:(NSRect)frameRect window:(CocoaGraphicsWindow*)window {
|
||||
self = [super initWithFrame: frameRect];
|
||||
|
||||
_context = context;
|
||||
[self setCanDrawConcurrently:YES];
|
||||
|
||||
// If a layer ends up becoming attached to the view, tell AppKit we'll manage
|
||||
@ -37,10 +36,6 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSOpenGLContext*) openGLContext {
|
||||
return _context;
|
||||
}
|
||||
|
||||
- (GraphicsWindow*) graphicsWindow {
|
||||
return _graphicsWindow;
|
||||
}
|
||||
@ -170,14 +165,9 @@
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(void)setLayer:(CALayer*)layer
|
||||
{
|
||||
[super setLayer:layer];
|
||||
-(void)setLayer:(CALayer*)layer {
|
||||
[super setLayer:layer];
|
||||
|
||||
// Starting in macOS 10.14, a CALayer will still be attached to a view even
|
||||
// if `wantsLayer` is false. If we don't update the context now, only a
|
||||
// black screen will be rendered until the context is updated some other
|
||||
// way (like through a window resize event).
|
||||
[_context update];
|
||||
_graphicsWindow->update_context();
|
||||
}
|
||||
@end
|
||||
|
@ -12,11 +12,8 @@
|
||||
*/
|
||||
|
||||
#include "config_cocoadisplay.h"
|
||||
#include "cocoaGraphicsBuffer.h"
|
||||
#include "cocoaGraphicsPipe.h"
|
||||
#include "cocoaGraphicsStateGuardian.h"
|
||||
#include "cocoaGraphicsWindow.h"
|
||||
#include "graphicsPipeSelection.h"
|
||||
#include "dconfig.h"
|
||||
#include "pandaSystem.h"
|
||||
|
||||
@ -50,15 +47,6 @@ init_libcocoadisplay() {
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
CocoaGraphicsBuffer::init_type();
|
||||
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");
|
||||
}
|
||||
|
@ -1,10 +1,8 @@
|
||||
#include "config_cocoadisplay.mm"
|
||||
#include "cocoaGraphicsBuffer.mm"
|
||||
#include "cocoaGraphicsPipe.mm"
|
||||
#include "cocoaGraphicsStateGuardian.mm"
|
||||
#include "cocoaGraphicsWindow.mm"
|
||||
#include "cocoaPandaApp.mm"
|
||||
#include "cocoaPandaView.mm"
|
||||
#include "cocoaPandaWindow.mm"
|
||||
#include "cocoaPandaWindowDelegate.mm"
|
||||
#include "cocoaPandaAppDelegate.mm"
|
||||
#include "config_cocoadisplay.mm"
|
||||
|
28
panda/src/cocoagldisplay/CMakeLists.txt
Normal file
28
panda/src/cocoagldisplay/CMakeLists.txt
Normal file
@ -0,0 +1,28 @@
|
||||
if(NOT APPLE OR NOT HAVE_GL OR NOT HAVE_COCOA)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(P3COCOAGLDISPLAY_HEADERS
|
||||
cocoaGLGraphicsBuffer.h cocoaGLGraphicsBuffer.I
|
||||
cocoaGLGraphicsPipe.h cocoaGLGraphicsPipe.I
|
||||
cocoaGLGraphicsStateGuardian.h cocoaGLGraphicsStateGuardian.I
|
||||
cocoaGLGraphicsWindow.h cocoaGLGraphicsWindow.I
|
||||
config_cocoagldisplay.h
|
||||
)
|
||||
|
||||
set(P3COCOAGLDISPLAY_SOURCES
|
||||
cocoaGLGraphicsBuffer.mm
|
||||
cocoaGLGraphicsPipe.mm
|
||||
cocoaGLGraphicsStateGuardian.mm
|
||||
cocoaGLGraphicsWindow.mm
|
||||
config_cocoagldisplay.mm
|
||||
)
|
||||
|
||||
composite_sources(p3cocoagldisplay P3COCOAGLDISPLAY_SOURCES)
|
||||
add_component_library(p3cocoagldisplay SYMBOL BUILDING_PANDA_COCOAGLDISPLAY
|
||||
${P3COCOAGLDISPLAY_HEADERS} ${P3COCOAGLDISPLAY_SOURCES})
|
||||
target_link_libraries(p3cocoagldisplay p3cocoadisplay p3glgsg panda)
|
||||
|
||||
if(NOT BUILD_METALIBS)
|
||||
install(TARGETS p3cocoagldisplay EXPORT OpenGL COMPONENT OpenGL DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
@ -6,7 +6,7 @@
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file cocoaGraphicsBuffer.I
|
||||
* @file cocoaGLGraphicsBuffer.I
|
||||
* @author rdb
|
||||
* @date 2017-12-19
|
||||
*/
|
@ -6,7 +6,7 @@
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file cocoaGraphicsBuffer.h
|
||||
* @file cocoaGLGraphicsBuffer.h
|
||||
* @author rdb
|
||||
* @date 2017-12-19
|
||||
*/
|
||||
@ -21,15 +21,15 @@
|
||||
* 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 EXPCL_PANDA_COCOADISPLAY CocoaGraphicsBuffer : public GLGraphicsBuffer {
|
||||
class EXPCL_PANDA_COCOAGLDISPLAY CocoaGLGraphicsBuffer : public GLGraphicsBuffer {
|
||||
public:
|
||||
CocoaGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
const std::string &name,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
const WindowProperties &win_prop,
|
||||
int flags,
|
||||
GraphicsStateGuardian *gsg,
|
||||
GraphicsOutput *host);
|
||||
CocoaGLGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
const std::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);
|
||||
@ -44,7 +44,7 @@ public:
|
||||
}
|
||||
static void init_type() {
|
||||
GLGraphicsBuffer::init_type();
|
||||
register_type(_type_handle, "CocoaGraphicsBuffer",
|
||||
register_type(_type_handle, "CocoaGLGraphicsBuffer",
|
||||
GLGraphicsBuffer::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
@ -56,6 +56,6 @@ private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "cocoaGraphicsBuffer.I"
|
||||
#include "cocoaGLGraphicsBuffer.I"
|
||||
|
||||
#endif
|
@ -6,25 +6,25 @@
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file cocoaGraphicsBuffer.mm
|
||||
* @file cocoaGLGraphicsBuffer.mm
|
||||
* @author rdb
|
||||
* @date 2017-12-19
|
||||
*/
|
||||
|
||||
#include "cocoaGraphicsBuffer.h"
|
||||
#include "cocoaGraphicsStateGuardian.h"
|
||||
#include "cocoaGLGraphicsBuffer.h"
|
||||
#include "cocoaGLGraphicsStateGuardian.h"
|
||||
#include "config_cocoadisplay.h"
|
||||
#include "cocoaGraphicsPipe.h"
|
||||
|
||||
#import <OpenGL/OpenGL.h>
|
||||
|
||||
TypeHandle CocoaGraphicsBuffer::_type_handle;
|
||||
TypeHandle CocoaGLGraphicsBuffer::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CocoaGraphicsBuffer::
|
||||
CocoaGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
CocoaGLGraphicsBuffer::
|
||||
CocoaGLGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
const std::string &name,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
const WindowProperties &win_prop,
|
||||
@ -41,13 +41,13 @@ CocoaGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
* return true if the frame should be rendered, or false if it should be
|
||||
* skipped.
|
||||
*/
|
||||
bool CocoaGraphicsBuffer::
|
||||
bool CocoaGLGraphicsBuffer::
|
||||
begin_frame(FrameMode mode, Thread *current_thread) {
|
||||
if (_gsg == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CocoaGraphicsStateGuardian *cocoagsg;
|
||||
CocoaGLGraphicsStateGuardian *cocoagsg;
|
||||
DCAST_INTO_R(cocoagsg, _gsg, false);
|
||||
nassertr(cocoagsg->_context != nil, false);
|
||||
|
||||
@ -66,14 +66,14 @@ begin_frame(FrameMode mode, Thread *current_thread) {
|
||||
* completed for a given frame. It should do whatever finalization is
|
||||
* required.
|
||||
*/
|
||||
void CocoaGraphicsBuffer::
|
||||
void CocoaGLGraphicsBuffer::
|
||||
end_frame(FrameMode mode, Thread *current_thread) {
|
||||
nassertv(_gsg != nullptr);
|
||||
|
||||
GLGraphicsBuffer::end_frame(mode, current_thread);
|
||||
|
||||
// Release the context.
|
||||
CocoaGraphicsStateGuardian *cocoagsg;
|
||||
CocoaGLGraphicsStateGuardian *cocoagsg;
|
||||
DCAST_INTO_V(cocoagsg, _gsg);
|
||||
cocoagsg->unlock_context();
|
||||
}
|
||||
@ -82,16 +82,16 @@ end_frame(FrameMode mode, Thread *current_thread) {
|
||||
* 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::
|
||||
bool CocoaGLGraphicsBuffer::
|
||||
open_buffer() {
|
||||
CocoaGraphicsPipe *cocoa_pipe;
|
||||
DCAST_INTO_R(cocoa_pipe, _pipe, false);
|
||||
|
||||
// GSG CreationInitialization
|
||||
CocoaGraphicsStateGuardian *cocoagsg;
|
||||
CocoaGLGraphicsStateGuardian *cocoagsg;
|
||||
if (_gsg == nullptr) {
|
||||
// There is no old gsg. Create a new one.
|
||||
cocoagsg = new CocoaGraphicsStateGuardian(_engine, _pipe, nullptr);
|
||||
cocoagsg = new CocoaGLGraphicsStateGuardian(_engine, _pipe, nullptr);
|
||||
cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->get_display_id(), false);
|
||||
_gsg = cocoagsg;
|
||||
} else {
|
||||
@ -99,7 +99,7 @@ open_buffer() {
|
||||
// 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 = new CocoaGLGraphicsStateGuardian(_engine, _pipe, cocoagsg);
|
||||
cocoagsg->choose_pixel_format(_fb_properties, cocoa_pipe->get_display_id(), false);
|
||||
_gsg = cocoagsg;
|
||||
}
|
||||
@ -153,11 +153,11 @@ open_buffer() {
|
||||
/**
|
||||
* Closes the buffer right now. Called from the window thread.
|
||||
*/
|
||||
void CocoaGraphicsBuffer::
|
||||
void CocoaGLGraphicsBuffer::
|
||||
close_buffer() {
|
||||
if (_gsg != nullptr) {
|
||||
CocoaGraphicsStateGuardian *cocoagsg;
|
||||
cocoagsg = DCAST(CocoaGraphicsStateGuardian, _gsg);
|
||||
CocoaGLGraphicsStateGuardian *cocoagsg;
|
||||
cocoagsg = DCAST(CocoaGLGraphicsStateGuardian, _gsg);
|
||||
|
||||
if (cocoagsg != nullptr && cocoagsg->_context != nil) {
|
||||
cocoagsg->lock_context();
|
12
panda/src/cocoagldisplay/cocoaGLGraphicsPipe.I
Normal file
12
panda/src/cocoagldisplay/cocoaGLGraphicsPipe.I
Normal file
@ -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 cocoaGLGraphicsPipe.I
|
||||
* @author rdb
|
||||
* @date 2023-03-20
|
||||
*/
|
65
panda/src/cocoagldisplay/cocoaGLGraphicsPipe.h
Normal file
65
panda/src/cocoagldisplay/cocoaGLGraphicsPipe.h
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* 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 cocoaGLGraphicsPipe.h
|
||||
* @author rdb
|
||||
* @date 2023-03-20
|
||||
*/
|
||||
|
||||
#ifndef COCOAGLGRAPHICSPIPE_H
|
||||
#define COCOAGLGRAPHICSPIPE_H
|
||||
|
||||
#include "cocoaGraphicsPipe.h"
|
||||
|
||||
class FrameBufferProperties;
|
||||
|
||||
/**
|
||||
* This graphics pipe represents the interface for creating OpenGL graphics
|
||||
* windows on a Cocoa-based (e.g. Mac OS X) client.
|
||||
*/
|
||||
class EXPCL_PANDA_COCOAGLDISPLAY CocoaGLGraphicsPipe : public CocoaGraphicsPipe {
|
||||
public:
|
||||
CocoaGLGraphicsPipe(CGDirectDisplayID display = CGMainDisplayID());
|
||||
virtual ~CocoaGLGraphicsPipe();
|
||||
|
||||
virtual std::string get_interface_name() const;
|
||||
static PT(GraphicsPipe) pipe_constructor();
|
||||
|
||||
protected:
|
||||
virtual PT(GraphicsOutput) make_output(const std::string &name,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
const WindowProperties &win_prop,
|
||||
int flags,
|
||||
GraphicsEngine *engine,
|
||||
GraphicsStateGuardian *gsg,
|
||||
GraphicsOutput *host,
|
||||
int retry,
|
||||
bool &precertify);
|
||||
virtual PT(GraphicsStateGuardian) make_callback_gsg(GraphicsEngine *engine);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
CocoaGraphicsPipe::init_type();
|
||||
register_type(_type_handle, "CocoaGLGraphicsPipe",
|
||||
CocoaGraphicsPipe::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 "cocoaGLGraphicsPipe.I"
|
||||
|
||||
#endif
|
150
panda/src/cocoagldisplay/cocoaGLGraphicsPipe.mm
Normal file
150
panda/src/cocoagldisplay/cocoaGLGraphicsPipe.mm
Normal file
@ -0,0 +1,150 @@
|
||||
/**
|
||||
* 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 cocoaGLGraphicsPipe.mm
|
||||
* @author rdb
|
||||
* @date 2023-03-20
|
||||
*/
|
||||
|
||||
#include "cocoaGLGraphicsPipe.h"
|
||||
#include "cocoaGLGraphicsBuffer.h"
|
||||
#include "cocoaGLGraphicsWindow.h"
|
||||
#include "cocoaGLGraphicsStateGuardian.h"
|
||||
#include "config_cocoagldisplay.h"
|
||||
#include "frameBufferProperties.h"
|
||||
|
||||
TypeHandle CocoaGLGraphicsPipe::_type_handle;
|
||||
|
||||
/**
|
||||
* Takes a CoreGraphics display ID, which defaults to the main display.
|
||||
*/
|
||||
CocoaGLGraphicsPipe::
|
||||
CocoaGLGraphicsPipe(CGDirectDisplayID display) : CocoaGraphicsPipe(display) {
|
||||
_supported_types = OT_window | OT_buffer | OT_texture_buffer;
|
||||
_is_valid = true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CocoaGLGraphicsPipe::
|
||||
~CocoaGLGraphicsPipe() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
std::string CocoaGLGraphicsPipe::
|
||||
get_interface_name() const {
|
||||
return "OpenGL";
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is passed to the GraphicsPipeSelection object to allow the
|
||||
* user to make a default CocoaGLGraphicsPipe.
|
||||
*/
|
||||
PT(GraphicsPipe) CocoaGLGraphicsPipe::
|
||||
pipe_constructor() {
|
||||
return new CocoaGLGraphicsPipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new window on the pipe, if possible.
|
||||
*/
|
||||
PT(GraphicsOutput) CocoaGLGraphicsPipe::
|
||||
make_output(const std::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 nullptr;
|
||||
}
|
||||
|
||||
CocoaGLGraphicsStateGuardian *cocoagsg = nullptr;
|
||||
if (gsg != nullptr) {
|
||||
DCAST_INTO_R(cocoagsg, gsg, nullptr);
|
||||
}
|
||||
|
||||
// First thing to try: a CocoaGLGraphicsWindow
|
||||
|
||||
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 ||
|
||||
(flags & BF_can_bind_layered) != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return new CocoaGLGraphicsWindow(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}
|
||||
|
||||
// Second thing to try: a GLGraphicsBuffer. This requires a context, so if
|
||||
// we don't have a host window, we instead create a CocoaGLGraphicsBuffer,
|
||||
// which wraps around GLGraphicsBuffer and manages a context.
|
||||
|
||||
if (retry == 1) {
|
||||
if (!gl_support_fbo ||
|
||||
(flags & (BF_require_parasite | BF_require_window)) != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
// 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() ||
|
||||
fb_prop.get_back_buffers() > 0 ||
|
||||
fb_prop.get_accum_bits() > 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (cocoagsg != nullptr && cocoagsg->is_valid() && !cocoagsg->needs_reset()) {
|
||||
if (!cocoagsg->_supports_framebuffer_object ||
|
||||
cocoagsg->_glDrawBuffers == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
else if (fb_prop.is_basic()) {
|
||||
// Early success - if we are sure that this buffer WILL meet specs, we
|
||||
// can precertify it.
|
||||
precertify = true;
|
||||
}
|
||||
}
|
||||
if (host != nullptr) {
|
||||
return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
} else {
|
||||
return new CocoaGLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing else left to try.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when make_output() is used to create a
|
||||
* CallbackGraphicsWindow. If the GraphicsPipe can construct a GSG that's not
|
||||
* associated with any particular window object, do so now, assuming the
|
||||
* correct graphics context has been set up externally.
|
||||
*/
|
||||
PT(GraphicsStateGuardian) CocoaGLGraphicsPipe::
|
||||
make_callback_gsg(GraphicsEngine *engine) {
|
||||
return new CocoaGLGraphicsStateGuardian(engine, this, nullptr);
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file cocoaGraphicsStateGuardian.I
|
||||
* @file cocoaGLGraphicsStateGuardian.I
|
||||
* @author rdb
|
||||
* @date 2012-05-14
|
||||
*/
|
||||
@ -15,7 +15,7 @@
|
||||
* Gets the FrameBufferProperties for all windows and buffers that use this
|
||||
* GSG.
|
||||
*/
|
||||
INLINE const FrameBufferProperties &CocoaGraphicsStateGuardian::
|
||||
INLINE const FrameBufferProperties &CocoaGLGraphicsStateGuardian::
|
||||
get_fb_properties() const {
|
||||
return _fbprops;
|
||||
}
|
||||
@ -23,7 +23,7 @@ get_fb_properties() const {
|
||||
/**
|
||||
* Locks the context.
|
||||
*/
|
||||
INLINE void CocoaGraphicsStateGuardian::
|
||||
INLINE void CocoaGLGraphicsStateGuardian::
|
||||
lock_context() {
|
||||
nassertv(_context != nil);
|
||||
CGLLockContext((CGLContextObj) [_context CGLContextObj]);
|
||||
@ -32,7 +32,7 @@ lock_context() {
|
||||
/**
|
||||
* Unlocks the context.
|
||||
*/
|
||||
INLINE void CocoaGraphicsStateGuardian::
|
||||
INLINE void CocoaGLGraphicsStateGuardian::
|
||||
unlock_context() {
|
||||
nassertv(_context != nil);
|
||||
CGLUnlockContext((CGLContextObj) [_context CGLContextObj]);
|
@ -6,13 +6,13 @@
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file cocoaGraphicsStateGuardian.h
|
||||
* @file cocoaGLGraphicsStateGuardian.h
|
||||
* @author rdb
|
||||
* @date 2012-05-14
|
||||
*/
|
||||
|
||||
#ifndef COCOAGRAPHICSSTATEGUARDIAN_H
|
||||
#define COCOAGRAPHICSSTATEGUARDIAN_H
|
||||
#ifndef COCOAGLGRAPHICSSTATEGUARDIAN_H
|
||||
#define COCOAGLGRAPHICSSTATEGUARDIAN_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "cocoaGraphicsPipe.h"
|
||||
@ -26,7 +26,7 @@
|
||||
* A tiny specialization on GLGraphicsStateGuardian to add some Cocoa-specific
|
||||
* information.
|
||||
*/
|
||||
class EXPCL_PANDA_COCOADISPLAY CocoaGraphicsStateGuardian : public GLGraphicsStateGuardian {
|
||||
class EXPCL_PANDA_COCOAGLDISPLAY CocoaGLGraphicsStateGuardian : public GLGraphicsStateGuardian {
|
||||
public:
|
||||
INLINE const FrameBufferProperties &get_fb_properties() const;
|
||||
void get_properties(FrameBufferProperties &properties,
|
||||
@ -35,10 +35,10 @@ public:
|
||||
CGDirectDisplayID display,
|
||||
bool need_pbuffer);
|
||||
|
||||
CocoaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
CocoaGraphicsStateGuardian *share_with);
|
||||
CocoaGLGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
CocoaGLGraphicsStateGuardian *share_with);
|
||||
|
||||
virtual ~CocoaGraphicsStateGuardian();
|
||||
virtual ~CocoaGLGraphicsStateGuardian();
|
||||
bool setup_vsync();
|
||||
|
||||
INLINE void lock_context();
|
||||
@ -64,7 +64,7 @@ public:
|
||||
}
|
||||
static void init_type() {
|
||||
GLGraphicsStateGuardian::init_type();
|
||||
register_type(_type_handle, "CocoaGraphicsStateGuardian",
|
||||
register_type(_type_handle, "CocoaGLGraphicsStateGuardian",
|
||||
GLGraphicsStateGuardian::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
@ -76,6 +76,6 @@ private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "cocoaGraphicsStateGuardian.I"
|
||||
#include "cocoaGLGraphicsStateGuardian.I"
|
||||
|
||||
#endif
|
@ -6,12 +6,12 @@
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file cocoaGraphicsStateGuardian.mm
|
||||
* @file cocoaGLGraphicsStateGuardian.mm
|
||||
* @author rdb
|
||||
* @date 2012-05-14
|
||||
*/
|
||||
|
||||
#include "cocoaGraphicsStateGuardian.h"
|
||||
#include "cocoaGLGraphicsStateGuardian.h"
|
||||
#include "config_cocoadisplay.h"
|
||||
#include "lightReMutexHolder.h"
|
||||
|
||||
@ -30,34 +30,34 @@
|
||||
|
||||
/**
|
||||
* Called whenever a display wants a frame. The context argument contains the
|
||||
* applicable CocoaGraphicsStateGuardian.
|
||||
* applicable CocoaGLGraphicsStateGuardian.
|
||||
*/
|
||||
static CVReturn
|
||||
display_link_cb(CVDisplayLinkRef link, const CVTimeStamp *now,
|
||||
const CVTimeStamp* output_time, CVOptionFlags flags_in,
|
||||
CVOptionFlags *flags_out, void *context) {
|
||||
CocoaGraphicsStateGuardian *gsg = (CocoaGraphicsStateGuardian *)context;
|
||||
CocoaGLGraphicsStateGuardian *gsg = (CocoaGLGraphicsStateGuardian *)context;
|
||||
gsg->_swap_lock.lock();
|
||||
gsg->_swap_condition.notify();
|
||||
gsg->_swap_lock.unlock();
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
|
||||
TypeHandle CocoaGraphicsStateGuardian::_type_handle;
|
||||
TypeHandle CocoaGLGraphicsStateGuardian::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CocoaGraphicsStateGuardian::
|
||||
CocoaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
CocoaGraphicsStateGuardian *share_with) :
|
||||
CocoaGLGraphicsStateGuardian::
|
||||
CocoaGLGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
CocoaGLGraphicsStateGuardian *share_with) :
|
||||
GLGraphicsStateGuardian(engine, pipe),
|
||||
_swap_condition(_swap_lock)
|
||||
{
|
||||
_share_context = nil;
|
||||
_context = nil;
|
||||
|
||||
if (share_with != (CocoaGraphicsStateGuardian *)NULL) {
|
||||
if (share_with != (CocoaGLGraphicsStateGuardian *)NULL) {
|
||||
_prepared_objects = share_with->get_prepared_objects();
|
||||
_share_context = share_with->_context;
|
||||
}
|
||||
@ -66,8 +66,8 @@ CocoaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CocoaGraphicsStateGuardian::
|
||||
~CocoaGraphicsStateGuardian() {
|
||||
CocoaGLGraphicsStateGuardian::
|
||||
~CocoaGLGraphicsStateGuardian() {
|
||||
if (_format != nil) {
|
||||
[_format release];
|
||||
}
|
||||
@ -88,7 +88,7 @@ CocoaGraphicsStateGuardian::
|
||||
* Creates a CVDisplayLink, which tells us when the display the window is on
|
||||
* will want a frame.
|
||||
*/
|
||||
bool CocoaGraphicsStateGuardian::
|
||||
bool CocoaGLGraphicsStateGuardian::
|
||||
setup_vsync() {
|
||||
if (_display_link != nil) {
|
||||
// Already set up.
|
||||
@ -125,7 +125,7 @@ setup_vsync() {
|
||||
/**
|
||||
* Gets the FrameBufferProperties to match the indicated config.
|
||||
*/
|
||||
void CocoaGraphicsStateGuardian::
|
||||
void CocoaGLGraphicsStateGuardian::
|
||||
get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_format, int screen) {
|
||||
|
||||
properties.clear();
|
||||
@ -210,7 +210,7 @@ get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_for
|
||||
* 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::
|
||||
void CocoaGLGraphicsStateGuardian::
|
||||
choose_pixel_format(const FrameBufferProperties &properties,
|
||||
CGDirectDisplayID display,
|
||||
bool need_pbuffer) {
|
||||
@ -357,7 +357,7 @@ choose_pixel_format(const FrameBufferProperties &properties,
|
||||
/**
|
||||
* Queries the runtime version of OpenGL in use.
|
||||
*/
|
||||
void CocoaGraphicsStateGuardian::
|
||||
void CocoaGLGraphicsStateGuardian::
|
||||
query_gl_version() {
|
||||
GLGraphicsStateGuardian::query_gl_version();
|
||||
|
||||
@ -381,7 +381,7 @@ query_gl_version() {
|
||||
* 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::
|
||||
void *CocoaGLGraphicsStateGuardian::
|
||||
do_get_extension_func(const char *name) {
|
||||
char* fullname = (char*) malloc(strlen(name) + 2);
|
||||
strcpy(fullname + 1, name);
|
12
panda/src/cocoagldisplay/cocoaGLGraphicsWindow.I
Normal file
12
panda/src/cocoagldisplay/cocoaGLGraphicsWindow.I
Normal file
@ -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 cocoaGLGraphicsWindow.I
|
||||
* @author rdb
|
||||
* @date 2023-03-18
|
||||
*/
|
66
panda/src/cocoagldisplay/cocoaGLGraphicsWindow.h
Normal file
66
panda/src/cocoagldisplay/cocoaGLGraphicsWindow.h
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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 cocoaGLGraphicsWindow.h
|
||||
* @author rdb
|
||||
* @date 2023-03-18
|
||||
*/
|
||||
|
||||
#ifndef COCOAGLGRAPHICSWINDOW_H
|
||||
#define COCOAGLGRAPHICSWINDOW_H
|
||||
|
||||
#include "cocoaGraphicsWindow.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class EXPCL_PANDA_COCOADISPLAY CocoaGLGraphicsWindow : public CocoaGraphicsWindow {
|
||||
public:
|
||||
CocoaGLGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
const std::string &name,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
const WindowProperties &win_prop,
|
||||
int flags,
|
||||
GraphicsStateGuardian *gsg,
|
||||
GraphicsOutput *host);
|
||||
virtual ~CocoaGLGraphicsWindow();
|
||||
|
||||
virtual bool begin_frame(FrameMode mode, Thread *current_thread);
|
||||
virtual void end_frame(FrameMode mode, Thread *current_thread);
|
||||
virtual void end_flip();
|
||||
|
||||
virtual void update_context();
|
||||
virtual void unbind_context();
|
||||
|
||||
protected:
|
||||
virtual bool open_window();
|
||||
|
||||
private:
|
||||
bool _vsync_enabled = false;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
CocoaGraphicsWindow::init_type();
|
||||
register_type(_type_handle, "CocoaGLGraphicsWindow",
|
||||
CocoaGraphicsWindow::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 "cocoaGLGraphicsWindow.I"
|
||||
|
||||
#endif
|
274
panda/src/cocoagldisplay/cocoaGLGraphicsWindow.mm
Normal file
274
panda/src/cocoagldisplay/cocoaGLGraphicsWindow.mm
Normal file
@ -0,0 +1,274 @@
|
||||
/**
|
||||
* 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 cocoaGLGraphicsWindow.mm
|
||||
* @author rdb
|
||||
* @date 2023-03-18
|
||||
*/
|
||||
|
||||
#include "cocoaGLGraphicsWindow.h"
|
||||
#include "cocoaGLGraphicsStateGuardian.h"
|
||||
#include "config_cocoadisplay.h"
|
||||
|
||||
#import <OpenGL/OpenGL.h>
|
||||
|
||||
TypeHandle CocoaGLGraphicsWindow::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CocoaGLGraphicsWindow::
|
||||
CocoaGLGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
const std::string &name,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
const WindowProperties &win_prop,
|
||||
int flags,
|
||||
GraphicsStateGuardian *gsg,
|
||||
GraphicsOutput *host) :
|
||||
CocoaGraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CocoaGLGraphicsWindow::
|
||||
~CocoaGLGraphicsWindow() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 CocoaGLGraphicsWindow::
|
||||
begin_frame(FrameMode mode, Thread *current_thread) {
|
||||
PStatTimer timer(_make_current_pcollector, current_thread);
|
||||
|
||||
begin_frame_spam(mode);
|
||||
if (_gsg == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CocoaGLGraphicsStateGuardian *cocoagsg;
|
||||
DCAST_INTO_R(cocoagsg, _gsg, false);
|
||||
nassertr(cocoagsg->_context != nil, false);
|
||||
nassertr(_view != nil, false);
|
||||
|
||||
// Place a lock on the context.
|
||||
cocoagsg->lock_context();
|
||||
|
||||
// Set the drawable.
|
||||
// Although not recommended, it is technically possible to use the same
|
||||
// context with multiple different-sized windows. If that happens, the
|
||||
// context needs to be updated accordingly.
|
||||
if ([cocoagsg->_context view] != _view) {
|
||||
// XXX I'm not 100% sure that changing the view requires it to update.
|
||||
_context_needs_update = true;
|
||||
[cocoagsg->_context setView:_view];
|
||||
|
||||
if (cocoadisplay_cat.is_spam()) {
|
||||
cocoadisplay_cat.spam()
|
||||
<< "Switching context to view " << _view << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Update the context if necessary, to make it reallocate buffers etc.
|
||||
if (_context_needs_update) {
|
||||
if ([NSThread isMainThread]) {
|
||||
[cocoagsg->_context update];
|
||||
_context_needs_update = false;
|
||||
} else {
|
||||
cocoagsg->unlock_context();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Lock the view for drawing.
|
||||
if (!_properties.get_fullscreen()) {
|
||||
nassertr_always([_view lockFocusIfCanDraw], false);
|
||||
}
|
||||
|
||||
// Make the context current.
|
||||
[cocoagsg->_context makeCurrentContext];
|
||||
|
||||
// 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.)
|
||||
cocoagsg->reset_if_new();
|
||||
|
||||
if (mode == FM_render) {
|
||||
// begin_render_texture();
|
||||
clear_cube_map_selection();
|
||||
}
|
||||
|
||||
_gsg->set_current_properties(&get_fb_properties());
|
||||
return _gsg->begin_frame(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 CocoaGLGraphicsWindow::
|
||||
end_frame(FrameMode mode, Thread *current_thread) {
|
||||
end_frame_spam(mode);
|
||||
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
||||
|
||||
if (!_properties.get_fullscreen()) {
|
||||
[_view unlockFocus];
|
||||
}
|
||||
// Release the context.
|
||||
CocoaGLGraphicsStateGuardian *cocoagsg;
|
||||
DCAST_INTO_V(cocoagsg, _gsg);
|
||||
|
||||
cocoagsg->unlock_context();
|
||||
|
||||
if (mode == FM_render) {
|
||||
// end_render_texture();
|
||||
copy_to_textures();
|
||||
}
|
||||
|
||||
_gsg->end_frame(current_thread);
|
||||
|
||||
if (mode == FM_render) {
|
||||
trigger_flip();
|
||||
clear_cube_map_selection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will be called within the draw thread after begin_flip() has
|
||||
* been called on all windows, to finish the exchange of the front and back
|
||||
* buffers.
|
||||
*
|
||||
* This should cause the window to wait for the flip, if necessary.
|
||||
*/
|
||||
void CocoaGLGraphicsWindow::
|
||||
end_flip() {
|
||||
if (_gsg != nullptr && _flip_ready) {
|
||||
|
||||
CocoaGLGraphicsStateGuardian *cocoagsg;
|
||||
DCAST_INTO_V(cocoagsg, _gsg);
|
||||
|
||||
if (_vsync_enabled) {
|
||||
AtomicAdjust::Integer cur_frame = ClockObject::get_global_clock()->get_frame_count();
|
||||
if (AtomicAdjust::set(cocoagsg->_last_wait_frame, cur_frame) != cur_frame) {
|
||||
cocoagsg->_swap_lock.lock();
|
||||
cocoagsg->_swap_condition.wait();
|
||||
cocoagsg->_swap_lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
cocoagsg->lock_context();
|
||||
|
||||
// Swap the front and back buffer.
|
||||
[cocoagsg->_context flushBuffer];
|
||||
|
||||
[[_view window] flushWindow];
|
||||
|
||||
cocoagsg->unlock_context();
|
||||
}
|
||||
GraphicsWindow::end_flip();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the window right now. Called from the window thread. Returns true
|
||||
* if the window is successfully opened, or false if there was a problem.
|
||||
*/
|
||||
bool CocoaGLGraphicsWindow::
|
||||
open_window() {
|
||||
// GSG CreationInitialization
|
||||
CocoaGLGraphicsStateGuardian *cocoagsg;
|
||||
if (_gsg == nullptr) {
|
||||
// There is no old gsg. Create a new one.
|
||||
cocoagsg = new CocoaGLGraphicsStateGuardian(_engine, _pipe, nullptr);
|
||||
cocoagsg->choose_pixel_format(_fb_properties, _display, 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 CocoaGLGraphicsStateGuardian(_engine, _pipe, cocoagsg);
|
||||
cocoagsg->choose_pixel_format(_fb_properties, _display, false);
|
||||
_gsg = cocoagsg;
|
||||
}
|
||||
}
|
||||
|
||||
if (cocoagsg->_context == nil) {
|
||||
// Could not obtain a proper context.
|
||||
_gsg.clear();
|
||||
close_window();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CocoaGraphicsWindow::open_window()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make the context current.
|
||||
cocoagsg->lock_context();
|
||||
_context_needs_update = false;
|
||||
[cocoagsg->_context makeCurrentContext];
|
||||
[cocoagsg->_context setView:_view];
|
||||
[cocoagsg->_context update];
|
||||
|
||||
cocoagsg->reset_if_new();
|
||||
cocoagsg->unlock_context();
|
||||
|
||||
if (!cocoagsg->is_valid()) {
|
||||
close_window();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cocoagsg->get_fb_properties().verify_hardware_software
|
||||
(_fb_properties, cocoagsg->get_gl_renderer())) {
|
||||
close_window();
|
||||
return false;
|
||||
}
|
||||
_fb_properties = cocoagsg->get_fb_properties();
|
||||
|
||||
_vsync_enabled = sync_video && cocoagsg->setup_vsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the context.
|
||||
*/
|
||||
void CocoaGLGraphicsWindow::
|
||||
update_context() {
|
||||
CocoaGLGraphicsStateGuardian *cocoagsg;
|
||||
cocoagsg = DCAST(CocoaGLGraphicsStateGuardian, _gsg);
|
||||
|
||||
if (cocoagsg != nullptr && cocoagsg->_context != nil) {
|
||||
cocoagsg->lock_context();
|
||||
_context_needs_update = false;
|
||||
[cocoagsg->_context update];
|
||||
cocoagsg->unlock_context();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbinds the context from the window.
|
||||
*/
|
||||
void CocoaGLGraphicsWindow::
|
||||
unbind_context() {
|
||||
CocoaGLGraphicsStateGuardian *cocoagsg;
|
||||
cocoagsg = DCAST(CocoaGLGraphicsStateGuardian, _gsg);
|
||||
|
||||
if (cocoagsg != nullptr && cocoagsg->_context != nil) {
|
||||
cocoagsg->lock_context();
|
||||
[cocoagsg->_context clearDrawable];
|
||||
cocoagsg->unlock_context();
|
||||
}
|
||||
}
|
21
panda/src/cocoagldisplay/config_cocoagldisplay.h
Normal file
21
panda/src/cocoagldisplay/config_cocoagldisplay.h
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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 config_cocoagldisplay.h
|
||||
* @author rdb
|
||||
* @date 2023-03-20
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_COCOAGLDISPLAY_H
|
||||
#define CONFIG_COCOAGLDISPLAY_H
|
||||
|
||||
#include "config_cocoadisplay.h"
|
||||
|
||||
extern EXPCL_PANDA_COCOAGLDISPLAY void init_libcocoagldisplay();
|
||||
|
||||
#endif
|
60
panda/src/cocoagldisplay/config_cocoagldisplay.mm
Normal file
60
panda/src/cocoagldisplay/config_cocoagldisplay.mm
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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 config_cocoagldisplay.mm
|
||||
* @author rdb
|
||||
* @date 2023-03-20
|
||||
*/
|
||||
|
||||
#include "config_cocoagldisplay.h"
|
||||
#include "cocoaGLGraphicsBuffer.h"
|
||||
#include "cocoaGLGraphicsPipe.h"
|
||||
#include "cocoaGLGraphicsStateGuardian.h"
|
||||
#include "cocoaGLGraphicsWindow.h"
|
||||
#include "graphicsPipeSelection.h"
|
||||
#include "dconfig.h"
|
||||
#include "pandaSystem.h"
|
||||
|
||||
#if !defined(CPPPARSER) && !defined(LINK_ALL_STATIC) && !defined(BUILDING_PANDA_COCOAGLDISPLAY)
|
||||
#error Buildsystem error: BUILDING_PANDA_COCOAGLDISPLAY not defined
|
||||
#endif
|
||||
|
||||
Configure(config_cocoagldisplay);
|
||||
|
||||
ConfigureFn(config_cocoagldisplay) {
|
||||
init_libcocoagldisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_libcocoagldisplay() {
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
init_libcocoadisplay();
|
||||
|
||||
CocoaGLGraphicsBuffer::init_type();
|
||||
CocoaGLGraphicsPipe::init_type();
|
||||
CocoaGLGraphicsStateGuardian::init_type();
|
||||
CocoaGLGraphicsWindow::init_type();
|
||||
|
||||
GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
|
||||
selection->add_pipe_type(CocoaGLGraphicsPipe::get_class_type(),
|
||||
CocoaGLGraphicsPipe::pipe_constructor);
|
||||
|
||||
PandaSystem *ps = PandaSystem::get_global_ptr();
|
||||
ps->set_system_tag("OpenGL", "window_system", "Cocoa");
|
||||
}
|
5
panda/src/cocoagldisplay/p3cocoagldisplay_composite1.mm
Normal file
5
panda/src/cocoagldisplay/p3cocoagldisplay_composite1.mm
Normal file
@ -0,0 +1,5 @@
|
||||
#include "cocoaGLGraphicsBuffer.mm"
|
||||
#include "cocoaGLGraphicsPipe.mm"
|
||||
#include "cocoaGLGraphicsStateGuardian.mm"
|
||||
#include "cocoaGLGraphicsWindow.mm"
|
||||
#include "config_cocoagldisplay.mm"
|
@ -111,6 +111,7 @@
|
||||
/* BUILDING_PANDAGL for these: */
|
||||
#ifdef BUILDING_PANDAGL
|
||||
#define BUILDING_PANDA_COCOADISPLAY
|
||||
#define BUILDING_PANDA_COCOAGLDISPLAY
|
||||
#define BUILDING_PANDA_GLGSG
|
||||
#define BUILDING_PANDA_GLXDISPLAY
|
||||
#define BUILDING_PANDA_WGLDISPLAY
|
||||
@ -162,6 +163,14 @@
|
||||
#define EXPTP_PANDA_COCOADISPLAY IMPORT_TEMPL
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_PANDA_COCOAGLDISPLAY
|
||||
#define EXPCL_PANDA_COCOAGLDISPLAY EXPORT_CLASS
|
||||
#define EXPTP_PANDA_COCOAGLDISPLAY EXPORT_TEMPL
|
||||
#else
|
||||
#define EXPCL_PANDA_COCOAGLDISPLAY IMPORT_CLASS
|
||||
#define EXPTP_PANDA_COCOAGLDISPLAY IMPORT_TEMPL
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_PANDA_COLLIDE
|
||||
#define EXPCL_PANDA_COLLIDE EXPORT_CLASS
|
||||
#define EXPTP_PANDA_COLLIDE EXPORT_TEMPL
|
||||
|
Loading…
x
Reference in New Issue
Block a user