mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-07 12:23:16 -04:00
subprocess window
This commit is contained in:
parent
d24c039650
commit
37e76f402d
@ -37,7 +37,9 @@
|
|||||||
stencilRenderStates.h \
|
stencilRenderStates.h \
|
||||||
stereoDisplayRegion.I stereoDisplayRegion.h \
|
stereoDisplayRegion.I stereoDisplayRegion.h \
|
||||||
displaySearchParameters.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 \
|
#define INCLUDED_SOURCES \
|
||||||
standardMunger.cxx \
|
standardMunger.cxx \
|
||||||
@ -62,7 +64,8 @@
|
|||||||
stencilRenderStates.cxx \
|
stencilRenderStates.cxx \
|
||||||
stereoDisplayRegion.cxx \
|
stereoDisplayRegion.cxx \
|
||||||
displaySearchParameters.cxx \
|
displaySearchParameters.cxx \
|
||||||
displayInformation.cxx
|
displayInformation.cxx \
|
||||||
|
subprocessWindow.cxx
|
||||||
|
|
||||||
#define INSTALL_HEADERS \
|
#define INSTALL_HEADERS \
|
||||||
standardMunger.I standardMunger.h \
|
standardMunger.I standardMunger.h \
|
||||||
@ -90,12 +93,31 @@
|
|||||||
stencilRenderStates.h \
|
stencilRenderStates.h \
|
||||||
stereoDisplayRegion.I stereoDisplayRegion.h \
|
stereoDisplayRegion.I stereoDisplayRegion.h \
|
||||||
displaySearchParameters.h \
|
displaySearchParameters.h \
|
||||||
displayInformation.h
|
displayInformation.h \
|
||||||
|
subprocessWindow.h subprocessWindow.I \
|
||||||
|
subprocessWindowBuffer.h subprocessWindowBuffer.I
|
||||||
|
|
||||||
#define IGATESCAN all
|
#define IGATESCAN all
|
||||||
|
|
||||||
#end lib_target
|
#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
|
#begin test_bin_target
|
||||||
#define TARGET test_display
|
#define TARGET test_display
|
||||||
#define LOCAL_LIBS \
|
#define LOCAL_LIBS \
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "parasiteBuffer.h"
|
#include "parasiteBuffer.h"
|
||||||
#include "pandaSystem.h"
|
#include "pandaSystem.h"
|
||||||
#include "stereoDisplayRegion.h"
|
#include "stereoDisplayRegion.h"
|
||||||
|
#include "subprocessWindow.h"
|
||||||
|
|
||||||
ConfigureDef(config_display);
|
ConfigureDef(config_display);
|
||||||
NotifyCategoryDef(display, "");
|
NotifyCategoryDef(display, "");
|
||||||
@ -289,6 +290,15 @@ ConfigVariableInt parent_window_handle
|
|||||||
"an HWND on Windows, or the NSWindow pointer or XWindow pointer "
|
"an HWND on Windows, or the NSWindow pointer or XWindow pointer "
|
||||||
"converted to an integer, on OSX and X11."));
|
"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
|
ConfigVariableString framebuffer_mode
|
||||||
("framebuffer-mode", "",
|
("framebuffer-mode", "",
|
||||||
PRC_DESC("No longer has any effect. Do not use."));
|
PRC_DESC("No longer has any effect. Do not use."));
|
||||||
@ -400,6 +410,9 @@ init_libdisplay() {
|
|||||||
ParasiteBuffer::init_type();
|
ParasiteBuffer::init_type();
|
||||||
StandardMunger::init_type();
|
StandardMunger::init_type();
|
||||||
StereoDisplayRegion::init_type();
|
StereoDisplayRegion::init_type();
|
||||||
|
#ifdef SUPPORT_SUBPROCESS_WINDOW
|
||||||
|
SubprocessWindow::init_type();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_THREADS) && defined(DO_PIPELINING)
|
#if defined(HAVE_THREADS) && defined(DO_PIPELINING)
|
||||||
PandaSystem *ps = PandaSystem::get_global_ptr();
|
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 ConfigVariableEnum<WindowProperties::ZOrder> z_order;
|
||||||
extern EXPCL_PANDA_DISPLAY ConfigVariableString window_title;
|
extern EXPCL_PANDA_DISPLAY ConfigVariableString window_title;
|
||||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt parent_window_handle;
|
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 ConfigVariableString framebuffer_mode;
|
||||||
extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_hardware;
|
extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_hardware;
|
||||||
|
@ -13,3 +13,4 @@
|
|||||||
#include "displaySearchParameters.cxx"
|
#include "displaySearchParameters.cxx"
|
||||||
#include "displayInformation.cxx"
|
#include "displayInformation.cxx"
|
||||||
#include "stereoDisplayRegion.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
|
// Function: WindowProperties::set_mouse_mode
|
||||||
// Access: Published
|
// 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::
|
INLINE void WindowProperties::
|
||||||
set_mouse_mode(MouseMode mode) {
|
set_mouse_mode(MouseMode mode) {
|
||||||
@ -760,7 +771,7 @@ set_mouse_mode(MouseMode mode) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: WindowProperties::get_mouse_mode
|
// Function: WindowProperties::get_mouse_mode
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Removes the z_order specification from the properties.
|
// Description: See set_mouse_mode().
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE WindowProperties::MouseMode WindowProperties::
|
INLINE WindowProperties::MouseMode WindowProperties::
|
||||||
get_mouse_mode() const {
|
get_mouse_mode() const {
|
||||||
@ -768,9 +779,9 @@ get_mouse_mode() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: WindowProperties::has_moude_mode
|
// Function: WindowProperties::has_mouse_mode
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Removes the z_order specification from the properties.
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool WindowProperties::
|
INLINE bool WindowProperties::
|
||||||
has_mouse_mode() const {
|
has_mouse_mode() const {
|
||||||
@ -780,7 +791,7 @@ has_mouse_mode() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: WindowProperties::clear_mouse_mode
|
// Function: WindowProperties::clear_mouse_mode
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Removes the z_order specification from the properties.
|
// Description: Removes the mouse_mode specification from the properties.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void WindowProperties::
|
INLINE void WindowProperties::
|
||||||
clear_mouse_mode() {
|
clear_mouse_mode() {
|
||||||
@ -791,7 +802,22 @@ clear_mouse_mode() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: WindowProperties::set_parent_window
|
// Function: WindowProperties::set_parent_window
|
||||||
// Access: Published
|
// 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::
|
INLINE void WindowProperties::
|
||||||
set_parent_window(size_t parent) {
|
set_parent_window(size_t parent) {
|
||||||
@ -802,7 +828,7 @@ set_parent_window(size_t parent) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: WindowProperties::get_parent_window
|
// Function: WindowProperties::get_parent_window
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Removes the parent Window
|
// Description: Returns the parent window specification.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE size_t WindowProperties::
|
INLINE size_t WindowProperties::
|
||||||
get_parent_window() const {
|
get_parent_window() const {
|
||||||
@ -830,6 +856,70 @@ clear_parent_window() {
|
|||||||
_parent_window = (size_t)NULL;
|
_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 &
|
INLINE ostream &
|
||||||
operator << (ostream &out, const WindowProperties &properties) {
|
operator << (ostream &out, const WindowProperties &properties) {
|
||||||
|
@ -45,6 +45,7 @@ operator = (const WindowProperties ©) {
|
|||||||
_flags = copy._flags;
|
_flags = copy._flags;
|
||||||
_mouse_mode = copy._mouse_mode;
|
_mouse_mode = copy._mouse_mode;
|
||||||
_parent_window = copy._parent_window;
|
_parent_window = copy._parent_window;
|
||||||
|
_subprocess_window = copy._subprocess_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -86,7 +87,11 @@ get_default() {
|
|||||||
if (parent_window_handle.get_value() != 0) {
|
if (parent_window_handle.get_value() != 0) {
|
||||||
props.set_parent_window(parent_window_handle);
|
props.set_parent_window(parent_window_handle);
|
||||||
}
|
}
|
||||||
|
if (subprocess_window.has_value()) {
|
||||||
|
props.set_subprocess_window(subprocess_window);
|
||||||
|
}
|
||||||
props.set_mouse_mode(M_absolute);
|
props.set_mouse_mode(M_absolute);
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,8 +127,8 @@ operator == (const WindowProperties &other) const {
|
|||||||
_icon_filename == other._icon_filename &&
|
_icon_filename == other._icon_filename &&
|
||||||
_cursor_filename == other._cursor_filename &&
|
_cursor_filename == other._cursor_filename &&
|
||||||
_mouse_mode == other._mouse_mode &&
|
_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;
|
_flags = 0;
|
||||||
_mouse_mode = M_absolute;
|
_mouse_mode = M_absolute;
|
||||||
_parent_window = 0;
|
_parent_window = 0;
|
||||||
|
_subprocess_window = Filename();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -200,15 +206,15 @@ add_properties(const WindowProperties &other) {
|
|||||||
if (other.has_z_order()) {
|
if (other.has_z_order()) {
|
||||||
set_z_order(other.get_z_order());
|
set_z_order(other.get_z_order());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other.has_mouse_mode()) {
|
if (other.has_mouse_mode()) {
|
||||||
set_mouse_mode(other.get_mouse_mode());
|
set_mouse_mode(other.get_mouse_mode());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other.has_parent_window()) {
|
if (other.has_parent_window()) {
|
||||||
set_parent_window(other.get_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()) {
|
if (has_parent_window()) {
|
||||||
out << "parent:" << get_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 {
|
class EXPCL_PANDA_DISPLAY WindowProperties {
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
|
|
||||||
|
|
||||||
enum ZOrder {
|
enum ZOrder {
|
||||||
Z_bottom,
|
Z_bottom,
|
||||||
Z_normal,
|
Z_normal,
|
||||||
@ -132,12 +130,16 @@ PUBLISHED:
|
|||||||
INLINE bool has_z_order() const;
|
INLINE bool has_z_order() const;
|
||||||
INLINE void clear_z_order();
|
INLINE void clear_z_order();
|
||||||
|
|
||||||
|
|
||||||
INLINE void set_parent_window(size_t parent);
|
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 bool has_parent_window() const;
|
||||||
INLINE void clear_parent_window();
|
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 add_properties(const WindowProperties &other);
|
||||||
|
|
||||||
void output(ostream &out) const;
|
void output(ostream &out) const;
|
||||||
@ -147,22 +149,23 @@ private:
|
|||||||
// structure have been filled in by the user, and which remain
|
// structure have been filled in by the user, and which remain
|
||||||
// unspecified.
|
// unspecified.
|
||||||
enum Specified {
|
enum Specified {
|
||||||
S_origin = 0x0001,
|
S_origin = 0x00001,
|
||||||
S_size = 0x0002,
|
S_size = 0x00002,
|
||||||
S_title = 0x0004,
|
S_title = 0x00004,
|
||||||
S_undecorated = 0x0008,
|
S_undecorated = 0x00008,
|
||||||
S_fullscreen = 0x0010,
|
S_fullscreen = 0x00010,
|
||||||
S_foreground = 0x0020,
|
S_foreground = 0x00020,
|
||||||
S_minimized = 0x0040,
|
S_minimized = 0x00040,
|
||||||
S_open = 0x0080,
|
S_open = 0x00080,
|
||||||
S_cursor_hidden = 0x0100,
|
S_cursor_hidden = 0x00100,
|
||||||
S_fixed_size = 0x0200,
|
S_fixed_size = 0x00200,
|
||||||
S_z_order = 0x0400,
|
S_z_order = 0x00400,
|
||||||
S_icon_filename = 0x0800,
|
S_icon_filename = 0x00800,
|
||||||
S_cursor_filename = 0x1000,
|
S_cursor_filename = 0x01000,
|
||||||
S_mouse_mode = 0x2000,
|
S_mouse_mode = 0x02000,
|
||||||
S_parent_window = 0x4000,
|
S_parent_window = 0x04000,
|
||||||
S_raw_mice = 0x8000,
|
S_raw_mice = 0x08000,
|
||||||
|
S_subprocess_window = 0x10000,
|
||||||
};
|
};
|
||||||
|
|
||||||
// This bitmask represents the true/false settings for various
|
// This bitmask represents the true/false settings for various
|
||||||
@ -189,8 +192,9 @@ private:
|
|||||||
Filename _cursor_filename;
|
Filename _cursor_filename;
|
||||||
Filename _icon_filename;
|
Filename _icon_filename;
|
||||||
ZOrder _z_order;
|
ZOrder _z_order;
|
||||||
int _flags;
|
unsigned int _flags;
|
||||||
size_t _parent_window; // a HWND or WindowRef or .. what ever it is on X win...
|
size_t _parent_window; // a HWND or WindowRef or ..
|
||||||
|
Filename _subprocess_window;
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPCL_PANDA_DISPLAY ostream &
|
EXPCL_PANDA_DISPLAY ostream &
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#include "osxGraphicsBuffer.h"
|
#include "osxGraphicsBuffer.h"
|
||||||
#include "osxGraphicsStateGuardian.h"
|
#include "osxGraphicsStateGuardian.h"
|
||||||
#include "pnmImage.h"
|
#include "pnmImage.h"
|
||||||
|
#include "subprocessWindow.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TypeHandle osxGraphicsPipe::_type_handle;
|
TypeHandle osxGraphicsPipe::_type_handle;
|
||||||
@ -221,7 +223,7 @@ make_output(const string &name,
|
|||||||
DCAST_INTO_R(osxgsg, gsg, NULL);
|
DCAST_INTO_R(osxgsg, gsg, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// First thing to try: a osxGraphicsWindow
|
// First thing to try: an osxGraphicsWindow
|
||||||
|
|
||||||
if (retry == 0) {
|
if (retry == 0) {
|
||||||
if (((flags&BF_require_parasite)!=0)||
|
if (((flags&BF_require_parasite)!=0)||
|
||||||
@ -232,6 +234,13 @@ make_output(const string &name,
|
|||||||
((flags&BF_can_bind_every)!=0)) {
|
((flags&BF_can_bind_every)!=0)) {
|
||||||
return NULL;
|
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,
|
return new osxGraphicsWindow(engine, this, name, fb_prop, win_prop,
|
||||||
flags, gsg, host);
|
flags, gsg, host);
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
reMutex.I reMutex.h \
|
reMutex.I reMutex.h \
|
||||||
reMutexDirect.h reMutexDirect.I \
|
reMutexDirect.h reMutexDirect.I \
|
||||||
reMutexHolder.I reMutexHolder.h \
|
reMutexHolder.I reMutexHolder.h \
|
||||||
semaphore.h semaphore.I \
|
psemaphore.h psemaphore.I \
|
||||||
thread.h thread.I threadImpl.h \
|
thread.h thread.I threadImpl.h \
|
||||||
threadDummyImpl.h threadDummyImpl.I \
|
threadDummyImpl.h threadDummyImpl.I \
|
||||||
threadPosixImpl.h threadPosixImpl.I \
|
threadPosixImpl.h threadPosixImpl.I \
|
||||||
@ -113,7 +113,7 @@
|
|||||||
reMutex.cxx \
|
reMutex.cxx \
|
||||||
reMutexDirect.cxx \
|
reMutexDirect.cxx \
|
||||||
reMutexHolder.cxx \
|
reMutexHolder.cxx \
|
||||||
semaphore.cxx \
|
psemaphore.cxx \
|
||||||
thread.cxx \
|
thread.cxx \
|
||||||
threadDummyImpl.cxx \
|
threadDummyImpl.cxx \
|
||||||
threadPosixImpl.cxx \
|
threadPosixImpl.cxx \
|
||||||
@ -172,7 +172,7 @@
|
|||||||
reMutex.I reMutex.h \
|
reMutex.I reMutex.h \
|
||||||
reMutexDirect.h reMutexDirect.I \
|
reMutexDirect.h reMutexDirect.I \
|
||||||
reMutexHolder.I reMutexHolder.h \
|
reMutexHolder.I reMutexHolder.h \
|
||||||
semaphore.h semaphore.I \
|
psemaphore.h psemaphore.I \
|
||||||
thread.h thread.I threadImpl.h \
|
thread.h thread.I threadImpl.h \
|
||||||
threadDummyImpl.h threadDummyImpl.I \
|
threadDummyImpl.h threadDummyImpl.I \
|
||||||
threadPosixImpl.h threadPosixImpl.I \
|
threadPosixImpl.h threadPosixImpl.I \
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
#include "pipelineCyclerTrivialImpl.cxx"
|
#include "pipelineCyclerTrivialImpl.cxx"
|
||||||
#include "pipelineCyclerTrueImpl.cxx"
|
#include "pipelineCyclerTrueImpl.cxx"
|
||||||
#include "pmutex.cxx"
|
#include "pmutex.cxx"
|
||||||
|
#include "psemaphore.cxx"
|
||||||
#include "pythonThread.cxx"
|
#include "pythonThread.cxx"
|
||||||
#include "reMutex.cxx"
|
#include "reMutex.cxx"
|
||||||
#include "reMutexDirect.cxx"
|
#include "reMutexDirect.cxx"
|
||||||
#include "reMutexHolder.cxx"
|
#include "reMutexHolder.cxx"
|
||||||
#include "semaphore.cxx"
|
|
||||||
#include "thread.cxx"
|
#include "thread.cxx"
|
||||||
#include "threadDummyImpl.cxx"
|
#include "threadDummyImpl.cxx"
|
||||||
#include "threadPosixImpl.cxx"
|
#include "threadPosixImpl.cxx"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Filename: semaphore.I
|
// Filename: psemaphore.I
|
||||||
// Created by: drose (13Oct08)
|
// Created by: drose (13Oct08)
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
@ -1,4 +1,4 @@
|
|||||||
// Filename: semaphore.cxx
|
// Filename: psemaphore.cxx
|
||||||
// Created by: drose (13Oct08)
|
// Created by: drose (13Oct08)
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -12,7 +12,7 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "semaphore.h"
|
#include "psemaphore.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Semaphore::output
|
// Function: Semaphore::output
|
@ -1,4 +1,4 @@
|
|||||||
// Filename: semaphore.h
|
// Filename: psemaphore.h
|
||||||
// Created by: drose (13Oct08)
|
// Created by: drose (13Oct08)
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -12,8 +12,8 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SEMAPHORE_H
|
#ifndef PSEMAPHORE_H
|
||||||
#define SEMAPHORE_H
|
#define PSEMAPHORE_H
|
||||||
|
|
||||||
#include "pandabase.h"
|
#include "pandabase.h"
|
||||||
#include "pmutex.h"
|
#include "pmutex.h"
|
||||||
@ -58,6 +58,6 @@ operator << (ostream &out, const Semaphore &sem) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "semaphore.I"
|
#include "psemaphore.I"
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -21,6 +21,7 @@
|
|||||||
#include "tinyOsxGraphicsWindow.h"
|
#include "tinyOsxGraphicsWindow.h"
|
||||||
#include "tinyGraphicsBuffer.h"
|
#include "tinyGraphicsBuffer.h"
|
||||||
#include "pnmImage.h"
|
#include "pnmImage.h"
|
||||||
|
#include "subprocessWindow.h"
|
||||||
|
|
||||||
TypeHandle TinyOsxGraphicsPipe::_type_handle;
|
TypeHandle TinyOsxGraphicsPipe::_type_handle;
|
||||||
|
|
||||||
@ -234,6 +235,13 @@ make_output(const string &name,
|
|||||||
return NULL;
|
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,
|
return new TinyOsxGraphicsWindow(engine, this, name, fb_prop, win_prop,
|
||||||
flags, gsg, host);
|
flags, gsg, host);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user