From bbbe8cbf9f33ce20e0be920ec815eeda3caf455a Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 13 Feb 2004 00:55:48 +0000 Subject: [PATCH] add show-pbuffers --- panda/src/wgldisplay/config_wgldisplay.cxx | 6 + panda/src/wgldisplay/config_wgldisplay.h | 1 + panda/src/wgldisplay/wglGraphicsBuffer.cxx | 148 +++++++++++++++++++-- panda/src/wgldisplay/wglGraphicsBuffer.h | 3 + 4 files changed, 150 insertions(+), 8 deletions(-) diff --git a/panda/src/wgldisplay/config_wgldisplay.cxx b/panda/src/wgldisplay/config_wgldisplay.cxx index f5fa84822f..e4116e8c00 100644 --- a/panda/src/wgldisplay/config_wgldisplay.cxx +++ b/panda/src/wgldisplay/config_wgldisplay.cxx @@ -67,3 +67,9 @@ bool gl_force_invalid = config_wgldisplay.GetBool("gl-force-invalid", false); // requested. It only affects fullscreen windows. bool gl_do_vidmemsize_check = config_wgldisplay.GetBool("gl-do-vidmemsize-check", true); +// For now, we fake offscreen rendering without using the +// poorly-supported pbuffer extension; we simply render into an +// invisible window. Some drivers don't like that, so for these +// drivers set show-pbuffers to true to force the window to be visible +// so you can at least get some work done. +bool show_pbuffers = config_wgldisplay.GetBool("show-pbuffers", false); diff --git a/panda/src/wgldisplay/config_wgldisplay.h b/panda/src/wgldisplay/config_wgldisplay.h index 434721c765..7443301fd1 100644 --- a/panda/src/wgldisplay/config_wgldisplay.h +++ b/panda/src/wgldisplay/config_wgldisplay.h @@ -29,5 +29,6 @@ extern EXPCL_PANDAGL void init_libwgldisplay(); extern int gl_force_pixfmt; extern bool gl_force_invalid; extern bool gl_do_vidmemsize_check; +extern bool show_pbuffers; #endif diff --git a/panda/src/wgldisplay/wglGraphicsBuffer.cxx b/panda/src/wgldisplay/wglGraphicsBuffer.cxx index fb8c46b88d..043cfaa559 100644 --- a/panda/src/wgldisplay/wglGraphicsBuffer.cxx +++ b/panda/src/wgldisplay/wglGraphicsBuffer.cxx @@ -103,20 +103,45 @@ void wglGraphicsBuffer:: begin_flip() { if (_gsg != (GraphicsStateGuardian *)NULL) { make_current(); + glFinish(); if (has_texture()) { // Use glCopyTexImage2D to copy the framebuffer to the texture. // This appears to be the only way to "render to a texture" in // OpenGL; there's no interface to make the offscreen buffer // itself be a texture. - DisplayRegion dr(_x_size, _y_size); - get_texture()->copy(_gsg, &dr, _gsg->get_render_buffer(RenderBuffer::T_back)); + PT(DisplayRegion) dr = make_scratch_display_region(_x_size, _y_size); + get_texture()->copy(_gsg, dr, _gsg->get_render_buffer(RenderBuffer::T_back)); } SwapBuffers(_window_dc); } } +//////////////////////////////////////////////////////////////////// +// Function: wglGraphicsBuffer::process_events +// Access: Public, Virtual +// Description: Do whatever processing is necessary to ensure that +// the window responds to user events. Also, honor any +// requests recently made via request_properties() +// +// This function is called only within the window +// thread. +//////////////////////////////////////////////////////////////////// +void wglGraphicsBuffer:: +process_events() { + GraphicsBuffer::process_events(); + + MSG msg; + + // Handle all the messages on the queue in a row. Some of these + // might be for another window, but they will get dispatched + // appropriately. + while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { + process_1_event(); + } +} + //////////////////////////////////////////////////////////////////// // Function: wglGraphicsBuffer::close_buffer // Access: Protected, Virtual @@ -150,13 +175,14 @@ open_buffer() { // only are wgl extensions incredibly convoluted to get to, but the // pbuffer extension turned out not be supported on the Intel card I // tried it on, and crashed the driver for the nVidia card I tried - // it on. And it's not even supported on the software reference - // implementation. Not a good record. + // it on. And it's not even supported on the Microsoft software + // reference implementation. Not a good record. // In lieu of the pbuffer extension, it appears that rendering to a - // window that is simply never shown works fine. + // window that is hidden works fine on some drivers (although it + // doesn't work on other drivers). - DWORD window_style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; + DWORD window_style = WS_POPUP | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW; RECT win_rect; SetRect(&win_rect, 0, 0, _x_size, _y_size); @@ -182,6 +208,11 @@ open_buffer() { return false; } + ShowWindow(_window, SW_SHOWNORMAL); + if (!show_pbuffers) { + ShowWindow(_window, SW_HIDE); + } + _window_dc = GetDC(_window); wglGraphicsStateGuardian *wglgsg; @@ -195,8 +226,30 @@ open_buffer() { } _is_valid = true; + return true; } + +//////////////////////////////////////////////////////////////////// +// Function: wglGraphicsBuffer::process_1_event +// Access: Private, Static +// Description: Handles one event from the message queue. +//////////////////////////////////////////////////////////////////// +void wglGraphicsBuffer:: +process_1_event() { + MSG msg; + + if (!GetMessage(&msg, NULL, 0, 0)) { + // WM_QUIT received. We need a cleaner way to deal with this. + // DestroyAllWindows(false); + exit(msg.wParam); // this will invoke AtExitFn + } + + // Translate virtual key messages + TranslateMessage(&msg); + // Call window_proc + DispatchMessage(&msg); +} //////////////////////////////////////////////////////////////////// // Function: wglGraphicsBuffer::register_window_class @@ -217,7 +270,7 @@ register_window_class() { // Clear before filling in window structure! ZeroMemory(&wc, sizeof(WNDCLASS)); wc.style = CS_OWNDC; - wc.lpfnWndProc = DefWindowProc; + wc.lpfnWndProc = static_window_proc; wc.hInstance = instance; wc.lpszClassName = _window_class_name; @@ -233,10 +286,89 @@ register_window_class() { // Function: wglGraphicsBuffer::static_window_proc // Access: Private, Static // Description: This is attached to the window class for all -// WinGraphicsWindow windows; it is called to handle +// wglGraphicsBuffer windows; it is called to handle // window events. //////////////////////////////////////////////////////////////////// LONG WINAPI wglGraphicsBuffer:: static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { return DefWindowProc(hwnd, msg, wparam, lparam); } + + + + + +/* + if (wglgsg->_supports_pixel_format) { + // Get ready to query for a suitable pixel format that meets our + // minimum requirements. + static const int MAX_ATTRIBS = 128; + static const int MAX_PFORMATS = 128; + int iattributes[2*MAX_ATTRIBS]; + float fattributes[2*MAX_ATTRIBS]; + int nfattribs = 0; + int niattribs = 0; + // Attribute arrays must be "0" terminated--for simplicity, first + // just zero-out the array then fill from left to right. + for ( int a = 0; a < 2*MAX_ATTRIBS; a++ ) + { + iattributes[a] = 0; + fattributes[a] = 0; + } + // Since we are trying to create a pbuffer, the pixel format we + // request (and subsequently use) must be "pbuffer capable". + iattributes[2*niattribs ] = WGL_DRAW_TO_PBUFFER_ARB; + iattributes[2*niattribs+1] = true; + niattribs++; + // We require a minimum of 24-bit depth. + iattributes[2*niattribs ] = WGL_DEPTH_BITS_ARB; + iattributes[2*niattribs+1] = 24; + niattribs++; + // We require a minimum of 8-bits for each R, G, B, and A. + iattributes[2*niattribs ] = WGL_RED_BITS_ARB; + iattributes[2*niattribs+1] = 8; + niattribs++; + iattributes[2*niattribs ] = WGL_GREEN_BITS_ARB; + iattributes[2*niattribs+1] = 8; + niattribs++; + iattributes[2*niattribs ] = WGL_BLUE_BITS_ARB; + iattributes[2*niattribs+1] = 8; + niattribs++; + iattributes[2*niattribs ] = WGL_ALPHA_BITS_ARB; + iattributes[2*niattribs+1] = 8; + niattribs++; + // Now obtain a list of pixel formats that meet these minimum + // requirements. + int pformat[MAX_PFORMATS]; + memset(pformat, 0, sizeof(pformat)); + unsigned int nformats = 0; + if (!wglgsg->_wglChoosePixelFormatARB(_window_dc, iattributes, fattributes, + MAX_PFORMATS, pformat, &nformats)) { + cerr << "pbuffer creation error: Couldn't find a suitable pixel format.\n"; + } else { + cerr << "Found " << nformats << " formats, selecting " << pformat[0] << "\n"; + pbformat = pformat[0]; + } + } + + HPBUFFERARB _pbuffer; + wglMakeCurrent(_window_dc, wglgsg->get_context(_window_dc)); + wglgsg->reset_if_new(); + + cerr << "Creating pbuffer(" << _window_dc << ", " << wglgsg->get_pfnum() + << ", " << _x_size << ", " << _y_size << ", ...)\n"; + int attrib_list[] = { + 0, + }; + + HDC hdc = wglGetCurrentDC(); + cerr << "current dc = " << hdc << " window dc = " << _window_dc << "\n"; + _pbuffer = wglgsg->_wglCreatePbufferARB(hdc, pbformat, + _x_size, _y_size, attrib_list); + cerr << "pbuffer = " << (void *)_pbuffer << "\n"; + + if (_pbuffer == NULL) { + wgldisplay_cat.error() + << "Attempt to create pbuffer failed.\n"; + } +*/ diff --git a/panda/src/wgldisplay/wglGraphicsBuffer.h b/panda/src/wgldisplay/wglGraphicsBuffer.h index 216aee4996..aec32bd3bb 100644 --- a/panda/src/wgldisplay/wglGraphicsBuffer.h +++ b/panda/src/wgldisplay/wglGraphicsBuffer.h @@ -21,6 +21,7 @@ #include "pandabase.h" #include "graphicsBuffer.h" +#include "wglExtensions.h" #include @@ -44,6 +45,7 @@ public: virtual void release_gsg(); virtual void begin_flip(); + virtual void process_events(); protected: virtual void close_buffer(); @@ -51,6 +53,7 @@ protected: private: bool make_window(); + static void process_1_event(); static void register_window_class(); static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);