add GraphicsOutput::make_texture_buffer()

This commit is contained in:
David Rose 2004-02-28 00:25:23 +00:00
parent 42507f9852
commit 2bf87f010a
6 changed files with 143 additions and 1 deletions

View File

@ -81,6 +81,24 @@ const string screenshot_extension = config_display.GetString("screenshot-extensi
// interactively. Handy during development of multipass algorithms.
const bool show_buffers = config_display.GetBool("show-buffers", false);
// Set this true to make GraphicsOutput::make_render_texture() try to
// create a parasite buffer before it tries to create an offscreen
// buffer. This may be desired if you know your graphics API does not
// support render-directly-to-texture and you want to minimize
// framebuffer memory.
const bool prefer_parasite_buffer = config_display.GetBool("prefer-parasite-buffer", false);
// Set this true to make GraphicsOutput::make_render_texture() first
// try to create a single-buffered offscreen buffer, before falling
// back to a double-buffered one (or whatever kind the source window
// has). This is true by default to reduce waste of framebuffer
// memory, but you may get a performance benefit by setting it to
// false (since in that case the buffer can share a graphics context
// with the window).
const bool prefer_single_buffer = config_display.GetBool("prefer-single-buffer", true);
// Use the variable load-display to specify the name of the default
// graphics display library or GraphicsPipe to load. It is the name
// of a shared library (or * for all libraries named in aux-display),

View File

@ -42,6 +42,9 @@ extern const string screenshot_extension;
extern const bool show_buffers;
extern const bool prefer_parasite_buffer;
extern const bool prefer_single_buffer;
extern EXPCL_PANDA const bool multiple_windows;
extern EXPCL_PANDA void init_libdisplay();

View File

@ -298,6 +298,94 @@ get_display_region(int n) const {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::make_texture_buffer
// Access: Published
// Description: Creates and returns an offscreen buffer for rendering
// into, the result of which will be a texture suitable
// for applying to geometry within the scene rendered
// into this window.
//
// This will attempt to be smart about maximizing render
// performance while minimizing framebuffer waste. It
// might return a GraphicsBuffer set to render directly
// into a texture, if possible; or it might return a
// ParasiteBuffer that renders into this window. The
// return value is NULL if the buffer could not be
// created for some reason.
//
// Assuming the return value is not NULL, the texture
// that is represents the scene rendered to the new
// buffer can be accessed by buffer->get_texture().
// When you are done using the buffer, you should remove
// it with a call to GraphicsEngine::remove_window().
////////////////////////////////////////////////////////////////////
GraphicsOutput *GraphicsOutput::
make_texture_buffer(const string &name, int x_size, int y_size) {
GraphicsStateGuardian *gsg = get_gsg();
GraphicsEngine *engine = gsg->get_engine();
GraphicsOutput *host = get_host();
// The new buffer should be drawn before this buffer is drawn. If
// the user requires more control than this, he can set the sort
// value himself.
int sort = get_sort() - 1;
if (show_buffers) {
// If show_buffers is true, just go ahead and call make_buffer(),
// since it all amounts to the same thing anyway--this will
// actually create a new GraphicsWindow.
return engine->make_buffer(gsg, name, sort, x_size, y_size, true);
}
GraphicsOutput *buffer = NULL;
// If the user so indicated in the Configrc file, try to create a
// parasite buffer first. We can only do this if the requested size
// fits within the available framebuffer size.
if (prefer_parasite_buffer &&
(x_size <= host->get_x_size() && y_size <= host->get_y_size())) {
buffer = engine->make_parasite(host, name, sort, x_size, y_size);
if (buffer != (GraphicsOutput *)NULL) {
return buffer;
}
}
// Attempt to create a single-buffered offscreen buffer.
if (prefer_single_buffer) {
FrameBufferProperties sb_props = gsg->get_properties();
int orig_mode = sb_props.get_frame_buffer_mode();
int sb_mode = (orig_mode & ~FrameBufferProperties::FM_buffer) | FrameBufferProperties::FM_single_buffer;
sb_props.set_frame_buffer_mode(sb_mode);
if (sb_mode != orig_mode) {
PT(GraphicsStateGuardian) sb_gsg =
engine->make_gsg(gsg->get_pipe(), sb_props, gsg);
if (sb_gsg != (GraphicsStateGuardian *)NULL) {
buffer = engine->make_buffer(sb_gsg, name, sort, x_size, y_size, true);
if (buffer != (GraphicsOutput *)NULL) {
return buffer;
}
}
}
}
// All right, attempt to create an offscreen buffer, using the same
// GSG. This will be a double-buffered offscreen buffer, if the
// source window is double-buffered.
buffer = engine->make_buffer(gsg, name, sort, x_size, y_size, true);
if (buffer != (GraphicsOutput *)NULL) {
return buffer;
}
// Looks like we have to settle for a parasite buffer.
if (x_size <= host->get_x_size() && y_size <= host->get_y_size()) {
return engine->make_parasite(host, name, sort, x_size, y_size);
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::make_scratch_display_region
// Access: Public
@ -325,6 +413,20 @@ make_scratch_display_region(int x_size, int y_size) {
region->copy_clear_settings(*this);
return region;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::get_host
// Access: Public, Virtual
// Description: This is normally called only from within
// make_texture_buffer(). When called on a
// ParasiteBuffer, it returns the host of that buffer;
// but when called on some other buffer, it returns the
// buffer itself.
////////////////////////////////////////////////////////////////////
GraphicsOutput *GraphicsOutput::
get_host() {
return this;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsOutput::request_open

View File

@ -95,6 +95,8 @@ PUBLISHED:
int get_num_display_regions() const;
DisplayRegion *get_display_region(int n) const;
GraphicsOutput *make_texture_buffer(const string &name, int x_size, int y_size);
INLINE Filename save_screenshot_default(const string &prefix = "screenshot");
INLINE bool save_screenshot(const Filename &filename);
INLINE bool get_screenshot(PNMImage &image);
@ -109,6 +111,8 @@ public:
INLINE bool operator < (const GraphicsOutput &other) const;
virtual GraphicsOutput *get_host();
virtual void request_open();
virtual void request_close();

View File

@ -54,7 +54,7 @@ ParasiteBuffer(GraphicsOutput *host, const string &name,
_is_valid = true;
nassertv(_x_size < host->get_x_size() && _y_size < host->get_y_size());
nassertv(_x_size <= host->get_x_size() && _y_size <= host->get_y_size());
}
////////////////////////////////////////////////////////////////////
@ -77,6 +77,20 @@ is_active() const {
return _host->is_active();
}
////////////////////////////////////////////////////////////////////
// Function: ParasiteBuffer::get_host
// Access: Public, Virtual
// Description: This is normally called only from within
// make_texture_buffer(). When called on a
// ParasiteBuffer, it returns the host of that buffer;
// but when called on some other buffer, it returns the
// buffer itself.
////////////////////////////////////////////////////////////////////
GraphicsOutput *ParasiteBuffer::
get_host() {
return _host;
}
////////////////////////////////////////////////////////////////////
// Function: ParasiteBuffer::make_current
// Access: Public, Virtual

View File

@ -63,6 +63,7 @@ PUBLISHED:
virtual bool is_active() const;
public:
virtual GraphicsOutput *get_host();
virtual void make_current();
private: