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.

This commit is contained in:
David Rose 2012-02-10 18:21:55 +00:00
parent c9138166fa
commit d743dc8a55
14 changed files with 101 additions and 81 deletions

View File

@ -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();
}
}

View File

@ -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();
}
////////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -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();
}
////////////////////////////////////////////////////////////////////

View File

@ -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();

View File

@ -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);
}

View File

@ -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();
}
////////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -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();
}
////////////////////////////////////////////////////////////////////

View File

@ -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:

View File

@ -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();
}
////////////////////////////////////////////////////////////////////

View File

@ -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();

View File

@ -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

View File

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