Browse Source

The buffer flip should be performed in end_flip(), not in begin_flip(). This long-existing mistake caused double-flips with parasite buffers in effect.

David Rose 14 years ago
parent
commit
d743dc8a55

+ 17 - 9
panda/src/display/graphicsEngine.cxx

@@ -1624,20 +1624,28 @@ process_events(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
 ////////////////////////////////////////////////////////////////////
 void GraphicsEngine::
 flip_windows(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
-  Windows::const_iterator wi;
-  for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
-    GraphicsOutput *win = (*wi);
+  size_t num_windows = wlist.size();
+  size_t warray_size = num_windows * sizeof(GraphicsOutput *);
+  size_t warray_count = 0;
+  GraphicsOutput **warray = (GraphicsOutput **)alloca(warray_size);
+
+  size_t i;
+  for (i = 0; i < num_windows; ++i) {
+    GraphicsOutput *win = wlist[i];
     if (win->flip_ready()) {
+      nassertv(warray_count < num_windows);
+      warray[warray_count] = win;
+      ++warray_count;
+
       PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
       win->begin_flip();
     }
   }
-  for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
-    GraphicsOutput *win = (*wi);
-    if (win->flip_ready()) {
-      PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
-      win->end_flip();
-    }
+
+  for (i = 0; i < warray_count; ++i) {
+    GraphicsOutput *win = warray[i];
+    PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
+    win->end_flip();
   }
 }
 

+ 8 - 11
panda/src/egldisplay/eglGraphicsWindow.cxx

@@ -212,22 +212,18 @@ end_frame(FrameMode mode, Thread *current_thread) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: eglGraphicsWindow::begin_flip
+//     Function: eglGraphicsWindow::end_flip
 //       Access: Public, Virtual
 //  Description: This function will be called within the draw thread
-//               after end_frame() has been called on all windows, to
-//               initiate the exchange of the front and back buffers.
+//               after begin_flip() has been called on all windows, to
+//               finish the exchange of the front and back buffers.
 //
-//               This should instruct the window to prepare for the
-//               flip at the next video sync, but it should not wait.
-//
-//               We have the two separate functions, begin_flip() and
-//               end_flip(), to make it easier to flip all of the
-//               windows at the same time.
+//               This should cause the window to wait for the flip, if
+//               necessary.
 ////////////////////////////////////////////////////////////////////
 void eglGraphicsWindow::
-begin_flip() {
-  if (_gsg != (GraphicsStateGuardian *)NULL) {
+end_flip() {
+  if (_gsg != (GraphicsStateGuardian *)NULL && _flip_ready) {
 
     // It doesn't appear to be necessary to ensure the graphics
     // context is current before flipping the windows, and insisting
@@ -238,6 +234,7 @@ begin_flip() {
     LightReMutexHolder holder(eglGraphicsPipe::_x_mutex);
     eglSwapBuffers(_egl_display, _egl_surface);
   }
+  GraphicsWindow::end_flip();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/egldisplay/eglGraphicsWindow.h

@@ -41,7 +41,7 @@ public:
   virtual bool move_pointer(int device, int x, int y);
   virtual bool begin_frame(FrameMode mode, Thread *current_thread);
   virtual void end_frame(FrameMode mode, Thread *current_thread);
-  virtual void begin_flip();
+  virtual void end_flip();
 
   virtual void process_events();
   virtual void set_properties_now(WindowProperties &properties);

+ 8 - 11
panda/src/glxdisplay/glxGraphicsWindow.cxx

@@ -104,22 +104,18 @@ begin_frame(FrameMode mode, Thread *current_thread) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: glxGraphicsWindow::begin_flip
+//     Function: glxGraphicsWindow::end_flip
 //       Access: Public, Virtual
 //  Description: This function will be called within the draw thread
-//               after end_frame() has been called on all windows, to
-//               initiate the exchange of the front and back buffers.
+//               after begin_flip() has been called on all windows, to
+//               finish the exchange of the front and back buffers.
 //
-//               This should instruct the window to prepare for the
-//               flip at the next video sync, but it should not wait.
-//
-//               We have the two separate functions, begin_flip() and
-//               end_flip(), to make it easier to flip all of the
-//               windows at the same time.
+//               This should cause the window to wait for the flip, if
+//               necessary.
 ////////////////////////////////////////////////////////////////////
 void glxGraphicsWindow::
-begin_flip() {
-  if (_gsg != (GraphicsStateGuardian *)NULL) {
+end_flip() {
+  if (_gsg != (GraphicsStateGuardian *)NULL && _flip_ready) {
 
     // It doesn't appear to be necessary to ensure the graphics
     // context is current before flipping the windows, and insisting
@@ -130,6 +126,7 @@ begin_flip() {
     LightReMutexHolder holder(glxGraphicsPipe::_x_mutex);
     glXSwapBuffers(_display, _xwindow);
   }
+  GraphicsWindow::end_flip();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/glxdisplay/glxGraphicsWindow.h

@@ -39,7 +39,7 @@ public:
   virtual ~glxGraphicsWindow() {};
 
   virtual bool begin_frame(FrameMode mode, Thread *current_thread);
-  virtual void begin_flip();
+  virtual void end_flip();
 
 protected:
   virtual void close_window();

+ 1 - 1
panda/src/grutil/pfmFile.cxx

@@ -602,7 +602,7 @@ merge(const PfmFile &other) {
 ////////////////////////////////////////////////////////////////////
 PT(BoundingHexahedron) PfmFile::
 compute_planar_bounds(PN_stdfloat point_dist, PN_stdfloat sample_radius) const {
-  return compute_planar_bounds(LPoint2::zero(), point_dist, sample_radius, false);
+  return compute_planar_bounds(LPoint2(0.5, 0.5), point_dist, sample_radius, false);
 }
 
 

+ 12 - 10
panda/src/tinydisplay/tinySDLGraphicsWindow.cxx

@@ -111,21 +111,22 @@ end_frame(FrameMode mode, Thread *current_thread) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: TinySDLGraphicsWindow::begin_flip
+//     Function: TinySDLGraphicsWindow::end_flip
 //       Access: Public, Virtual
 //  Description: This function will be called within the draw thread
-//               after end_frame() has been called on all windows, to
-//               initiate the exchange of the front and back buffers.
+//               after begin_flip() has been called on all windows, to
+//               finish the exchange of the front and back buffers.
 //
-//               This should instruct the window to prepare for the
-//               flip at the next video sync, but it should not wait.
-//
-//               We have the two separate functions, begin_flip() and
-//               end_flip(), to make it easier to flip all of the
-//               windows at the same time.
+//               This should cause the window to wait for the flip, if
+//               necessary.
 ////////////////////////////////////////////////////////////////////
 void TinySDLGraphicsWindow::
-begin_flip() {
+end_flip() {
+  if (!_flip_ready) {
+    GraphicsWindow::end_flip();
+    return;
+  }
+
   int fb_xsize = get_fb_x_size();
   int fb_ysize = get_fb_y_size();
 
@@ -154,6 +155,7 @@ begin_flip() {
   }
 
   SDL_Flip(_screen);
+  GraphicsWindow::end_flip();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/tinydisplay/tinySDLGraphicsWindow.h

@@ -42,7 +42,7 @@ public:
 
   virtual bool begin_frame(FrameMode mode, Thread *current_thread);
   virtual void end_frame(FrameMode mode, Thread *current_thread);
-  virtual void begin_flip();
+  virtual void end_flip();
 
   virtual void process_events();
   virtual void set_properties_now(WindowProperties &properties);

+ 12 - 10
panda/src/tinydisplay/tinyWinGraphicsWindow.cxx

@@ -116,21 +116,22 @@ end_frame(FrameMode mode, Thread *current_thread) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: TinyWinGraphicsWindow::begin_flip
+//     Function: TinyWinGraphicsWindow::end_flip
 //       Access: Public, Virtual
 //  Description: This function will be called within the draw thread
-//               after end_frame() has been called on all windows, to
-//               initiate the exchange of the front and back buffers.
+//               after begin_flip() has been called on all windows, to
+//               finish the exchange of the front and back buffers.
 //
-//               This should instruct the window to prepare for the
-//               flip at the next video sync, but it should not wait.
-//
-//               We have the two separate functions, begin_flip() and
-//               end_flip(), to make it easier to flip all of the
-//               windows at the same time.
+//               This should cause the window to wait for the flip, if
+//               necessary.
 ////////////////////////////////////////////////////////////////////
 void TinyWinGraphicsWindow::
-begin_flip() {
+end_flip() {
+  if (!_flip_ready) {
+    GraphicsWindow::end_flip();
+    return;
+  }
+
   HBITMAP bm = CreateCompatibleBitmap(_hdc, _frame_buffer->xsize, _frame_buffer->ysize);
   HDC bmdc = CreateCompatibleDC(_hdc);
   SelectObject(bmdc, bm);
@@ -155,6 +156,7 @@ begin_flip() {
   DeleteDC(bmdc);
   DeleteObject(bm);
   GdiFlush();
+  GraphicsWindow::end_flip();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/tinydisplay/tinyWinGraphicsWindow.h

@@ -41,7 +41,7 @@ public:
   virtual bool begin_frame(FrameMode mode, Thread *current_thread);
   virtual void end_frame(FrameMode mode, Thread *current_thread);
 
-  virtual void begin_flip();
+  virtual void end_flip();
   virtual bool supports_pixel_zoom() const;
 
 protected:

+ 9 - 11
panda/src/tinydisplay/tinyXGraphicsWindow.cxx

@@ -140,22 +140,19 @@ end_frame(FrameMode mode, Thread *current_thread) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: TinyXGraphicsWindow::begin_flip
+//     Function: TinyXGraphicsWindow::end_flip
 //       Access: Public, Virtual
 //  Description: This function will be called within the draw thread
-//               after end_frame() has been called on all windows, to
-//               initiate the exchange of the front and back buffers.
+//               after begin_flip() has been called on all windows, to
+//               finish the exchange of the front and back buffers.
 //
-//               This should instruct the window to prepare for the
-//               flip at the next video sync, but it should not wait.
-//
-//               We have the two separate functions, begin_flip() and
-//               end_flip(), to make it easier to flip all of the
-//               windows at the same time.
+//               This should cause the window to wait for the flip, if
+//               necessary.
 ////////////////////////////////////////////////////////////////////
 void TinyXGraphicsWindow::
-begin_flip() {
-  if (_xwindow == (X11_Window)NULL) {
+end_flip() {
+  if (_xwindow == (X11_Window)NULL || !_flip_ready) {
+    GraphicsWindow::end_flip();
     return;
   }
 
@@ -177,6 +174,7 @@ begin_flip() {
   XPutImage(_display, _xwindow, _gc, _ximage, 0, 0, 0, 0,
             _full_frame_buffer->xsize, _full_frame_buffer->ysize);
   XFlush(_display);
+  GraphicsWindow::end_flip();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/tinydisplay/tinyXGraphicsWindow.h

@@ -41,7 +41,7 @@ public:
 
   virtual bool begin_frame(FrameMode mode, Thread *current_thread);
   virtual void end_frame(FrameMode mode, Thread *current_thread);
-  virtual void begin_flip();
+  virtual void end_flip();
   virtual bool supports_pixel_zoom() const;
 
   virtual void process_events();

+ 28 - 13
panda/src/wgldisplay/wglGraphicsWindow.cxx

@@ -138,19 +138,6 @@ end_frame(FrameMode mode, Thread *current_thread) {
 ////////////////////////////////////////////////////////////////////
 void wglGraphicsWindow::
 begin_flip() {
-  if (_hdc) {
-    // The documentation on SwapBuffers() is not at all clear on
-    // whether the GL context needs to be current before it can be
-    // called.  Empirically, it appears that it is not necessary in
-    // many cases, but it definitely is necessary at least in the case
-    // of Mesa on Windows.
-    wglGraphicsStateGuardian *wglgsg;
-    DCAST_INTO_V(wglgsg, _gsg);
-    HGLRC context = wglgsg->get_context(_hdc);
-    nassertv(context);
-    wglGraphicsPipe::wgl_make_current(_hdc, context, &_make_current_pcollector);
-    SwapBuffers(_hdc);
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -184,6 +171,34 @@ ready_flip() {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: wglGraphicsWindow::end_flip
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after begin_flip() has been called on all windows, to
+//               finish the exchange of the front and back buffers.
+//
+//               This should cause the window to wait for the flip, if
+//               necessary.
+////////////////////////////////////////////////////////////////////
+void wglGraphicsWindow::
+end_flip() {
+  if (_hdc != NULL && _flip_ready) {
+    // The documentation on SwapBuffers() is not at all clear on
+    // whether the GL context needs to be current before it can be
+    // called.  Empirically, it appears that it is not necessary in
+    // many cases, but it definitely is necessary at least in the case
+    // of Mesa on Windows.
+    wglGraphicsStateGuardian *wglgsg;
+    DCAST_INTO_V(wglgsg, _gsg);
+    HGLRC context = wglgsg->get_context(_hdc);
+    nassertv(context);
+    wglGraphicsPipe::wgl_make_current(_hdc, context, &_make_current_pcollector);
+    SwapBuffers(_hdc);
+  }
+  WinGraphicsWindow::end_flip();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: wglGraphicsWindow::close_window
 //       Access: Protected, Virtual

+ 1 - 0
panda/src/wgldisplay/wglGraphicsWindow.h

@@ -39,6 +39,7 @@ public:
 
   virtual void begin_flip();
   virtual void ready_flip();
+  virtual void end_flip();
 
 protected:
   virtual void close_window();