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

panda/src/wgldisplay/wglGraphicsPipe.cxx

Go to the documentation of this file.
00001 // Filename: wglGraphicsPipe.cxx
00002 // Created by:  drose (20Dec02)
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 "wglGraphicsPipe.h"
00020 #include "config_wgldisplay.h"
00021 #include "config_windisplay.h"
00022 
00023 typedef enum {Software, MCD, ICD} OGLDriverType;
00024 static const char * const OGLDrvStrings[] = { "Software", "MCD", "ICD" };
00025 
00026 TypeHandle wglGraphicsPipe::_type_handle;
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: wglGraphicsPipe::Constructor
00030 //       Access: Public
00031 //  Description: 
00032 ////////////////////////////////////////////////////////////////////
00033 wglGraphicsPipe::
00034 wglGraphicsPipe() {
00035 }
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: wglGraphicsPipe::Destructor
00039 //       Access: Public, Virtual
00040 //  Description: 
00041 ////////////////////////////////////////////////////////////////////
00042 wglGraphicsPipe::
00043 ~wglGraphicsPipe() {
00044 }
00045 
00046 ////////////////////////////////////////////////////////////////////
00047 //     Function: wglGraphicsPipe::get_interface_name
00048 //       Access: Published, Virtual
00049 //  Description: Returns the name of the rendering interface
00050 //               associated with this GraphicsPipe.  This is used to
00051 //               present to the user to allow him/her to choose
00052 //               between several possible GraphicsPipes available on a
00053 //               particular platform, so the name should be meaningful
00054 //               and unique for a given platform.
00055 ////////////////////////////////////////////////////////////////////
00056 string wglGraphicsPipe::
00057 get_interface_name() const {
00058   return "OpenGL";
00059 }
00060 
00061 ////////////////////////////////////////////////////////////////////
00062 //     Function: wglGraphicsPipe::pipe_constructor
00063 //       Access: Public, Static
00064 //  Description: This function is passed to the GraphicsPipeSelection
00065 //               object to allow the user to make a default
00066 //               wglGraphicsPipe.
00067 ////////////////////////////////////////////////////////////////////
00068 PT(GraphicsPipe) wglGraphicsPipe::
00069 pipe_constructor() {
00070   return new wglGraphicsPipe;
00071 }
00072 
00073 ////////////////////////////////////////////////////////////////////
00074 //     Function: wglGraphicsPipe::make_gsg
00075 //       Access: Protected, Virtual
00076 //  Description: Creates a new GSG to use the pipe (but no windows
00077 //               have been created yet for the GSG).  This method will
00078 //               be called in the draw thread for the GSG.
00079 ////////////////////////////////////////////////////////////////////
00080 PT(GraphicsStateGuardian) wglGraphicsPipe::
00081 make_gsg(const FrameBufferProperties &properties) {
00082   if (!_is_valid) {
00083     return NULL;
00084   }
00085   
00086   FrameBufferProperties new_properties = properties;
00087 
00088   // Get a handle to the screen's DC so we can choose a pixel format
00089   // (and a corresponding set of frame buffer properties) suitable for
00090   // rendering to windows on this screen.
00091   HDC hdc = GetDC(NULL);
00092   int pfnum = choose_pfnum(new_properties, hdc);
00093 
00094   if (gl_force_pixfmt != 0) {
00095     wgldisplay_cat.info()
00096       << "overriding pixfmt choice algorithm (" << pfnum 
00097       << ") with gl-force-pixfmt(" << gl_force_pixfmt << ")\n";
00098     pfnum = gl_force_pixfmt;
00099   }
00100 
00101   if (wgldisplay_cat.is_debug()) {
00102     wgldisplay_cat.debug()
00103       << "config() - picking pixfmt #" << pfnum <<endl;
00104   }
00105 
00106   // Now we're done with the screen's hdc, so release it.
00107   ReleaseDC(NULL, hdc);
00108 
00109   // Now we can make a GSG.
00110   PT(wglGraphicsStateGuardian) gsg = 
00111     new wglGraphicsStateGuardian(new_properties, pfnum);
00112 
00113   return gsg.p();
00114 }
00115 
00116 ////////////////////////////////////////////////////////////////////
00117 //     Function: wglGraphicsPipe::make_window
00118 //       Access: Protected, Virtual
00119 //  Description: Creates a new window on the pipe, if possible.
00120 ////////////////////////////////////////////////////////////////////
00121 PT(GraphicsWindow) wglGraphicsPipe::
00122 make_window(GraphicsStateGuardian *gsg) {
00123   return new wglGraphicsWindow(this, gsg);
00124 }
00125 
00126 ////////////////////////////////////////////////////////////////////
00127 //     Function: wglGraphicsPipe::choose_pfnum
00128 //       Access: Private
00129 //  Description: Selects a suitable pixel format number for the given
00130 //               frame buffer properties.  Returns the selected number
00131 //               if successful, or 0 otherwise.
00132 //
00133 //               If successful, this may modify properties to reflect
00134 //               the actual visual chosen.
00135 ////////////////////////////////////////////////////////////////////
00136 int wglGraphicsPipe::
00137 choose_pfnum(FrameBufferProperties &properties, HDC hdc) const {
00138   int pfnum;
00139   bool bUsingSoftware = false;
00140 
00141   if (force_software_renderer) {
00142     pfnum = find_pixfmtnum(properties, hdc, false);
00143     
00144     if (pfnum == 0) {
00145       wgldisplay_cat.error()
00146         << "Couldn't find compatible software-renderer OpenGL pixfmt, check your window properties!\n";
00147       return 0;
00148     }
00149     bUsingSoftware = true;
00150 
00151   } else {
00152     pfnum = find_pixfmtnum(properties, hdc, true);
00153     if (pfnum == 0) {
00154       if (allow_software_renderer) {
00155         pfnum = find_pixfmtnum(properties, hdc, false);
00156         if (pfnum == 0) {
00157           wgldisplay_cat.error()
00158             << "Couldn't find HW or Software OpenGL pixfmt appropriate for this desktop!!\n";
00159         }
00160       } else {
00161         wgldisplay_cat.error()
00162           << "Couldn't find HW-accelerated OpenGL pixfmt appropriate for this desktop!!\n";
00163       }
00164       
00165       if (pfnum == 0) {
00166         wgldisplay_cat.error()
00167           << "make sure OpenGL driver is installed, and try reducing the screen size, reducing the\n"
00168           << "desktop screen pixeldepth to 16bpp,and check your panda window properties\n";
00169         return 0;
00170       }
00171       bUsingSoftware = true;
00172     }
00173   }
00174   
00175   if (bUsingSoftware) {
00176     wgldisplay_cat.info()
00177       << "Couldn't find compatible OGL HW pixelformat, using software rendering.\n";
00178   }
00179   
00180   return pfnum;
00181 }
00182 
00183 ////////////////////////////////////////////////////////////////////
00184 //     Function: wglGraphicsPipe::find_pixfmtnum
00185 //       Access: Private
00186 //  Description: This helper routine looks for either HW-only or
00187 //               SW-only format, but not both.  Returns the
00188 //               pixelformat number, or 0 if a suitable format could
00189 //               not be found.
00190 ////////////////////////////////////////////////////////////////////
00191 int wglGraphicsPipe::
00192 find_pixfmtnum(FrameBufferProperties &properties, HDC hdc,
00193                bool bLookforHW) const {
00194   int frame_buffer_mode = properties.get_frame_buffer_mode();
00195   bool want_depth_bits = properties.has_depth_bits();
00196   bool want_color_bits = properties.has_color_bits();
00197   OGLDriverType drvtype;
00198 
00199   PIXELFORMATDESCRIPTOR pfd;
00200   ZeroMemory(&pfd,sizeof(PIXELFORMATDESCRIPTOR));
00201   pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
00202   pfd.nVersion = 1;
00203 
00204   // just use the pixfmt of the current desktop
00205 
00206   int MaxPixFmtNum = 
00207     DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
00208   int cur_bpp = GetDeviceCaps(hdc,BITSPIXEL);
00209   int pfnum;
00210 
00211   for(pfnum = 1; pfnum <= MaxPixFmtNum; pfnum++) {
00212     DescribePixelFormat(hdc, pfnum, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
00213 
00214     // official, nvidia sanctioned way.
00215     if ((pfd.dwFlags & PFD_GENERIC_FORMAT) != 0) {
00216       drvtype = Software;
00217     } else if (pfd.dwFlags & PFD_GENERIC_ACCELERATED) {
00218       drvtype = MCD;
00219     } else {
00220       drvtype = ICD;
00221     }
00222 
00223     // skip driver types we are not looking for
00224     if (bLookforHW) {
00225       if (drvtype == Software) {
00226         continue;
00227       }
00228     } else {
00229       if (drvtype != Software) {
00230         continue;
00231       }
00232     }
00233 
00234     if ((pfd.iPixelType == PFD_TYPE_COLORINDEX) && 
00235         (frame_buffer_mode & FrameBufferProperties::FM_index) == 0) {
00236       continue;
00237     }
00238 
00239     DWORD dwReqFlags = (PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW);
00240 
00241     if (wgldisplay_cat.is_debug()) {
00242       wgldisplay_cat->debug()
00243         << "----------------" << endl;
00244 
00245       if ((frame_buffer_mode & FrameBufferProperties::FM_alpha) != 0) {
00246         wgldisplay_cat->debug()
00247           << "want alpha, pfd says '"
00248           << (int)(pfd.cAlphaBits) << "'" << endl;
00249       }
00250       if ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0) {
00251         wgldisplay_cat->debug()
00252           << "want depth, pfd says '"
00253           << (int)(pfd.cDepthBits) << "'" << endl;
00254       }
00255       if ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0) {
00256         wgldisplay_cat->debug()
00257           << "want stencil, pfd says '"
00258           << (int)(pfd.cStencilBits) << "'" << endl;
00259       }
00260       wgldisplay_cat->debug()
00261         << "final flag check " << (int)(pfd.dwFlags & dwReqFlags) << " =? "
00262         << (int)dwReqFlags << endl;
00263       wgldisplay_cat->debug() 
00264         << "pfd bits = " << (int)(pfd.cColorBits) << endl;
00265       wgldisplay_cat->debug() 
00266         << "cur_bpp = " << cur_bpp << endl;
00267     }
00268 
00269     if ((frame_buffer_mode & FrameBufferProperties::FM_double_buffer) != 0) {
00270       dwReqFlags|= PFD_DOUBLEBUFFER;
00271     }
00272     if ((frame_buffer_mode & FrameBufferProperties::FM_alpha) != 0 && 
00273         (pfd.cAlphaBits==0)) {
00274       continue;
00275     }
00276     if ((frame_buffer_mode & FrameBufferProperties::FM_depth) != 0 && 
00277         (pfd.cDepthBits==0)) {
00278       continue;
00279     }
00280     if ((frame_buffer_mode & FrameBufferProperties::FM_stencil) != 0 && 
00281         (pfd.cStencilBits==0)) {
00282       continue;
00283     }
00284 
00285     if ((pfd.dwFlags & dwReqFlags) != dwReqFlags) {
00286       continue;
00287     }
00288 
00289     // now we ignore the specified want_color_bits for windowed mode
00290     // instead we use the current screen depth
00291 
00292     if ((pfd.cColorBits!=cur_bpp) && 
00293         (!((cur_bpp==16) && (pfd.cColorBits==15))) && 
00294         (!((cur_bpp==32) && (pfd.cColorBits==24)))) {
00295       continue;
00296     }
00297 
00298     // We've passed all the tests, go ahead and pick this fmt.
00299     // Note: could go continue looping looking for more alpha bits or
00300     // more depth bits so this would pick 16bpp depth buffer, probably
00301     // not 24bpp
00302     break;
00303   }
00304 
00305   if (pfnum > MaxPixFmtNum) {
00306     pfnum = 0;
00307   }
00308 
00309   return pfnum;
00310 }

Generated on Fri May 2 00:44:43 2003 for Panda by doxygen1.3