diff --git a/direct/src/showbase/BufferViewer.py b/direct/src/showbase/BufferViewer.py index f23b7b3c2d..79bcbeabec 100644 --- a/direct/src/showbase/BufferViewer.py +++ b/direct/src/showbase/BufferViewer.py @@ -20,6 +20,8 @@ class BufferViewer(DirectObject): self.cullsort = 10000 self.cards = [] self.cardindex = 0 + self.cardmaker = CardMaker("cubemaker") + self.cardmaker.setFrame(-1,1,-1,1) self.task = 0 self.window = 0 self.dirty = 1 @@ -39,7 +41,7 @@ class BufferViewer(DirectObject): # started. self.enable(self.enabled) - def isValidTextureSet(self, list): + def isValidTextureSet(self, x): """Access: private. Returns true if the parameter is a list of GraphicsOutput and Texture, or the keyword 'all'.""" if (isinstance(x, list)): @@ -270,10 +272,18 @@ class BufferViewer(DirectObject): for itex in range(win.countTextures()): tex = win.getTexture(itex) if (include.has_key(tex)) and (exclude.has_key(tex)==0): - card = win.getTextureCard() - card.setTexture(tex) - cards.append(card) + if (tex.getTextureType() == Texture.TTCubeMap): + for face in range(6): + self.cardmaker.setUvRangeCube(face) + card = NodePath(self.cardmaker.generate()) + card.setTexture(tex) + cards.append(card) + else: + card = win.getTextureCard() + card.setTexture(tex) + cards.append(card) wins.append(win) + exclude[tex] = 1 self.cards = cards if (len(cards)==0): self.task = 0 diff --git a/doc/makepanda/confauto.in b/doc/makepanda/confauto.in index 0e9eb47fbc..5e9c98fa8b 100755 --- a/doc/makepanda/confauto.in +++ b/doc/makepanda/confauto.in @@ -88,3 +88,7 @@ egg-object-type-direct-widget collide-mask { 0x80000000 } { # Define a new cull bin that will render on top of everything else. cull-bin gui-popup 60 unsorted + +# Paranoid clock. This fixes flaky hardware clocks. + +paranoid-clock 1 diff --git a/panda/src/display/frameBufferProperties.h b/panda/src/display/frameBufferProperties.h index a1891da9ae..22abe75053 100644 --- a/panda/src/display/frameBufferProperties.h +++ b/panda/src/display/frameBufferProperties.h @@ -64,6 +64,7 @@ PUBLISHED: INLINE bool has_mode(int bit) const; INLINE bool is_single_buffered() const; INLINE bool is_stereo() const; + bool subsumes(const FrameBufferProperties &prop) const; INLINE void set_frame_buffer_mode(int frameBuffer_mode); diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index c159c58cf6..ad3c779478 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -450,7 +450,6 @@ remove_all_windows() { _windows.clear(); - _app.do_release(this); _app.do_close(this); terminate_threads(); } @@ -922,7 +921,6 @@ cull_and_draw_together(const GraphicsEngine::Windows &wlist) { for (wi = wlist.begin(); wi != wlist.end(); ++wi) { GraphicsOutput *win = (*wi); if (win->is_active() && win->get_gsg()->is_active()) { - win->get_gsg()->set_current_properties(&win->get_fb_properties()); if (win->begin_frame(GraphicsOutput::FM_render)) { win->clear(); @@ -1088,7 +1086,6 @@ draw_bins(const GraphicsEngine::Windows &wlist) { for (wi = wlist.begin(); wi != wlist.end(); ++wi) { GraphicsOutput *win = (*wi); if (win->is_active() && win->get_gsg()->is_active()) { - win->get_gsg()->set_current_properties(&win->get_fb_properties()); if (win->begin_frame(GraphicsOutput::FM_render)) { win->clear(); @@ -1149,7 +1146,6 @@ make_contexts(const GraphicsEngine::Windows &wlist) { Windows::const_iterator wi; for (wi = wlist.begin(); wi != wlist.end(); ++wi) { GraphicsOutput *win = (*wi); - win->get_gsg()->set_current_properties(&win->get_fb_properties()); if (win->begin_frame(GraphicsOutput::FM_refresh)) { win->end_frame(GraphicsOutput::FM_refresh); } @@ -1599,27 +1595,6 @@ terminate_threads() { thread->_cv_mutex.lock(); } - // Now tell them to release their windows' graphics contexts. - for (ti = _threads.begin(); ti != _threads.end(); ++ti) { - RenderThread *thread = (*ti).second; - - while (thread->_thread_state != TS_wait) { - thread->_cv_done.wait(); - } - thread->_thread_state = TS_do_release; - thread->_cv_start.signal(); - thread->_cv_mutex.release(); - } - - // Grab the mutex again to wait for the above to complete. - for (ti = _threads.begin(); ti != _threads.end(); ++ti) { - RenderThread *thread = (*ti).second; - thread->_cv_mutex.lock(); - while (thread->_thread_state != TS_wait) { - thread->_cv_done.wait(); - } - } - // Now tell them to close their windows and terminate. for (ti = _threads.begin(); ti != _threads.end(); ++ti) { RenderThread *thread = (*ti).second; @@ -1776,30 +1751,6 @@ remove_window(GraphicsOutput *window) { Windows::iterator wi; - wi = _cdraw.find(ptwin); - if (wi != _cdraw.end()) { - // The window is on our _cdraw list, meaning its GSG operations are - // serviced by this thread (cull and draw in the same operation). - - // Move it to the pending release thread so we can release the GSG - // when the thread next runs. We can't do this immediately, - // because we might not have been called from the subthread. - _pending_release.push_back(ptwin); - _cdraw.erase(wi); - } - - wi = _draw.find(ptwin); - if (wi != _draw.end()) { - // The window is on our _draw list, meaning its GSG operations are - // serviced by this thread (draw performed on this thread). - - // Move it to the pending release thread so we can release the GSG - // when the thread next runs. We can't do this immediately, - // because we might not have been called from the subthread. - _pending_release.push_back(ptwin); - _draw.erase(wi); - } - wi = _window.find(ptwin); if (wi != _window.end()) { // The window is on our _window list, meaning its open/close @@ -1924,22 +1875,6 @@ do_flip(GraphicsEngine *engine) { engine->flip_windows(_draw); } -//////////////////////////////////////////////////////////////////// -// Function: GraphicsEngine::WindowRenderer::do_release -// Access: Public -// Description: Releases the rendering contexts for all windows on -// the _draw list. -//////////////////////////////////////////////////////////////////// -void GraphicsEngine::WindowRenderer:: -do_release(GraphicsEngine *) { - MutexHolder holder(_wl_lock); - Windows::iterator wi; - for (wi = _draw.begin(); wi != _draw.end(); ++wi) { - GraphicsOutput *win = (*wi); - win->release_gsg(); - } -} - //////////////////////////////////////////////////////////////////// // Function: GraphicsEngine::WindowRenderer::do_close // Access: Public @@ -1982,16 +1917,6 @@ void GraphicsEngine::WindowRenderer:: do_pending(GraphicsEngine *engine) { MutexHolder holder(_wl_lock); - if (!_pending_release.empty()) { - // Release any GSG's that were waiting. - Windows::iterator wi; - for (wi = _pending_release.begin(); wi != _pending_release.end(); ++wi) { - GraphicsOutput *win = (*wi); - win->release_gsg(); - } - _pending_release.clear(); - } - if (!_pending_close.empty()) { // Close any windows that were pending closure, but only if their // associated GSG has already been released. @@ -2128,7 +2053,6 @@ thread_main() { case TS_do_release: do_pending(_engine); - do_release(_engine); break; case TS_do_windows: diff --git a/panda/src/display/graphicsEngine.h b/panda/src/display/graphicsEngine.h index b039b524f1..96a5dcce2e 100644 --- a/panda/src/display/graphicsEngine.h +++ b/panda/src/display/graphicsEngine.h @@ -294,7 +294,6 @@ private: Windows _window; // window stage, i.e. process windowing events // These are not kept sorted. - Windows _pending_release; // moved from _draw, pending release_gsg. Windows _pending_close; // moved from _window, pending close. GSGs _gsgs; // draw stage diff --git a/panda/src/display/graphicsOutput.I b/panda/src/display/graphicsOutput.I index a2e015bd78..37be90c4f4 100644 --- a/panda/src/display/graphicsOutput.I +++ b/panda/src/display/graphicsOutput.I @@ -106,12 +106,27 @@ get_texture(int i) const { return _textures[i]._texture; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsOutput::get_texture_plane +// Access: Published +// Description: Returns the RenderTexturePlane associated with the +// nth render-texture. Returns 0 if there is no such +// texture. +//////////////////////////////////////////////////////////////////// +INLINE GraphicsOutput::RenderTexturePlane GraphicsOutput:: +get_texture_plane(int i) const { + if ((i < 0) || (i >= ((int)_textures.size()))) { + return (RenderTexturePlane)0; + } + return _textures[i]._plane; +} + //////////////////////////////////////////////////////////////////// // 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. +// nth render-texture. Returns RTM_none if there is +// no such texture. //////////////////////////////////////////////////////////////////// INLINE GraphicsOutput::RenderTextureMode GraphicsOutput:: get_rtm_mode(int i) const { diff --git a/panda/src/display/graphicsOutput.cxx b/panda/src/display/graphicsOutput.cxx index b95766f181..a9d4120799 100644 --- a/panda/src/display/graphicsOutput.cxx +++ b/panda/src/display/graphicsOutput.cxx @@ -218,23 +218,49 @@ clear_render_textures() { // // If tex is not NULL, it is the texture that will be // set up for rendering into; otherwise, a new Texture -// object will be created (in which case you may call -// get_texture() to retrieve the new texture pointer -// later). +// object will be created, in which case you may call +// get_texture() to retrieve the new texture pointer. // +// You can specify a bitplane to attach the texture to. +// the legal choices are: +// +// * RTP_depth +// * RTP_stencil +// * RTP_color +// * RTP_aux_rgba_0 +// * RTP_aux_rgba_1 +// * RTP_aux_rgba_2 +// * RTP_aux_rgba_3 +// +// If you do not specify a bitplane to attach the +// texture to, this routine will use a default based +// on the texture's format: +// +// * F_depth_component attaches to RTP_depth +// * F_stencil_index attaches to RTP_stencil +// * all other formats attach to RTP_color. +// +// The texture's format will be changed to match +// the format of the bitplane to which it is attached. +// For example, if you pass in an F_rgba texture and +// order that it be attached to RTP_depth, it will turn +// into an F_depth_component texture. +// // Also see make_texture_buffer(), which is a // higher-level interface for preparing // render-to-a-texture mode. //////////////////////////////////////////////////////////////////// void GraphicsOutput:: -add_render_texture(Texture *tex, RenderTextureMode mode) { +add_render_texture(Texture *tex, RenderTextureMode mode, + RenderTexturePlane plane) { if (mode == RTM_none) { return; } MutexHolder holder(_lock); throw_event("render-texture-targets-changed"); - + + // Create texture if necessary. if (tex == (Texture *)NULL) { tex = new Texture(get_name()); tex->set_wrap_u(Texture::WM_clamp); @@ -242,13 +268,45 @@ add_render_texture(Texture *tex, RenderTextureMode mode) { } else { tex->clear_ram_image(); } - tex->set_match_framebuffer_format(true); + + // Choose a default bitplane. + if (plane == RTP_COUNT) { + if (tex->get_format()==Texture::F_depth_component) { + plane = RTP_depth; + } else if (tex->get_format()==Texture::F_stencil_index) { + plane = RTP_stencil; + } else { + plane = RTP_color; + } + } + + // Set the texture's format to match the bitplane. + // (And validate the bitplane, while we're at it). + + if (plane == RTP_depth) { + tex->set_format(Texture::F_depth_component); + tex->set_match_framebuffer_format(true); + } else if (plane == RTP_stencil) { + tex->set_format(Texture::F_stencil_index); + tex->set_match_framebuffer_format(true); + } else if ((plane == RTP_color)|| + (plane == RTP_aux_rgba_0)|| + (plane == RTP_aux_rgba_1)|| + (plane == RTP_aux_rgba_2)|| + (plane == RTP_aux_rgba_3)) { + tex->set_format(Texture::F_rgba); + tex->set_match_framebuffer_format(true); + } else { + display_cat.error() << + "add_render_texture: invalid bitplane specified.\n"; + return; + } // 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). - tex->set_x_size(get_x_size()); - tex->set_y_size(get_y_size()); + tex->set_x_size(Texture::up_to_power_2(get_x_size())); + tex->set_y_size(Texture::up_to_power_2(get_y_size())); if ((mode == RTM_bind_or_copy)&&(support_render_texture==0)) { mode = RTM_copy_texture; @@ -259,36 +317,15 @@ add_render_texture(Texture *tex, RenderTextureMode mode) { } } + RenderTexture result; result._texture = tex; + result._plane = plane; 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(); - } } //////////////////////////////////////////////////////////////////// @@ -778,21 +815,6 @@ make_cube_map(const string &name, int size, NodePath &camera_rig, tex->set_wrap_v(Texture::WM_clamp); GraphicsOutput *buffer; - // I'll remove this permanently in a few days. - // if (show_buffers) { - // // If show_buffers is true, we'd like to create a window with the - // // six buffers spread out and all visible at once, for the user's - // // convenience. - // buffer = make_texture_buffer(name, size * 3, size * 2, tex, to_ram); - // tex->set_x_size(size); - // tex->set_y_size(size); - // - // } else { - // // In the normal case, the six buffers are stacked on top of each - // // other like pancakes. - // buffer = make_texture_buffer(name, size, size, tex, to_ram); - // } - buffer = make_texture_buffer(name, size, size, tex, to_ram); // We don't need to clear the overall buffer; instead, we'll clear @@ -811,13 +833,6 @@ make_cube_map(const string &name, int size, NodePath &camera_rig, camera_np.look_at(cube_faces[i]._look_at, cube_faces[i]._up); DisplayRegion *dr; - // I'll remove this permanently in a few days. - Josh - // if (show_buffers) { - // const ShowBuffersCubeMapRegions &r = cube_map_regions[i]; - // dr = buffer->make_display_region(r.l, r.r, r.b, r.t); - // } else { - // dr = buffer->make_display_region(); - // } dr = buffer->make_display_region(); dr->set_cube_map_index(i); @@ -1093,21 +1108,6 @@ void GraphicsOutput:: select_cube_map(int) { } -//////////////////////////////////////////////////////////////////// -// Function: GraphicsOutput::release_gsg -// Access: Public -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. The window will be -// permanently unable to render; this is normally called -// only just before destroying the window. This should -// only be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void GraphicsOutput:: -release_gsg() { - _gsg.clear(); - _active = false; -} - //////////////////////////////////////////////////////////////////// // Function: GraphicsOutput::begin_flip // Access: Public, Virtual diff --git a/panda/src/display/graphicsOutput.h b/panda/src/display/graphicsOutput.h index 80e08338fc..75a223d642 100644 --- a/panda/src/display/graphicsOutput.h +++ b/panda/src/display/graphicsOutput.h @@ -82,6 +82,28 @@ PUBLISHED: RTM_triggered_copy_ram, }; + // It seems awkward to have this type, and also + // RenderBuffer::Type. However, the fact that RenderBuffer::Type + // is a bitmask makes it awfully awkward to work with. + enum RenderTexturePlane { + RTP_color, + RTP_depth, + RTP_stencil, + RTP_aux_rgba_0, + RTP_aux_rgba_1, + RTP_aux_rgba_2, + RTP_aux_rgba_3, + RTP_aux_hrgba_0, + RTP_aux_hrgba_1, + RTP_aux_hrgba_2, + RTP_aux_hrgba_3, + RTP_aux_float_0, + RTP_aux_float_1, + RTP_aux_float_2, + RTP_aux_float_3, + RTP_COUNT + }; + // There are many reasons to call begin_frame/end_frame. enum FrameMode { FM_render, // We are rendering a frame. @@ -98,9 +120,11 @@ PUBLISHED: INLINE int count_textures() const; INLINE bool has_texture() const; INLINE Texture *get_texture(int i=0) const; + INLINE RenderTexturePlane get_texture_plane(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 add_render_texture(Texture *tex, RenderTextureMode mode, + RenderTexturePlane bitplane=RTP_COUNT); void setup_render_texture(Texture *tex, bool allow_bind, bool to_ram); INLINE int get_x_size() const; @@ -200,8 +224,6 @@ public: void change_scenes(DisplayRegion *new_dr); virtual void select_cube_map(int cube_map_index); - virtual void release_gsg(); - // These methods will be called within the app (main) thread. virtual void begin_flip(); virtual void end_flip(); @@ -226,6 +248,7 @@ protected: class RenderTexture { public: PT(Texture) _texture; + RenderTexturePlane _plane; RenderTextureMode _rtm_mode; }; PT(GraphicsStateGuardian) _gsg; diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index cca5212306..ece7a55418 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -185,6 +185,8 @@ public: virtual void end_scene(); virtual void end_frame(); + void set_current_properties(FrameBufferProperties *properties); + virtual bool depth_offset_decals(); virtual CPT(RenderState) begin_decal_base_first(); virtual CPT(RenderState) begin_decal_nested(); @@ -244,8 +246,6 @@ protected: virtual void bind_clip_plane(const NodePath &plane, int plane_id); virtual void end_bind_clip_planes(); - void set_current_properties(FrameBufferProperties *properties); - virtual void free_pointers(); virtual void close_gsg(); void panic_deactivate(); diff --git a/panda/src/display/renderBuffer.h b/panda/src/display/renderBuffer.h index 4e9395a833..90fcf87699 100644 --- a/panda/src/display/renderBuffer.h +++ b/panda/src/display/renderBuffer.h @@ -38,16 +38,19 @@ public: T_aux_rgba_1 = 0x00000002, T_aux_rgba_2 = 0x00000004, T_aux_rgba_3 = 0x00000008, + T_aux_rgba_ALL = 0x0000000F, - T_aux_hrgba_0 = 0x00000010, - T_aux_hrgba_1 = 0x00000020, - T_aux_hrgba_2 = 0x00000040, + T_aux_hrgba_0 = 0x00000010, // These can't really be implemented until + T_aux_hrgba_1 = 0x00000020, // we have support for hrgba textures. + T_aux_hrgba_2 = 0x00000040, // I've just added the bits for the future. T_aux_hrgba_3 = 0x00000080, + T_aux_hrgba_ALL = 0x000000F0, - T_aux_float_0 = 0x00000100, - T_aux_float_1 = 0x00000200, - T_aux_float_2 = 0x00000400, + T_aux_float_0 = 0x00000100, // These can't really be implemented until + T_aux_float_1 = 0x00000200, // we have support for float textures. + T_aux_float_2 = 0x00000400, // I've just added the bits for the future. T_aux_float_3 = 0x00000800, + T_aux_float_ALL = 0x00000F00, T_aux_undef_0 = 0x00001000, T_aux_undef_1 = 0x00002000, diff --git a/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx b/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx index 7d483f4277..55c5d82257 100644 --- a/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx +++ b/panda/src/dxgsg8/wdxGraphicsBuffer8.cxx @@ -95,6 +95,7 @@ begin_frame(FrameMode mode) { clear_cube_map_selection(); } + _gsg->set_current_properties(&get_fb_properties()); return _gsg->begin_frame(); } @@ -328,20 +329,6 @@ select_cube_map(int cube_map_index) { } } -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer8::release_gsg -// Access: Public, Virtual -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. The window will be -// permanently unable to render; this is normally called -// only just before destroying the window. This should -// only be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsBuffer8:: -release_gsg() { - GraphicsBuffer::release_gsg(); -} - //////////////////////////////////////////////////////////////////// // Function: wdxGraphicsBuffer8::process_events // Access: Public, Virtual @@ -398,6 +385,9 @@ close_buffer() { this -> _new_z_stencil_surface -> Release ( ); this -> _new_z_stencil_surface = NULL; } + + _gsg.clear(); + _active = false; } _cube_map_index = -1; diff --git a/panda/src/dxgsg8/wdxGraphicsBuffer8.h b/panda/src/dxgsg8/wdxGraphicsBuffer8.h index c3efd7826a..f5df9f81fd 100644 --- a/panda/src/dxgsg8/wdxGraphicsBuffer8.h +++ b/panda/src/dxgsg8/wdxGraphicsBuffer8.h @@ -48,7 +48,6 @@ public: virtual void end_frame(FrameMode mode); virtual void select_cube_map(int cube_map_index); - virtual void release_gsg(); virtual void process_events(); diff --git a/panda/src/dxgsg8/wdxGraphicsWindow8.cxx b/panda/src/dxgsg8/wdxGraphicsWindow8.cxx index e6713275b2..62126733ad 100644 --- a/panda/src/dxgsg8/wdxGraphicsWindow8.cxx +++ b/panda/src/dxgsg8/wdxGraphicsWindow8.cxx @@ -98,7 +98,8 @@ begin_frame(FrameMode mode) { if (mode == FM_render) { clear_cube_map_selection(); } - + + _gsg->set_current_properties(&get_fb_properties()); bool return_val = _gsg->begin_frame(); _dxgsg->set_render_target(); return return_val; @@ -251,6 +252,10 @@ verify_window_sizes(int numsizes, int *dimen) { void wdxGraphicsWindow8:: close_window() { wdxdisplay8_cat.debug() << "wdx closed window\n"; + if (_gsg != (GraphicsStateGuardian*)NULL) { + _gsg.clear(); + _active = false; + } _dxgsg->release_swap_chain(&_wcontext); WinGraphicsWindow::close_window(); } diff --git a/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx b/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx index 6d5de163fe..1f9d0f5ed2 100644 --- a/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx +++ b/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx @@ -93,6 +93,7 @@ begin_frame(FrameMode mode) { clear_cube_map_selection(); } + _gsg->set_current_properties(&get_fb_properties()); return _gsg->begin_frame(); } @@ -364,20 +365,6 @@ select_cube_map(int cube_map_index) { } } -//////////////////////////////////////////////////////////////////// -// Function: wdxGraphicsBuffer9::release_gsg -// Access: Public, Virtual -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. The window will be -// permanently unable to render; this is normally called -// only just before destroying the window. This should -// only be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void wdxGraphicsBuffer9:: -release_gsg() { - GraphicsBuffer::release_gsg(); -} - //////////////////////////////////////////////////////////////////// // Function: wdxGraphicsBuffer9::process_events // Access: Public, Virtual @@ -434,6 +421,9 @@ close_buffer() { this -> _new_z_stencil_surface -> Release ( ); this -> _new_z_stencil_surface = NULL; } + + _gsg.clear(); + _active = false; } _cube_map_index = -1; diff --git a/panda/src/dxgsg9/wdxGraphicsBuffer9.h b/panda/src/dxgsg9/wdxGraphicsBuffer9.h index 97bc08df07..76b2765e88 100644 --- a/panda/src/dxgsg9/wdxGraphicsBuffer9.h +++ b/panda/src/dxgsg9/wdxGraphicsBuffer9.h @@ -48,8 +48,6 @@ public: virtual void end_frame(FrameMode mode); virtual void select_cube_map(int cube_map_index); - virtual void release_gsg(); - virtual void process_events(); protected: diff --git a/panda/src/dxgsg9/wdxGraphicsWindow9.cxx b/panda/src/dxgsg9/wdxGraphicsWindow9.cxx index bb330bf82d..ccdae94328 100755 --- a/panda/src/dxgsg9/wdxGraphicsWindow9.cxx +++ b/panda/src/dxgsg9/wdxGraphicsWindow9.cxx @@ -119,6 +119,7 @@ begin_frame(FrameMode mode) { clear_cube_map_selection(); } + _gsg->set_current_properties(&get_fb_properties()); bool return_val = _gsg->begin_frame(); _dxgsg->set_render_target(); return return_val; @@ -252,6 +253,10 @@ verify_window_sizes(int numsizes, int *dimen) { void wdxGraphicsWindow9:: close_window() { wdxdisplay9_cat.debug() << "wdx closed window\n"; + if (_gsg != (GraphicsStateGuardian *)NULL) { + _gsg.clear(); + _active = false; + } _dxgsg->release_swap_chain(&_wcontext); WinGraphicsWindow::close_window(); } diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index 0a72732721..5bf05ed700 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -40,17 +40,10 @@ CLP(GraphicsBuffer)(GraphicsPipe *pipe, _fbo = 0; _rb_size_x = 0; _rb_size_y = 0; - for (int i=0; ibegin_frame(FM_parasite)) { return false; } @@ -88,33 +78,52 @@ begin_frame(FrameMode mode) { if (mode == FM_render) { rebuild_bitplanes(); clear_cube_map_selection(); - - // Verify that the frame buffer is ready for rendering. - GLenum status = glgsg->_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); - if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { - GLCAT.error() << "EXT_framebuffer_object reports non-framebuffer-completeness.\n"; - switch(status) { - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: - GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\n"; break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: - GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\n"; break; - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: - GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n"; break; - case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: - GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n"; break; - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: - GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n"; break; - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: - GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n"; break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - GLCAT.error() << "FRAMEBUFFER_UNSUPPORTED_EXT\n"; break; - default: - GLCAT.error() << "OTHER PROBLEM\n"; break; - } - glgsg->bind_fbo(0); + if (!check_fbo()) { return false; } } + + _gsg->set_current_properties(&get_fb_properties()); + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: glGraphicsBuffer::check_fbo +// Access: Private +// Description: Calls 'glCheckFramebufferStatus'. On error, +// prints out an appropriate error message and unbinds +// the fbo. Returns true for OK or false for error. +//////////////////////////////////////////////////////////////////// +bool CLP(GraphicsBuffer):: +check_fbo() { + CLP(GraphicsStateGuardian) *glgsg; + DCAST_INTO_R(glgsg, _gsg, false); + + GLenum status = glgsg->_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { + GLCAT.error() << "EXT_framebuffer_object reports non-framebuffer-completeness.\n"; + switch(status) { + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\n"; break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: + GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\n"; break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: + GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n"; break; + case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: + GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n"; break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: + GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n"; break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: + GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n"; break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + GLCAT.error() << "FRAMEBUFFER_UNSUPPORTED_EXT\n"; break; + default: + GLCAT.error() << "OTHER PROBLEM\n"; break; + } + + glgsg->bind_fbo(0); + return false; + } return true; } @@ -151,26 +160,45 @@ rebuild_bitplanes() { _host->get_y_size()); } } - int desired_x = _x_size; - int desired_y = _y_size; + int bitplane_x = _x_size; + int bitplane_y = _y_size; if (!glgsg->get_supports_tex_non_pow2()) { - desired_x = Texture::up_to_power_2(desired_x); - desired_y = Texture::up_to_power_2(desired_y); + bitplane_x = Texture::up_to_power_2(bitplane_x); + bitplane_y = Texture::up_to_power_2(bitplane_y); + } + bool rb_resize = false; + if ((bitplane_x != _rb_size_x)|| + (bitplane_y != _rb_size_y)) { + _rb_size_x = bitplane_x; + _rb_size_y = bitplane_y; + rb_resize = true; } - // Scan the textures list and determine what should be attached. + // These variables indicate what should be bound to each bitplane. - Texture *attach[SLOT_COUNT]; - for (int i=0; iget_format(); - + RenderTexturePlane plane = get_texture_plane(i); + // If it's a not a 2D texture or a cube map, punt it. if ((tex->get_texture_type() != Texture::TT_2d_texture)&& (tex->get_texture_type() != Texture::TT_cube_map)) { @@ -178,106 +206,123 @@ rebuild_bitplanes() { continue; } - // Identify right attachment point. - - int slot = SLOT_COUNT; - if (fmt == Texture::F_depth_component) { - slot = SLOT_depth; - } else if (fmt == Texture::F_stencil_index) { - slot = SLOT_stencil; - } else if ((fmt == Texture::F_rgba)||(fmt == Texture::F_rgb)) { - slot = SLOT_color; - } else { - _textures[i]._rtm_mode = RTM_copy_texture; - continue; - } - - // If there's already a texture bound to this slot, - // then punt this texture. - if (attach[slot]) { + // If I can't find an appropriate slot, or if there's + // already a texture bound to this slot, then punt + // this texture. + + if (attach[plane]) { _textures[i]._rtm_mode = RTM_copy_texture; continue; } // Assign the texture to this slot. - attach[slot] = tex; + attach[plane] = tex; } // For all slots, update the slot. - - for (int slot=0; slotget_x_size() == desired_x)&& - (tex->get_y_size() == desired_y)) { - continue; - } - - // Bind the texture to the slot. - tex->set_x_size(desired_x); - tex->set_y_size(desired_y); - TextureContext *tc = tex->prepare_now(glgsg->get_prepared_objects(), glgsg); - nassertv(tc != (TextureContext *)NULL); - CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - - if (tex->get_texture_type() == Texture::TT_2d_texture) { - glgsg->upload_blank_image(tex, gtc); - glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, _attach_point[slot], - GL_TEXTURE_2D, gtc->_index, 0); - } else { - glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, _attach_point[slot], - GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, gtc->_index, 0); - } - _tex[slot] = tex; - - // If there was a renderbuffer bound to this slot, delete it. - if (_rb[slot] != 0) { - glgsg->_glDeleteRenderbuffers(1, &(_rb[slot])); - _rb[slot] = 0; - } - - } else { - - // If a renderbuffer is already attached to the slot, and it's - // the right size, then no update of this slot is needed. - if ((_rb[slot] != 0)&& - (_rb_size_x == desired_x)&& - (_rb_size_y == desired_y)) { - continue; - } - - // If there's no renderbuffer for this slot, create one. - if (_rb[slot] == 0) { - glgsg->_glGenRenderbuffers(1, &(_rb[slot])); - } - - // Resize the renderbuffer appropriately. - glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, _rb[slot]); - glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, _slot_format[slot], - desired_x, desired_y); - glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0); - - // Bind the renderbuffer to the slot. - glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, _attach_point[slot], - GL_RENDERBUFFER_EXT, _rb[slot]); - - // Toss any texture that was connected to the slot. - _tex[slot] = 0; - } - } - // These record the size of all nonzero renderbuffers. - _rb_size_x = desired_x; - _rb_size_y = desired_y; + bind_slot(rb_resize, attach, RTP_depth, + GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT, Texture::F_depth_component); + //bind_slot(rb_resize, attach, RTP_stencil, + // GL_STENCIL_ATTACHMENT_EXT, GL_STENCIL_INDEX, Texture::F_stencil_index); + bind_slot(rb_resize, attach, RTP_color, + GL_COLOR_ATTACHMENT0_EXT, GL_RGBA, Texture::F_rgba); + int next = GL_COLOR_ATTACHMENT1_EXT; + for (int i=0; i<_fb_properties.get_aux_rgba(); i++) { + bind_slot(rb_resize, attach, (RenderTexturePlane)(RTP_aux_rgba_0+i), + next, GL_RGBA, Texture::F_rgba); + next += 1; + } + for (int i=0; i<_fb_properties.get_aux_hrgba(); i++) { + bind_slot(rb_resize, attach, (RenderTexturePlane)(RTP_aux_hrgba_0+i), + next, GL_RGBA, Texture::F_rgba); + next += 1; + } + for (int i=0; i<_fb_properties.get_aux_float(); i++) { + bind_slot(rb_resize, attach, (RenderTexturePlane)(RTP_aux_float_0+i), + next, GL_RGBA, Texture::F_rgba); + next += 1; + } glgsg->report_my_gl_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: glGraphicsBuffer::bind_slot +// Access: Private +// Description: Attaches either a texture or a renderbuffer to the +// specified bitplane. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsBuffer):: +bind_slot(bool rb_resize, Texture **attach, RenderTexturePlane slot, + GLenum attachpoint, GLenum texformat, Texture::Format fmt) { + + CLP(GraphicsStateGuardian) *glgsg; + DCAST_INTO_V(glgsg, _gsg); + + Texture *tex = attach[slot]; + if (tex) { + // If the texture is already bound to the slot, and it's + // the right size, then no update of this slot is needed. + if ((_tex[slot] == tex)&& + (tex->get_x_size() == _rb_size_x)&& + (tex->get_y_size() == _rb_size_y)) { + return; + } + + // Bind the texture to the slot. + tex->set_x_size(_rb_size_x); + tex->set_y_size(_rb_size_y); + tex->set_format(fmt); + TextureContext *tc = tex->prepare_now(glgsg->get_prepared_objects(), glgsg); + nassertv(tc != (TextureContext *)NULL); + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); + glgsg->apply_texture(tc); + + if (tex->get_texture_type() == Texture::TT_2d_texture) { + glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, attachpoint, + GL_TEXTURE_2D, gtc->_index, 0); + } else { + glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, attachpoint, + GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, gtc->_index, 0); + } + _tex[slot] = tex; + + // If there was a renderbuffer bound to this slot, delete it. + if (_rb[slot] != 0) { + glgsg->_glDeleteRenderbuffers(1, &(_rb[slot])); + _rb[slot] = 0; + } + + } else { + + // If a renderbuffer is already attached to the slot, and it's + // the right size, then no update of this slot is needed. + if ((_rb[slot] != 0)&&(!rb_resize)) { + return; + } + + // If there's no renderbuffer for this slot, create one. + if (_rb[slot] == 0) { + glgsg->_glGenRenderbuffers(1, &(_rb[slot])); + } + + // Resize the renderbuffer appropriately. + glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, _rb[slot]); + glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, texformat, + _rb_size_x, _rb_size_y); + glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0); + + // Bind the renderbuffer to the slot. + glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, attachpoint, + GL_RENDERBUFFER_EXT, _rb[slot]); + + // Toss any texture that was connected to the slot. + _tex[slot] = 0; + } +} + //////////////////////////////////////////////////////////////////// // Function: glGraphicsBuffer::generate_mipmaps // Access: Private @@ -292,7 +337,7 @@ generate_mipmaps() { CLP(GraphicsStateGuardian) *glgsg; DCAST_INTO_V(glgsg, _gsg); - for (int slot=0; slotuses_mipmaps())) { glgsg->_state._texture = 0; @@ -395,7 +440,7 @@ close_buffer() { DCAST_INTO_V(glgsg, _gsg); // Delete the renderbuffers. - for (int i=0; i_glDeleteRenderbuffers(1, &(_rb[i])); _rb[i] = 0; @@ -408,5 +453,9 @@ close_buffer() { // Delete the FBO itself. nassertv(_fbo != 0); glgsg->_glDeleteFramebuffers(1, &_fbo); + + // Release the Gsg + _gsg.clear(); + _active = false; } diff --git a/panda/src/glstuff/glGraphicsBuffer_src.h b/panda/src/glstuff/glGraphicsBuffer_src.h index b40e1918fd..104c907dbe 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.h +++ b/panda/src/glstuff/glGraphicsBuffer_src.h @@ -25,21 +25,15 @@ // // The glGraphicsBuffer is based on the OpenGL // EXT_framebuffer_object and ARB_draw_buffers extensions. -// This design has three significant advantages over the -// wglGraphicsBuffer and glxGraphicsBuffer. +// This design has significant advantages over the +// older wglGraphicsBuffer and glxGraphicsBuffer. // -// As you might expect, this type of buffer can export -// its color buffer as a texture. But it can also export -// its depth buffer, its stencil buffer, and any number -// of auxiliary buffers. This is the biggest advantage: -// it can render to many textures at the same time. -// -// There is also a speed advantage. When using a -// glGraphicsBuffer, it is not necessary to call the -// extremely expensive wglMakeCurrent on buffer switches. -// -// The glGraphicsBuffer can also track the size of a host -// window, and automatically resize itself to match. +// * Can export depth and stencil. +// * Supports auxiliary bitplanes. +// * Supports non-power-of-two padding. +// * Supports tracking of host window size. +// * Faster than pbuffers. +// * Can render onto a texture without clearing it first. // // If either of the necessary OpenGL extensions is not // available, then the glGraphicsBuffer will not be @@ -69,24 +63,18 @@ protected: private: + void bind_slot(bool rb_resize, Texture **attach, RenderTexturePlane plane, + GLenum attachpoint, GLenum texformat, Texture::Format fmt); + bool check_fbo(); void generate_mipmaps(); void rebuild_bitplanes(); - enum { - SLOT_color, - SLOT_depth, - SLOT_stencil, - SLOT_COUNT - }; - GLuint _fbo; int _rb_size_x; int _rb_size_y; - GLuint _rb[SLOT_COUNT]; - PT(Texture) _tex[SLOT_COUNT]; - GLenum _attach_point[SLOT_COUNT]; - GLenum _slot_format[SLOT_COUNT]; - + PT(Texture) _tex[RTP_COUNT]; + GLuint _rb[RTP_COUNT]; + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index e4c5a2608c..07fa836357 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -3024,24 +3024,15 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, TextureContext *tc = tex->prepare_now(get_prepared_objects(), this); nassertv(tc != (TextureContext *)NULL); CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); + apply_texture(tc); if (z >= 0) { // Copy to a cube map face. This doesn't seem to work too well // with CopyTexSubImage2D, so we always use CopyTexImage2D. - GLP(BindTexture)(GL_TEXTURE_CUBE_MAP_ARB, gtc->_index); GLP(CopyTexImage2D)(GL_TEXTURE_CUBE_MAP_POSITIVE_X + z, 0, get_internal_image_format(tex), xo, yo, w, h, 0); - } else { - // If the texture has never been uploaded before, create it. We - // cannot use glCopyTexImage2D to create a texture that may be - // larger than the screen, so use glTexImage2D with arbitrary - // data. - GLP(BindTexture)(GL_TEXTURE_2D, gtc->_index); - upload_blank_image(tex, gtc); - - // Copy the pixel data from the frame buffer. GLP(CopyTexSubImage2D)(GL_TEXTURE_2D, 0, 0, 0, xo, yo, w, h); } @@ -6375,11 +6366,14 @@ bool CLP(GraphicsStateGuardian):: upload_texture(CLP(TextureContext) *gtc) { Texture *tex = gtc->get_texture(); CPTA_uchar image = tex->get_ram_image(); - if (image.is_null()) { - return false; - } - Texture::CompressionMode image_compression = tex->get_ram_image_compression(); + Texture::CompressionMode image_compression; + if (image.is_null()) { + image_compression = Texture::CM_off; + } else { + image_compression = tex->get_ram_image_compression(); + } + int width = tex->get_x_size(); int height = tex->get_y_size(); int depth = tex->get_z_size(); @@ -6409,71 +6403,75 @@ upload_texture(CLP(TextureContext) *gtc) { return false; } - int texel_size = tex->get_num_components() * tex->get_component_width(); + if (!image.is_null()) { - // If it doesn't fit, we have to reduce it on-the-fly. This is kind - // of expensive and it doesn't look great; it would have been better - // if the user had specified max-texture-dimension to reduce the - // texture at load time instead. Of course, the user doesn't always - // know ahead of time what the hardware limits are. - if (max_dimension > 0 && image_compression == Texture::CM_off) { - if (width > max_dimension) { - int byte_chunk = texel_size; - int stride = 1; - int new_width = width; - while (new_width > max_dimension) { - stride <<= 1; - new_width >>= 1; + // If it doesn't fit, we have to reduce it on-the-fly. This is kind + // of expensive and it doesn't look great; it would have been better + // if the user had specified max-texture-dimension to reduce the + // texture at load time instead. Of course, the user doesn't always + // know ahead of time what the hardware limits are. + if (max_dimension > 0 && image_compression == Texture::CM_off) { + if (width > max_dimension) { + int texel_size = tex->get_num_components() * tex->get_component_width(); + int byte_chunk = texel_size; + int stride = 1; + int new_width = width; + while (new_width > max_dimension) { + stride <<= 1; + new_width >>= 1; + } + GLCAT.info() + << "Reducing width of " << tex->get_name() + << " from " << width << " to " << new_width << "\n"; + image = reduce_image(image, byte_chunk, stride); + width = new_width; } - GLCAT.info() - << "Reducing width of " << tex->get_name() - << " from " << width << " to " << new_width << "\n"; - image = reduce_image(image, byte_chunk, stride); - width = new_width; - } - if (height > max_dimension) { - int byte_chunk = width * texel_size; - int stride = 1; - int new_height = height; - while (new_height > max_dimension) { - stride <<= 1; - new_height >>= 1; + if (height > max_dimension) { + int texel_size = tex->get_num_components() * tex->get_component_width(); + int byte_chunk = width * texel_size; + int stride = 1; + int new_height = height; + while (new_height > max_dimension) { + stride <<= 1; + new_height >>= 1; + } + GLCAT.info() + << "Reducing height of " << tex->get_name() + << " from " << height << " to " << new_height << "\n"; + image = reduce_image(image, byte_chunk, stride); + height = new_height; } - GLCAT.info() - << "Reducing height of " << tex->get_name() - << " from " << height << " to " << new_height << "\n"; - image = reduce_image(image, byte_chunk, stride); - height = new_height; - } - if (depth > max_dimension) { - int byte_chunk = height * width * texel_size; - int stride = 1; - int new_depth = depth; - while (new_depth > max_dimension) { - stride <<= 1; - new_depth >>= 1; + if (depth > max_dimension) { + int texel_size = tex->get_num_components() * tex->get_component_width(); + int byte_chunk = height * width * texel_size; + int stride = 1; + int new_depth = depth; + while (new_depth > max_dimension) { + stride <<= 1; + new_depth >>= 1; + } + GLCAT.info() + << "Reducing depth of " << tex->get_name() + << " from " << depth << " to " << new_depth << "\n"; + image = reduce_image(image, byte_chunk, stride); + depth = new_depth; } - GLCAT.info() - << "Reducing depth of " << tex->get_name() - << " from " << depth << " to " << new_depth << "\n"; - image = reduce_image(image, byte_chunk, stride); - depth = new_depth; } - } - - if (!_supports_bgr) { - // If the GL doesn't claim to support BGR, we may have to reverse - // the component ordering of the image. - image = fix_component_ordering(image, external_format, tex); - } + + if (!_supports_bgr) { + // If the GL doesn't claim to support BGR, we may have to reverse + // the component ordering of the image. + image = fix_component_ordering(image, external_format, tex); + } #ifndef NDEBUG - if (image_compression == Texture::CM_off) { - int wanted_size = - compute_gl_image_size(width, height, depth, external_format, component_type); - nassertr(wanted_size == (int)image.size(), false); - } + if (image_compression == Texture::CM_off) { + int wanted_size = + compute_gl_image_size(width, height, depth, external_format, component_type); + nassertr(wanted_size == (int)image.size(), false); + } #endif // NDEBUG + } GLP(PixelStorei)(GL_UNPACK_ALIGNMENT, 1); @@ -6541,7 +6539,9 @@ upload_texture(CLP(TextureContext) *gtc) { gtc->_depth = depth; #ifdef DO_PSTATS - gtc->update_data_size_bytes(get_texture_memory_size(tex)); + if (!image.is_null()) { + gtc->update_data_size_bytes(get_texture_memory_size(tex)); + } #endif report_my_gl_errors(); @@ -6552,59 +6552,6 @@ upload_texture(CLP(TextureContext) *gtc) { return false; } -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::upload_blank_image -// Access: Private -// Description: Uploads a blank, non-mipmapped image to the specified -// texture object. This is usually used to prepare the -// texture for render-to-texture operations. -//////////////////////////////////////////////////////////////////// -bool CLP(GraphicsStateGuardian):: -upload_blank_image(Texture *tex, CLP(TextureContext) *gtc) - -{ - GLint internal_format = get_internal_image_format(tex); - - if ((gtc->_already_applied == false)|| - (gtc->_internal_format != internal_format)|| - (gtc->_width != tex->get_x_size())|| - (gtc->_height != tex->get_y_size())|| - (gtc->_depth != 1)) { - - GLP(BindTexture)(GL_TEXTURE_2D, gtc->_index); - - char *image = new char[tex->get_x_size() * tex->get_y_size()]; - memset(image, 128, tex->get_x_size() * tex->get_y_size()); - - switch (tex->get_format()) { - case Texture::F_depth_component: - GLP(TexImage2D)(GL_TEXTURE_2D, 0, internal_format, - tex->get_x_size(), tex->get_y_size(), 0, - GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, image); - break; - case Texture::F_stencil_index: - GLP(TexImage2D)(GL_TEXTURE_2D, 0, internal_format, - tex->get_x_size(), tex->get_y_size(), 0, - GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, image); - break; - default: - GLP(TexImage2D)(GL_TEXTURE_2D, 0, internal_format, - tex->get_x_size(), tex->get_y_size(), 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, image); - break; - } - - delete image; - - gtc->_already_applied = true; - gtc->_internal_format = internal_format; - gtc->_width = tex->get_x_size(); - gtc->_height = tex->get_y_size(); - gtc->_depth = 1; - } - - return true; -} //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::upload_texture_image @@ -6622,7 +6569,7 @@ upload_texture_image(CLP(TextureContext) *gtc, Texture::CompressionMode image_compression) { // Make sure the error stack is cleared out before we begin. report_my_gl_errors(); - + if (target == GL_NONE) { // Unsupported target (e.g. 3-d texturing on GL 1.1). return false; @@ -6633,6 +6580,7 @@ upload_texture_image(CLP(TextureContext) *gtc, PStatTimer timer(_load_texture_pcollector); Texture *tex = gtc->get_texture(); + CPTA_uchar image = tex->get_ram_image(); if (GLCAT.is_debug()) { if (image_compression != Texture::CM_off) { @@ -6644,33 +6592,11 @@ upload_texture_image(CLP(TextureContext) *gtc, } } - int num_ram_mipmap_levels = 1; + int num_ram_mipmap_levels = 0; bool load_ram_mipmaps = false; - if (uses_mipmaps) { - num_ram_mipmap_levels = tex->get_num_ram_mipmap_images(); - - if (num_ram_mipmap_levels == 1) { - // No RAM mipmap levels available. Should we generate some? - if (!_supports_generate_mipmap || - (!auto_generate_mipmaps && image_compression == Texture::CM_off)) { - // Yes, the GL won't generate them, so we need to. - tex->generate_ram_mipmap_images(); - num_ram_mipmap_levels = tex->get_num_ram_mipmap_images(); - } - } - - if (num_ram_mipmap_levels != 1) { - // We will load the mipmap levels from RAM. Don't ask the GL to - // generate them. - if (_supports_generate_mipmap) { - GLP(TexParameteri)(target, GL_GENERATE_MIPMAP, false); - } - load_ram_mipmaps = true; - - } else { - // We don't have mipmap levels in RAM. Ask the GL to generate - // them if it can. + if (image.is_null()) { + if (uses_mipmaps) { if (_supports_generate_mipmap) { GLP(TexParameteri)(target, GL_GENERATE_MIPMAP, true); } else { @@ -6679,10 +6605,46 @@ upload_texture_image(CLP(TextureContext) *gtc, uses_mipmaps = false; } } + } else { + num_ram_mipmap_levels = 1; + if (uses_mipmaps) { + num_ram_mipmap_levels = tex->get_num_ram_mipmap_images(); + + if (num_ram_mipmap_levels == 1) { + // No RAM mipmap levels available. Should we generate some? + if (!_supports_generate_mipmap || + (!auto_generate_mipmaps && image_compression == Texture::CM_off)) { + // Yes, the GL won't generate them, so we need to. + tex->generate_ram_mipmap_images(); + num_ram_mipmap_levels = tex->get_num_ram_mipmap_images(); + } + } + + if (num_ram_mipmap_levels != 1) { + // We will load the mipmap levels from RAM. Don't ask the GL to + // generate them. + if (_supports_generate_mipmap) { + GLP(TexParameteri)(target, GL_GENERATE_MIPMAP, false); + } + load_ram_mipmaps = true; + + } else { + // We don't have mipmap levels in RAM. Ask the GL to generate + // them if it can. + if (_supports_generate_mipmap) { + GLP(TexParameteri)(target, GL_GENERATE_MIPMAP, true); + } else { + // If it can't, do without mipmaps. + GLP(TexParameteri)(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + uses_mipmaps = false; + } + } + } } - + int highest_level = 0; - + + if (!gtc->_already_applied || gtc->_internal_format != internal_format || gtc->_width != width || @@ -6690,6 +6652,24 @@ upload_texture_image(CLP(TextureContext) *gtc, gtc->_depth != depth) { // We need to reload a new image. + if (num_ram_mipmap_levels == 0) { + int *blank_image = new int[width * height]; + int color = 0xFF808080; + switch (z) { + case 0: color = 0xFF0000FF; break; + case 1: color = 0xFF00FF00; break; + case 2: color = 0xFFFF0000; break; + case 3: color = 0xFF00FFFF; break; + case 4: color = 0xFFFFFF00; break; + case 5: color = 0xFFFF00FF; break; + } + for (int i=0; iget_ram_mipmap_image(n); if (image == (const unsigned char *)NULL) { diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index c3a951e854..ae000b7c79 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -274,7 +274,6 @@ protected: void specify_texture(Texture *tex); void apply_texture(TextureContext *tc); bool upload_texture(CLP(TextureContext) *gtc); - bool upload_blank_image(Texture *tex, CLP(TextureContext) *gtc); bool upload_texture_image(CLP(TextureContext) *gtc, bool uses_mipmaps, GLenum target, GLint internal_format, int width, int height, int depth, @@ -372,8 +371,6 @@ public: bool _supports_draw_range_elements; PFNGLDRAWRANGEELEMENTSPROC _glDrawRangeElements; - bool _supports_depth_texture; - PFNGLTEXIMAGE3DPROC _glTexImage3D; PFNGLTEXSUBIMAGE3DPROC _glTexSubImage3D; diff --git a/panda/src/glxdisplay/glxGraphicsBuffer.cxx b/panda/src/glxdisplay/glxGraphicsBuffer.cxx index 7feb36d993..56f35872a2 100644 --- a/panda/src/glxdisplay/glxGraphicsBuffer.cxx +++ b/panda/src/glxdisplay/glxGraphicsBuffer.cxx @@ -97,6 +97,8 @@ begin_frame(FrameMode mode) { // begin_render_texture(); clear_cube_map_selection(); } + + _gsg()->set_current_properties(&get_fb_properties()); return _gsg->begin_frame(); } @@ -128,21 +130,6 @@ end_frame(FrameMode mode) { } } -//////////////////////////////////////////////////////////////////// -// Function: glxGraphicsBuffer::release_gsg -// Access: Public -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. The window will be -// permanently unable to render; this is normally called -// only just before destroying the window. This should -// only be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void glxGraphicsBuffer:: -release_gsg() { - glXMakeCurrent(_display, None, NULL); - GraphicsBuffer::release_gsg(); -} - //////////////////////////////////////////////////////////////////// // Function: glxGraphicsBuffer::close_buffer // Access: Protected, Virtual @@ -151,6 +138,12 @@ release_gsg() { //////////////////////////////////////////////////////////////////// void glxGraphicsBuffer:: close_buffer() { + if (_gsg != (GraphicsStateGuardian *)NULL) { + glXMakeCurrent(_display, None, NULL); + _gsg.clear(); + _active = false; + } + if (_pbuffer != None) { glXDestroyPbuffer(_display, _pbuffer); _pbuffer = None; diff --git a/panda/src/glxdisplay/glxGraphicsBuffer.h b/panda/src/glxdisplay/glxGraphicsBuffer.h index 4a89702f5c..bee7165d63 100644 --- a/panda/src/glxdisplay/glxGraphicsBuffer.h +++ b/panda/src/glxdisplay/glxGraphicsBuffer.h @@ -45,7 +45,6 @@ public: virtual bool begin_frame(FrameMode mode); virtual void end_frame(FrameMode mode); - virtual void release_gsg(); protected: virtual void close_buffer(); diff --git a/panda/src/glxdisplay/glxGraphicsWindow.cxx b/panda/src/glxdisplay/glxGraphicsWindow.cxx index 0eea2e5497..86955e251f 100644 --- a/panda/src/glxdisplay/glxGraphicsWindow.cxx +++ b/panda/src/glxdisplay/glxGraphicsWindow.cxx @@ -105,20 +105,6 @@ move_pointer(int device, int x, int y) { return true; } -//////////////////////////////////////////////////////////////////// -// Function: glxGraphicsWindow::release_gsg -// Access: Public -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. The window will be -// permanently unable to render; this is normally called -// only just before destroying the window. This should -// only be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void glxGraphicsWindow:: -release_gsg() { - glXMakeCurrent(_display, None, NULL); - GraphicsWindow::release_gsg(); -} //////////////////////////////////////////////////////////////////// // Function: glxGraphicsWindow::begin_frame @@ -157,6 +143,8 @@ begin_frame(FrameMode mode) { // begin_render_texture(); clear_cube_map_selection(); } + + _gsg()->set_current_properties(&get_fb_properties()); return _gsg->begin_frame(); } @@ -375,8 +363,7 @@ process_events() { // In this case, the default case, the app does not intend // to service the request, so we do by closing the window. - // TODO: don't call release_gsg() in the window thread. - release_gsg(); + // TODO: don't release the gsg in the window thread. close_window(); properties.set_open(false); system_changed_properties(properties); @@ -493,6 +480,12 @@ set_properties_now(WindowProperties &properties) { //////////////////////////////////////////////////////////////////// void glxGraphicsWindow:: close_window() { + if (_gsg != (GraphicsStateGuardian *)NULL) { + glXMakeCurrent(_display, None, NULL); + _gsg.clear(); + _active = false; + } + if (_ic != (XIC)NULL) { XDestroyIC(_ic); _ic = (XIC)NULL; diff --git a/panda/src/glxdisplay/glxGraphicsWindow.h b/panda/src/glxdisplay/glxGraphicsWindow.h index fa63ee4205..52a14d5ab3 100644 --- a/panda/src/glxdisplay/glxGraphicsWindow.h +++ b/panda/src/glxdisplay/glxGraphicsWindow.h @@ -41,8 +41,6 @@ public: virtual ~glxGraphicsWindow(); virtual bool move_pointer(int device, int x, int y); - virtual void release_gsg(); - virtual bool begin_frame(FrameMode mode); virtual void end_frame(FrameMode mode); virtual void begin_flip(); diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 59d770cd4c..843a75773b 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -931,6 +931,7 @@ set_ram_image(PTA_uchar image, Texture::CompressionMode compression, //////////////////////////////////////////////////////////////////// void Texture:: clear_ram_image() { + ++_modified; _ram_image_compression = CM_off; _ram_images.clear(); } diff --git a/panda/src/grutil/cardMaker.I b/panda/src/grutil/cardMaker.I index daa557ca4d..5ca228dd2d 100644 --- a/panda/src/grutil/cardMaker.I +++ b/panda/src/grutil/cardMaker.I @@ -60,103 +60,6 @@ set_has_3d_uvs(bool flag) { _has_3d_uvs = flag; } -//////////////////////////////////////////////////////////////////// -// Function: CardMaker::set_uv_range -// Access: Public -// Description: Sets the range of UV's that will be applied to the -// vertices. If set_has_uvs() is true (as it is by -// default), the vertices will be generated with the -// indicated range of UV's, which will be useful if a -// texture is applied. -//////////////////////////////////////////////////////////////////// -INLINE void CardMaker:: -set_uv_range(const TexCoord3f &ll, const TexCoord3f &lr, const TexCoord3f &ur, const TexCoord3f &ul) { - _ll_tex = ll; - _lr_tex = lr; - _ur_tex = ur; - _ul_tex = ul; - _has_uvs = true; - _has_3d_uvs = true; -} - -//////////////////////////////////////////////////////////////////// -// Function: CardMaker::set_uv_range -// Access: Public -// Description: Sets the range of UV's that will be applied to the -// vertices. If set_has_uvs() is true (as it is by -// default), the vertices will be generated with the -// indicated range of UV's, which will be useful if a -// texture is applied. -//////////////////////////////////////////////////////////////////// -INLINE void CardMaker:: -set_uv_range(const TexCoordf &ll, const TexCoordf &lr, const TexCoordf &ur, const TexCoordf &ul) { - _ll_tex.set(ll[0], ll[1], 0.0f); - _lr_tex.set(lr[0], lr[1], 0.0f); - _ur_tex.set(ur[0], ur[1], 0.0f); - _ul_tex.set(ul[0], ul[1], 0.0f); - _has_uvs = true; - _has_3d_uvs = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: CardMaker::set_uv_range -// Access: Public -// Description: Sets the range of UV's that will be applied to the -// vertices. If set_has_uvs() is true (as it is by -// default), the vertices will be generated with the -// indicated range of UV's, which will be useful if a -// texture is applied. -//////////////////////////////////////////////////////////////////// -INLINE void CardMaker:: -set_uv_range(const TexCoordf &ll, const TexCoordf &ur) { - _ll_tex.set(ll[0], ll[1], 0.0f); - _lr_tex.set(ur[0], ll[1], 0.0f); - _ur_tex.set(ur[0], ur[1], 0.0f); - _ul_tex.set(ll[0], ur[1], 0.0f); - _has_uvs = true; - _has_3d_uvs = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: CardMaker::set_uv_range -// Access: Public -// Description: Sets the range of UV's that will be applied to the -// vertices. If set_has_uvs() is true (as it is by -// default), the vertices will be generated with the -// indicated range of UV's, which will be useful if a -// texture is applied. -//////////////////////////////////////////////////////////////////// -INLINE void CardMaker:: -set_uv_range(const LVector4f &x, const LVector4f &y, const LVector4f &z) { - _ll_tex.set(x[0], y[0], z[0]); - _lr_tex.set(x[1], y[1], z[1]); - _ur_tex.set(x[2], y[2], z[2]); - _ul_tex.set(x[3], y[3], z[3]); - _has_uvs = true; - _has_3d_uvs = true; -} - -//////////////////////////////////////////////////////////////////// -// Function: CardMaker::set_uv_range_cube -// Access: Public -// Description: Sets the range of UV's that will be applied to the -// vertices appropriately for a cube-map face. -//////////////////////////////////////////////////////////////////// -INLINE void CardMaker:: -set_uv_range_cube(int face) { - LVector4f varya(-1, 1, 1, -1); - LVector4f varyb(-1, -1, 1, 1); - LVector4f fixed( 1, 1, 1, 1); - switch(face) { - case 0: set_uv_range( fixed, -varyb, varya); break; // positive_x - case 1: set_uv_range(-fixed, -varyb, -varya); break; // negative_x - case 2: set_uv_range(-varya, fixed, varyb); break; // positive_y - case 3: set_uv_range(-varya, -fixed, -varyb); break; // negative_y - case 4: set_uv_range(-varya, -varyb, fixed); break; // positive_z - case 5: set_uv_range( varya, -varyb, -fixed); break; // negative_z - } -} - //////////////////////////////////////////////////////////////////// // Function: CardMaker::set_frame // Access: Public diff --git a/panda/src/grutil/cardMaker.cxx b/panda/src/grutil/cardMaker.cxx index 425075b350..e2e3f53086 100644 --- a/panda/src/grutil/cardMaker.cxx +++ b/panda/src/grutil/cardMaker.cxx @@ -159,6 +159,103 @@ generate() { return gnode.p(); } +//////////////////////////////////////////////////////////////////// +// Function: CardMaker::set_uv_range +// Access: Public +// Description: Sets the range of UV's that will be applied to the +// vertices. If set_has_uvs() is true (as it is by +// default), the vertices will be generated with the +// indicated range of UV's, which will be useful if a +// texture is applied. +//////////////////////////////////////////////////////////////////// +INLINE void CardMaker:: +set_uv_range(const TexCoord3f &ll, const TexCoord3f &lr, const TexCoord3f &ur, const TexCoord3f &ul) { + _ll_tex = ll; + _lr_tex = lr; + _ur_tex = ur; + _ul_tex = ul; + _has_uvs = true; + _has_3d_uvs = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: CardMaker::set_uv_range +// Access: Public +// Description: Sets the range of UV's that will be applied to the +// vertices. If set_has_uvs() is true (as it is by +// default), the vertices will be generated with the +// indicated range of UV's, which will be useful if a +// texture is applied. +//////////////////////////////////////////////////////////////////// +INLINE void CardMaker:: +set_uv_range(const TexCoordf &ll, const TexCoordf &lr, const TexCoordf &ur, const TexCoordf &ul) { + _ll_tex.set(ll[0], ll[1], 0.0f); + _lr_tex.set(lr[0], lr[1], 0.0f); + _ur_tex.set(ur[0], ur[1], 0.0f); + _ul_tex.set(ul[0], ul[1], 0.0f); + _has_uvs = true; + _has_3d_uvs = false; +} + +//////////////////////////////////////////////////////////////////// +// Function: CardMaker::set_uv_range +// Access: Public +// Description: Sets the range of UV's that will be applied to the +// vertices. If set_has_uvs() is true (as it is by +// default), the vertices will be generated with the +// indicated range of UV's, which will be useful if a +// texture is applied. +//////////////////////////////////////////////////////////////////// +INLINE void CardMaker:: +set_uv_range(const TexCoordf &ll, const TexCoordf &ur) { + _ll_tex.set(ll[0], ll[1], 0.0f); + _lr_tex.set(ur[0], ll[1], 0.0f); + _ur_tex.set(ur[0], ur[1], 0.0f); + _ul_tex.set(ll[0], ur[1], 0.0f); + _has_uvs = true; + _has_3d_uvs = false; +} + +//////////////////////////////////////////////////////////////////// +// Function: CardMaker::set_uv_range +// Access: Public +// Description: Sets the range of UV's that will be applied to the +// vertices. If set_has_uvs() is true (as it is by +// default), the vertices will be generated with the +// indicated range of UV's, which will be useful if a +// texture is applied. +//////////////////////////////////////////////////////////////////// +INLINE void CardMaker:: +set_uv_range(const LVector4f &x, const LVector4f &y, const LVector4f &z) { + _ll_tex.set(x[0], y[0], z[0]); + _lr_tex.set(x[1], y[1], z[1]); + _ur_tex.set(x[2], y[2], z[2]); + _ul_tex.set(x[3], y[3], z[3]); + _has_uvs = true; + _has_3d_uvs = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: CardMaker::set_uv_range_cube +// Access: Public +// Description: Sets the range of UV's that will be applied to the +// vertices appropriately for a cube-map face. +//////////////////////////////////////////////////////////////////// +INLINE void CardMaker:: +set_uv_range_cube(int face) { + LVector4f varya(-1, 1, 1, -1); + LVector4f varyb(-1, -1, 1, 1); + LVector4f fixed( 1, 1, 1, 1); + switch(face) { + case 0: set_uv_range( fixed, -varyb, -varya); break; // positive_x + case 1: set_uv_range(-fixed, -varyb, varya); break; // negative_x + case 2: set_uv_range( varya, fixed, varyb); break; // positive_y + case 3: set_uv_range( varya, -fixed, -varyb); break; // negative_y + case 4: set_uv_range( varya, -varyb, fixed); break; // positive_z + case 5: set_uv_range(-varya, -varyb, -fixed); break; // negative_z + } +} + //////////////////////////////////////////////////////////////////// // Function: CardMaker::rescale_source_geometry // Access: Private diff --git a/panda/src/grutil/cardMaker.h b/panda/src/grutil/cardMaker.h index 682379dcd9..1ecad731a4 100644 --- a/panda/src/grutil/cardMaker.h +++ b/panda/src/grutil/cardMaker.h @@ -38,13 +38,14 @@ PUBLISHED: INLINE ~CardMaker(); void reset(); - INLINE void set_uv_range(const TexCoordf &ll, const TexCoordf &ur); - INLINE void set_uv_range(const TexCoordf &ll, const TexCoordf &lr, const TexCoordf &ur, const TexCoordf &ul); - INLINE void set_uv_range(const TexCoord3f &ll, const TexCoord3f &lr, const TexCoord3f &ur, const TexCoord3f &ul); - INLINE void set_uv_range(const LVector4f &x, const LVector4f &y, const LVector4f &z); + void set_uv_range(const TexCoordf &ll, const TexCoordf &ur); + void set_uv_range(const TexCoordf &ll, const TexCoordf &lr, const TexCoordf &ur, const TexCoordf &ul); + void set_uv_range(const TexCoord3f &ll, const TexCoord3f &lr, const TexCoord3f &ur, const TexCoord3f &ul); + void set_uv_range(const LVector4f &x, const LVector4f &y, const LVector4f &z); + void set_uv_range_cube(int face); + INLINE void set_has_uvs(bool flag); INLINE void set_has_3d_uvs(bool flag); - INLINE void set_uv_range_cube(int face); INLINE void set_frame(float left, float right, float bottom, float top); INLINE void set_frame(const LVecBase4f &frame); diff --git a/panda/src/mesadisplay/osMesaGraphicsBuffer.cxx b/panda/src/mesadisplay/osMesaGraphicsBuffer.cxx index b07d9bfb83..f6a846b3ae 100644 --- a/panda/src/mesadisplay/osMesaGraphicsBuffer.cxx +++ b/panda/src/mesadisplay/osMesaGraphicsBuffer.cxx @@ -76,6 +76,7 @@ begin_frame(FrameMode mode) { // begin_render_texture(); clear_cube_map_selection(); } + _gsg->set_current_properties(&get_fb_properties()); return _gsg->begin_frame(); } diff --git a/panda/src/osxdisplay/osxGraphicsBuffer.cxx b/panda/src/osxdisplay/osxGraphicsBuffer.cxx index 6098bc99e2..028ce67405 100644 --- a/panda/src/osxdisplay/osxGraphicsBuffer.cxx +++ b/panda/src/osxdisplay/osxGraphicsBuffer.cxx @@ -82,6 +82,7 @@ begin_frame(FrameMode mode) { // begin_render_texture(); clear_cube_map_selection(); } + _gsg->set_current_properties(&get_fb_properties()); return _gsg->begin_frame(); } @@ -113,20 +114,6 @@ end_frame(FrameMode mode) { clear_cube_map_selection(); } } -//////////////////////////////////////////////////////////////////// -// Function: osxGraphicsBuffer::release_gsg -// Access: Public -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. The window will be -// permanently unable to render; this is normally called -// only just before destroying the window. This should -// only be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void osxGraphicsBuffer:: -release_gsg() { - //osxMakeCurrent(_display, None, NULL); - GraphicsBuffer::release_gsg(); -} //////////////////////////////////////////////////////////////////// // Function: osxGraphicsBuffer::close_buffer @@ -136,7 +123,11 @@ release_gsg() { //////////////////////////////////////////////////////////////////// void osxGraphicsBuffer:: close_buffer() { - + if (_gsg != (GraphicsStateGuardian *)NULL) { + //osxMakeCurrent(_display, None, NULL); + _gsg.clear(); + _active = false; + } _is_valid = false; } diff --git a/panda/src/osxdisplay/osxGraphicsBuffer.h b/panda/src/osxdisplay/osxGraphicsBuffer.h index aeff202c84..f561dd7fa5 100644 --- a/panda/src/osxdisplay/osxGraphicsBuffer.h +++ b/panda/src/osxdisplay/osxGraphicsBuffer.h @@ -45,8 +45,6 @@ public: virtual bool begin_frame(FrameMode mode); virtual void end_frame(FrameMode mode); - virtual void release_gsg(); - protected: virtual void close_buffer(); diff --git a/panda/src/osxdisplay/osxGraphicsWindow.cxx b/panda/src/osxdisplay/osxGraphicsWindow.cxx index a26b92e1b9..a00512ff72 100644 --- a/panda/src/osxdisplay/osxGraphicsWindow.cxx +++ b/panda/src/osxdisplay/osxGraphicsWindow.cxx @@ -568,8 +568,8 @@ bool osxGraphicsWindow::begin_frame(FrameMode mode) - _gsg->reset_if_new(); - + _gsg->reset_if_new(); + _gsg->set_current_properties(&get_fb_properties()); return _gsg->begin_frame(); } @@ -590,22 +590,6 @@ void osxGraphicsWindow::end_frame(FrameMode mode) trigger_flip(); } -//////////////////////////////////////////////////////////////////// -// Function: osxGraphicsWindow::release_gsg -// Access: Public, Virtual -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. The window will be -// permanently unable to render; this is normally called -// only just before destroying the window. This should -// only be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void osxGraphicsWindow::release_gsg() -{ - ReleaseSystemResources(); - - GraphicsWindow::release_gsg(); -} - //////////////////////////////////////////////////////////////////// // Function: osxGraphicsWindow::begin_flip // Access: Public, Virtual @@ -632,11 +616,12 @@ void osxGraphicsWindow::begin_flip() // Description: Closes the window right now. Called from the window // thread. //////////////////////////////////////////////////////////////////// -void osxGraphicsWindow::close_window() { - - ReleaseSystemResources(); - GraphicsWindow::close_window(); - +void osxGraphicsWindow::close_window() +{ + ReleaseSystemResources(); + _gsg.clear(); + _active = false; + GraphicsWindow::close_window(); } ////////////////////////////////////////////////////////// diff --git a/panda/src/osxdisplay/osxGraphicsWindow.h b/panda/src/osxdisplay/osxGraphicsWindow.h index b8836ad4b6..8fa567f52e 100644 --- a/panda/src/osxdisplay/osxGraphicsWindow.h +++ b/panda/src/osxdisplay/osxGraphicsWindow.h @@ -50,7 +50,6 @@ public: virtual bool move_pointer(int device, int x, int y); // virtual void make_current(); - virtual void release_gsg(); virtual bool begin_frame(FrameMode mode); virtual void end_frame(FrameMode mode); virtual void begin_flip(); diff --git a/panda/src/wgldisplay/wglGraphicsBuffer.cxx b/panda/src/wgldisplay/wglGraphicsBuffer.cxx index 8c02d05328..92dc7d055a 100644 --- a/panda/src/wgldisplay/wglGraphicsBuffer.cxx +++ b/panda/src/wgldisplay/wglGraphicsBuffer.cxx @@ -91,13 +91,15 @@ begin_frame(FrameMode mode) { } } } - + wglMakeCurrent(_pbuffer_dc, wglgsg->get_context(_pbuffer_dc)); if (mode == FM_render) { begin_render_texture(); clear_cube_map_selection(); } + + _gsg->set_current_properties(&get_fb_properties()); return _gsg->begin_frame(); } @@ -228,20 +230,6 @@ select_cube_map(int cube_map_index) { wglgsg->_wglSetPbufferAttribARB(_pbuffer, iattrib_list); } -//////////////////////////////////////////////////////////////////// -// Function: wglGraphicsBuffer::release_gsg -// Access: Public, Virtual -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. The window will be -// permanently unable to render; this is normally called -// only just before destroying the window. This should -// only be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void wglGraphicsBuffer:: -release_gsg() { - GraphicsBuffer::release_gsg(); -} - //////////////////////////////////////////////////////////////////// // Function: wglGraphicsBuffer::process_events // Access: Public, Virtual @@ -284,7 +272,11 @@ close_buffer() { if (_pbuffer) { wglgsg->_wglDestroyPbufferARB(_pbuffer); } + + _gsg.clear(); + _active = false; } + _pbuffer_dc = 0; _pbuffer = 0; diff --git a/panda/src/wgldisplay/wglGraphicsBuffer.h b/panda/src/wgldisplay/wglGraphicsBuffer.h index 82e2f1d620..1a89432795 100644 --- a/panda/src/wgldisplay/wglGraphicsBuffer.h +++ b/panda/src/wgldisplay/wglGraphicsBuffer.h @@ -53,7 +53,6 @@ public: virtual void end_frame(FrameMode mode); virtual void select_cube_map(int cube_map_index); - virtual void release_gsg(); virtual void process_events(); diff --git a/panda/src/wgldisplay/wglGraphicsWindow.cxx b/panda/src/wgldisplay/wglGraphicsWindow.cxx index 5df37db6c9..ad616a87a4 100644 --- a/panda/src/wgldisplay/wglGraphicsWindow.cxx +++ b/panda/src/wgldisplay/wglGraphicsWindow.cxx @@ -168,7 +168,7 @@ begin_frame(FrameMode mode) { if (_gsg == (GraphicsStateGuardian *)NULL) { return false; } - + wglGraphicsStateGuardian *wglgsg; DCAST_INTO_R(wglgsg, _gsg, false); @@ -181,6 +181,7 @@ begin_frame(FrameMode mode) { clear_cube_map_selection(); } + _gsg->set_current_properties(&get_fb_properties()); return _gsg->begin_frame(); } @@ -213,21 +214,6 @@ end_frame(FrameMode mode) { } } -//////////////////////////////////////////////////////////////////// -// Function: wglGraphicsWindow::release_gsg -// Access: Public, Virtual -// Description: Releases the current GSG pointer, if it is currently -// held, and resets the GSG to NULL. The window will be -// permanently unable to render; this is normally called -// only just before destroying the window. This should -// only be called from within the draw thread. -//////////////////////////////////////////////////////////////////// -void wglGraphicsWindow:: -release_gsg() { - wglMakeCurrent(_hdc, NULL); - GraphicsWindow::release_gsg(); -} - //////////////////////////////////////////////////////////////////// // Function: wglGraphicsWindow::begin_flip // Access: Public, Virtual @@ -268,6 +254,11 @@ begin_flip() { //////////////////////////////////////////////////////////////////// void wglGraphicsWindow:: close_window() { + if (_gsg != (GraphicsStateGuardian *)NULL) { + wglMakeCurrent(_hdc, NULL); + _gsg.clear(); + _active = false; + } ReleaseDC(_hWnd, _hdc); _hdc = (HDC)0; WinGraphicsWindow::close_window(); diff --git a/panda/src/wgldisplay/wglGraphicsWindow.h b/panda/src/wgldisplay/wglGraphicsWindow.h index f50aaaa71c..3bc2401a3c 100644 --- a/panda/src/wgldisplay/wglGraphicsWindow.h +++ b/panda/src/wgldisplay/wglGraphicsWindow.h @@ -40,7 +40,6 @@ public: virtual bool begin_frame(FrameMode mode); virtual void end_frame(FrameMode mode); - virtual void release_gsg(); virtual void begin_flip(); protected: