Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/dxgsg8/wdxGraphicsWindow8.cxx

Go to the documentation of this file.
00001 // Filename: wdxGraphicsWindow8.cxx
00002 // Created by:  mike (09Jan00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include <errno.h>
00020 #include <time.h>
00021 #include <math.h>
00022 #include <tchar.h>
00023 #include "wdxGraphicsPipe8.h"
00024 #include "wdxGraphicsWindow8.h"
00025 #include "config_dxgsg8.h"
00026 
00027 #include "keyboardButton.h"
00028 #include "mouseButton.h"
00029 #include "throw_event.h"
00030 
00031 #ifdef DO_PSTATS
00032 #include "pStatTimer.h"
00033 #endif
00034 
00035 #include <ddraw.h>
00036 #include <map>
00037 
00038 TypeHandle wdxGraphicsWindow8::_type_handle;
00039 
00040 #define WDX_WINDOWCLASSNAME "wdxDisplay"
00041 #define WDX_WINDOWCLASSNAME_NOCURSOR WDX_WINDOWCLASSNAME "_NoCursor"
00042 #define DEFAULT_CURSOR IDC_ARROW
00043 
00044 // define this to enable debug testing of dinput joystick
00045 //#define DINPUT_DEBUG_POLL
00046 
00047 typedef map<HWND,wdxGraphicsWindow8 *> HWND_PANDAWIN_MAP;
00048 
00049 HWND_PANDAWIN_MAP hwnd_pandawin_map;
00050 wdxGraphicsWindow8* global_wdxwinptr = NULL;  // need this for temporary windproc
00051 
00052 #define MAX_DISPLAYS 20
00053 
00054 #define PAUSED_TIMER_ID        7   // completely arbitrary choice
00055 #define JOYSTICK_POLL_TIMER_ID 8
00056 #define DX_IS_READY ((_dxgsg!=NULL)&&(_dxgsg->GetDXReady()))
00057 
00058 LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam,LPARAM lparam);
00059 
00060 /*
00061 // because we dont have access to ModifierButtons, as a hack just synchronize state of these
00062 // keys on get/lose keybd focus
00063 #define NUM_MODIFIER_KEYS 16
00064 unsigned int hardcoded_modifier_buttons[NUM_MODIFIER_KEYS]={VK_SHIFT,VK_MENU,VK_CONTROL,VK_SPACE,VK_TAB,
00065                                                             VK_UP,VK_DOWN,VK_LEFT,VK_RIGHT,VK_PRIOR,VK_NEXT,VK_HOME,VK_END,
00066                                                             VK_INSERT,VK_DELETE,VK_ESCAPE};
00067 */
00068 //#define UNKNOWN_VIDMEM_SIZE 0xFFFFFFFF
00069 
00070 ////////////////////////////////////////////////////////////////////
00071 //     Function: wdxGraphicsWindow8::Constructor
00072 //       Access: Public
00073 //  Description:
00074 ////////////////////////////////////////////////////////////////////
00075 wdxGraphicsWindow8::
00076 wdxGraphicsWindow8(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
00077   WinGraphicsWindow(pipe, gsg) 
00078 {
00079   // dont actually create the window in the constructor.  reason: multi-threading requires
00080   // panda C++ window object to exist in separate thread from actual API window
00081 
00082   _dxgsg = DCAST(DXGraphicsStateGuardian8, gsg);
00083   _depth_buffer_bpp = 0;
00084   _awaiting_restore = false;
00085   ZeroMemory(&_wcontext,sizeof(_wcontext));
00086 }
00087 
00088 ////////////////////////////////////////////////////////////////////
00089 //     Function: wdxGraphicsWindow8::Destructor
00090 //       Access: Public, Virtual
00091 //  Description:
00092 ////////////////////////////////////////////////////////////////////
00093 wdxGraphicsWindow8::
00094 ~wdxGraphicsWindow8() {
00095 }
00096 
00097 void wdxGraphicsWindow8::
00098 make_current(void) {
00099   DXGraphicsStateGuardian8 *dxgsg;
00100   DCAST_INTO_V(dxgsg, _gsg);
00101   //wglMakeCurrent(_hdc, wdxgsg->_context);
00102   dxgsg->set_context(&_wcontext);
00103 
00104   // Now that we have made the context current to a window, we can
00105   // reset the GSG state if this is the first time it has been used.
00106   // (We can't just call reset() when we construct the GSG, because
00107   // reset() requires having a current context.)
00108   dxgsg->reset_if_new();
00109 }
00110 
00111 /* BUGBUG:  need to reinstate these methods ASAP.  they were incorrectly moved from the GraphicsWindow to the GSG
00112             apps need to know the framebuffer format so they can create texture/rendertgt with same fmt
00113 int wdxGraphicsWindow8::
00114 get_depth_bitwidth(void) {
00115     assert(_dxgsg!=NULL);
00116     if(_dxgsg->scrn.PresParams.EnableAutoDepthStencil)
00117        return _dxgsg->scrn.depth_buffer_bitdepth;
00118      else return 0;
00119 
00120 // GetSurfaceDesc is not reliable, on GF2, GetSurfDesc returns 32bpp when you created a 24bpp zbuf
00121 // instead store the depth used at creation time
00122 
00123 //    DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd);
00124 //    _dxgsg->_zbuf->GetSurfaceDesc(&ddsd);
00125 //  return ddsd.ddpfPixelFormat.dwRGBBitCount;
00126 }
00127 
00128 void wdxGraphicsWindow8::
00129 get_framebuffer_format(PixelBuffer::Type &fb_type, PixelBuffer::Format &fb_format) {
00130     assert(_dxgsg!=NULL);
00131 
00132     fb_type = PixelBuffer::T_unsigned_byte;
00133     // this is sortof incorrect, since for F_rgb5 it's really 5 bits per channel
00134     //would have to change a lot of texture stuff to make this correct though
00135 
00136     if(IS_16BPP_DISPLAY_FORMAT(_dxgsg->scrn.PresParams.BackBufferFormat))
00137         fb_format = PixelBuffer::F_rgb5;
00138      else fb_format = PixelBuffer::F_rgb;
00139 }
00140 */
00141 
00142 ////////////////////////////////////////////////////////////////////
00143 //     Function: wdxGraphicsWindow8::verify_window_sizes
00144 //       Access: Public, Virtual
00145 //  Description: Determines which of the indicated window sizes are
00146 //               supported by available hardware (e.g. in fullscreen
00147 //               mode).
00148 //
00149 //               On entry, dimen is an array containing contiguous x,y
00150 //               pairs specifying possible display sizes; it is
00151 //               numsizes*2 words long.  The function will zero out
00152 //               any invalid x,y size pairs.  The return value is the
00153 //               number of valid sizes that were found.
00154 ////////////////////////////////////////////////////////////////////
00155 int wdxGraphicsWindow8::
00156 verify_window_sizes(int numsizes, int *dimen) {
00157   // unfortunately this only works AFTER you make the window
00158   // initially, so its really mostly useful for resizes only
00159   assert(IS_VALID_PTR(_dxgsg));
00160 
00161   int num_valid_modes = 0;
00162 
00163   wdxGraphicsPipe8 *dxpipe;
00164   DCAST_INTO_R(dxpipe, _pipe, 0);
00165 
00166   // not requesting same refresh rate since changing res might not
00167   // support same refresh rate at new size
00168 
00169   int *pCurDim = dimen;
00170 
00171   for (int i=0; i < numsizes; i++, pCurDim += 2) {
00172     int x_size = pCurDim[0];
00173     int y_size = pCurDim[1];
00174 
00175     bool bIsGoodMode = false;
00176     bool CouldntFindAnyValidZBuf;
00177     D3DFORMAT newPixFmt = D3DFMT_UNKNOWN;
00178 
00179     if (dxpipe->special_check_fullscreen_resolution(_wcontext, x_size, y_size)) {
00180       // bypass the test below for certain cards we know have valid modes
00181       bIsGoodMode=true;
00182 
00183     } else {
00184       if (_wcontext.bIsLowVidMemCard) {
00185         bIsGoodMode = ((x_size == 640) && (y_size == 480));
00186       } else  {
00187         dxpipe->search_for_valid_displaymode(_wcontext, x_size, y_size, _wcontext.PresParams.EnableAutoDepthStencil != false,
00188                                      IS_STENCIL_FORMAT(_wcontext.PresParams.AutoDepthStencilFormat),
00189                                      &_wcontext.SupportedScreenDepthsMask,
00190                                      &CouldntFindAnyValidZBuf, &newPixFmt, dx_force_16bpp_zbuffer);
00191         bIsGoodMode = (newPixFmt != D3DFMT_UNKNOWN);
00192       }
00193     }
00194 
00195     if (bIsGoodMode) {
00196       num_valid_modes++;
00197     } else {
00198       // tell caller the mode is invalid
00199       pCurDim[0] = 0;
00200       pCurDim[1] = 0;
00201     }
00202 
00203     if (wdxdisplay8_cat.is_spam()) {
00204       wdxdisplay8_cat.spam()
00205         << "Fullscrn Mode (" << x_size << "," << y_size << ")\t" 
00206         << (bIsGoodMode ? "V" : "Inv") <<"alid\n";
00207     }
00208   }
00209 
00210   return num_valid_modes;
00211 }
00212 
00213 ////////////////////////////////////////////////////////////////////
00214 //     Function: wdxGraphicsWindow8::begin_frame
00215 //       Access: Public, Virtual
00216 //  Description: This function will be called within the draw thread
00217 //               before beginning rendering for a given frame.  It
00218 //               should do whatever setup is required, and return true
00219 //               if the frame should be rendered, or false if it
00220 //               should be skipped.
00221 ////////////////////////////////////////////////////////////////////
00222 bool wdxGraphicsWindow8::
00223 begin_frame() {
00224   if (_awaiting_restore) {
00225     // The fullscreen window was recently restored; we can't continue
00226     // until the GSG says we can.
00227     if (!_dxgsg->CheckCooperativeLevel()) {
00228       // Keep waiting.
00229       return false;
00230     }
00231     _awaiting_restore = false;
00232 
00233     init_resized_window();
00234   }
00235 
00236   return WinGraphicsWindow::begin_frame();
00237 }
00238 
00239 ////////////////////////////////////////////////////////////////////
00240 //     Function: wdxGraphicsWindow8::end_flip
00241 //       Access: Public, Virtual
00242 //  Description: This function will be called within the draw thread
00243 //               after begin_flip() has been called on all windows, to
00244 //               finish the exchange of the front and back buffers.
00245 //
00246 //               This should cause the window to wait for the flip, if
00247 //               necessary.
00248 ////////////////////////////////////////////////////////////////////
00249 void wdxGraphicsWindow8::
00250 end_flip() {
00251   if (_dxgsg != (DXGraphicsStateGuardian8 *)NULL && is_active()) {
00252     _dxgsg->show_frame();
00253   }
00254 }
00255 
00256 ////////////////////////////////////////////////////////////////////
00257 //     Function: wdxGraphicsWindow8::fullscreen_restored
00258 //       Access: Protected, Virtual
00259 //  Description: This is a hook for derived classes to do something
00260 //               special, if necessary, when a fullscreen window has
00261 //               been restored after being minimized.  The given
00262 //               WindowProperties struct will be applied to this
00263 //               window's properties after this function returns.
00264 ////////////////////////////////////////////////////////////////////
00265 void wdxGraphicsWindow8::
00266 fullscreen_restored(WindowProperties &properties) {
00267   // In DX8, unlike DX7, for some reason we can't immediately start
00268   // rendering as soon as the window is restored, even though
00269   // BeginScene() says we can.  Instead, we have to wait until
00270   // TestCooperativeLevel() lets us in.  We need to set a flag so we
00271   // can handle this special case in begin_frame().
00272   if (_dxgsg != NULL) {
00273     _awaiting_restore = true;
00274   }
00275 }
00276 
00277 ////////////////////////////////////////////////////////////////////
00278 //     Function: wdxGraphicsWindow8::handle_reshape
00279 //       Access: Protected, Virtual
00280 //  Description: Called in the window thread when the window size or
00281 //               location is changed, this updates the properties
00282 //               structure accordingly.
00283 ////////////////////////////////////////////////////////////////////
00284 void wdxGraphicsWindow8::
00285 handle_reshape() {
00286   GdiFlush();
00287   WinGraphicsWindow::handle_reshape();
00288 
00289   if (_dxgsg != NULL) {
00290     // create the new resized rendertargets
00291     WindowProperties props = get_properties();
00292     int x_size = props.get_x_size();
00293     int y_size = props.get_y_size();
00294     bool resize_succeeded = reset_device_resize_window(x_size, y_size);
00295     if (!resize_succeeded) {
00296       if (wdxdisplay8_cat.is_debug()) {
00297         wdxdisplay8_cat.debug()
00298           << "windowed_resize to size: (" << x_size << "," << y_size
00299           << ") failed due to out-of-memory\n";
00300       } else {
00301         if (wdxdisplay8_cat.is_debug()) {
00302           int x_origin = props.get_x_origin();
00303           int y_origin = props.get_y_origin();
00304           wdxdisplay8_cat.debug()
00305             << "windowed_resize to origin: (" << x_origin << ","
00306             << y_origin << "), size: (" << x_size
00307             << "," << y_size << ")\n";
00308         }
00309       }
00310     }
00311   }
00312 }
00313 
00314 ////////////////////////////////////////////////////////////////////
00315 //     Function: wdxGraphicsWindow8::do_fullscreen_resize
00316 //       Access: Protected, Virtual
00317 //  Description: Called in the window thread to resize a fullscreen
00318 //               window.
00319 ////////////////////////////////////////////////////////////////////
00320 bool wdxGraphicsWindow8::
00321 do_fullscreen_resize(int x_size, int y_size) {
00322   bool bCouldntFindValidZBuf;
00323   D3DFORMAT pixFmt;
00324   bool bNeedZBuffer = (_wcontext.PresParams.EnableAutoDepthStencil!=false);
00325   bool bNeedStencilBuffer = IS_STENCIL_FORMAT(_wcontext.PresParams.AutoDepthStencilFormat);
00326 
00327   wdxGraphicsPipe8 *dxpipe;
00328   DCAST_INTO_R(dxpipe, _pipe, false);
00329 
00330   bool bIsGoodMode=false;
00331 
00332   if (!dxpipe->special_check_fullscreen_resolution(_wcontext, x_size,y_size)) {
00333     // bypass the lowvidmem test below for certain "lowmem" cards we know have valid modes
00334 
00335     // wdxdisplay8_cat.info() << "1111111 lowvidmemcard="<< _wcontext.bIsLowVidMemCard << endl;
00336     if (_wcontext.bIsLowVidMemCard && (!((x_size==640) && (y_size==480)))) {
00337       wdxdisplay8_cat.error() << "resize() failed: will not try to resize low vidmem device #" << _wcontext.CardIDNum << " to non-640x480!\n";
00338       goto Error_Return;
00339     }
00340   }
00341 
00342   // must ALWAYS use search_for_valid_displaymode even if we know
00343   // a-priori that res is valid so we can get a valid pixfmt
00344   dxpipe->search_for_valid_displaymode(_wcontext, x_size, y_size, 
00345                                bNeedZBuffer, bNeedStencilBuffer,
00346                                &_wcontext.SupportedScreenDepthsMask,
00347                                &bCouldntFindValidZBuf,
00348                                &pixFmt, dx_force_16bpp_zbuffer);
00349   bIsGoodMode=(pixFmt!=D3DFMT_UNKNOWN);
00350 
00351   if (!bIsGoodMode) {
00352     wdxdisplay8_cat.error() << "resize() failed: "
00353                            << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes")
00354                            << " at " << x_size << "x" << y_size << " for device #" << _wcontext.CardIDNum <<endl;
00355     goto Error_Return;
00356   }
00357 
00358   // reset_device_resize_window handles both windowed & fullscrn,
00359   // so need to set new displaymode manually here
00360   _wcontext.DisplayMode.Width=x_size;
00361   _wcontext.DisplayMode.Height=y_size;
00362   _wcontext.DisplayMode.Format = pixFmt;
00363   _wcontext.DisplayMode.RefreshRate = D3DPRESENT_RATE_DEFAULT;
00364 
00365   _wcontext.PresParams.BackBufferFormat = pixFmt;   // make reset_device_resize use presparams or displaymode??
00366 
00367   bool bResizeSucceeded = reset_device_resize_window(x_size, y_size);
00368 
00369   if (!bResizeSucceeded) {
00370     wdxdisplay8_cat.error() << "resize() failed with OUT-OF-MEMORY error!\n";
00371 
00372     if ((!IS_16BPP_DISPLAY_FORMAT(_wcontext.PresParams.BackBufferFormat)) &&
00373        (_wcontext.SupportedScreenDepthsMask & (R5G6B5_FLAG|X1R5G5B5_FLAG))) {
00374       // fallback strategy, if we trying >16bpp, fallback to 16bpp buffers
00375       _wcontext.DisplayMode.Format = ((_wcontext.SupportedScreenDepthsMask & R5G6B5_FLAG) ? D3DFMT_R5G6B5 : D3DFMT_X1R5G5B5);
00376       dx_force_16bpp_zbuffer=true;
00377       if (wdxdisplay8_cat.info())
00378         wdxdisplay8_cat.info() << "CreateDevice failed with out-of-vidmem, retrying w/16bpp buffers on device #"<< _wcontext.CardIDNum << endl;
00379 
00380       bResizeSucceeded= reset_device_resize_window(x_size, y_size);  // create the new resized rendertargets
00381     }
00382   }
00383 
00384  Error_Return:
00385 
00386   if (wdxdisplay8_cat.is_debug())
00387     wdxdisplay8_cat.debug() << "fullscrn resize("<<x_size<<","<<y_size<<") " << (bResizeSucceeded ? "succeeds\n" : "fails\n");
00388 
00389   return bResizeSucceeded;
00390 }
00391 
00392 #if 1
00393 //////////////////////////////////////////////////////////////////
00394 //     Function: WinGraphicsWindow::window_proc
00395 //       Access: Private
00396 //  Description: This is the nonstatic window_proc function.  It is
00397 //               called to handle window events for this particular
00398 //               window.
00399 ////////////////////////////////////////////////////////////////////
00400 LONG wdxGraphicsWindow8::
00401 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
00402   return WinGraphicsWindow::window_proc(hwnd,msg,wparam,lparam);
00403 }
00404 
00405 #else
00406 
00407 ////////////////////////////////////////////////////////////////////
00408 //     Function: window_proc
00409 //       Access:
00410 //  Description:
00411 ////////////////////////////////////////////////////////////////////
00412 LONG wdxGraphicsWindow8::
00413 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
00414     int button = -1;
00415     int x, y, width, height;
00416 
00417     switch(msg) {
00418         case WM_SETCURSOR: {
00419             // Turn off any GDI window cursor
00420             //  dx8 cursor not working yet
00421 
00422             if(dx_use_dx_cursor && is_fullscreen()) {
00423                 //            SetCursor( NULL );
00424             //                _dxgsg->scrn.pD3DDevice->ShowCursor(true);
00425 
00426                 set_cursor_visibility(true);
00427                 return TRUE; // prevent Windows from setting cursor to window class cursor (see docs on WM_SETCURSOR)
00428             }
00429             break;
00430         }
00431 
00432         case WM_PAINT: {
00433            // primarily seen when app window is 'uncovered'
00434            if((_WindowAdjustingType != NotAdjusting) || (!DX_IS_READY)) {
00435              // let DefWndProc do WM_ERASEBKGND & just draw black,
00436              // rather than forcing Present to stretchblt the old window contents
00437              // into the new size
00438              break;
00439            }
00440 
00441            PAINTSTRUCT ps;
00442            BeginPaint(hwnd, &ps);
00443            if(DX_IS_READY) {
00444               _dxgsg->show_frame(true);  // 'true' since just want to show the last rendered backbuf, if any
00445            }
00446            EndPaint(hwnd, &ps);
00447            return 0;
00448         }
00449 
00450         case WM_IME_STARTCOMPOSITION:
00451           // In case we're running fullscreen mode, we have to turn on
00452           // explicit DX support for overlay windows now, so we'll be able
00453           // to see the IME window.
00454           _dxgsg->support_overlay_window(true);
00455           break;
00456 
00457         case WM_IME_ENDCOMPOSITION:
00458           // Turn off the support for overlay windows, since we're done
00459           // with the IME window for now and it just slows things down.
00460           _dxgsg->support_overlay_window(false);
00461           break;
00462 
00463         case WM_ENTERSIZEMOVE:
00464              if(_dxgsg!=NULL) 
00465                 _dxgsg->SetDXReady(false);   // dont see pic during resize
00466              _WindowAdjustingType = MovingOrResizing;
00467           break;
00468 
00469         case WM_EXITSIZEMOVE: {
00470             #ifdef _DEBUG
00471               wdxdisplay_cat.spam()  << "WM_EXITSIZEMOVE received"  << endl;
00472             #endif
00473 
00474             if(_WindowAdjustingType==Resizing) {
00475                 bool bSucceeded=handle_windowed_resize(hwnd,true);
00476 
00477                 if(!bSucceeded) {
00478                     #if 0
00479                                 bugbug need to fix this stuff
00480                                 SetWindowPos(hwnd,NULL,0,0,lastxsize,lastysize,SWP_NOMOVE |
00481                     #endif
00482                 }
00483             }
00484 
00485             _WindowAdjustingType = NotAdjusting;
00486             _dxgsg->SetDXReady(true);
00487             return 0;
00488         }
00489 
00490         case WM_SIZE: {
00491 
00492             #ifdef _DEBUG
00493                 {
00494                     width = LOWORD(lparam);  height = HIWORD(lparam);
00495                     wdxdisplay_cat.spam() << "WM_SIZE received with width:" << width << "  height: " << height << " flags: " <<
00496                     ((wparam == SIZE_MAXHIDE)? "SIZE_MAXHIDE " : "") << ((wparam == SIZE_MAXSHOW)? "SIZE_MAXSHOW " : "") <<
00497                     ((wparam == SIZE_MINIMIZED)? "SIZE_MINIMIZED " : "") << ((wparam == SIZE_RESTORED)? "SIZE_RESTORED " : "") <<
00498                     ((wparam == SIZE_MAXIMIZED)? "SIZE_MAXIMIZED " : "") << endl;
00499                 }
00500             #endif
00501                 // old comment -- added SIZE_RESTORED to handle 3dfx case
00502                 if(_props._fullscreen || ((_dxgsg==NULL) || (_dxgsg->scrn.hWnd==NULL)) || ((wparam != SIZE_RESTORED) && (wparam != SIZE_MAXIMIZED)))
00503                     break;
00504 
00505                 width = LOWORD(lparam);  height = HIWORD(lparam);
00506 
00507                 if((_props._xsize != width) || (_props._ysize != height)) {
00508                     _WindowAdjustingType = Resizing;
00509 
00510                  // for maximized,unmaximize, need to call resize code artificially
00511                  // since no WM_EXITSIZEMOVE is generated.
00512                  if(wparam==SIZE_MAXIMIZED) {
00513                        _bSizeIsMaximized=TRUE;
00514                        window_proc(hwnd, WM_EXITSIZEMOVE, 0x0,0x0);
00515                  } else if((wparam==SIZE_RESTORED) && _bSizeIsMaximized) {
00516                        _bSizeIsMaximized=FALSE;  // only want to reinit dx if restoring from maximized state
00517                        window_proc(hwnd, WM_EXITSIZEMOVE, 0x0,0x0);
00518                  }
00519                 }
00520 
00521                 break;
00522             }
00523     
00524         case WM_ERASEBKGND: {
00525             // WM_ERASEBKGND will be ignored during resizing, because
00526             // we dont want WM_PAINT's generated as user is manually resizing window.
00527             
00528             // for the intermediate resizing images that WM_PAINT would show to be useful, 
00529             // the panda window parameters need to be reset on every
00530             // WM_SIZE event and that isnt happening yet
00531 
00532             if(_WindowAdjustingType)
00533                 break;
00534             return 0;  // dont let GDI waste time redrawing the deflt background
00535         }
00536 
00537         case WM_TIMER:
00538             // 2 cases of app deactivation:
00539             //
00540             // 1) user has switched out of fullscreen mode
00541             //    this is first signalled when ACTIVATEAPP returns false
00542             //    for this case, we dont wake up until WM_SIZE returns restore or maximize
00543             //    and WM_TIMER just periodically reawakens app for idle processing
00544 
00545             //    unfortunately this doesnt seem to work because RestoreAllSurfaces doesn't
00546             //    seem to think we're back in the original displaymode even after I've received
00547             //    the WM_DISPLAYCHANGE msg, and returns WRONGMODE error.  So the only way I can
00548             //    think of to make this work is to have the timer periodically check for restored
00549             //    coop level, as it does in case 2)
00550 
00551             //
00552             // 2) windowed app has lost access to dx because another app has taken dx exclusive mode
00553             //    here we rely on WM_TIMER to periodically check if it is ok to reawaken app.
00554             //    windowed apps currently run regardless of if its window is in the foreground
00555             //    so we cannot rely on window messages to reawaken app
00556 
00557             if((wparam==_PandaPausedTimer) && ((!_window_active)||_active_minimized_fullscreen)) {
00558                 assert(_dxgsg!=NULL);
00559                 _dxgsg->CheckCooperativeLevel(DO_REACTIVATE_WINDOW);
00560 
00561                 // wdxdisplay_cat.spam() << "periodic return of control to app\n";
00562                 _return_control_to_app = true;
00563                 // throw_event("PandaPaused");
00564                 // do we still need to do this since I return control to app periodically using timer msgs?
00565                 // does app need to know to avoid major computation?
00566             }
00567 
00568          #ifdef DINPUT_DEBUG_POLL
00569             // probably want to get rid of this in favor of event-based input
00570             if(dx_use_joystick && (wparam==_pParentWindowGroup->_pDInputInfo->_JoystickPollTimer)) {
00571                 DIJOYSTATE2 js;
00572                 ZeroMemory(&js,sizeof(js));
00573                 if(_pParentWindowGroup->_pDInputInfo->ReadJoystick(0,js)) {
00574                     // for now just print stuff out to make sure it works
00575                     wdxdisplay_cat.debug() << "joyPos (X: " << js.lX << ",Y: " << js.lY << ",Z: " << js.lZ << ")\n";
00576                     for(int i=0;i<128;i++) {
00577                         if(js.rgbButtons[i]!=0)
00578                             wdxdisplay_cat.debug() << "joyButton "<< i << " pressed\n";
00579                     }
00580                 } else {
00581                     wdxdisplay_cat.error() << "read of Joystick failed!\n";
00582                     exit(1);
00583                 }
00584             }
00585           #endif
00586             return 0;
00587 
00588         case WM_CLOSE:
00589             #ifdef _DEBUG
00590               wdxdisplay_cat.spam()  << "WM_CLOSE received\n";
00591             #endif
00592          // close_window();
00593           delete _pParentWindowGroup;
00594 
00595           // BUGBUG:  right now there is no way to tell the panda app the graphics window is invalid or
00596           //          has been closed by the user, to prevent further methods from being called on the window.
00597           //          this needs to be added to panda for multiple windows to work.  in the meantime, just
00598           //          trigger an exit here if # windows==0, since that is the expected behavior when all
00599           //          windows are closed (should be done by the app though, and it assumes you only make this
00600           //          type of panda gfx window)
00601 
00602           if(hwnd_pandawin_map.size()==0) {
00603               exit(0);
00604           }
00605           return 0;
00606 
00607         case WM_ACTIVATEAPP: {
00608             #ifdef _DEBUG
00609               wdxdisplay_cat.spam()  << "WM_ACTIVATEAPP(" << (bool)(wparam!=0) <<") received\n";
00610             #endif
00611 
00612            if((!wparam) && _props._fullscreen) {
00613                deactivate_window();
00614                return 0;
00615            }         // dont want to reactivate until window is actually un-minimized (see WM_SIZE)
00616            break;
00617         }
00618     }
00619 
00620   return WinGraphicsWindow::window_proc(hwnd,msg,wparam,lparam);
00621 }
00622 #endif
00623 
00624 ////////////////////////////////////////////////////////////////////
00625 //     Function: wdxGraphicsWindow8::create_screen_buffers_and_device
00626 //       Access: Private
00627 //  Description: Called whenever the window is resized, this recreates
00628 //               the necessary buffers for rendering.
00629 //
00630 //               Sets _depth_buffer_bpp appropriately.
00631 ////////////////////////////////////////////////////////////////////
00632 void wdxGraphicsWindow8::
00633 create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer) {
00634   wdxGraphicsPipe8 *dxpipe;
00635   DCAST_INTO_V(dxpipe, _pipe);
00636 
00637   // only want dx_pick_best_screenres to apply to initial startup, and 
00638   // since the initial res has already been picked, dont use auto-res-select in any future init sequence.
00639   dx_pick_best_screenres = false;
00640 
00641   DWORD dwRenderWidth=Display.DisplayMode.Width;
00642   DWORD dwRenderHeight=Display.DisplayMode.Height;
00643   LPDIRECT3D8 pD3D8=Display.pD3D8;
00644   D3DCAPS8 *pD3DCaps = &Display.d3dcaps;
00645   D3DPRESENT_PARAMETERS* pPresParams = &Display.PresParams;
00646   RECT view_rect;
00647   HRESULT hr;
00648 
00649   // BUGBUG: need to change panda to put frame buffer properties with GraphicsWindow, not GSG!!
00650   int frame_buffer_mode = _gsg->get_properties().get_frame_buffer_mode();
00651   bool bWantStencil = ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0);
00652 
00653   PRINT_REFCNT(wdxdisplay8,pD3D8);
00654 
00655   assert(pD3D8!=NULL);
00656   assert(pD3DCaps->DevCaps & D3DDEVCAPS_HWRASTERIZATION);
00657 
00658   pPresParams->BackBufferFormat = Display.DisplayMode.Format;  // dont need dest alpha, so just use adapter format
00659 
00660   if (dx_sync_video && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) {
00661     wdxdisplay8_cat.info() << "HW doesnt support syncing to vertical refresh, ignoring dx_sync_video\n";
00662     dx_sync_video=false;
00663   }
00664 
00665   // verify the rendertarget fmt one last time
00666   if (FAILED(pD3D8->CheckDeviceFormat(Display.CardIDNum, D3DDEVTYPE_HAL, Display.DisplayMode.Format,D3DUSAGE_RENDERTARGET,
00667                                      D3DRTYPE_SURFACE, pPresParams->BackBufferFormat))) {
00668     wdxdisplay8_cat.error() << "device #"<<Display.CardIDNum<< " CheckDeviceFmt failed for surface fmt "<< D3DFormatStr(pPresParams->BackBufferFormat) << endl;
00669     goto Fallback_to_16bpp_buffers;
00670   }
00671 
00672   if (FAILED(pD3D8->CheckDeviceType(Display.CardIDNum,D3DDEVTYPE_HAL, Display.DisplayMode.Format,pPresParams->BackBufferFormat,
00673                                    is_fullscreen()))) {
00674     wdxdisplay8_cat.error() << "device #"<<Display.CardIDNum<< " CheckDeviceType failed for surface fmt "<< D3DFormatStr(pPresParams->BackBufferFormat) << endl;
00675     goto Fallback_to_16bpp_buffers;
00676   }
00677 
00678   if (Display.PresParams.EnableAutoDepthStencil) {
00679     if (!dxpipe->find_best_depth_format(Display, Display.DisplayMode,
00680                                &Display.PresParams.AutoDepthStencilFormat,
00681                                bWantStencil, false)) {
00682       wdxdisplay8_cat.error()
00683         << "find_best_depth_format failed in CreateScreenBuffers for device #"
00684         << Display.CardIDNum << endl;
00685       goto Fallback_to_16bpp_buffers;
00686     }
00687     _depth_buffer_bpp = D3DFMT_to_DepthBits(Display.PresParams.AutoDepthStencilFormat);
00688   } else {
00689     _depth_buffer_bpp = 0;
00690   }
00691 
00692   pPresParams->Windowed = !is_fullscreen();
00693 
00694   if (dx_multisample_antialiasing_level>1) {
00695     // need to check both rendertarget and zbuffer fmts
00696     hr = pD3D8->CheckDeviceMultiSampleType(Display.CardIDNum, D3DDEVTYPE_HAL, Display.DisplayMode.Format,
00697                                            is_fullscreen(), D3DMULTISAMPLE_TYPE(dx_multisample_antialiasing_level));
00698     if (FAILED(hr)) {
00699       wdxdisplay8_cat.fatal() << "device #"<<Display.CardIDNum<< " doesnt support multisample level "<<dx_multisample_antialiasing_level <<"surface fmt "<< D3DFormatStr(Display.DisplayMode.Format) <<endl;
00700       exit(1);
00701     }
00702 
00703     if (Display.PresParams.EnableAutoDepthStencil) {
00704       hr = pD3D8->CheckDeviceMultiSampleType(Display.CardIDNum, D3DDEVTYPE_HAL, Display.PresParams.AutoDepthStencilFormat,
00705                                              is_fullscreen(), D3DMULTISAMPLE_TYPE(dx_multisample_antialiasing_level));
00706       if (FAILED(hr)) {
00707         wdxdisplay8_cat.fatal() << "device #"<<Display.CardIDNum<< " doesnt support multisample level "<<dx_multisample_antialiasing_level <<"surface fmt "<< D3DFormatStr(Display.PresParams.AutoDepthStencilFormat) <<endl;
00708         exit(1);
00709       }
00710     }
00711 
00712     pPresParams->MultiSampleType = D3DMULTISAMPLE_TYPE(dx_multisample_antialiasing_level);
00713 
00714     if (wdxdisplay8_cat.is_info())
00715       wdxdisplay8_cat.info() << "device #"<<Display.CardIDNum<< " using multisample antialiasing level "<<dx_multisample_antialiasing_level <<endl;
00716   }
00717 
00718   pPresParams->BackBufferCount = 1;
00719   pPresParams->Flags = 0x0;
00720   pPresParams->hDeviceWindow = Display.hWnd;
00721   pPresParams->BackBufferWidth = Display.DisplayMode.Width;
00722   pPresParams->BackBufferHeight = Display.DisplayMode.Height;
00723   DWORD dwBehaviorFlags=0x0;
00724 
00725   if (_wcontext.bIsTNLDevice) {
00726     dwBehaviorFlags|=D3DCREATE_HARDWARE_VERTEXPROCESSING;
00727     // note: we could create a pure device in this case if I eliminated the GetRenderState calls in dxgsg
00728 
00729     // also, no software vertex processing available since I specify D3DCREATE_HARDWARE_VERTEXPROCESSING
00730     // and not D3DCREATE_MIXED_VERTEXPROCESSING
00731   } else {
00732     dwBehaviorFlags|=D3DCREATE_SOFTWARE_VERTEXPROCESSING;
00733   }
00734 
00735   if (dx_preserve_fpu_state)
00736     dwBehaviorFlags|=D3DCREATE_FPU_PRESERVE;
00737 
00738   // if window is not foreground in exclusive mode, ddraw thinks you are 'not active', so
00739   // it changes your WM_ACTIVATEAPP from true to false, causing us
00740   // to go into a 'wait-for WM_ACTIVATEAPP true' loop, and the event never comes so we hang
00741   // in fullscreen wait.  also doing this for windowed mode since it was requested.
00742   if (!SetForegroundWindow(Display.hWnd)) {
00743     wdxdisplay8_cat.warning() << "SetForegroundWindow() failed!\n";
00744   }
00745 
00746   if (is_fullscreen()) {
00747     pPresParams->SwapEffect = D3DSWAPEFFECT_DISCARD;  // we dont care about preserving contents of old frame
00748     pPresParams->FullScreen_PresentationInterval = (dx_sync_video ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
00749     pPresParams->FullScreen_RefreshRateInHz = Display.DisplayMode.RefreshRate;
00750 
00751 #ifdef _DEBUG
00752     if (pPresParams->MultiSampleType != D3DMULTISAMPLE_NONE)
00753       assert(pPresParams->SwapEffect == D3DSWAPEFFECT_DISCARD);  // only valid effect for multisample
00754 #endif
00755 
00756     ClearToBlack(Display.hWnd, get_properties());
00757 
00758     hr = pD3D8->CreateDevice(Display.CardIDNum, D3DDEVTYPE_HAL, _hWnd,
00759                              dwBehaviorFlags, pPresParams, &Display.pD3DDevice);
00760 
00761     if (FAILED(hr)) {
00762       wdxdisplay8_cat.fatal() << "D3D CreateDevice failed for device #" << Display.CardIDNum << ", " << D3DERRORSTRING(hr);
00763 
00764       if (hr == D3DERR_OUTOFVIDEOMEMORY)
00765         goto Fallback_to_16bpp_buffers;
00766     }
00767 
00768     SetRect(&view_rect, 0, 0, dwRenderWidth, dwRenderHeight);
00769   }   // end create full screen buffers
00770 
00771   else {          // CREATE WINDOWED BUFFERS
00772 
00773     if (!(pD3DCaps->Caps2 & D3DCAPS2_CANRENDERWINDOWED)) {
00774       wdxdisplay8_cat.fatal() << "the 3D HW cannot render windowed, exiting..." << endl;
00775       exit(1);
00776     }
00777 
00778     D3DDISPLAYMODE dispmode;
00779     hr = Display.pD3D8->GetAdapterDisplayMode(Display.CardIDNum, &dispmode);
00780 
00781     if (FAILED(hr)) {
00782       wdxdisplay8_cat.fatal() << "GetAdapterDisplayMode failed" << D3DERRORSTRING(hr);
00783       exit(1);
00784     }
00785 
00786     if (dispmode.Format == D3DFMT_P8) {
00787       wdxdisplay8_cat.fatal() << "Can't run windowed in an 8-bit or less display mode" << endl;
00788       exit(1);
00789     }
00790 
00791     pPresParams->FullScreen_PresentationInterval = 0;
00792 
00793     if (dx_multisample_antialiasing_level<2) {
00794       if (dx_sync_video) {
00795         pPresParams->SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
00796       } else {
00797         pPresParams->SwapEffect = D3DSWAPEFFECT_DISCARD;  //D3DSWAPEFFECT_COPY;  does this make any difference?
00798       }
00799     } else {
00800       pPresParams->SwapEffect = D3DSWAPEFFECT_DISCARD;
00801     }
00802 
00803     assert((dwRenderWidth==pPresParams->BackBufferWidth)&&(dwRenderHeight==pPresParams->BackBufferHeight));
00804 
00805     hr = pD3D8->CreateDevice(Display.CardIDNum, D3DDEVTYPE_HAL, _hWnd,
00806                              dwBehaviorFlags, pPresParams, &Display.pD3DDevice);
00807 
00808     if (FAILED(hr)) {
00809       wdxdisplay8_cat.fatal() << "D3D CreateDevice failed for device #" << Display.CardIDNum << D3DERRORSTRING(hr);
00810       exit(1);
00811     }
00812   }  // end create windowed buffers
00813 
00814   //  ========================================================
00815 
00816   PRINT_REFCNT(wdxdisplay8,_wcontext.pD3DDevice);
00817 
00818   if (pPresParams->EnableAutoDepthStencil) {
00819     _dxgsg->_buffer_mask |= RenderBuffer::T_depth;
00820     if (IS_STENCIL_FORMAT(pPresParams->AutoDepthStencilFormat))
00821       _dxgsg->_buffer_mask |= RenderBuffer::T_stencil;
00822   }
00823 
00824   init_resized_window();
00825 
00826   return;
00827 
00828  Fallback_to_16bpp_buffers:
00829 
00830   if ((!IS_16BPP_DISPLAY_FORMAT(pPresParams->BackBufferFormat)) &&
00831      (Display.SupportedScreenDepthsMask & (R5G6B5_FLAG|X1R5G5B5_FLAG))) {
00832     // fallback strategy, if we trying >16bpp, fallback to 16bpp buffers
00833 
00834     Display.DisplayMode.Format = ((Display.SupportedScreenDepthsMask & R5G6B5_FLAG) ? D3DFMT_R5G6B5 : D3DFMT_X1R5G5B5);
00835 
00836     if (wdxdisplay8_cat.info()) {
00837       wdxdisplay8_cat.info()
00838         << "CreateDevice failed with out-of-vidmem, retrying w/16bpp buffers on device #"
00839         << Display.CardIDNum << endl;
00840     }
00841     create_screen_buffers_and_device(Display, true);
00842     return;
00843 
00844   } else if (!((dwRenderWidth==640)&&(dwRenderHeight==480))) {
00845     if (wdxdisplay8_cat.info())
00846       wdxdisplay8_cat.info() << "CreateDevice failed w/out-of-vidmem, retrying at 640x480 w/16bpp buffers on device #"<< Display.CardIDNum << endl;
00847     // try final fallback to 640x480x16
00848     Display.DisplayMode.Width=640;
00849     Display.DisplayMode.Height=480;
00850     create_screen_buffers_and_device(Display, true);
00851     return;
00852 
00853   } else {
00854     wdxdisplay8_cat.fatal() 
00855       << "Can't create any screen buffers, bailing out.\n";
00856     exit(1);
00857   }
00858 }
00859 
00860 ////////////////////////////////////////////////////////////////////
00861 //     Function: wdxGraphicsWindow8::choose_device
00862 //       Access: Private
00863 //  Description: Looks at the list of available graphics adapters and
00864 //               chooses a suitable one for the window.
00865 //
00866 //               Returns true if successful, false on failure.
00867 ////////////////////////////////////////////////////////////////////
00868 bool wdxGraphicsWindow8::
00869 choose_device(void) {
00870   HRESULT hr;
00871 
00872   wdxGraphicsPipe8 *dxpipe;
00873   DCAST_INTO_R(dxpipe, _pipe, false);
00874 
00875   int num_adapters = dxpipe->_pD3D8->GetAdapterCount();
00876   DXDeviceInfoVec device_infos;
00877 
00878   for (int i = 0; i < num_adapters; i++) {
00879     D3DADAPTER_IDENTIFIER8 adapter_info;
00880     ZeroMemory(&adapter_info, sizeof(D3DADAPTER_IDENTIFIER8));
00881     hr = dxpipe->_pD3D8->GetAdapterIdentifier(i, D3DENUM_NO_WHQL_LEVEL, &adapter_info);
00882     if (FAILED(hr)) {
00883       wdxdisplay8_cat.fatal()
00884         << "D3D GetAdapterID(" << i << ") failed: "
00885         << D3DERRORSTRING(hr) << endl;
00886       continue;
00887     }
00888      
00889     LARGE_INTEGER *DrvVer = &adapter_info.DriverVersion;
00890 
00891     wdxdisplay8_cat.info()
00892       << "D3D8." << (dxpipe->_bIsDX81 ?"1":"0") << " Adapter[" << i << "]: " << adapter_info.Description 
00893       << ", Driver: " << adapter_info.Driver << ", DriverVersion: ("
00894       << HIWORD(DrvVer->HighPart) << "." << LOWORD(DrvVer->HighPart) << "."
00895       << HIWORD(DrvVer->LowPart) << "." << LOWORD(DrvVer->LowPart)
00896       << ")\nVendorID: 0x" << (void*) adapter_info.VendorId 
00897       << " DeviceID: 0x" <<  (void*) adapter_info.DeviceId
00898       << " SubsysID: 0x" << (void*) adapter_info.SubSysId
00899       << " Revision: 0x" << (void*) adapter_info.Revision << endl;
00900     
00901     HMONITOR hMon = dxpipe->_pD3D8->GetAdapterMonitor(i);
00902     if (hMon == NULL) {
00903       wdxdisplay8_cat.info()
00904         << "D3D8 Adapter[" << i << "]: seems to be disabled, skipping it\n";
00905       continue;
00906     }
00907 
00908     DXDeviceInfo devinfo;
00909     ZeroMemory(&devinfo, sizeof(devinfo));
00910     memcpy(&devinfo.guidDeviceIdentifier, &adapter_info.DeviceIdentifier, 
00911            sizeof(GUID));
00912     strncpy(devinfo.szDescription, adapter_info.Description,
00913             MAX_DEVICE_IDENTIFIER_STRING);
00914     strncpy(devinfo.szDriver, adapter_info.Driver,
00915             MAX_DEVICE_IDENTIFIER_STRING);
00916     devinfo.VendorID = adapter_info.VendorId;
00917     devinfo.DeviceID = adapter_info.DeviceId;
00918     devinfo.hMon = hMon;
00919     devinfo.cardID = i;
00920 
00921     device_infos.push_back(devinfo);
00922   }
00923 
00924   if (device_infos.empty()) {
00925     wdxdisplay8_cat.error()
00926       << "No available D3D8 devices found.\n";
00927     return false;
00928   }
00929 
00930   // Since some adapters may have been disabled, we should re-obtain
00931   // the number of available adapters.
00932   num_adapters = (int)device_infos.size();
00933 
00934   // Now choose a suitable adapter.
00935 
00936   int adapter_num = D3DADAPTER_DEFAULT;
00937 
00938   // Eventually, we should have some interface for specifying a device
00939   // index interactively, instead of only via Configrc.
00940   if (dx_preferred_device_id != -1) {
00941     if (dx_preferred_device_id < 0 || dx_preferred_device_id >= num_adapters) {
00942       wdxdisplay8_cat.error()
00943         << "invalid 'dx-preferred-device-id', valid values are 0-" 
00944         << num_adapters - 1 << ", using default adapter instead.\n";
00945     } else {
00946       adapter_num = dx_preferred_device_id;
00947     }
00948   }
00949 
00950   UINT good_device_count=0;
00951   for(UINT devnum=0;devnum<device_infos.size() /*&& (good_device_count < num_windows)*/;devnum++) {
00952       if(search_for_device(dxpipe,&device_infos[devnum]))
00953           good_device_count++;
00954   }
00955 
00956   if(good_device_count==0) {
00957      wdxdisplay8_cat.fatal() << "no usable display devices, exiting...\n";
00958      return false;
00959   }
00960 
00961   return true;
00962 }
00963 
00964 /*
00965 primary init sequence of old method, still need to integrate multi-window functionality
00966 void wdxGraphicsWindow8Group::initWindowGroup(void) {
00967     HRESULT hr;
00968 
00969     assert(_windows.size()>0);
00970     _hOldForegroundWindow=GetForegroundWindow();
00971     _bClosingAllWindows= false;
00972 
00973     UINT num_windows=_windows.size();
00974 
00975     #define D3D8_NAME "d3d8.dll"
00976     #define D3DCREATE8 "Direct3DCreate8"
00977 
00978     _hD3D8_DLL = LoadLibrary(D3D8_NAME);
00979     if(_hD3D8_DLL == 0) {
00980         wdxdisplay_cat.fatal() << "PandaDX8 requires DX8, can't locate " << D3D8_NAME <<"!\n";
00981         exit(1);
00982     }
00983 
00984     _hMouseCursor = NULL;
00985     _bLoadedCustomCursor = false;
00986 
00987     _pDInputInfo = NULL;
00988 
00989     // can only get multimon HW acceleration in fullscrn on DX7
00990 
00991     UINT numMonitors = GetSystemMetrics(SM_CMONITORS);
00992 
00993     if(numMonitors < num_windows) {
00994         if(numMonitors==0) {
00995              numMonitors=1;   //win95 system will fail this call
00996           } else {
00997               wdxdisplay_cat.fatal() << "system has only " << numMonitors << " monitors attached, couldn't find enough devices to meet multi window reqmt of " << num_windows << endl;
00998               exit(1);
00999           }
01000     }
01001 
01002    // Do all DX7 stuff first
01003    //  find_all_card_memavails();
01004 
01005     LPDIRECT3D8 pD3D8;
01006 
01007     typedef LPDIRECT3D8 (WINAPI *Direct3DCreate8_ProcPtr)(UINT SDKVersion);
01008 
01009     // dont want to statically link to possibly non-existent d3d8 dll, so must call D3DCr8 indirectly
01010     Direct3DCreate8_ProcPtr D3DCreate8_Ptr =
01011         (Direct3DCreate8_ProcPtr) GetProcAddress(_hD3D8_DLL, D3DCREATE8);
01012 
01013     if(D3DCreate8_Ptr == NULL) {
01014         wdxdisplay_cat.fatal() << "GetProcAddress for "<< D3DCREATE8 << "failed!" << endl;
01015         exit(1);
01016     }
01017 
01018 // these were taken from the 8.0 and 8.1 d3d8.h SDK headers
01019 #define D3D_SDK_VERSION_8_0  120
01020 #define D3D_SDK_VERSION_8_1  220
01021 
01022     // are we using 8.0 or 8.1?
01023     WIN32_FIND_DATA TempFindData;
01024     HANDLE hFind;
01025     char tmppath[MAX_PATH];
01026     GetSystemDirectory(tmppath,MAX_PATH);
01027     strcat(tmppath,"\\dpnhpast.dll");
01028     hFind = FindFirstFile ( tmppath,&TempFindData );
01029     if(hFind != INVALID_HANDLE_VALUE) {
01030          FindClose(hFind);
01031          _bIsDX81=true;
01032          pD3D8 = (*D3DCreate8_Ptr)(D3D_SDK_VERSION_8_1);
01033     } else {
01034         _bIsDX81=false;
01035         pD3D8 = (*D3DCreate8_Ptr)(D3D_SDK_VERSION_8_0);
01036     }
01037 
01038     if(pD3D8==NULL) {
01039         wdxdisplay_cat.fatal() << D3DCREATE8 << " failed!\n";
01040         exit(1);
01041     }
01042 
01043     _numAdapters = pD3D8->GetAdapterCount();
01044     if(_numAdapters < num_windows) {
01045         wdxdisplay_cat.fatal() << "couldn't find enough devices attached to meet multi window reqmt of " << num_windows << endl;
01046         exit(1);
01047     }
01048 
01049     for(UINT i=0;i<_numAdapters;i++) {
01050         D3DADAPTER_IDENTIFIER8 adapter_info;
01051         ZeroMemory(&adapter_info,sizeof(D3DADAPTER_IDENTIFIER8));
01052         hr = pD3D8->GetAdapterIdentifier(i,D3DENUM_NO_WHQL_LEVEL,&adapter_info);
01053         if(FAILED(hr)) {
01054             wdxdisplay_cat.fatal() << "D3D GetAdapterID failed" << D3DERRORSTRING(hr);
01055         }
01056 
01057         LARGE_INTEGER *DrvVer=&adapter_info.DriverVersion;
01058 
01059         wdxdisplay_cat.info() << "D3D8 Adapter[" << i << "]: " << adapter_info.Description <<
01060                                ", Driver: " << adapter_info.Driver << ", DriverVersion: ("
01061             << HIWORD(DrvVer->HighPart) << "." << LOWORD(DrvVer->HighPart) << "."
01062             << HIWORD(DrvVer->LowPart) << "." << LOWORD(DrvVer->LowPart) << ")\nVendorID: 0x"
01063             << (void*) adapter_info.VendorId << " DeviceID: 0x" <<  (void*) adapter_info.DeviceId
01064             << " SubsysID: 0x" << (void*) adapter_info.SubSysId << " Revision: 0x"
01065             << (void*) adapter_info.Revision << endl;
01066 
01067         HMONITOR hMon=pD3D8->GetAdapterMonitor(i);
01068         if(hMon==NULL) {
01069             wdxdisplay_cat.info() << "D3D8 Adapter[" << i << "]: seems to be disabled, skipping it\n";
01070             continue;
01071         }
01072 
01073         DXDeviceInfo devinfo;
01074         ZeroMemory(&devinfo,sizeof(devinfo));
01075         memcpy(&devinfo.guidDeviceIdentifier,&adapter_info.DeviceIdentifier,sizeof(GUID));
01076         strncpy(devinfo.szDescription,adapter_info.Description,MAX_DEVICE_IDENTIFIER_STRING);
01077         strncpy(devinfo.szDriver,adapter_info.Driver,MAX_DEVICE_IDENTIFIER_STRING);
01078         devinfo.VendorID=adapter_info.VendorId;
01079         devinfo.DeviceID=adapter_info.DeviceId;
01080         devinfo.hMon=hMon;
01081         devinfo.cardID=i;
01082 
01083         _DeviceInfoVec.push_back(devinfo);
01084     }
01085 
01086     for(UINT i=0;i<num_windows;i++) {
01087         _windows[i]->config_window(this);
01088     }
01089 
01090     UINT good_device_count=0;
01091 
01092     if(num_windows==1) {
01093         UINT D3DAdapterNum = D3DADAPTER_DEFAULT;
01094 
01095         if(dx_preferred_deviceID!=-1) {
01096             if(dx_preferred_deviceID>=(int)_numAdapters) {
01097                 wdxdisplay_cat.fatal() << "invalid 'dx-preferred-device-id', valid values are 0-" << _numAdapters-1 << ", using default adapter 0 instead\n";
01098             } else D3DAdapterNum=dx_preferred_deviceID;
01099         }
01100         if(_windows[0]->search_for_device(pD3D8,&(_DeviceInfoVec[D3DAdapterNum])))
01101             good_device_count=1;
01102     } else {
01103         for(UINT devnum=0;devnum<_DeviceInfoVec.size() && (good_device_count < num_windows);devnum++) {
01104             if(_windows[devnum]->search_for_device(pD3D8,&(_DeviceInfoVec[devnum])))
01105                 good_device_count++;
01106         }
01107     }
01108 
01109     if(good_device_count < num_windows) {
01110       if(good_device_count==0)
01111          wdxdisplay_cat.fatal() << "no usable display devices, exiting...\n";
01112        else wdxdisplay_cat.fatal() << "multi-device request for " << num_windows << "devices, found only "<< good_device_count << " usable ones, exiting!";
01113       exit(1);
01114     }
01115 
01116     _DeviceInfoVec.clear();  // dont need this anymore
01117 
01118     if(wdxdisplay_cat.is_debug() && (g_pCardIDVec!=NULL)) {
01119       // print out the MaxAvailVidMems
01120       for(UINT i=0;i<_windows.size();i++) {
01121         D3DADAPTER_IDENTIFIER8 adapter_info;
01122         pD3D8->GetAdapterIdentifier(_windows[i]->_wcontext.CardIDNum,D3DENUM_NO_WHQL_LEVEL,&adapter_info);
01123         wdxdisplay_cat.info() << "D3D8 Adapter[" << i << "]: " << adapter_info.Description
01124                               << ", MaxAvailVideoMem: " << _windows[i]->_wcontext.MaxAvailVidMem
01125                               << ", IsLowVidMemCard: " << (_windows[i]->_wcontext.bIsLowVidMemCard ? "true" : "false") << endl;
01126       }
01127     }
01128 
01129     CreateWindows();  // creates win32 windows  (need to do this before Setting coopLvls and display modes,
01130                       // but after we have all the monitor handles needed by CreateWindow()
01131 
01132 //    SetCoopLevelsAndDisplayModes();
01133 
01134     if(dx_show_fps_meter)
01135        _windows[0]->_dxgsg->_bShowFPSMeter = true;  // just show fps on 1st mon
01136 
01137     for(UINT i=0;i<num_windows;i++) {
01138         _windows[i]->CreateScreenBuffersAndDevice(_windows[i]->_wcontext);
01139     }
01140 
01141     for(UINT i=0;i<num_windows;i++) {
01142         _windows[i]->finish_window_setup();
01143     }
01144 
01145     SAFE_DELETE(g_pCardIDVec);  // dont need this anymore
01146 
01147     for(UINT i=0;i<num_windows;i++) {
01148         _windows[i]->_dxgsg->SetDXReady(true);
01149     }
01150 
01151     dx_pick_best_screenres = false;   // only want to do this on startup, not resize
01152 
01153   #ifdef DINPUT_DEBUG_POLL
01154     if(dx_use_joystick) {
01155         _pDInputInfo = new DInput8Info;
01156         assert(_pDInputInfo !=NULL);
01157        if(!_pDInputInfo->InitDirectInput()) {
01158            wdxdisplay_cat.error() << "InitDirectInput failed!\n";
01159            exit(1);
01160        }
01161 
01162        if(!_pDInputInfo->CreateJoystickOrPad(_hParentWindow)) {  // associate w/parent window of group for now
01163            wdxdisplay_cat.error() << "CreateJoystickOrPad failed!\n";
01164            exit(1);
01165        }
01166 
01167         // for now, just set up a WM_TIMER to poll the joystick.
01168         // could configure it to do event-based input, and that is default w/action mapping
01169         // which would be better, less processor intensive
01170 
01171         #define POLL_FREQUENCY_HZ  3
01172         _pDInputInfo->_JoystickPollTimer = SetTimer(_hParentWindow, JOYSTICK_POLL_TIMER_ID, 1000/POLL_FREQUENCY_HZ, NULL);
01173         if(_pDInputInfo->_JoystickPollTimer!=JOYSTICK_POLL_TIMER_ID) {
01174            wdxdisplay_cat.error() << "Error in joystick SetTimer!\n";
01175        }
01176     }
01177   #endif
01178 }
01179 */
01180 
01181 ////////////////////////////////////////////////////////////////////
01182 //     Function: wdxGraphicsWindow8::search_for_device
01183 //       Access: Private
01184 //  Description: Searches for a suitable hardware device for
01185 //               rendering.
01186 ////////////////////////////////////////////////////////////////////
01187 bool wdxGraphicsWindow8::
01188 search_for_device(wdxGraphicsPipe8 *dxpipe, DXDeviceInfo *device_info) {
01189 
01190   assert(dxpipe != NULL);  
01191   WindowProperties properties = get_properties();
01192   DWORD dwRenderWidth = properties.get_x_size();
01193   DWORD dwRenderHeight = properties.get_y_size();
01194   HRESULT hr;
01195   LPDIRECT3D8 pD3D8 = dxpipe->_pD3D8;
01196 
01197   assert(_dxgsg != NULL);  
01198   _wcontext.pD3D8 = pD3D8;
01199   _wcontext.bIsDX81 = dxpipe->_bIsDX81;
01200   _wcontext.CardIDNum = device_info->cardID;  // could this change by end?
01201 
01202   int frame_buffer_mode = _gsg->get_properties().get_frame_buffer_mode();
01203   bool bWantStencil = ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0);
01204   
01205   hr = pD3D8->GetAdapterIdentifier(device_info->cardID, D3DENUM_NO_WHQL_LEVEL,
01206                                    &_wcontext.DXDeviceID);
01207   if (FAILED(hr)) {
01208     wdxdisplay8_cat.error()
01209       << "D3D GetAdapterID failed" << D3DERRORSTRING(hr);
01210     return false;
01211   }
01212   
01213   D3DCAPS8 d3dcaps;
01214   hr = pD3D8->GetDeviceCaps(device_info->cardID,D3DDEVTYPE_HAL,&d3dcaps);
01215   if (FAILED(hr)) {
01216     if ((hr==D3DERR_INVALIDDEVICE)||(hr==D3DERR_NOTAVAILABLE)) {
01217       wdxdisplay8_cat.error()
01218         << "No DirectX 8 D3D-capable 3D hardware detected for device # "
01219         << device_info->cardID << " (" <<device_info->szDescription 
01220         << ")!\n";
01221     } else {
01222       wdxdisplay8_cat.error()
01223         << "GetDeviceCaps failed: " << D3DERRORSTRING(hr) << endl;
01224     }
01225     return false;
01226   }
01227   
01228   //search_for_valid_displaymode needs these to be set
01229   memcpy(&_wcontext.d3dcaps, &d3dcaps,sizeof(D3DCAPS8));
01230   _wcontext.CardIDNum = device_info->cardID;
01231   
01232   _wcontext.MaxAvailVidMem = UNKNOWN_VIDMEM_SIZE;
01233   _wcontext.bIsLowVidMemCard = false;
01234   
01235   // bugbug: wouldnt we like to do GetAVailVidMem so we can do
01236   // upper-limit memory computation for dx8 cards too?  otherwise
01237   // verify_window_sizes cant do much
01238   if ((d3dcaps.MaxStreams==0) || dx_pick_best_screenres) {
01239     if (wdxdisplay8_cat.is_debug()) {
01240       wdxdisplay8_cat.debug()
01241         << "checking vidmem size\n";
01242     }
01243     //    assert(IS_VALID_PTR(_pParentWindowGroup));
01244     
01245     // look for low memory video cards
01246     //    _pParentWindowGroup->find_all_card_memavails();
01247     
01248     UINT IDnum;
01249     
01250     // simple linear search to match DX7 card info w/DX8 card ID
01251     for (IDnum=0; IDnum < dxpipe->_card_ids.size(); IDnum++) {
01252       //      wdxdisplay8_cat.info()
01253       //        << "comparing '" << dxpipe->_card_ids[IDnum].Driver
01254       //        << "' to '" << _wcontext.DXDeviceID.Driver << "'\n";
01255       if (//(stricmp(dxpipe->_card_ids[IDnum].szDriver,device_info->szDriver)==0) &&
01256          (device_info->VendorID==dxpipe->_card_ids[IDnum].VendorID) &&
01257          (device_info->DeviceID==dxpipe->_card_ids[IDnum].DeviceID) &&
01258          (device_info->hMon==dxpipe->_card_ids[IDnum].hMon))
01259         break;
01260     }
01261     
01262     if (IDnum < dxpipe->_card_ids.size()) {
01263       _wcontext.MaxAvailVidMem = dxpipe->_card_ids[IDnum].MaxAvailVidMem;
01264       _wcontext.bIsLowVidMemCard = dxpipe->_card_ids[IDnum].bIsLowVidMemCard;
01265     } else {
01266       wdxdisplay8_cat.error()
01267         << "Error: couldnt find a CardID match in DX7 info, assuming card is not a lowmem card\n";
01268     }
01269   }
01270 
01271   if ((bWantStencil) && (d3dcaps.StencilCaps==0x0)) {
01272     wdxdisplay8_cat.fatal()
01273       << "Stencil ability requested, but device #" << device_info->cardID
01274       << " (" << _wcontext.DXDeviceID.Description
01275       << "), has no stencil capability!\n";
01276     return false;
01277   }
01278 
01279   // just because TNL is true, it doesnt mean vtx shaders are
01280   // supported in HW (see GF2) for this case, you probably want MIXED
01281   // processing to use HW for fixed-fn vertex processing and SW for
01282   // vtx shaders
01283   _wcontext.bIsTNLDevice = 
01284     ((d3dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0);
01285   _wcontext.bCanUseHWVertexShaders = 
01286     (d3dcaps.VertexShaderVersion >= D3DVS_VERSION(1, 0));
01287   _wcontext.bCanUsePixelShaders = 
01288     (d3dcaps.PixelShaderVersion >= D3DPS_VERSION(1, 0));
01289 
01290   bool bNeedZBuffer = 
01291     ((!(d3dcaps.RasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )) &&
01292      ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0));
01293 
01294   _wcontext.PresParams.EnableAutoDepthStencil = bNeedZBuffer;
01295 
01296   D3DFORMAT pixFmt = D3DFMT_UNKNOWN;
01297 
01298   if (is_fullscreen()) {
01299     bool bCouldntFindValidZBuf;
01300     if (!_wcontext.bIsLowVidMemCard) {
01301       bool bUseDefaultSize = dx_pick_best_screenres &&
01302         ((_wcontext.MaxAvailVidMem == UNKNOWN_VIDMEM_SIZE) ||
01303          is_badvidmem_card(&_wcontext.DXDeviceID));
01304 
01305       if (dx_pick_best_screenres && !bUseDefaultSize) {
01306         typedef struct {
01307           UINT memlimit;
01308           DWORD scrnX,scrnY;
01309         } Memlimres;
01310 
01311         const Memlimres MemRes[] = {
01312           {       0,  640, 480},
01313           { 8000000,  800, 600},
01314 #if 0
01315           {16000000, 1024, 768},
01316           {32000000, 1280,1024},  // 32MB+ cards will choose this
01317 #else
01318           // unfortunately the 32MB card perf varies greatly (TNT2-GF2),
01319           // so we need to be conservative since frame rate difference
01320           // can change from 15->30fps when going from 1280x1024->800x600
01321           // on low-end 32mb cards
01322           {16000000,  800, 600},
01323           {32000000,  800, 600},  // 32MB+ cards will choose this
01324 #endif
01325           // some monitors have trouble w/1600x1200, so dont pick this by deflt,
01326           // even though 64MB cards should handle it              
01327           {64000000, 1280,1024}   // 64MB+ cards will choose this
01328         };
01329         const NumResLims = (sizeof(MemRes)/sizeof(Memlimres));
01330 
01331         for(int i = NumResLims - 1; i >= 0; i--) {
01332           // find biggest slot card can handle
01333           if (_wcontext.MaxAvailVidMem > MemRes[i].memlimit) {
01334             dwRenderWidth = MemRes[i].scrnX;
01335             dwRenderHeight = MemRes[i].scrnY;
01336 
01337             wdxdisplay8_cat.info()
01338               << "pick_best_screenres: trying " << dwRenderWidth 
01339               << "x" << dwRenderHeight << " based on "
01340               << _wcontext.MaxAvailVidMem << " bytes avail\n";
01341 
01342              dxpipe->search_for_valid_displaymode(_wcontext,dwRenderWidth, dwRenderHeight, 
01343                                          bNeedZBuffer, bWantStencil,
01344                                          &_wcontext.SupportedScreenDepthsMask,
01345                                          &bCouldntFindValidZBuf,
01346                                          &pixFmt, dx_force_16bpp_zbuffer);
01347 
01348             // note I'm not saving refresh rate, will just use adapter
01349             // default at given res for now
01350 
01351             if (pixFmt != D3DFMT_UNKNOWN) {
01352               break;
01353             }
01354 
01355             wdxdisplay8_cat.info()
01356               << "skipping scrnres; "
01357               << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes")
01358               << " at " << dwRenderWidth << "x" << dwRenderHeight
01359               << " for device #" << _wcontext.CardIDNum << endl;
01360           }
01361         }
01362         // otherwise just go with whatever was specified (we probably shouldve marked this card as lowmem if it gets to end of loop w/o breaking
01363       }
01364 
01365       if (pixFmt == D3DFMT_UNKNOWN) {
01366         if (bUseDefaultSize) {
01367           wdxdisplay8_cat.info()
01368             << "pick_best_screenres: defaulted 800x600 based on no reliable vidmem size\n";
01369           dwRenderWidth=800;
01370           dwRenderHeight=600;
01371         }
01372 
01373         dxpipe->search_for_valid_displaymode(_wcontext, dwRenderWidth, dwRenderHeight,
01374                                      bNeedZBuffer, bWantStencil,
01375                                      &_wcontext.SupportedScreenDepthsMask,
01376                                      &bCouldntFindValidZBuf,
01377                                      &pixFmt, dx_force_16bpp_zbuffer);
01378 
01379         // note I'm not saving refresh rate, will just use adapter
01380         // default at given res for now
01381 
01382         if (pixFmt == D3DFMT_UNKNOWN) {
01383           wdxdisplay8_cat.error()
01384             << (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes")
01385             << " at " << dwRenderWidth << "x" << dwRenderHeight << " for device #" << _wcontext.CardIDNum <<endl;
01386 
01387           // run it again in verbose mode to get more dbg info to log
01388           dxpipe->search_for_valid_displaymode(_wcontext,dwRenderWidth, dwRenderHeight,
01389                                        bNeedZBuffer, bWantStencil,
01390                                        &_wcontext.SupportedScreenDepthsMask,
01391                                        &bCouldntFindValidZBuf,
01392                                        &pixFmt, dx_force_16bpp_zbuffer, true);
01393           return false;
01394         }
01395       }
01396     } else {
01397       // Low Memory card
01398       dwRenderWidth=640;
01399       dwRenderHeight=480;
01400       dx_force_16bpptextures = true;
01401 
01402       // need to autoforce 16bpp zbuf?  or let user use that extra mem for textures/framebuf res/etc?
01403       // most lowmem cards only do 16bpp Z anyway, but we wont force it for now
01404 
01405       dxpipe->search_for_valid_displaymode(_wcontext,dwRenderWidth, dwRenderHeight,
01406                                    bNeedZBuffer, bWantStencil,
01407                                    &_wcontext.SupportedScreenDepthsMask,
01408                                    &bCouldntFindValidZBuf,
01409                                    &pixFmt, dx_force_16bpp_zbuffer);
01410 
01411       // hack: figuring out exactly what res to use is tricky, instead I will
01412       // just use 640x480 if we have < 3 meg avail
01413 
01414       if (_wcontext.SupportedScreenDepthsMask & R5G6B5_FLAG) {
01415         pixFmt = D3DFMT_R5G6B5;
01416       } else if (_wcontext.SupportedScreenDepthsMask & X1R5G5B5_FLAG) {
01417         pixFmt = D3DFMT_X1R5G5B5;
01418       } else {
01419         wdxdisplay8_cat.fatal()
01420           << "Low Memory VidCard has no supported FullScreen 16bpp resolutions at "
01421           << dwRenderWidth << "x" << dwRenderHeight << " for device #"
01422           << device_info->cardID << " (" 
01423           << _wcontext.DXDeviceID.Description << "), skipping device...\n";
01424 
01425         // run it again in verbose mode to get more dbg info to log
01426         dxpipe->search_for_valid_displaymode(_wcontext, dwRenderWidth, dwRenderHeight,
01427                                      bNeedZBuffer, bWantStencil,
01428                                      &_wcontext.SupportedScreenDepthsMask,
01429                                      &bCouldntFindValidZBuf,
01430                                      &pixFmt, dx_force_16bpp_zbuffer, 
01431                                      true /* verbose mode on*/);
01432         return false;
01433       }
01434 
01435       if (wdxdisplay8_cat.is_info()) {
01436         wdxdisplay8_cat.info()
01437           << "Available VidMem (" << _wcontext.MaxAvailVidMem
01438           << ") is under threshold, using 640x480 16bpp rendertargets to save tex vidmem.\n";
01439       }
01440     }
01441   } else {
01442     // Windowed Mode
01443 
01444     D3DDISPLAYMODE dispmode;
01445     hr = pD3D8->GetAdapterDisplayMode(device_info->cardID,&dispmode);
01446     if (FAILED(hr)) {
01447       wdxdisplay8_cat.error()
01448         << "GetAdapterDisplayMode(" << device_info->cardID
01449         << ") failed" << D3DERRORSTRING(hr);
01450       return false;
01451     }
01452     pixFmt = dispmode.Format;
01453   }
01454 
01455   _wcontext.DisplayMode.Width = dwRenderWidth;
01456   _wcontext.DisplayMode.Height = dwRenderHeight;
01457   _wcontext.DisplayMode.Format = pixFmt;
01458   _wcontext.DisplayMode.RefreshRate = D3DPRESENT_RATE_DEFAULT;
01459   _wcontext.hMon = device_info->hMon;
01460 
01461   if (dwRenderWidth != properties.get_x_size() ||
01462       dwRenderHeight != properties.get_y_size()) {
01463     // This is probably not the best place to put this; I'm just putting
01464     // it here for now because if dx_pick_best_screenres is true, the
01465     // code above might have changed the size of the window
01466     // unexpectedly.  This code gets called when make_gsg() is called,
01467     // which means it is called in the draw thread, but this method
01468     // should really be called from the window thread.  In DirectX those
01469     // may always be the same threads anyway, so we may be all right.
01470     // Still, it's a little strange that the window may change size
01471     // after it has already been opened, at the time we create the GSG
01472     // for it; it would be better if we could find a way to do this
01473     // resolution-selection logic earlier, say at the time the window is
01474     // created.
01475     system_changed_size(dwRenderWidth, dwRenderHeight);
01476     WindowProperties resized_props;
01477     resized_props.set_size(dwRenderWidth, dwRenderHeight);
01478     _properties.add_properties(resized_props);
01479   }
01480 
01481   return true;
01482 }
01483 
01484 
01485 ////////////////////////////////////////////////////////////////////
01486 //     Function: wdxGraphicsWindow8::reset_device_resize_window
01487 //       Access: Private
01488 //  Description: Called after a window (either fullscreen or windowed)
01489 //               has been resized, this recreates the D3D structures
01490 //               to match the new size.
01491 ////////////////////////////////////////////////////////////////////
01492 bool wdxGraphicsWindow8::
01493 reset_device_resize_window(UINT new_xsize, UINT new_ysize) {
01494   assert((new_xsize > 0) && (new_ysize > 0));
01495   bool bRetval = true;
01496 
01497   D3DPRESENT_PARAMETERS d3dpp;
01498   memcpy(&d3dpp, &_wcontext.PresParams, sizeof(D3DPRESENT_PARAMETERS));
01499   d3dpp.BackBufferWidth = new_xsize;
01500   d3dpp.BackBufferHeight = new_ysize;
01501   HRESULT hr = _dxgsg->reset_d3d_device(&d3dpp);
01502   
01503   if (FAILED(hr)) {
01504     bRetval = false;
01505     wdxdisplay8_cat.error()
01506       << "reset_device_resize_window Reset() failed" << D3DERRORSTRING(hr);
01507     if (hr == D3DERR_OUTOFVIDEOMEMORY) {
01508       hr = _dxgsg->reset_d3d_device(&_wcontext.PresParams);
01509       if (FAILED(hr)) {
01510         wdxdisplay8_cat.error()
01511           << "reset_device_resize_window Reset() failed OutOfVidmem, then failed again doing Reset w/original params:" << D3DERRORSTRING(hr);
01512         exit(1);
01513       } else {
01514         if (wdxdisplay8_cat.is_info())
01515           wdxdisplay8_cat.info()
01516             << "reset of original size (" << _wcontext.PresParams.BackBufferWidth
01517             << "," << _wcontext.PresParams.BackBufferHeight << ") succeeded\n";
01518       }
01519     } else {
01520       wdxdisplay8_cat.fatal() 
01521         << "Can't reset device, bailing out.\n";
01522       exit(1);
01523     }
01524   }
01525   
01526   init_resized_window();
01527   return bRetval;
01528 }
01529 
01530 ////////////////////////////////////////////////////////////////////
01531 //     Function: wdxGraphicsWindow8::init_resized_window
01532 //       Access: Private
01533 //  Description: Reinitializes the window after it has been resized,
01534 //               or after it is first created.
01535 //
01536 //               Assumes CreateDevice or Device->Reset() has just been
01537 //               called, and the new size is specified in
01538 //               _wcontext.PresParams.
01539 ////////////////////////////////////////////////////////////////////
01540 void wdxGraphicsWindow8::
01541 init_resized_window() {
01542   HRESULT hr;
01543 
01544   DWORD newWidth = _wcontext.PresParams.BackBufferWidth;
01545   DWORD newHeight = _wcontext.PresParams.BackBufferHeight;
01546 
01547   assert((newWidth!=0) && (newHeight!=0));
01548   assert(_wcontext.hWnd!=NULL);
01549 
01550   if (_wcontext.PresParams.Windowed) {
01551     POINT ul,lr;
01552     RECT client_rect;
01553 
01554     // need to figure out x,y origin offset of window client area on screen
01555     // (we already know the client area size)
01556 
01557     GetClientRect(_wcontext.hWnd, &client_rect);
01558     ul.x = client_rect.left;
01559     ul.y = client_rect.top;
01560     lr.x = client_rect.right;
01561     lr.y=client_rect.bottom;
01562     ClientToScreen(_wcontext.hWnd, &ul);
01563     ClientToScreen(_wcontext.hWnd, &lr);
01564     client_rect.left = ul.x;
01565     client_rect.top = ul.y;
01566     client_rect.right = lr.x;
01567     client_rect.bottom = lr.y;
01568     //    _props._xorg = client_rect.left;  // _props should reflect view rectangle
01569     //    _props._yorg = client_rect.top;
01570 
01571     /*
01572 #ifdef _DEBUG
01573     // try to make sure GDI and DX agree on window client area size
01574     // but client rect will not include any offscreen areas, so dont
01575     // do check if window was bigger than screen (there are other bad
01576     // cases too, like when window is positioned partly offscreen,
01577     // or if window trim border make size bigger than screen)
01578 
01579     RECT desktop_rect;
01580     GetClientRect(GetDesktopWindow(), &desktop_rect);
01581     int x_size = get_properties().get_x_size();
01582     int y_size = get_properties().get_y_size();
01583     if ((x_size < RECT_X_SIZE(desktop_rect)) && 
01584         (y_size < RECT_Y_SIZE(desktop_rect)))
01585       assert((RECT_X_SIZE(client_rect) == newWidth) &&
01586              (RECT_Y_SIZE(client_rect) == newHeight));
01587 #endif
01588     */
01589   }
01590 
01591   //  resized(newWidth, newHeight);  // update panda channel/display rgn info, _props.x_size, _props.y_size
01592 
01593   // clear window to black ASAP
01594   assert(_wcontext.hWnd!=NULL);
01595   ClearToBlack(_wcontext.hWnd, get_properties());
01596 
01597   // clear textures and VB's out of video&AGP mem, so cache is reset
01598   hr = _wcontext.pD3DDevice->ResourceManagerDiscardBytes(0);
01599   if (FAILED(hr)) {
01600     wdxdisplay8_cat.error()
01601       << "ResourceManagerDiscardBytes failed for device #" 
01602       << _wcontext.CardIDNum << D3DERRORSTRING(hr);
01603   }
01604 
01605   _dxgsg->set_context(&_wcontext); 
01606   // Note: dx_init will fill in additional fields in _wcontext, like supportedtexfmts
01607   _dxgsg->dx_init();
01608 
01609   if(dx_use_dx_cursor && is_fullscreen()) {
01610       hr = CreateDX8Cursor(_wcontext.pD3DDevice,_mouse_cursor,dx_show_cursor_watermark);
01611       if(FAILED(hr))
01612           wdxdisplay8_cat.error() << "CreateDX8Cursor failed!" <<  D3DERRORSTRING(hr);
01613   }
01614 }
01615 
01616 ////////////////////////////////////////////////////////////////////
01617 //     Function: wdxGraphicsWindow8::D3DFMT_to_DepthBits
01618 //       Access: Private, Static
01619 //  Description: Returns the number of depth bits represented by the
01620 //               indicated D3DFORMAT value.
01621 ////////////////////////////////////////////////////////////////////
01622 int wdxGraphicsWindow8::
01623 D3DFMT_to_DepthBits(D3DFORMAT fmt) {
01624   switch(fmt) {
01625   case D3DFMT_D16:
01626     return 16;
01627 
01628   case D3DFMT_D24X8:
01629   case D3DFMT_D24X4S4:
01630   case D3DFMT_D24S8:
01631     return 24;
01632 
01633   case D3DFMT_D32:
01634     return 32;
01635 
01636   case D3DFMT_D15S1:
01637     return 15;
01638 
01639   default:
01640     wdxdisplay8_cat.debug()
01641       << "D3DFMT_DepthBits: unhandled D3DFMT!\n";
01642     return 0;
01643   }
01644 }
01645 
01646 ////////////////////////////////////////////////////////////////////
01647 //     Function: wdxGraphicsWindow8::is_badvidmem_card
01648 //       Access: Private, Static
01649 //  Description: Returns true if the indicated video adapter card is
01650 //               known to report an inaccurate figure for available
01651 //               video memory.
01652 ////////////////////////////////////////////////////////////////////
01653 bool wdxGraphicsWindow8::
01654 is_badvidmem_card(D3DADAPTER_IDENTIFIER8 *pDevID) {
01655   // dont trust Intel cards since they often use regular memory as vidmem
01656   if (pDevID->VendorId == 0x00008086) {
01657     return true;
01658   }
01659 
01660   return false;
01661 }
01662 
01663 ////////////////////////////////////////////////////////////////////
01664 //     Function: wdxGraphicsWindow8::open_window
01665 //       Access: Protected, Virtual
01666 //  Description: Opens the window right now.  Called from the window
01667 //               thread.  Returns true if the window is successfully
01668 //               opened, or false if there was a problem.
01669 ////////////////////////////////////////////////////////////////////
01670 bool wdxGraphicsWindow8::
01671 open_window(void) {
01672   if(!choose_device()) {
01673       return false;
01674   }
01675 
01676   if (!WinGraphicsWindow::open_window()) {
01677     return false;
01678   }
01679 
01680   _wcontext.hWnd = _hWnd;
01681   create_screen_buffers_and_device(_wcontext, dx_force_16bpp_zbuffer);
01682 
01683   return true;
01684 }
01685 
01686 bool wdxGraphicsWindow8::
01687 handle_mouse_motion(int x, int y) {
01688   (void) WinGraphicsWindow::handle_mouse_motion(x,y);
01689   if(dx_use_dx_cursor && is_fullscreen() && (_wcontext.pD3DDevice!=NULL)) {
01690       _wcontext.pD3DDevice->SetCursorPosition(x,y,D3DCURSOR_IMMEDIATE_UPDATE);
01691       // return true to indicate wind_proc should return 0 instead of going to DefaultWindowProc
01692       return true;
01693   }
01694   return false;
01695 }
01696 
01697 #if 0
01698 // does NOT override _props._bCursorIsVisible
01699 INLINE void wdxGraphicsWindow::
01700 set_cursor_visibility(bool bVisible) {
01701   if(_props._bCursorIsVisible) {
01702       if(dx_use_dx_cursor) {
01703           ShowCursor(false);
01704           if(IS_VALID_PTR(_wcontext.pD3DDevice))
01705               _dxgsg->scrn.pD3DDevice->ShowCursor(bVisible);
01706       } else {
01707          ShowCursor(bVisible);
01708       }
01709   } else {
01710       ShowCursor(false);
01711       if(dx_use_dx_cursor && IS_VALID_PTR(_wcontext.pD3DDevice))
01712           _dxgsg->scrn.pD3DDevice->ShowCursor(false);
01713   }
01714 }
01715 #endif

Generated on Fri May 2 00:37:21 2003 for Panda by doxygen1.3