From efc2a9ce26bb949bfd840b36112434520f7013db Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Thu, 27 Oct 2005 21:11:26 +0000 Subject: [PATCH] *** empty log message *** --- panda/src/display/graphicsOutput.I | 61 +++- panda/src/display/graphicsOutput.cxx | 297 +++++++++++------- panda/src/display/graphicsOutput.h | 36 ++- panda/src/display/graphicsStateGuardian.cxx | 33 -- panda/src/display/graphicsStateGuardian.h | 3 - panda/src/gsgbase/graphicsStateGuardianBase.h | 5 +- panda/src/wgldisplay/wglGraphicsBuffer.cxx | 131 ++++++-- panda/src/wgldisplay/wglGraphicsBuffer.h | 3 + .../wgldisplay/wglGraphicsStateGuardian.cxx | 60 ---- .../src/wgldisplay/wglGraphicsStateGuardian.h | 3 - 10 files changed, 356 insertions(+), 276 deletions(-) diff --git a/panda/src/display/graphicsOutput.I b/panda/src/display/graphicsOutput.I index 2734a5cbc9..a465c992bd 100644 --- a/panda/src/display/graphicsOutput.I +++ b/panda/src/display/graphicsOutput.I @@ -60,30 +60,36 @@ get_name() const { return _name; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsOutput::count_textures +// Access: Published +// Description: If the GraphicsOutput is set to render into a +// texture, returns the number of textures that are +// being rendered into. Normally, the textures would +// be associated with different buffers - a color +// texture, a depth texture, and a stencil texture. +//////////////////////////////////////////////////////////////////// +INLINE int GraphicsOutput:: +count_textures() const { + return _textures.size(); +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsOutput::has_texture // Access: Published -// Description: Returns true if the GraphicsOutput is set to render -// into a texture, or false otherwise. -// -// Normally, this will only be true for a GraphicsBuffer -// object, and only when want_texture is passed in as -// true to the GraphicsBuffer constructor. If -// show-buffers is true, this may also be set for a -// GraphicsWindow, which is in this case serving in the -// place of a GraphicsBuffer. +// Description: Returns true if the GraphicsOutput is rendering +// into any textures at all. //////////////////////////////////////////////////////////////////// INLINE bool GraphicsOutput:: has_texture() const { - return !(_texture.is_null()); + return (_textures.size() > 0); } //////////////////////////////////////////////////////////////////// // Function: GraphicsOutput::get_texture // Access: Published -// Description: Returns the texture into which the GraphicsOutput -// renders, if has_texture() is true, or NULL if -// has_texture() is false. +// Description: Returns the nth texture into which the GraphicsOutput +// renders. Returns NULL if there is no such texture. // // If the texture is non-NULL, it may be applied to // geometry to be rendered for any other windows or @@ -93,8 +99,26 @@ has_texture() const { // the texture will be invalid. //////////////////////////////////////////////////////////////////// INLINE Texture *GraphicsOutput:: -get_texture() const { - return _texture; +get_texture(int i) const { + if ((i < 0) || (i >= ((int)_textures.size()))) { + return (Texture *)NULL; + } + return _textures[i]._texture; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsOutput::get_rtm_mode +// Access: Published +// Description: Returns the RenderTextureMode associated with the +// nth texture. Returns RTM_none if there is no such +// texture. +//////////////////////////////////////////////////////////////////// +INLINE GraphicsOutput::RenderTextureMode GraphicsOutput:: +get_rtm_mode(int i) const { + if ((i < 0) || (i >= ((int)_textures.size()))) { + return RTM_none; + } + return _textures[i]._rtm_mode; } //////////////////////////////////////////////////////////////////// @@ -225,7 +249,12 @@ INLINE bool GraphicsOutput:: get_delete_flag() const { // We only delete the window or buffer automatically when it is // no longer associated with a texture. - return _delete_flag && !_hold_texture.is_valid_pointer(); + for (int i=0; i<(int)_hold_textures.size(); i++) { + if (_hold_textures[i].is_valid_pointer()) { + return false; + } + } + return _delete_flag; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/graphicsOutput.cxx b/panda/src/display/graphicsOutput.cxx index 029e3ade60..25d13d7500 100644 --- a/panda/src/display/graphicsOutput.cxx +++ b/panda/src/display/graphicsOutput.cxx @@ -80,7 +80,6 @@ GraphicsOutput(GraphicsPipe *pipe, GraphicsStateGuardian *gsg, _y_size = 0; _has_size = false; _is_valid = false; - _rtm_mode = RTM_none; _flip_ready = false; _needs_context = true; _cube_map_index = -1; @@ -187,12 +186,24 @@ GraphicsOutput:: } //////////////////////////////////////////////////////////////////// -// Function: GraphicsOutput::setup_render_texture +// Function: GraphicsOutput::clear_render_textures +// Access: Published +// Description: If the GraphicsOutput is currently rendering to +// a texture, then all textures are dissociated from +// the GraphicsOuput. +//////////////////////////////////////////////////////////////////// +void GraphicsOutput:: +clear_render_textures() { + MutexHolder holder(_lock); + _textures.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsOutput::add_render_texture // Access: Published // Description: Creates a new Texture object, suitable for rendering -// the contents of this buffer into, and stores it in -// _texture. This also disassociates the previous -// texture (if any). +// the contents of this buffer into, and appends it to +// the list of render textures. // // If tex is not NULL, it is the texture that will be // set up for rendering into; otherwise, a new Texture @@ -200,66 +211,84 @@ GraphicsOutput:: // get_texture() to retrieve the new texture pointer // later). // -// If allow_bind is true, and this GraphicsOutput is an -// offscreen graphics buffer that has not yet been -// rendered into, it will attempt to set up the buffer -// for rendering directly into the texture, avoiding the -// cost of the copy-to-texture-memory each frame. This -// is not supported by all graphics hardware, but if it -// is not supported, this option is quietly ignored. -// -// If to_ram is true, the texture image will be -// downloaded from the framebuffer memory into system -// RAM each frame, which is more expensive but allows -// the texture to subsequently be applied to any GSG. -// Otherwise, the texture image remains in texture -// memory only. -// // Also see make_texture_buffer(), which is a // higher-level interface for preparing // render-to-a-texture mode. //////////////////////////////////////////////////////////////////// void GraphicsOutput:: -setup_render_texture(Texture *tex, RenderTextureMode mode) { +add_render_texture(Texture *tex, RenderTextureMode mode) { if (mode == RTM_none) { return; } MutexHolder holder(_lock); - _rtm_mode = mode; if (tex == (Texture *)NULL) { - _texture = new Texture(get_name()); - _texture->set_wrap_u(Texture::WM_clamp); - _texture->set_wrap_v(Texture::WM_clamp); + tex = new Texture(get_name()); + tex->set_wrap_u(Texture::WM_clamp); + tex->set_wrap_v(Texture::WM_clamp); } else { - _texture = tex; - _texture->clear_ram_image(); + tex->clear_ram_image(); } - _texture->set_match_framebuffer_format(true); + tex->set_match_framebuffer_format(true); // Go ahead and tell the texture our anticipated size, even if it // might be inaccurate (particularly if this is a GraphicsWindow, // which has system-imposed restrictions on size). - _texture->set_x_size(get_x_size()); - _texture->set_y_size(get_y_size()); - + tex->set_x_size(get_x_size()); + tex->set_y_size(get_y_size()); + + RenderTexture result; + result._texture = tex; + result._rtm_mode = mode; + _textures.push_back(result); + nassertv(_gsg != (GraphicsStateGuardian *)NULL); set_inverted(_gsg->get_copy_texture_inverted()); + + // Sanity check that we don't have two textures of the same type. + int count_stencil_textures = 0; + int count_depth_textures = 0; + int count_color_textures = 0; + for (int i=0; iget_format(); + if (fmt == Texture::F_depth_component) { + count_depth_textures += 1; + } else if (fmt == Texture::F_stencil_index) { + count_stencil_textures += 1; + } else { + count_color_textures += 1; + } + } + if ((count_color_textures > 1)|| + (count_depth_textures > 1)|| + (count_stencil_textures > 1)) { + display_cat.error() << + "Currently, each GraphicsOutput can only render to one color texture, " + "one depth texture, and one stencil texture at a time. RTM aborted.\n"; + clear_render_textures(); + } } //////////////////////////////////////////////////////////////////// // Function: GraphicsOutput::setup_render_texture // Access: Published -// Description: +// Description: This is a deprecated interface that made sense back +// when GraphicsOutputs could only render into one +// texture at a time. From now on, use +// clear_render_textures and add_render_texture +// instead. //////////////////////////////////////////////////////////////////// void GraphicsOutput:: setup_render_texture(Texture *tex, bool allow_bind, bool to_ram) { + display_cat.warning() << + "Using deprecated setup_render_texture interface.\n"; + clear_render_textures(); if (to_ram) { - setup_render_texture(tex, RTM_copy_ram); + add_render_texture(tex, RTM_copy_ram); } else if (allow_bind) { - setup_render_texture(tex, RTM_bind_or_copy); + add_render_texture(tex, RTM_bind_or_copy); } else { - setup_render_texture(tex, RTM_copy_texture); + add_render_texture(tex, RTM_copy_texture); } } @@ -577,7 +606,20 @@ get_texture_card() { PT(GeomNode) gnode = new GeomNode("texture card"); gnode->add_geom(_texture_card); NodePath path(gnode); - path.set_texture(get_texture(), 0); + + // The texture card, by default, is textured with the first + // render-to-texture output texture. Depth and stencil + // textures are ignored. The user can freely alter the + // card's texture attrib. + for (int i=0; iget_format() != Texture::F_depth_component) && + (texture->get_format() != Texture::F_stencil_index)) { + path.set_texture(texture, 0); + break; + } + } + return path; } @@ -635,7 +677,7 @@ make_texture_buffer(const string &name, int x_size, int y_size, // host window size. If the user requests this, we have to use a // parasite buffer. buffer = engine->make_parasite(host, name, sort, x_size, y_size); - buffer->setup_render_texture(tex, false, to_ram); + buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture); return buffer; } @@ -644,7 +686,7 @@ make_texture_buffer(const string &name, int x_size, int y_size, // since it all amounts to the same thing anyway--this will // actually create a new GraphicsWindow. buffer = engine->make_buffer(gsg, name, sort, x_size, y_size); - buffer->setup_render_texture(tex, false, to_ram); + buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture); return buffer; } @@ -661,7 +703,7 @@ make_texture_buffer(const string &name, int x_size, int y_size, (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) { - buffer->setup_render_texture(tex, false, to_ram); + buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture); return buffer; } } @@ -680,7 +722,11 @@ make_texture_buffer(const string &name, int x_size, int y_size, buffer = engine->make_buffer(sb_gsg, name, sort, x_size, y_size); if (buffer != (GraphicsOutput *)NULL) { // Check the buffer for goodness. - buffer->setup_render_texture(tex, allow_bind, to_ram); + if (allow_bind) { + buffer->add_render_texture(tex, RTM_bind_or_copy); + } else { + buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture); + } engine->open_windows(); if (buffer->is_valid()) { return buffer; @@ -700,7 +746,11 @@ make_texture_buffer(const string &name, int x_size, int y_size, // source window is double-buffered. buffer = engine->make_buffer(gsg, name, sort, x_size, y_size); if (buffer != (GraphicsOutput *)NULL) { - buffer->setup_render_texture(tex, allow_bind, to_ram); + if (allow_bind) { + buffer->add_render_texture(tex, RTM_bind_or_copy); + } else { + buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture); + } engine->open_windows(); if (buffer->is_valid()) { return buffer; @@ -714,7 +764,7 @@ make_texture_buffer(const string &name, int x_size, int y_size, // Looks like we have to settle for a parasite buffer. if (x_size <= host->get_x_size() && y_size <= host->get_y_size()) { buffer = engine->make_parasite(host, name, sort, x_size, y_size); - buffer->setup_render_texture(tex, false, to_ram); + buffer->add_render_texture(tex, to_ram ? RTM_copy_ram : RTM_copy_texture); return buffer; } @@ -926,10 +976,7 @@ begin_frame() { // Okay, we already have a GSG, so activate it. make_current(); - if (_rtm_mode == RTM_bind_or_copy) { - // Release the texture so we can render into the frame buffer. - _gsg->framebuffer_release_texture(this, get_texture()); - } + begin_render_texture(); _cube_map_index = -1; _cube_map_dr = NULL; @@ -982,33 +1029,24 @@ end_frame() { nassertv(_gsg != (GraphicsStateGuardian *)NULL); _gsg->end_frame(); - // If _rtm_mode isn't RTM_none, it means we should copy or lock the - // framebuffer to the GraphicsOutput's associated texture after the - // frame has rendered. - if (_rtm_mode != RTM_none) { + // Handle all render-to-texture operations that use bind-to-texture + end_render_texture(); + + // Handle all render-to-texture operations that use copy-to-texture + for (int i=0; iframebuffer_bind_to_texture(this, get_texture())) { - display_cat.warning() - << "Lock-to-texture failed, resorting to copy.\n"; - _rtm_mode = RTM_copy_texture; - } - } - if ((_rtm_mode == RTM_copy_texture)|| - (_rtm_mode == RTM_copy_ram)|| - ((_rtm_mode == RTM_triggered_copy_texture)&&(_trigger_copy))|| - ((_rtm_mode == RTM_triggered_copy_ram)&&(_trigger_copy))) { - _trigger_copy = false; + if ((rtm_mode == RTM_copy_texture)|| + (rtm_mode == RTM_copy_ram)|| + ((rtm_mode == RTM_triggered_copy_texture)&&(_trigger_copy))|| + ((rtm_mode == RTM_triggered_copy_ram)&&(_trigger_copy))) { if (display_cat.is_debug()) { display_cat.debug() << "Copying texture for " << get_name() << " at frame end.\n"; @@ -1017,30 +1055,31 @@ end_frame() { } RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type()); if (_cube_map_dr != (DisplayRegion *)NULL) { - if ((_rtm_mode == RTM_copy_ram)||(_rtm_mode == RTM_triggered_copy_ram)) { - _gsg->framebuffer_copy_to_ram(get_texture(), _cube_map_index, + if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) { + _gsg->framebuffer_copy_to_ram(texture, _cube_map_index, _cube_map_dr, buffer); } else { - _gsg->framebuffer_copy_to_texture(get_texture(), _cube_map_index, + _gsg->framebuffer_copy_to_texture(texture, _cube_map_index, _cube_map_dr, buffer); } } else { - if ((_rtm_mode == RTM_copy_ram)||(_rtm_mode == RTM_triggered_copy_ram)) { - _gsg->framebuffer_copy_to_ram(get_texture(), _cube_map_index, + if ((rtm_mode == RTM_copy_ram)||(rtm_mode == RTM_triggered_copy_ram)) { + _gsg->framebuffer_copy_to_ram(texture, _cube_map_index, _default_display_region, buffer); } else { - _gsg->framebuffer_copy_to_texture(get_texture(), _cube_map_index, + _gsg->framebuffer_copy_to_texture(texture, _cube_map_index, _default_display_region, buffer); } } } } - + _trigger_copy = false; + // If we're not single-buffered, we're now ready to flip. if (!_gsg->get_properties().is_single_buffered()) { _flip_ready = true; } - + // In one-shot mode, we request the GraphicsEngine to delete the // window after we have rendered a frame. if (_one_shot) { @@ -1059,23 +1098,53 @@ end_frame() { // If we were rendering directly to texture, we can't delete the // buffer until the texture is gone too. - if (_rtm_mode == RTM_bind_or_copy) { - _hold_texture = _texture; + for (int i=0; iget_render_buffer(get_draw_buffer_type()); - if (_rtm_mode == RTM_copy_ram) { - _gsg->framebuffer_copy_to_ram(get_texture(), old_cube_map_index, - old_cube_map_dr, buffer); - } else { - _gsg->framebuffer_copy_to_texture(get_texture(), old_cube_map_index, - old_cube_map_dr, buffer); + for (int i=0; iget_render_buffer(get_draw_buffer_type()); + if (rtm_mode == RTM_copy_ram) { + _gsg->framebuffer_copy_to_ram(texture, old_cube_map_index, + old_cube_map_dr, buffer); + } else { + _gsg->framebuffer_copy_to_texture(texture, old_cube_map_index, + old_cube_map_dr, buffer); + } } } } diff --git a/panda/src/display/graphicsOutput.h b/panda/src/display/graphicsOutput.h index 2f7766210d..31836ba218 100644 --- a/panda/src/display/graphicsOutput.h +++ b/panda/src/display/graphicsOutput.h @@ -84,11 +84,14 @@ PUBLISHED: INLINE GraphicsPipe *get_pipe() const; INLINE const string &get_name() const; - INLINE bool has_texture() const; - INLINE Texture *get_texture() const; - void setup_render_texture(Texture *tex, RenderTextureMode mode); + INLINE int count_textures() const; + INLINE bool has_texture() const; + INLINE Texture *get_texture(int i=0) const; + INLINE RenderTextureMode get_rtm_mode(int i=0) const; + void clear_render_textures(); + void add_render_texture(Texture *tex, RenderTextureMode mode); void setup_render_texture(Texture *tex, bool allow_bind, bool to_ram); - + INLINE int get_x_size() const; INLINE int get_y_size() const; INLINE bool has_size() const; @@ -157,10 +160,13 @@ public: // It is an error to call any of the following methods from any // thread other than the draw thread. These methods are normally // called by the GraphicsEngine. - virtual bool begin_frame(); void clear(); + virtual bool begin_frame(); virtual void end_frame(); + virtual void begin_render_texture(); + virtual void end_render_texture(); + void change_scenes(DisplayRegion *new_dr); virtual void select_cube_map(int cube_map_index); @@ -182,11 +188,15 @@ public: protected: + class RenderTexture { + public: + PT(Texture) _texture; + RenderTextureMode _rtm_mode; + }; PT(GraphicsStateGuardian) _gsg; PT(GraphicsPipe) _pipe; string _name; - PT(Texture) _texture; - RenderTextureMode _rtm_mode; + pvector _textures; bool _flip_ready; bool _needs_context; int _cube_map_index; @@ -211,12 +221,12 @@ protected: bool _inverted; bool _delete_flag; - // This weak pointer is used to keep track of whether the buffer's - // bound Texture has been deleted or not. Until it has, we don't - // auto-close the buffer (since that would deallocate the memory - // associated with the texture). - WPT(Texture) _hold_texture; - + // These weak pointers are used to keep track of whether the + // buffer's bound Texture has been deleted or not. Until they have, + // we don't auto-close the buffer (since that would deallocate the + // memory associated with the texture). + pvector _hold_textures; + protected: Mutex _lock; // protects _display_regions. diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index ee5966f20e..aea5b73f6c 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -971,39 +971,6 @@ end_draw_primitives() { _vertex_data = NULL; } -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::framebuffer_bind_to_texture -// Access: Public, Virtual -// Description: Works in lieu of copy_texture() to bind the primary -// render buffer of the framebuffer to the indicated -// texture (which must have been created via -// GraphicsOutput::setup_render_texture()). -// -// If supported by the graphics backend, this will make -// the framebuffer memory directly accessible within the -// texture, but the frame cannot be rendered again until -// framebuffer_release_texture() is called. -// -// The return value is true if successful, false on -// failure. -//////////////////////////////////////////////////////////////////// -bool GraphicsStateGuardian:: -framebuffer_bind_to_texture(GraphicsOutput *, Texture *) { - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::framebuffer_release_texture -// Access: Public, Virtual -// Description: Undoes a previous call to -// framebuffer_bind_to_texture(). The framebuffer may -// again be rendered into, and the contents of the -// texture is undefined. -//////////////////////////////////////////////////////////////////// -void GraphicsStateGuardian:: -framebuffer_release_texture(GraphicsOutput *, Texture *) { -} - //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::do_issue_color_scale // Access: Public, Virtual diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 4d27586bc3..4add5bcea1 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -191,9 +191,6 @@ public: virtual void draw_points(const GeomPoints *primitive); virtual void end_draw_primitives(); - virtual bool framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex); - virtual void framebuffer_release_texture(GraphicsOutput *win, Texture *tex); - INLINE bool reset_if_new(); INLINE void mark_new(); virtual void reset(); diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 0a754d04a8..63411e6663 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -202,10 +202,7 @@ public: (Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb)=0; virtual bool framebuffer_copy_to_ram (Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb)=0; - - virtual bool framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex)=0; - virtual void framebuffer_release_texture(GraphicsOutput *win, Texture *tex)=0; - + virtual CoordinateSystem get_internal_coordinate_system() const=0; virtual void bind_light(PointLight *light_obj, const NodePath &light, diff --git a/panda/src/wgldisplay/wglGraphicsBuffer.cxx b/panda/src/wgldisplay/wglGraphicsBuffer.cxx index 127c2c019e..09a6f41be8 100644 --- a/panda/src/wgldisplay/wglGraphicsBuffer.cxx +++ b/panda/src/wgldisplay/wglGraphicsBuffer.cxx @@ -89,6 +89,75 @@ begin_frame() { return GraphicsBuffer::begin_frame(); } +//////////////////////////////////////////////////////////////////// +// Function: wglGraphicsStateGuardian::begin_render_texture +// Access: Public, Virtual +// Description: If the GraphicsOutput supports direct render-to-texture, +// and if any setup needs to be done during begin_frame, +// then the setup code should go here. Any textures that +// can not be rendered to directly should be reflagged +// as RTM_copy_texture. +//////////////////////////////////////////////////////////////////// +void wglGraphicsBuffer:: +begin_render_texture() { + wglGraphicsStateGuardian *wglgsg; + DCAST_INTO_V(wglgsg, _gsg); + + if (_gsg->get_properties().is_single_buffered()) { + wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB); + } else { + wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsOutput::end_render_texture +// Access: Public, Virtual +// Description: If the GraphicsOutput supports direct render-to-texture, +// and if any setup needs to be done during end_frame, +// then the setup code should go here. Any textures that +// could not be rendered to directly should be reflagged +// as RTM_copy_texture. +//////////////////////////////////////////////////////////////////// +void wglGraphicsBuffer:: +end_render_texture() { + wglGraphicsStateGuardian *wglgsg; + DCAST_INTO_V(wglgsg, _gsg); + + // Find the color texture, if there is one. That one can be bound to + // the framebuffer. All others must be marked RTM_copy_to_texture. + int tex_index = -1; + for (int i=0; iget_format() != Texture::F_depth_component)&& + (get_texture(i)->get_format() != Texture::F_stencil_index)&& + (tex_index < 0)) { + tex_index = i; + } else { + _textures[i]._rtm_mode = RTM_copy_texture; + } + } + } + + if (tex_index >= 0) { + Texture *tex = get_texture(tex_index); + TextureContext *tc = tex->prepare_now(_gsg->get_prepared_objects(), _gsg); + nassertv(tc != (TextureContext *)NULL); + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); + GLenum target = wglgsg->get_texture_target(tex->get_texture_type()); + if (target == GL_NONE) { + _textures[tex_index]._rtm_mode = RTM_copy_texture; + return; + } + GLP(BindTexture)(target, gtc->_index); + if (_gsg->get_properties().is_single_buffered()) { + wglgsg->_wglBindTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB); + } else { + wglgsg->_wglBindTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB); + } + } +} + //////////////////////////////////////////////////////////////////// // Function: wglGraphicsBuffer::select_cube_map // Access: Public, Virtual @@ -231,29 +300,6 @@ open_buffer() { } _pbuffer_dc = wglgsg->_wglGetPbufferDCARB(_pbuffer); - if (wgldisplay_cat.is_debug()) { - wgldisplay_cat.debug() - << "Created PBuffer " << _pbuffer << ", DC " << _pbuffer_dc << "\n"; - switch (_rtm_mode) { - case RTM_bind_or_copy: - wgldisplay_cat.debug() - << "pbuffer renders directly to texture.\n"; - break; - - case RTM_copy_texture: - wgldisplay_cat.debug() - << "pbuffer copies indirectly into texture.\n"; - break; - - case RTM_copy_ram: - wgldisplay_cat.debug() - << "pbuffer copies indirectly into system RAM.\n"; - break; - - default: - break; - } - } wglMakeCurrent(_pbuffer_dc, wglgsg->get_context(_pbuffer_dc)); wglgsg->report_my_gl_errors(); @@ -286,9 +332,15 @@ make_pbuffer(HDC twindow_dc) { if (wglgsg->_supports_pixel_format) { bool got_pbuffer_format = false; + bool any_binds = false; + + for (int i=0; i_supports_render_texture) { + if (any_binds && wglgsg->_supports_render_texture) { // First, try to get a pbuffer format that supports // render-to-texture. int new_pbformat = choose_pbuffer_format(twindow_dc, true); @@ -299,8 +351,13 @@ make_pbuffer(HDC twindow_dc) { } if (!got_pbuffer_format) { - // Failing that, just get a matching pbuffer format. - _rtm_mode = RTM_copy_texture; + // Failing that, just get a matching pbuffer format, + // and disable RTM_bind_or_copy. + for (int i=0; iget_format() != Texture::F_depth_component)&& + (get_texture(i)->get_format() != Texture::F_stencil_index)) { + bindtexture = get_texture(i); + break; + } + } + + if (bindtexture != 0) { if (_gsg->get_properties().get_frame_buffer_mode() & FrameBufferProperties::FM_alpha) { iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB; @@ -333,12 +400,12 @@ make_pbuffer(HDC twindow_dc) { iattrib_list[ni++] = WGL_TEXTURE_RGB_ARB; } - if (_texture->uses_mipmaps()) { + if (bindtexture->uses_mipmaps()) { iattrib_list[ni++] = WGL_MIPMAP_TEXTURE_ARB; iattrib_list[ni++] = 1; } - switch (_texture->get_texture_type()) { + switch (bindtexture->get_texture_type()) { case Texture::TT_cube_map: iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB; iattrib_list[ni++] = WGL_TEXTURE_CUBE_MAP_ARB; @@ -353,7 +420,7 @@ make_pbuffer(HDC twindow_dc) { iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB; iattrib_list[ni++] = WGL_TEXTURE_2D_ARB; } - } + } // Terminate the list. nassertr(ni <= max_attrib_list, false); diff --git a/panda/src/wgldisplay/wglGraphicsBuffer.h b/panda/src/wgldisplay/wglGraphicsBuffer.h index d513919ab9..04ef79de34 100644 --- a/panda/src/wgldisplay/wglGraphicsBuffer.h +++ b/panda/src/wgldisplay/wglGraphicsBuffer.h @@ -52,6 +52,9 @@ public: virtual void make_current(); virtual void release_gsg(); + virtual void begin_render_texture(); + virtual void end_render_texture(); + virtual void process_events(); protected: diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx index 5b2b5d2924..cc56ef5d4d 100755 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx @@ -63,66 +63,6 @@ wglGraphicsStateGuardian:: } } -//////////////////////////////////////////////////////////////////// -// Function: wglGraphicsStateGuardian::framebuffer_bind_to_texture -// Access: Public, Virtual -// Description: Works in lieu of copy_texture() to bind the primary -// render buffer of the framebuffer to the indicated -// texture (which must have been created via -// GraphicsOutput::setup_render_texture()). -// -// If supported by the graphics backend, this will make -// the framebuffer memory directly accessible within the -// texture, but the frame cannot be rendered again until -// framebuffer_release_texture() is called. -// -// The return value is true if successful, false on -// failure. -//////////////////////////////////////////////////////////////////// -bool wglGraphicsStateGuardian:: -framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex) { - wglGraphicsBuffer *buffer; - DCAST_INTO_R(buffer, win, false); - - TextureContext *tc = tex->prepare_now(get_prepared_objects(), this); - nassertr(tc != (TextureContext *)NULL, false); - CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - GLenum target = get_texture_target(tex->get_texture_type()); - if (target == GL_NONE) { - // Invalid texture, can't bind it. - return false; - } - GLP(BindTexture)(target, gtc->_index); - - if (get_properties().is_single_buffered()) { - _wglBindTexImageARB(buffer->_pbuffer, WGL_FRONT_LEFT_ARB); - } else { - _wglBindTexImageARB(buffer->_pbuffer, WGL_BACK_LEFT_ARB); - } - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: wglGraphicsStateGuardian::framebuffer_release_texture -// Access: Public, Virtual -// Description: Undoes a previous call to -// framebuffer_bind_to_texture(). The framebuffer may -// again be rendered into, and the contents of the -// texture is undefined. -//////////////////////////////////////////////////////////////////// -void wglGraphicsStateGuardian:: -framebuffer_release_texture(GraphicsOutput *win, Texture *) { - wglGraphicsBuffer *buffer; - DCAST_INTO_V(buffer, win); - - if (get_properties().is_single_buffered()) { - _wglReleaseTexImageARB(buffer->_pbuffer, WGL_FRONT_LEFT_ARB); - } else { - _wglReleaseTexImageARB(buffer->_pbuffer, WGL_BACK_LEFT_ARB); - } -} - //////////////////////////////////////////////////////////////////// // Function: wglGraphicsStateGuardian::reset // Access: Public, Virtual diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.h b/panda/src/wgldisplay/wglGraphicsStateGuardian.h index 9c764e91b2..71fc07a73c 100755 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.h +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.h @@ -43,9 +43,6 @@ public: INLINE bool made_context() const; INLINE HGLRC get_context(HDC hdc); - virtual bool framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex); - virtual void framebuffer_release_texture(GraphicsOutput *win, Texture *tex); - virtual void reset(); INLINE HDC get_twindow_dc();