allow resizing subprocess buffer

This commit is contained in:
David Rose 2009-07-22 07:07:57 +00:00
parent 961a754ec4
commit 6174ae7228
7 changed files with 180 additions and 78 deletions

View File

@ -221,14 +221,30 @@ set_wparams(const P3DWindowParams &wparams) {
// to the browser. Set up this mechanism.
int x_size = _wparams.get_win_width();
int y_size = _wparams.get_win_height();
if (_shared_fd == -1 && x_size != 0 && y_size != 0) {
_swbuffer = SubprocessWindowBuffer::new_buffer
(_shared_fd, _shared_mmap_size, _shared_filename, x_size, y_size);
if (_swbuffer != NULL) {
_reversed_buffer = new char[_swbuffer->get_framebuffer_size()];
if (x_size != 0 && y_size != 0) {
if (_swbuffer == NULL || _swbuffer->get_x_size() != x_size ||
_swbuffer->get_y_size() != y_size) {
// We need to open a new shared buffer.
if (_swbuffer != NULL) {
SubprocessWindowBuffer::destroy_buffer(_shared_fd, _shared_mmap_size,
_shared_filename, _swbuffer);
_swbuffer = NULL;
}
if (_reversed_buffer != NULL) {
delete[] _reversed_buffer;
_reversed_buffer = NULL;
}
_swbuffer = SubprocessWindowBuffer::new_buffer
(_shared_fd, _shared_mmap_size, _shared_filename, x_size, y_size);
if (_swbuffer != NULL) {
_reversed_buffer = new char[_swbuffer->get_framebuffer_size()];
}
}
xwparams->SetAttribute("subprocess_window", _shared_filename);
if (_swbuffer != NULL) {
xwparams->SetAttribute("subprocess_window", _shared_filename);
}
}
#endif // __APPLE__
@ -513,8 +529,6 @@ handle_event(P3D_event_data event) {
swb_event._flags = 0;
add_modifier_flags(swb_event._flags, er->modifiers);
bool keep_event = false;
switch (er->what) {
case mouseDown:
case mouseUp:
@ -526,7 +540,6 @@ handle_event(P3D_event_data event) {
} else {
swb_event._type = SubprocessWindowBuffer::ET_button_down;
}
keep_event = true;
retval = true;
}
break;
@ -544,7 +557,6 @@ handle_event(P3D_event_data event) {
} else {
swb_event._type = SubprocessWindowBuffer::ET_button_again;
}
keep_event = true;
retval = true;
}
break;
@ -556,7 +568,6 @@ handle_event(P3D_event_data event) {
case activateEvt:
_mouse_active = ((er->modifiers & 1) != 0);
keep_event = true;
break;
default:
@ -569,12 +580,10 @@ handle_event(P3D_event_data event) {
swb_event._flags |= SubprocessWindowBuffer::EF_mouse_position | SubprocessWindowBuffer::EF_has_mouse;
}
if (keep_event && _swbuffer != NULL) {
if (_swbuffer != NULL) {
_swbuffer->add_event(swb_event);
}
#elif defined(HAVE_X11)
#endif
return retval;
}
@ -785,6 +794,7 @@ void P3DInstance::
handle_notify_request(const string &message) {
// We look for certain notify events that have particular meaning
// to this instance.
nout << "Got notify: " << message << "\n" << flush;
if (message == "onpythonload") {
// Once Python is up and running, we can get the actual toplevel
// object from the Python side, and merge it with our own.

View File

@ -134,6 +134,7 @@ def buildDmg(startDir):
fstartDir = Filename.fromOsSpecific(startDir)
rootFilename = Filename(fstartDir, 'bundle')
output = Filename(fstartDir, 'nppanda3d.dmg')
output.unlink()
cmd = 'hdiutil create -fs HFS+ -srcfolder "%(dir)s" -volname "%(volname)s" "%(output)s"' % {
'dir' : rootFilename.toOsSpecific(),
'volname' : 'nppanda3d',

View File

@ -304,6 +304,8 @@ class AppRunner(DirectObject):
wp.setOrigin(x, y)
if width or height:
wp.setSize(width, height)
if subprocessWindow:
wp.setSubprocessWindow(subprocessWindow)
base.win.requestProperties(wp)
return

View File

@ -35,34 +35,24 @@ SubprocessWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
const WindowProperties &win_prop,
int flags,
GraphicsStateGuardian *gsg,
GraphicsOutput *host,
const string &filename) :
GraphicsOutput *host) :
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);
// This will be an offscreen buffer that we use to render the actual
// contents.
_buffer = NULL;
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.
// Create a texture to receive the contents of the framebuffer from
// the offscreen buffer.
_texture = new Texture(name);
_fd = -1;
_mmap_size = 0;
_filename = filename;
_filename = string();
_swbuffer = NULL;
_last_event_flags = 0;
}
@ -74,9 +64,7 @@ SubprocessWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
////////////////////////////////////////////////////////////////////
SubprocessWindow::
~SubprocessWindow() {
if (_buffer != NULL) {
_engine->remove_window(_buffer);
}
nassertv(_buffer == NULL);
nassertv(_swbuffer == NULL);
}
@ -193,7 +181,9 @@ end_frame(FrameMode mode, Thread *current_thread) {
void SubprocessWindow::
begin_flip() {
nassertv(_buffer != (GraphicsBuffer *)NULL);
nassertv(_swbuffer != NULL);
if (_swbuffer == NULL) {
return;
}
RenderBuffer buffer(_gsg, DrawableRegion::get_renderbuffer_type(RTP_color));
buffer = _gsg->get_render_buffer(_buffer->get_draw_buffer_type(),
@ -233,6 +223,54 @@ begin_flip() {
}
}
////////////////////////////////////////////////////////////////////
// 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) {
if (properties.has_subprocess_window() &&
properties.get_subprocess_window() != _filename) {
// We're changing the subprocess buffer filename; that means we
// might as well completely close and re-open the window.
internal_close_window();
_properties.add_properties(properties);
properties.clear();
internal_open_window();
set_size_and_recalc(_properties.get_x_size(), _properties.get_y_size());
throw_event(get_window_event(), this);
return;
}
GraphicsWindow::set_properties_now(properties);
if (!properties.is_any_specified()) {
// The base class has already handled this case.
return;
}
if (properties.has_subprocess_window()) {
// Redundant subprocess specification.
properties.clear_subprocess_window();
}
}
////////////////////////////////////////////////////////////////////
// Function: SubprocessWindow::close_window
// Access: Protected, Virtual
@ -241,20 +279,7 @@ begin_flip() {
////////////////////////////////////////////////////////////////////
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;
internal_close_window();
WindowProperties properties;
properties.set_open(false);
@ -271,28 +296,7 @@ close_window() {
////////////////////////////////////////////////////////////////////
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;
if (!internal_open_window()) {
return false;
}
@ -304,6 +308,88 @@ open_window() {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: SubprocessWindow::internal_close_window
// Access: Private
// Description: Closes the "window" and resets the buffer, without
// changing the WindowProperties.
////////////////////////////////////////////////////////////////////
void SubprocessWindow::
internal_close_window() {
if (_swbuffer != NULL) {
SubprocessWindowBuffer::close_buffer
(_fd, _mmap_size, _filename.to_os_specific(), _swbuffer);
_fd = -1;
_filename = string();
_swbuffer = NULL;
}
if (_buffer != NULL) {
_buffer->request_close();
_buffer->process_events();
_engine->remove_window(_buffer);
_buffer = NULL;
}
_is_valid = false;
}
////////////////////////////////////////////////////////////////////
// Function: SubprocessWindow::internal_open_window
// Access: Private
// Description: Opens the "window" and the associated offscreen
// buffer, without changing the WindowProperties.
////////////////////////////////////////////////////////////////////
bool SubprocessWindow::
internal_open_window() {
nassertr(_buffer == NULL, false);
// Create a buffer with the same properties as the window.
int flags = _creation_flags;
flags = ((flags & ~GraphicsPipe::BF_require_window) | GraphicsPipe::BF_refuse_window);
GraphicsOutput *buffer =
_engine->make_output(_pipe, _name, 0, _fb_properties, _properties,
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);
_buffer->request_open();
_buffer->process_events();
_is_valid = _buffer->is_valid();
}
if (!_is_valid) {
display_cat.error()
<< "Failed to open SubprocessWindowBuffer's internal offscreen buffer.\n";
return false;
}
_gsg = _buffer->get_gsg();
_filename = _properties.get_subprocess_window();
_swbuffer = SubprocessWindowBuffer::open_buffer
(_fd, _mmap_size, _filename.to_os_specific());
if (_swbuffer == NULL) {
close(_fd);
_fd = -1;
_filename = string();
_is_valid = false;
display_cat.error()
<< "Failed to open SubprocessWindowBuffer's shared-memory buffer "
<< _filename << "\n";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: SubprocessWindow::translate_key
// Access: Private

View File

@ -33,6 +33,7 @@
#include "graphicsBuffer.h"
#include "texture.h"
#include "subprocessWindowBuffer.h"
#include "filename.h"
////////////////////////////////////////////////////////////////////
// Class : SubprocessWindow
@ -55,8 +56,7 @@ public:
const WindowProperties &win_prop,
int flags,
GraphicsStateGuardian *gsg,
GraphicsOutput *host,
const string &filename);
GraphicsOutput *host);
virtual ~SubprocessWindow();
virtual void process_events();
@ -65,11 +65,16 @@ public:
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:
void internal_close_window();
bool internal_open_window();
ButtonHandle translate_key(int &keycode, int os_code, unsigned int flags) const;
void transition_button(unsigned int flag, ButtonHandle button);
@ -79,7 +84,7 @@ private:
int _fd;
size_t _mmap_size;
string _filename;
Filename _filename;
SubprocessWindowBuffer *_swbuffer;
unsigned int _last_event_flags;

View File

@ -237,8 +237,7 @@ make_output(const string &name,
#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());
flags, gsg, host);
}
#endif // SUPPORT_SUBPROCESS_WINDOW
return new osxGraphicsWindow(engine, this, name, fb_prop, win_prop,

View File

@ -238,8 +238,7 @@ make_output(const string &name,
#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());
flags, gsg, host);
}
#endif // SUPPORT_SUBPROCESS_WINDOW
return new TinyOsxGraphicsWindow(engine, this, name, fb_prop, win_prop,