mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-05 03:15:07 -04:00
subprocess window
This commit is contained in:
parent
d24c039650
commit
37e76f402d
@ -37,7 +37,9 @@
|
||||
stencilRenderStates.h \
|
||||
stereoDisplayRegion.I stereoDisplayRegion.h \
|
||||
displaySearchParameters.h \
|
||||
displayInformation.h
|
||||
displayInformation.h \
|
||||
subprocessWindow.h subprocessWindow.I \
|
||||
$[if $[and $[OSX_PLATFORM],$[HAVE_P3D_PLUGIN]], subprocessWindowBuffer.h subprocessWindowBuffer.I subprocessWindowBuffer.cxx]
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
standardMunger.cxx \
|
||||
@ -62,7 +64,8 @@
|
||||
stencilRenderStates.cxx \
|
||||
stereoDisplayRegion.cxx \
|
||||
displaySearchParameters.cxx \
|
||||
displayInformation.cxx
|
||||
displayInformation.cxx \
|
||||
subprocessWindow.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
standardMunger.I standardMunger.h \
|
||||
@ -90,12 +93,31 @@
|
||||
stencilRenderStates.h \
|
||||
stereoDisplayRegion.I stereoDisplayRegion.h \
|
||||
displaySearchParameters.h \
|
||||
displayInformation.h
|
||||
displayInformation.h \
|
||||
subprocessWindow.h subprocessWindow.I \
|
||||
subprocessWindowBuffer.h subprocessWindowBuffer.I
|
||||
|
||||
#define IGATESCAN all
|
||||
|
||||
#end lib_target
|
||||
|
||||
|
||||
#begin static_lib_target
|
||||
// We build a static library of just these files, so the plugin can
|
||||
// link with it in direct/src/plugin, without pulling in the rest of
|
||||
// Panda.
|
||||
|
||||
#define BUILD_TARGET $[and $[OSX_PLATFORM],$[HAVE_P3D_PLUGIN]]
|
||||
|
||||
#define TARGET subprocbuffer
|
||||
|
||||
#define SOURCES \
|
||||
subprocessWindowBuffer.h subprocessWindowBuffer.I \
|
||||
subprocessWindowBuffer.cxx
|
||||
|
||||
#end static_lib_target
|
||||
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET test_display
|
||||
#define LOCAL_LIBS \
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "parasiteBuffer.h"
|
||||
#include "pandaSystem.h"
|
||||
#include "stereoDisplayRegion.h"
|
||||
#include "subprocessWindow.h"
|
||||
|
||||
ConfigureDef(config_display);
|
||||
NotifyCategoryDef(display, "");
|
||||
@ -289,6 +290,15 @@ ConfigVariableInt parent_window_handle
|
||||
"an HWND on Windows, or the NSWindow pointer or XWindow pointer "
|
||||
"converted to an integer, on OSX and X11."));
|
||||
|
||||
ConfigVariableFilename subprocess_window
|
||||
("subprocess-window", "",
|
||||
PRC_DESC("The filename of a SubprocessWindowBuffer's temporary mmap file, "
|
||||
"used for opening a window in a child process and rendering "
|
||||
"to a different window in the parent process. "
|
||||
"This is specifically used for OSX when the plugin is compiled, "
|
||||
"and is not used or needed in other environments. See "
|
||||
"WindowProperties::set_subprocess_window()."));
|
||||
|
||||
ConfigVariableString framebuffer_mode
|
||||
("framebuffer-mode", "",
|
||||
PRC_DESC("No longer has any effect. Do not use."));
|
||||
@ -400,6 +410,9 @@ init_libdisplay() {
|
||||
ParasiteBuffer::init_type();
|
||||
StandardMunger::init_type();
|
||||
StereoDisplayRegion::init_type();
|
||||
#ifdef SUPPORT_SUBPROCESS_WINDOW
|
||||
SubprocessWindow::init_type();
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_THREADS) && defined(DO_PIPELINING)
|
||||
PandaSystem *ps = PandaSystem::get_global_ptr();
|
||||
|
@ -73,6 +73,7 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableFilename cursor_filename;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableEnum<WindowProperties::ZOrder> z_order;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableString window_title;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt parent_window_handle;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableFilename subprocess_window;
|
||||
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableString framebuffer_mode;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_hardware;
|
||||
|
@ -13,3 +13,4 @@
|
||||
#include "displaySearchParameters.cxx"
|
||||
#include "displayInformation.cxx"
|
||||
#include "stereoDisplayRegion.cxx"
|
||||
#include "subprocessWindow.cxx"
|
||||
|
14
panda/src/display/subprocessWindow.I
Normal file
14
panda/src/display/subprocessWindow.I
Normal file
@ -0,0 +1,14 @@
|
||||
// Filename: osxSubprocessWindow.I
|
||||
// Created by: drose (11Jul09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
275
panda/src/display/subprocessWindow.cxx
Normal file
275
panda/src/display/subprocessWindow.cxx
Normal file
@ -0,0 +1,275 @@
|
||||
// Filename: subprocessWindow.cxx
|
||||
// Created by: drose (11Jul09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "subprocessWindow.h"
|
||||
|
||||
#ifdef SUPPORT_SUBPROCESS_WINDOW
|
||||
|
||||
#include "graphicsEngine.h"
|
||||
|
||||
TypeHandle SubprocessWindow::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindow::Constructor
|
||||
// Access: Protected
|
||||
// Description: Normally, the SubprocessWindow constructor is not
|
||||
// called directly; these are created instead via the
|
||||
// GraphicsEngine::make_window() function.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SubprocessWindow::
|
||||
SubprocessWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
const string &name,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
const WindowProperties &win_prop,
|
||||
int flags,
|
||||
GraphicsStateGuardian *gsg,
|
||||
GraphicsOutput *host,
|
||||
const string &filename) :
|
||||
GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
|
||||
{
|
||||
GraphicsWindowInputDevice device =
|
||||
GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard/mouse");
|
||||
_input_devices.push_back(device);
|
||||
|
||||
// Create a buffer with the same properties as the window.
|
||||
flags = ((flags & ~GraphicsPipe::BF_require_window) | GraphicsPipe::BF_refuse_window);
|
||||
|
||||
GraphicsOutput *buffer =
|
||||
engine->make_output(pipe, name, 0,
|
||||
fb_prop, win_prop, flags, gsg, host);
|
||||
if (buffer != NULL) {
|
||||
_buffer = DCAST(GraphicsBuffer, buffer);
|
||||
// However, the buffer is not itself intended to be rendered. We
|
||||
// only render it indirectly, via callbacks in here.
|
||||
_buffer->set_active(false);
|
||||
}
|
||||
|
||||
// Now create a texture to receive the contents of the framebuffer
|
||||
// from the buffer.
|
||||
_texture = new Texture(name);
|
||||
|
||||
_fd = -1;
|
||||
_mmap_size = 0;
|
||||
_filename = filename;
|
||||
_swbuffer = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindow::Destructor
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SubprocessWindow::
|
||||
~SubprocessWindow() {
|
||||
if (_buffer != NULL) {
|
||||
_engine->remove_window(_buffer);
|
||||
}
|
||||
nassertv(_swbuffer == NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindow::process_events
|
||||
// Access: Public, Virtual
|
||||
// Description: Do whatever processing is necessary to ensure that
|
||||
// the window responds to user events. Also, honor any
|
||||
// requests recently made via request_properties().
|
||||
//
|
||||
// This function is called only within the window
|
||||
// thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SubprocessWindow::
|
||||
process_events() {
|
||||
GraphicsWindow::process_events();
|
||||
|
||||
if (_swbuffer != NULL) {
|
||||
SubprocessWindowBuffer::Event event;
|
||||
while (_swbuffer->get_event(event)) {
|
||||
// Deal with this event. For now, we only have mouse down/up.
|
||||
_input_devices[0].set_pointer_in_window(event._x, event._y);
|
||||
if (event._up) {
|
||||
_input_devices[0].button_up(MouseButton::one());
|
||||
} else {
|
||||
_input_devices[0].button_down(MouseButton::one());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindow::begin_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: This function will be called within the draw thread
|
||||
// before beginning rendering for a given frame. It
|
||||
// should do whatever setup is required, and return true
|
||||
// if the frame should be rendered, or false if it
|
||||
// should be skipped.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool SubprocessWindow::
|
||||
begin_frame(FrameMode mode, Thread *current_thread) {
|
||||
if (_swbuffer == NULL || _buffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_swbuffer->ready_for_write()) {
|
||||
// The other end hasn't removed a frame lately; don't bother to
|
||||
// render.
|
||||
Thread::force_yield();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = _buffer->begin_frame(mode, current_thread);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindow::end_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: This function will be called within the draw thread
|
||||
// after rendering is completed for a given frame. It
|
||||
// should do whatever finalization is required.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SubprocessWindow::
|
||||
end_frame(FrameMode mode, Thread *current_thread) {
|
||||
_buffer->end_frame(mode, current_thread);
|
||||
|
||||
if (mode == FM_render) {
|
||||
_flip_ready = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindow::begin_flip
|
||||
// Access: Public, Virtual
|
||||
// Description: This function will be called within the draw thread
|
||||
// after end_frame() has been called on all windows, to
|
||||
// initiate the exchange of the front and back buffers.
|
||||
//
|
||||
// This should instruct the window to prepare for the
|
||||
// flip at the next video sync, but it should not wait.
|
||||
//
|
||||
// We have the two separate functions, begin_flip() and
|
||||
// end_flip(), to make it easier to flip all of the
|
||||
// windows at the same time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SubprocessWindow::
|
||||
begin_flip() {
|
||||
nassertv(_buffer != (GraphicsBuffer *)NULL);
|
||||
nassertv(_swbuffer != NULL);
|
||||
|
||||
RenderBuffer buffer(_gsg, DrawableRegion::get_renderbuffer_type(RTP_color));
|
||||
buffer = _gsg->get_render_buffer(_buffer->get_draw_buffer_type(),
|
||||
_buffer->get_fb_properties());
|
||||
|
||||
bool copied =
|
||||
_gsg->framebuffer_copy_to_ram(_texture, -1,
|
||||
_default_display_region, buffer);
|
||||
|
||||
if (copied) {
|
||||
CPTA_uchar image = _texture->get_ram_image();
|
||||
size_t framebuffer_size = _swbuffer->get_framebuffer_size();
|
||||
nassertv(image.size() == framebuffer_size);
|
||||
|
||||
// Now copy the image to our shared framebuffer.
|
||||
void *target = _swbuffer->open_write_framebuffer();
|
||||
memcpy(target, image.p(), framebuffer_size);
|
||||
_swbuffer->close_write_framebuffer();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindow::close_window
|
||||
// Access: Protected, Virtual
|
||||
// Description: Closes the window right now. Called from the window
|
||||
// thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SubprocessWindow::
|
||||
close_window() {
|
||||
if (_swbuffer != NULL) {
|
||||
SubprocessWindowBuffer::close_buffer(_fd, _mmap_size, _filename, _swbuffer);
|
||||
_fd = -1;
|
||||
_filename = string();
|
||||
|
||||
_swbuffer = NULL;
|
||||
}
|
||||
|
||||
if (_buffer != NULL) {
|
||||
_buffer->request_close();
|
||||
_buffer->process_events();
|
||||
}
|
||||
|
||||
_is_valid = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindow::open_window
|
||||
// Access: Protected, Virtual
|
||||
// Description: 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 SubprocessWindow::
|
||||
open_window() {
|
||||
nout << "open_window\n";
|
||||
|
||||
if (_buffer != NULL) {
|
||||
_buffer->request_open();
|
||||
_buffer->process_events();
|
||||
|
||||
_is_valid = _buffer->is_valid();
|
||||
}
|
||||
|
||||
if (!_is_valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_gsg = _buffer->get_gsg();
|
||||
|
||||
_swbuffer = SubprocessWindowBuffer::open_buffer(_fd, _mmap_size, _filename);
|
||||
|
||||
if (_swbuffer == NULL) {
|
||||
close(_fd);
|
||||
_fd = -1;
|
||||
_filename = string();
|
||||
_is_valid = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindow::set_properties_now
|
||||
// Access: Public, Virtual
|
||||
// Description: Applies the requested set of properties to the
|
||||
// window, if possible, for instance to request a change
|
||||
// in size or minimization status.
|
||||
//
|
||||
// The window properties are applied immediately, rather
|
||||
// than waiting until the next frame. This implies that
|
||||
// this method may *only* be called from within the
|
||||
// window thread.
|
||||
//
|
||||
// The properties that have been applied are cleared
|
||||
// from the structure by this function; so on return,
|
||||
// whatever remains in the properties structure are
|
||||
// those that were unchanged for some reason (probably
|
||||
// because the underlying interface does not support
|
||||
// changing that property on an open window).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SubprocessWindow::
|
||||
set_properties_now(WindowProperties &properties) {
|
||||
GraphicsWindow::set_properties_now(properties);
|
||||
}
|
||||
|
||||
#endif // SUPPORT_SUBPROCESS_WINDOW
|
106
panda/src/display/subprocessWindow.h
Normal file
106
panda/src/display/subprocessWindow.h
Normal file
@ -0,0 +1,106 @@
|
||||
// Filename: subprocessWindow.h
|
||||
// Created by: drose (11Jul09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SUBPROCESSWINDOW_H
|
||||
#define SUBPROCESSWINDOW_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
// For now, a simple trigger whether to enable the subprocess window
|
||||
// support. We only build it on OSX, and only when the plugin is
|
||||
// enabled; because this is (presently) the only case where it's
|
||||
// useful.
|
||||
#if defined(HAVE_P3D_PLUGIN) && defined(IS_OSX)
|
||||
#define SUPPORT_SUBPROCESS_WINDOW 1
|
||||
#else
|
||||
#undef SUPPORT_SUBPROCESS_WINDOW
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_SUBPROCESS_WINDOW
|
||||
|
||||
#include "graphicsWindow.h"
|
||||
#include "graphicsBuffer.h"
|
||||
#include "texture.h"
|
||||
#include "subprocessWindowBuffer.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : SubprocessWindow
|
||||
// Description : This is a special "window" that actually renders to
|
||||
// an offscreen buffer, copies the pixels to RAM, and
|
||||
// then ships them to a parent process via shared memory
|
||||
// for rendering to the window.
|
||||
//
|
||||
// This whole nonsense is necessary because OSX doesn't
|
||||
// allow child processes to draw to, or attach windows
|
||||
// to, windows created in the parent process. There's a
|
||||
// rumor that 10.6 fixes this nonsense; this will remain
|
||||
// to be seen.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class SubprocessWindow : public GraphicsWindow {
|
||||
public:
|
||||
SubprocessWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
const string &name,
|
||||
const FrameBufferProperties &fb_prop,
|
||||
const WindowProperties &win_prop,
|
||||
int flags,
|
||||
GraphicsStateGuardian *gsg,
|
||||
GraphicsOutput *host,
|
||||
const string &filename);
|
||||
virtual ~SubprocessWindow();
|
||||
|
||||
virtual void process_events();
|
||||
|
||||
virtual bool begin_frame(FrameMode mode, Thread *current_thread);
|
||||
virtual void end_frame(FrameMode mode, Thread *current_thread);
|
||||
virtual void begin_flip();
|
||||
|
||||
virtual void set_properties_now(WindowProperties &properties);
|
||||
|
||||
protected:
|
||||
virtual void close_window();
|
||||
virtual bool open_window();
|
||||
|
||||
private:
|
||||
PT(GraphicsBuffer) _buffer;
|
||||
PT(Texture) _texture;
|
||||
|
||||
int _fd;
|
||||
size_t _mmap_size;
|
||||
string _filename;
|
||||
SubprocessWindowBuffer *_swbuffer;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
GraphicsWindow::init_type();
|
||||
register_type(_type_handle, "SubprocessWindow",
|
||||
GraphicsWindow::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "subprocessWindow.I"
|
||||
|
||||
#endif // SUPPORT_SUBPROCESS_WINDOW
|
||||
|
||||
#endif
|
||||
|
176
panda/src/display/subprocessWindowBuffer.I
Normal file
176
panda/src/display/subprocessWindowBuffer.I
Normal file
@ -0,0 +1,176 @@
|
||||
// Filename: subprocessWindowBuffer.I
|
||||
// Created by: drose (11Jul09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::get_x_size
|
||||
// Access: Public
|
||||
// Description: Returns the width of the framebuffer in pixels.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int SubprocessWindowBuffer::
|
||||
get_x_size() const {
|
||||
return _x_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::get_y_size
|
||||
// Access: Public
|
||||
// Description: Returns the height of the framebuffer in pixels.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline int SubprocessWindowBuffer::
|
||||
get_y_size() const {
|
||||
return _y_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::get_row_size
|
||||
// Access: Public
|
||||
// Description: Returns the length of a row of the framebuffer, in
|
||||
// bytes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline size_t SubprocessWindowBuffer::
|
||||
get_row_size() const {
|
||||
return _row_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::get_framebuffer_size
|
||||
// Access: Public
|
||||
// Description: Returns the total number of bytes in the framebuffer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline size_t SubprocessWindowBuffer::
|
||||
get_framebuffer_size() const {
|
||||
return _framebuffer_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::ready_for_read
|
||||
// Access: Public
|
||||
// Description: Returns true if the framebuffer data has been updated
|
||||
// since open_read_framebuffer() was last called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool SubprocessWindowBuffer::
|
||||
ready_for_read() const {
|
||||
return (_last_written != _last_read);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::ready_for_write
|
||||
// Access: Public
|
||||
// Description: Returns true if the framebuffer data has been read
|
||||
// since open_write_framebuffer() was last called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool SubprocessWindowBuffer::
|
||||
ready_for_write() const {
|
||||
return (_last_written == _last_read);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::open_read_framebuffer
|
||||
// Access: Public
|
||||
// Description: Returns a read-only pointer to the framebuffer. It
|
||||
// is only valid to call this if ready_for_read() has
|
||||
// returned true.
|
||||
//
|
||||
// You must call close_read_framebuffer() to indicate
|
||||
// you have finished reading.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline const void *SubprocessWindowBuffer::
|
||||
open_read_framebuffer() {
|
||||
assert(ready_for_read());
|
||||
return (void *)(this + 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::close_read_framebuffer
|
||||
// Access: Public
|
||||
// Description: Releases the framebuffer after a previous call to
|
||||
// open_read_framebuffer().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void SubprocessWindowBuffer::
|
||||
close_read_framebuffer() {
|
||||
_last_read = _last_written;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::open_write_framebuffer
|
||||
// Access: Public
|
||||
// Description: Returns a writable pointer to the framebuffer. It
|
||||
// is only valid to call this if ready_for_write() has
|
||||
// returned true.
|
||||
//
|
||||
// You must call close_write_framebuffer() to indicate
|
||||
// you have finished writing.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void *SubprocessWindowBuffer::
|
||||
open_write_framebuffer() {
|
||||
assert(ready_for_write());
|
||||
return (void *)(this + 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::close_write_framebuffer
|
||||
// Access: Public
|
||||
// Description: Releases the framebuffer after a previous call to
|
||||
// open_write_framebuffer().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline void SubprocessWindowBuffer::
|
||||
close_write_framebuffer() {
|
||||
++_last_written;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::add_event
|
||||
// Access: Public
|
||||
// Description: Adds a new Event to the queue. Returns false
|
||||
// if the queue was full.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool SubprocessWindowBuffer::
|
||||
add_event(const SubprocessWindowBuffer::Event &event) {
|
||||
if (((_event_in + 1) % max_events) == _event_out) {
|
||||
// The queue is full.
|
||||
return false;
|
||||
}
|
||||
_events[_event_in] = event;
|
||||
_event_in = (_event_in + 1) % max_events;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::has_event
|
||||
// Access: Public
|
||||
// Description: Returns true if the queue has at least one
|
||||
// Event to extract, false if it is empty.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool SubprocessWindowBuffer::
|
||||
has_event() const {
|
||||
return (_event_in != _event_out);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::get_event
|
||||
// Access: Public
|
||||
// Description: If the queue is nonempty, fills event with the first
|
||||
// Event on the queue and returns true. If the queue is
|
||||
// empty, returns false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
inline bool SubprocessWindowBuffer::
|
||||
get_event(SubprocessWindowBuffer::Event &event) {
|
||||
if (_event_in == _event_out) {
|
||||
return false;
|
||||
}
|
||||
event = _events[_event_out];
|
||||
_event_out = (_event_out + 1) % max_events;
|
||||
return true;
|
||||
}
|
291
panda/src/display/subprocessWindowBuffer.cxx
Normal file
291
panda/src/display/subprocessWindowBuffer.cxx
Normal file
@ -0,0 +1,291 @@
|
||||
// Filename: subprocessWindowBuffer.cxx
|
||||
// Created by: drose (11Jul09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "subprocessWindowBuffer.h"
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
const char SubprocessWindowBuffer::
|
||||
_magic_number[SubprocessWindowBuffer::magic_number_length] = "pNdaSWB";
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::operator new
|
||||
// Access: Private
|
||||
// Description: Placement operator. Returns addr, a trivial
|
||||
// pass-through.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void *SubprocessWindowBuffer::
|
||||
operator new(size_t, void *addr) {
|
||||
cerr << "operator new: " << addr << "\n";
|
||||
return addr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::Constructor
|
||||
// Access: Private
|
||||
// Description: This constructor is private; it is not intended to be
|
||||
// called directly. It is used in make_buffer() to
|
||||
// create a temporary local object, to determine the
|
||||
// required mmap_size for a given window size.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SubprocessWindowBuffer::
|
||||
SubprocessWindowBuffer(int x_size, int y_size) {
|
||||
cerr << "Constructing " << this << "\n";
|
||||
memcpy(_this_magic, _magic_number, magic_number_length);
|
||||
_x_size = x_size;
|
||||
_y_size = y_size;
|
||||
_row_size = _x_size * 4;
|
||||
_framebuffer_size = _row_size * y_size;
|
||||
_event_in = 0;
|
||||
_event_out = 0;
|
||||
_last_written = 0;
|
||||
_last_read = 0;
|
||||
|
||||
_mmap_size = sizeof(*this) + _framebuffer_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::Copy Constructor
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SubprocessWindowBuffer::
|
||||
SubprocessWindowBuffer(const SubprocessWindowBuffer ©) :
|
||||
_x_size(copy._x_size),
|
||||
_y_size(copy._y_size),
|
||||
_row_size(copy._row_size),
|
||||
_framebuffer_size(copy._framebuffer_size),
|
||||
_mmap_size(copy._mmap_size)
|
||||
{
|
||||
memcpy(_this_magic, _magic_number, magic_number_length);
|
||||
_event_in = 0;
|
||||
_event_out = 0;
|
||||
_last_written = 0;
|
||||
_last_read = 0;
|
||||
cerr << "Copy Constructing " << this << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::Destructor
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SubprocessWindowBuffer::
|
||||
~SubprocessWindowBuffer() {
|
||||
cerr << "Destructing " << this << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::new_buffer
|
||||
// Access: Public, Static
|
||||
// Description: Call this method to create a new buffer in shared
|
||||
// memory space. Supply the desired size of the window.
|
||||
//
|
||||
// This method will create the required shared-memory
|
||||
// buffer and return a SubprocessWindowBuffer allocated
|
||||
// within that shared memory, or NULL if there is a
|
||||
// failure allocating sufficient shared memory.
|
||||
//
|
||||
// It also creates a temporary file on disk and returns
|
||||
// fd, mmap_size, and filename, which the caller must
|
||||
// retain and eventually pass to destroy_buffer(). The
|
||||
// filename should be passed to the child process to
|
||||
// open with open_buffer().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SubprocessWindowBuffer *SubprocessWindowBuffer::
|
||||
new_buffer(int &fd, size_t &mmap_size, string &filename,
|
||||
int x_size, int y_size) {
|
||||
mmap_size = 0;
|
||||
fd = -1;
|
||||
|
||||
filename = tmpnam(NULL);
|
||||
cerr << "new_buffer: " << filename << "\n";
|
||||
|
||||
fd = open(filename.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
if (fd == -1) {
|
||||
perror(filename.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create a temporary object to determine the required size.
|
||||
SubprocessWindowBuffer temp(x_size, y_size);
|
||||
mmap_size = temp._mmap_size;
|
||||
|
||||
// Ensure the disk file is large enough.
|
||||
size_t zero_size = 1024;
|
||||
char zero[zero_size];
|
||||
memset(zero, 0, zero_size);
|
||||
for (size_t bi = 0; bi < mmap_size; bi += zero_size) {
|
||||
write(fd, zero, zero_size);
|
||||
}
|
||||
|
||||
cerr << "size = " << x_size << " * " << y_size << " = "
|
||||
<< mmap_size << " bytes\n";
|
||||
|
||||
void *shared_mem = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, 0);
|
||||
if (shared_mem == (void *)-1) {
|
||||
// Failure to map.
|
||||
close(fd);
|
||||
fd = -1;
|
||||
mmap_size = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cerr << "shared_mem = " << shared_mem << "\n";
|
||||
|
||||
// Now create the actual object in the shared-memory buffer.
|
||||
return new(shared_mem) SubprocessWindowBuffer(temp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::destroy_buffer
|
||||
// Access: Public, Static
|
||||
// Description: Destroys a buffer object created via a previous call
|
||||
// to new_buffer(). This destructs objects within the
|
||||
// buffer, unmaps the shared memory, and closes the file
|
||||
// descriptor.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SubprocessWindowBuffer::
|
||||
destroy_buffer(int fd, size_t mmap_size, const string &filename,
|
||||
SubprocessWindowBuffer *buffer) {
|
||||
buffer->~SubprocessWindowBuffer();
|
||||
close_buffer(fd, mmap_size, filename, buffer);
|
||||
|
||||
// This isn't really necessary, since our child process should have
|
||||
// unlinked it; but we do it anyway just for good measure (for
|
||||
// instance, in case the child process never got started). I
|
||||
// suppose there is some risk that we will accidentally delete
|
||||
// someone else's file this way, but the risk is small.
|
||||
unlink(filename.c_str());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::open_buffer
|
||||
// Access: Public, Static
|
||||
// Description: Call this method to open a reference to an existing
|
||||
// buffer in shared memory space. Supply the temporary
|
||||
// filename returned by new_buffer(), above (presumably
|
||||
// from the parent process).
|
||||
//
|
||||
// This method will mmap the required shared-memory
|
||||
// buffer and return a SubprocessWindowBuffer allocated
|
||||
// within that shared memory, or NULL if there is some
|
||||
// failure. The caller must retain fd, mmap_size, and
|
||||
// filename and eventually pass all three to
|
||||
// close_buffer().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SubprocessWindowBuffer *SubprocessWindowBuffer::
|
||||
open_buffer(int &fd, size_t &mmap_size, const string &filename) {
|
||||
cerr << "open_buffer: " << filename << "\n";
|
||||
|
||||
mmap_size = 0;
|
||||
|
||||
fd = open(filename.c_str(), O_RDWR);
|
||||
if (fd == -1) {
|
||||
perror(filename.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check that the disk file is large enough.
|
||||
off_t file_size = lseek(fd, 0, SEEK_END);
|
||||
if (file_size < sizeof(SubprocessWindowBuffer)) {
|
||||
cerr << filename << " not large enough.\n";
|
||||
close(fd);
|
||||
fd = -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// First, map enough memory to read the buffer object.
|
||||
size_t initial_size = sizeof(SubprocessWindowBuffer);
|
||||
void *shared_mem = mmap(NULL, initial_size, PROT_READ,
|
||||
MAP_SHARED, fd, 0);
|
||||
if (shared_mem == (void *)-1) {
|
||||
perror("mmap");
|
||||
cerr << "Couldn't map.\n";
|
||||
close(fd);
|
||||
fd = -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SubprocessWindowBuffer *temp = (SubprocessWindowBuffer *)shared_mem;
|
||||
if (!temp->verify_magic_number()) {
|
||||
cerr << "Not a subprocess window buffer: " << filename << "\n";
|
||||
munmap(shared_mem, initial_size);
|
||||
close(fd);
|
||||
fd = -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
mmap_size = temp->_mmap_size;
|
||||
|
||||
// Now unmap that and remap the proper-size buffer.
|
||||
munmap(shared_mem, initial_size);
|
||||
|
||||
if (file_size < mmap_size) {
|
||||
cerr << filename << " not large enough.\n";
|
||||
close(fd);
|
||||
fd = -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
shared_mem = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, 0);
|
||||
if (shared_mem == (void *)-1) {
|
||||
perror("mmap");
|
||||
cerr << "Couldn't map 2.\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Now that we've successfully opened and mapped the file, we can
|
||||
// safely delete it from the file system.
|
||||
unlink(filename.c_str());
|
||||
|
||||
SubprocessWindowBuffer *buffer = (SubprocessWindowBuffer *)shared_mem;
|
||||
assert(buffer->_mmap_size == mmap_size);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::close_buffer
|
||||
// Access: Public, Static
|
||||
// Description: Closes a buffer object created via a previous call
|
||||
// to open_buffer(). This unmaps the shared memory
|
||||
// and closes the file descriptor, but does not molest
|
||||
// the shared buffer itself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SubprocessWindowBuffer::
|
||||
close_buffer(int fd, size_t mmap_size, const string &filename,
|
||||
SubprocessWindowBuffer *buffer) {
|
||||
munmap((void *)buffer, mmap_size);
|
||||
close(fd);
|
||||
|
||||
// Guess we shouldn't unlink() the file here, since we already did
|
||||
// in open_buffer().
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SubprocessWindowBuffer::verify_magic_number
|
||||
// Access: Public
|
||||
// Description: Returns true if the buffer's magic number matches,
|
||||
// false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool SubprocessWindowBuffer::
|
||||
verify_magic_number() const {
|
||||
return (memcmp(_this_magic, _magic_number, magic_number_length) == 0);
|
||||
}
|
124
panda/src/display/subprocessWindowBuffer.h
Normal file
124
panda/src/display/subprocessWindowBuffer.h
Normal file
@ -0,0 +1,124 @@
|
||||
// Filename: subprocessWindowBuffer.h
|
||||
// Created by: drose (11Jul09)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SUBPROCESSWINDOWBUFFER_H
|
||||
#define SUBPROCESSWINDOWBUFFER_H
|
||||
|
||||
#include <stdio.h> // perror
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : SubprocessWindowBuffer
|
||||
// Description : This is a special class that is designed to faciliate
|
||||
// SubprocessWindow. It's intended to be allocated
|
||||
// within a shared memory buffer, and it contains space
|
||||
// for a framebuffer image to be stored for transferring
|
||||
// between processes, as well as appropriate
|
||||
// synchronization primitives.
|
||||
//
|
||||
// It's designed to be compiled outside of Panda, so
|
||||
// that code that doesn't link with Panda (in
|
||||
// particular, the Panda3D plugin core API) may still
|
||||
// link with this and use it.
|
||||
//
|
||||
// At the moment, and maybe indefinitely, it is only
|
||||
// compiled on OSX, and only when we are building
|
||||
// support for the plugin; because it is only needed
|
||||
// then.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class SubprocessWindowBuffer {
|
||||
private:
|
||||
void *operator new(size_t, void *addr);
|
||||
SubprocessWindowBuffer(int x_size, int y_size);
|
||||
SubprocessWindowBuffer(const SubprocessWindowBuffer ©);
|
||||
~SubprocessWindowBuffer();
|
||||
|
||||
public:
|
||||
static SubprocessWindowBuffer *new_buffer(int &fd, size_t &mmap_size,
|
||||
string &filename,
|
||||
int x_size, int y_size);
|
||||
static void destroy_buffer(int fd, size_t mmap_size,
|
||||
const string &filename,
|
||||
SubprocessWindowBuffer *buffer);
|
||||
|
||||
static SubprocessWindowBuffer *open_buffer(int &fd, size_t &mmap_size,
|
||||
const string &filename);
|
||||
static void close_buffer(int fd, size_t mmap_size,
|
||||
const string &filename,
|
||||
SubprocessWindowBuffer *buffer);
|
||||
|
||||
bool verify_magic_number() const;
|
||||
|
||||
inline int get_x_size() const;
|
||||
inline int get_y_size() const;
|
||||
inline size_t get_row_size() const;
|
||||
inline size_t get_framebuffer_size() const;
|
||||
|
||||
inline bool ready_for_read() const;
|
||||
inline bool ready_for_write() const;
|
||||
|
||||
inline const void *open_read_framebuffer();
|
||||
inline void close_read_framebuffer();
|
||||
inline void *open_write_framebuffer();
|
||||
inline void close_write_framebuffer();
|
||||
|
||||
class Event {
|
||||
public:
|
||||
// int _key; TODO.
|
||||
bool _up;
|
||||
int _x, _y; // position of mouse at the time of the event
|
||||
};
|
||||
|
||||
inline bool add_event(const Event &event);
|
||||
inline bool has_event() const;
|
||||
inline bool get_event(Event &event);
|
||||
|
||||
private:
|
||||
// The first thing we store in the buffer is a magic number, so we
|
||||
// don't accidentally memory-map the wrong file and attempt to treat
|
||||
// it as a window buffer.
|
||||
enum { magic_number_length = 8 };
|
||||
static const char _magic_number[magic_number_length];
|
||||
char _this_magic[magic_number_length];
|
||||
|
||||
// Then we have the required size of the entire structure, including
|
||||
// its data blocks.
|
||||
size_t _mmap_size;
|
||||
|
||||
// Then some other important parameters.
|
||||
int _x_size, _y_size;
|
||||
size_t _row_size;
|
||||
size_t _framebuffer_size;
|
||||
|
||||
// A circular queue of events.
|
||||
enum { max_events = 64 };
|
||||
int _event_in; // next slot to write an event to
|
||||
int _event_out; // next slot to read an event from
|
||||
Event _events[max_events];
|
||||
// The queue is empty when _event_in == _event_out.
|
||||
// It is full when _event_in == _event_out - 1, circularly.
|
||||
|
||||
// These sequence numbers are incremented as frames are written and
|
||||
// read.
|
||||
int _last_written;
|
||||
int _last_read;
|
||||
|
||||
// The framebuffer data begins immediately at the end of this class.
|
||||
};
|
||||
|
||||
#include "subprocessWindowBuffer.I"
|
||||
|
||||
#endif
|
@ -749,7 +749,18 @@ clear_z_order() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowProperties::set_mouse_mode
|
||||
// Access: Published
|
||||
// Description: Removes the z_order specification from the properties.
|
||||
// Description: Specifies the mode in which the window is to operate
|
||||
// its mouse pointer. The default is M_absolute, which
|
||||
// is the normal mode in which a mouse pointer operates;
|
||||
// but you can also set M_relative, which is
|
||||
// particularly useful for FPS-style mouse movements
|
||||
// where you have hidden the mouse pointer and are are
|
||||
// more interested in how fast the mouse is moving,
|
||||
// rather than precisely where the pointer is hovering.
|
||||
//
|
||||
// This has no effect on Windows and Linux, which do not
|
||||
// have this concept; but is important to do on OSX to
|
||||
// properly enable a smooth FPS-style mouselook mode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void WindowProperties::
|
||||
set_mouse_mode(MouseMode mode) {
|
||||
@ -760,7 +771,7 @@ set_mouse_mode(MouseMode mode) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowProperties::get_mouse_mode
|
||||
// Access: Published
|
||||
// Description: Removes the z_order specification from the properties.
|
||||
// Description: See set_mouse_mode().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE WindowProperties::MouseMode WindowProperties::
|
||||
get_mouse_mode() const {
|
||||
@ -768,9 +779,9 @@ get_mouse_mode() const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowProperties::has_moude_mode
|
||||
// Function: WindowProperties::has_mouse_mode
|
||||
// Access: Published
|
||||
// Description: Removes the z_order specification from the properties.
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool WindowProperties::
|
||||
has_mouse_mode() const {
|
||||
@ -780,7 +791,7 @@ has_mouse_mode() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowProperties::clear_mouse_mode
|
||||
// Access: Published
|
||||
// Description: Removes the z_order specification from the properties.
|
||||
// Description: Removes the mouse_mode specification from the properties.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void WindowProperties::
|
||||
clear_mouse_mode() {
|
||||
@ -791,7 +802,22 @@ clear_mouse_mode() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowProperties::set_parent_window
|
||||
// Access: Published
|
||||
// Description: Removes the z_order specification from the properties.
|
||||
// Description: Specifies the window that this window should be
|
||||
// attached to. If this is zero or unspecified, the
|
||||
// window will be created as a toplevel window on the
|
||||
// desktop; if this is nonzero, the window will be bound
|
||||
// as a child window to the indicated parent window.
|
||||
//
|
||||
// The actual value for "parent" is platform-specific.
|
||||
// On Windows, it is the HWND of the parent window, cast
|
||||
// to an unsigned integer. On X11, it is the Window
|
||||
// pointer of the parent window, similarly cast (yes,
|
||||
// it's a portability issue).
|
||||
//
|
||||
// On OSX, this is the NSWindow pointer, though there
|
||||
// appear to be some compatibility issues (OSX doesn't
|
||||
// easily support the parent-window model). On OSX,
|
||||
// consider using subprocess_window instead.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void WindowProperties::
|
||||
set_parent_window(size_t parent) {
|
||||
@ -802,7 +828,7 @@ set_parent_window(size_t parent) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowProperties::get_parent_window
|
||||
// Access: Published
|
||||
// Description: Removes the parent Window
|
||||
// Description: Returns the parent window specification.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t WindowProperties::
|
||||
get_parent_window() const {
|
||||
@ -830,6 +856,70 @@ clear_parent_window() {
|
||||
_parent_window = (size_t)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowProperties::set_subprocess_window
|
||||
// Access: Published
|
||||
// Description: Specifies that the window should be created as a
|
||||
// "subprocess window", which is a special concept
|
||||
// needed on OSX, to support windows that may run in a
|
||||
// subprocess and communicate the output of their
|
||||
// rendering to a parent process.
|
||||
//
|
||||
// To use it, create a SubprocessWindowBuffer in the
|
||||
// parent process, pass the resulting temporary filename
|
||||
// to the child process, and set that filename here
|
||||
// before opening a window. Panda will open a
|
||||
// SubprocessWindow instead of a normal window; and that
|
||||
// class will take the output of the rendering and write
|
||||
// it to the SubprocessWindowBuffer for the parent
|
||||
// process to extract.
|
||||
//
|
||||
// This is particularly useful for implementing the web
|
||||
// browser plugin on OSX, which requires exactly this
|
||||
// sort of process isolation in order to render to the
|
||||
// browser page.
|
||||
//
|
||||
// This feature is not currently available on other
|
||||
// platforms (and they have no need of it).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void WindowProperties::
|
||||
set_subprocess_window(const Filename &filename) {
|
||||
_subprocess_window = filename;
|
||||
_specified |= S_subprocess_window;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowProperties::get_subprocess_window
|
||||
// Access: Published
|
||||
// Description: Returns the filename specified to set_subprocess_window().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const Filename &WindowProperties::
|
||||
get_subprocess_window() const {
|
||||
return _subprocess_window;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowProperties::has_subprocess_window
|
||||
// Access: Published
|
||||
// Description: Returns true if set_subprocess_window() was set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool WindowProperties::
|
||||
has_subprocess_window() const {
|
||||
return ((_specified & S_subprocess_window) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WindowProperties::clear_subprocess_window
|
||||
// Access: Published
|
||||
// Description: Removes the subprocess_window specification from the
|
||||
// properties.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void WindowProperties::
|
||||
clear_subprocess_window() {
|
||||
_specified &= ~S_subprocess_window;
|
||||
_subprocess_window = Filename();
|
||||
}
|
||||
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const WindowProperties &properties) {
|
||||
|
@ -45,6 +45,7 @@ operator = (const WindowProperties ©) {
|
||||
_flags = copy._flags;
|
||||
_mouse_mode = copy._mouse_mode;
|
||||
_parent_window = copy._parent_window;
|
||||
_subprocess_window = copy._subprocess_window;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -86,7 +87,11 @@ get_default() {
|
||||
if (parent_window_handle.get_value() != 0) {
|
||||
props.set_parent_window(parent_window_handle);
|
||||
}
|
||||
if (subprocess_window.has_value()) {
|
||||
props.set_subprocess_window(subprocess_window);
|
||||
}
|
||||
props.set_mouse_mode(M_absolute);
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
@ -122,8 +127,8 @@ operator == (const WindowProperties &other) const {
|
||||
_icon_filename == other._icon_filename &&
|
||||
_cursor_filename == other._cursor_filename &&
|
||||
_mouse_mode == other._mouse_mode &&
|
||||
_parent_window == other._parent_window);
|
||||
|
||||
_parent_window == other._parent_window &&
|
||||
_subprocess_window == other._subprocess_window);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -147,6 +152,7 @@ clear() {
|
||||
_flags = 0;
|
||||
_mouse_mode = M_absolute;
|
||||
_parent_window = 0;
|
||||
_subprocess_window = Filename();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -200,15 +206,15 @@ add_properties(const WindowProperties &other) {
|
||||
if (other.has_z_order()) {
|
||||
set_z_order(other.get_z_order());
|
||||
}
|
||||
|
||||
if (other.has_mouse_mode()) {
|
||||
set_mouse_mode(other.get_mouse_mode());
|
||||
}
|
||||
|
||||
if (other.has_parent_window()) {
|
||||
set_parent_window(other.get_parent_window());
|
||||
}
|
||||
|
||||
if (other.has_subprocess_window()) {
|
||||
set_subprocess_window(other.get_subprocess_window());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -268,6 +274,9 @@ output(ostream &out) const {
|
||||
if (has_parent_window()) {
|
||||
out << "parent:" << get_parent_window() << " ";
|
||||
}
|
||||
if (has_subprocess_window()) {
|
||||
out << "subprocess_window:" << get_subprocess_window() << " ";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,6 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_DISPLAY WindowProperties {
|
||||
PUBLISHED:
|
||||
|
||||
|
||||
enum ZOrder {
|
||||
Z_bottom,
|
||||
Z_normal,
|
||||
@ -132,12 +130,16 @@ PUBLISHED:
|
||||
INLINE bool has_z_order() const;
|
||||
INLINE void clear_z_order();
|
||||
|
||||
|
||||
INLINE void set_parent_window(size_t parent);
|
||||
INLINE size_t get_parent_window() const;
|
||||
INLINE size_t get_parent_window() const;
|
||||
INLINE bool has_parent_window() const;
|
||||
INLINE void clear_parent_window();
|
||||
|
||||
INLINE void set_subprocess_window(const Filename &filename);
|
||||
INLINE const Filename &get_subprocess_window() const;
|
||||
INLINE bool has_subprocess_window() const;
|
||||
INLINE void clear_subprocess_window();
|
||||
|
||||
void add_properties(const WindowProperties &other);
|
||||
|
||||
void output(ostream &out) const;
|
||||
@ -147,22 +149,23 @@ private:
|
||||
// structure have been filled in by the user, and which remain
|
||||
// unspecified.
|
||||
enum Specified {
|
||||
S_origin = 0x0001,
|
||||
S_size = 0x0002,
|
||||
S_title = 0x0004,
|
||||
S_undecorated = 0x0008,
|
||||
S_fullscreen = 0x0010,
|
||||
S_foreground = 0x0020,
|
||||
S_minimized = 0x0040,
|
||||
S_open = 0x0080,
|
||||
S_cursor_hidden = 0x0100,
|
||||
S_fixed_size = 0x0200,
|
||||
S_z_order = 0x0400,
|
||||
S_icon_filename = 0x0800,
|
||||
S_cursor_filename = 0x1000,
|
||||
S_mouse_mode = 0x2000,
|
||||
S_parent_window = 0x4000,
|
||||
S_raw_mice = 0x8000,
|
||||
S_origin = 0x00001,
|
||||
S_size = 0x00002,
|
||||
S_title = 0x00004,
|
||||
S_undecorated = 0x00008,
|
||||
S_fullscreen = 0x00010,
|
||||
S_foreground = 0x00020,
|
||||
S_minimized = 0x00040,
|
||||
S_open = 0x00080,
|
||||
S_cursor_hidden = 0x00100,
|
||||
S_fixed_size = 0x00200,
|
||||
S_z_order = 0x00400,
|
||||
S_icon_filename = 0x00800,
|
||||
S_cursor_filename = 0x01000,
|
||||
S_mouse_mode = 0x02000,
|
||||
S_parent_window = 0x04000,
|
||||
S_raw_mice = 0x08000,
|
||||
S_subprocess_window = 0x10000,
|
||||
};
|
||||
|
||||
// This bitmask represents the true/false settings for various
|
||||
@ -189,8 +192,9 @@ private:
|
||||
Filename _cursor_filename;
|
||||
Filename _icon_filename;
|
||||
ZOrder _z_order;
|
||||
int _flags;
|
||||
size_t _parent_window; // a HWND or WindowRef or .. what ever it is on X win...
|
||||
unsigned int _flags;
|
||||
size_t _parent_window; // a HWND or WindowRef or ..
|
||||
Filename _subprocess_window;
|
||||
};
|
||||
|
||||
EXPCL_PANDA_DISPLAY ostream &
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "osxGraphicsBuffer.h"
|
||||
#include "osxGraphicsStateGuardian.h"
|
||||
#include "pnmImage.h"
|
||||
#include "subprocessWindow.h"
|
||||
|
||||
|
||||
|
||||
TypeHandle osxGraphicsPipe::_type_handle;
|
||||
@ -221,7 +223,7 @@ make_output(const string &name,
|
||||
DCAST_INTO_R(osxgsg, gsg, NULL);
|
||||
}
|
||||
|
||||
// First thing to try: a osxGraphicsWindow
|
||||
// First thing to try: an osxGraphicsWindow
|
||||
|
||||
if (retry == 0) {
|
||||
if (((flags&BF_require_parasite)!=0)||
|
||||
@ -232,6 +234,13 @@ make_output(const string &name,
|
||||
((flags&BF_can_bind_every)!=0)) {
|
||||
return NULL;
|
||||
}
|
||||
#ifdef SUPPORT_SUBPROCESS_WINDOW
|
||||
if (win_prop.has_subprocess_window()) {
|
||||
return new SubprocessWindow(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host,
|
||||
win_prop.get_subprocess_window().to_os_specific());
|
||||
}
|
||||
#endif // SUPPORT_SUBPROCESS_WINDOW
|
||||
return new osxGraphicsWindow(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@
|
||||
reMutex.I reMutex.h \
|
||||
reMutexDirect.h reMutexDirect.I \
|
||||
reMutexHolder.I reMutexHolder.h \
|
||||
semaphore.h semaphore.I \
|
||||
psemaphore.h psemaphore.I \
|
||||
thread.h thread.I threadImpl.h \
|
||||
threadDummyImpl.h threadDummyImpl.I \
|
||||
threadPosixImpl.h threadPosixImpl.I \
|
||||
@ -113,7 +113,7 @@
|
||||
reMutex.cxx \
|
||||
reMutexDirect.cxx \
|
||||
reMutexHolder.cxx \
|
||||
semaphore.cxx \
|
||||
psemaphore.cxx \
|
||||
thread.cxx \
|
||||
threadDummyImpl.cxx \
|
||||
threadPosixImpl.cxx \
|
||||
@ -172,7 +172,7 @@
|
||||
reMutex.I reMutex.h \
|
||||
reMutexDirect.h reMutexDirect.I \
|
||||
reMutexHolder.I reMutexHolder.h \
|
||||
semaphore.h semaphore.I \
|
||||
psemaphore.h psemaphore.I \
|
||||
thread.h thread.I threadImpl.h \
|
||||
threadDummyImpl.h threadDummyImpl.I \
|
||||
threadPosixImpl.h threadPosixImpl.I \
|
||||
|
@ -9,11 +9,11 @@
|
||||
#include "pipelineCyclerTrivialImpl.cxx"
|
||||
#include "pipelineCyclerTrueImpl.cxx"
|
||||
#include "pmutex.cxx"
|
||||
#include "psemaphore.cxx"
|
||||
#include "pythonThread.cxx"
|
||||
#include "reMutex.cxx"
|
||||
#include "reMutexDirect.cxx"
|
||||
#include "reMutexHolder.cxx"
|
||||
#include "semaphore.cxx"
|
||||
#include "thread.cxx"
|
||||
#include "threadDummyImpl.cxx"
|
||||
#include "threadPosixImpl.cxx"
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Filename: semaphore.I
|
||||
// Filename: psemaphore.I
|
||||
// Created by: drose (13Oct08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
@ -1,4 +1,4 @@
|
||||
// Filename: semaphore.cxx
|
||||
// Filename: psemaphore.cxx
|
||||
// Created by: drose (13Oct08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -12,7 +12,7 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "semaphore.h"
|
||||
#include "psemaphore.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Semaphore::output
|
@ -1,4 +1,4 @@
|
||||
// Filename: semaphore.h
|
||||
// Filename: psemaphore.h
|
||||
// Created by: drose (13Oct08)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -12,8 +12,8 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SEMAPHORE_H
|
||||
#define SEMAPHORE_H
|
||||
#ifndef PSEMAPHORE_H
|
||||
#define PSEMAPHORE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "pmutex.h"
|
||||
@ -58,6 +58,6 @@ operator << (ostream &out, const Semaphore &sem) {
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "semaphore.I"
|
||||
#include "psemaphore.I"
|
||||
|
||||
#endif
|
@ -21,6 +21,7 @@
|
||||
#include "tinyOsxGraphicsWindow.h"
|
||||
#include "tinyGraphicsBuffer.h"
|
||||
#include "pnmImage.h"
|
||||
#include "subprocessWindow.h"
|
||||
|
||||
TypeHandle TinyOsxGraphicsPipe::_type_handle;
|
||||
|
||||
@ -234,6 +235,13 @@ make_output(const string &name,
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#ifdef SUPPORT_SUBPROCESS_WINDOW
|
||||
if (win_prop.has_subprocess_window()) {
|
||||
return new SubprocessWindow(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host,
|
||||
win_prop.get_subprocess_window().to_os_specific());
|
||||
}
|
||||
#endif // SUPPORT_SUBPROCESS_WINDOW
|
||||
return new TinyOsxGraphicsWindow(engine, this, name, fb_prop, win_prop,
|
||||
flags, gsg, host);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user