// Ron Fosner's code for weighting pixel formats and forcing software.

/*===================================================================
This is your weighting function. Customize it to suit your needs.
You write it so that it examines the PFD passed in and returns a weighting
factor. You then select the largest weight (which is supposedly the best
pixel format). The optional bForceSoftwareFlag will eliminate any hardware
accelerated format from consideration (i.e. it'll force software rendering)
The currentColorDepth param is the current desktop color depth. Formats
that are in this color depth are preferred over others. If the color depth
isn't better
that 256 color mode, we don't select and pixel format.
===================================================================*/
unsigned WeightPixelFormats( PIXELFORMATDESCRIPTOR& pfd, unsigned
currentColorDepth, bool bForceSoftware )
{
   unsigned weight = 0;

   // if it's not the same color depth, double buffered in a Window, and in
RGBA mode
   //  with a z buffer we don't want it
   if ( currentColorDepth != pfd.cColorBits  || 
      !(pfd.dwFlags & PFD_SUPPORT_OPENGL) ||
      !(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
      ( pfd.cDepthBits <= 8 ) ||
      !(pfd.iPixelType == PFD_TYPE_RGBA)  )
       return(0);

   weight = 1;  // it's usable

   if ( pfd.dwFlags & PFD_DOUBLEBUFFER ) 
      {
      weight *= 2; // we like double buffered
      }

   // we like smaller (but nonzero depth buffers)
   // so weight smaller better - assume smallest is 16 bits, else ignore it
   if ( 16 <= pfd.cDepthBits )
      {
      weight += 128 - pfd.cDepthBits; // assume that the depth buffer will
never >= 128 bits
//      assert( pfd.cDepthBits <= 128 );
      }

   // only good for ICD's or generic, don't worry about mini-client drivers
   if ( pfd.dwFlags & PFD_GENERIC_FORMAT )
      {
      // software implementation
      }
   else
      {
      // hardware implementation
      if ( true == bForceSoftware )
         {
         weight = 0; // kill it
         }
      else
         {
         weight += 1024; 
         }
      }

   return( weight );
   
}

/*===================================================================
Use this function instead of ChoosePixelFormat, You pass in the Window
DC, the current desktop color depth, and a flag that's true if you only
want software rendering only. It will return the pixel format that will
be best suited (as selected by the WeightPixelFormats function). You then
use
the returned value for CreatePixelFormat.
Sugggestions/bugs report to Ron Fosner - ron@directx.com
===================================================================*/
int EnumPixelFormats( HDC hdc, unsigned colorDepth, bool bSoftware )
{
   int  iPixelFormat; 
   int  iCount; 
   unsigned weight = 0;

   PIXELFORMATDESCRIPTOR pfd2;
   
   PIXELFORMATDESCRIPTOR pfd = 
       {
       sizeof(PIXELFORMATDESCRIPTOR),// size of this pfd
       1,                      // version number
       PFD_DRAW_TO_WINDOW |    // support window
         PFD_SUPPORT_OPENGL |  // support OpenGL
         PFD_DOUBLEBUFFER,
       PFD_TYPE_RGBA,          // RGBA type
       32,
       0, 0, 0, 0, 0, 0,       // color bits ignored
       0,                      // no alpha buffer
       0,                      // shift bit ignored
       0,                      // no accumulation buffer
       0, 0, 0, 0,             // accum bits ignored
       16,                     // 16-bit z-buffer
       0,                      // no stencil buffer
       0,                      // no auxiliary buffer
       PFD_MAIN_PLANE,         // main layer
       0,                      // reserved
       0, 0, 0                 // layer masks ignored
       };
 
//   assert( NULL != hdc );
   iPixelFormat = 1;

   pfd2 = pfd;
   
   // obtain detailed information about 
   // the device context's first pixel format 
   iCount = 1 + ::DescribePixelFormat( hdc, iPixelFormat,  
        sizeof(PIXELFORMATDESCRIPTOR), &pfd2); 

   // use stupid OS function to select one by default in case we
   // can't come up with something better   
   iPixelFormat = ::ChoosePixelFormat( hdc, &pfd );
   if ( 0 == iPixelFormat )
      {
//      TRACE( "No OpenGL pixel formats found\n");
      return 0;
      }

//   TRACE("%d OpenGL pixel formats found\n", iCount-1);
     
   // pfd counts are 1 based (not 0)
   while ( --iCount )
      {
      ::DescribePixelFormat( hdc, iCount, sizeof(PIXELFORMATDESCRIPTOR),
&pfd ); 
      unsigned w = WeightPixelFormats( pfd, colorDepth, bSoftware );
       
      if ( w > weight ) // do we like this one better?
         {
         weight = w;
         iPixelFormat = iCount;
         }
      }

#if defined (_DEBUG)
//   ::DescribePixelFormat( hdc, iPixelFormat,
sizeof(PIXELFORMATDESCRIPTOR), &pfd ); 
//   TRACE("Pixel format %d selected\n",iPixelFormat);
//   TRACE("Pixel format has %d color & %d depth
bits\n",(int)pfd.cColorBits, (int)pfd.cDepthBits );
#endif

   return iPixelFormat;
}

