arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

pbuffer.cpp

Go to the documentation of this file.
00001 /// 5/31/02     Aaron Lefohn    Scientific Computing and Imaging Institute      
00002 /// School of Computing         University of Utah
00003 /// - Pbuffer class. 
00004 /// - This code based on a combination of code from ATI, Joe Kniss, and Milan Ikits
00005 
00006 
00007 #include "pbuffer.h"
00008 #include <stdio.h> // TODO: This needs to be nuked!
00009 #include <iostream>
00010 #include "glUtil.h"
00011 #include <assert.h>
00012 //#include "perfCounter.h"
00013 
00014 #define MAX_PFORMATS 256
00015 #define MAX_ATTRIBS  32
00016 
00017 using namespace std;
00018 
00019 PBuffer* PBuffer::m_curPbuff = NULL;
00020 
00021 #ifdef WIN32
00022 llong PBuffer::m_totEnableTime;
00023 #endif
00024 
00025 #define DEBUGGING 0
00026 
00027 PBuffer::PBuffer( int xDim, int yDim, unsigned int mode, PBuffRenCTX renderCTX)
00028 {
00029    initMembers(xDim, yDim, mode, renderCTX);
00030    create();
00031 }
00032 
00033 void PBuffer::initMembers( const int xDim, const int yDim, unsigned int mode, PBuffRenCTX renderCTX)
00034 {
00035    m_xDim = xDim;
00036    m_yDim = yDim;
00037    m_mode  = mode;
00038    m_numSurfaces = numSurfaces(mode);
00039    m_stateSaved = false;
00040    m_buffer = 0;
00041 
00042 #ifdef WIN32
00043    m_format = 0;
00044    m_surface = WGL_FRONT_LEFT_ARB;
00045    m_curBoundSurface = WGL_FRONT_LEFT_ARB;
00046    m_devCTX = NULL;
00047    m_renCTX = renderCTX;
00048    m_saveDevCTX = NULL;
00049    m_saveRenCTX = NULL;
00050 #else //Linux
00051    m_renCTX = renderCTX;
00052    m_window = 0;
00053 #endif
00054 
00055    m_saveDrawBuff = GL_FRONT;
00056    m_saveReadBuff = GL_FRONT;
00057    m_saveViewPort[0] = 0;
00058    m_saveViewPort[1] = 0;
00059    m_saveViewPort[2] = xDim;
00060    m_saveViewPort[3] = yDim;
00061 }
00062 
00063 
00064 PBuffer::~PBuffer()
00065 {
00066    if ( m_buffer )
00067    {
00068 #ifdef WIN32
00069       wglDeleteContext( m_renCTX );
00070       wglReleasePbufferDCARB( m_buffer, m_devCTX );
00071       wglDestroyPbufferARB( m_buffer );
00072 #else
00073       glXDestroyPbuffer(glXGetCurrentDisplay(), m_buffer);
00074 #endif
00075    }
00076 }
00077 
00078 // Extract the number of render surfaces from the 'mode'
00079 int PBuffer::numSurfaces( unsigned int mode )
00080 {
00081    int n = 0; // Number of surfaces
00082 
00083    // Enforce that single and double are not both specified.
00084    if( (mode & PBUFF_SINGLE) && (mode & PBUFF_DOUBLE) ) {
00085       cerr << "PBuffer::numSurfaces(...) Error:\n\t"
00086          << "Illegal to specify single and double buffered pbuffer\n\n";
00087       exit(1);
00088    }
00089 
00090    // Enforce only a single AUX buffer choice
00091    unsigned int auxs = PBUFF_AUX1 | PBUFF_AUX2 | PBUFF_AUX3 | 
00092       PBUFF_AUX4 | PBUFF_AUX5 | PBUFF_AUX6 |
00093       PBUFF_AUX7 | PBUFF_AUX8;
00094    auxs = mode & auxs;
00095    unsigned int auxsPrime = auxs & (auxs-1); // Zero-out the least signficant one bit
00096    if( auxsPrime != 0 ) {                          // Is powOfTwo if auxsPrime==0 b/c only 1, 1-bit
00097       cerr << "PBuffer::numSurfaces(...) Error:\n\t"
00098          << "Illegal to specify more than one PBUFF_AUX option\n\n";
00099       exit(1);
00100    }
00101 
00102    if( mode & PBUFF_SINGLE ) {
00103       n+=1;
00104    }
00105    if( mode & PBUFF_DOUBLE ) {
00106       n+=2;
00107    }
00108    if( mode & PBUFF_AUX1 ) {
00109       n+=1;
00110    }
00111    if( mode & PBUFF_AUX2 ) {
00112       n+=2;
00113    }
00114    if(  mode & PBUFF_AUX2 ) {
00115       n+=2;
00116    }
00117    if(  mode & PBUFF_AUX3 ) {
00118       n+=3;
00119    }
00120    if(  mode & PBUFF_AUX4 ) {
00121       n+=4;
00122    }
00123    if( mode & PBUFF_AUX5 ) {
00124       n+=5;
00125    }
00126    if(  mode & PBUFF_AUX6 ) {
00127       n+=6;
00128    }
00129    if(  mode & PBUFF_AUX7 ) {
00130       n+=7;
00131    }
00132    if(  mode & PBUFF_AUX8 ) {
00133       n+=8;
00134    }
00135 
00136    return n;
00137 }
00138 
00139 // Set WGL_FRONT_LEFT_ARB,      WGL_BACK_LEFT_ARB, WGL_FRONT_LEFT_ARB, 
00140 //         WGL_FRONT_RIGHT_ARB, WGL_BACK_LEFT_ARB, WGL_BACK_RIGHT_ARB 
00141 //     WGL_AUX0_ARB,            WGL_AUX1_ARB,      WGL_AUX2_ARB,                WGL_AUX3_ARB
00142 void PBuffer::setSurface( GLenum surface )
00143 {
00144 #ifdef WIN32
00145    if( surface != WGL_FRONT_LEFT_ARB &&
00146       surface != WGL_FRONT_RIGHT_ARB &&
00147       surface != WGL_BACK_LEFT_ARB &&
00148       surface != WGL_BACK_RIGHT_ARB &&
00149       surface != WGL_AUX0_ARB &&
00150       surface != WGL_AUX1_ARB &&
00151       surface != WGL_AUX2_ARB &&
00152       surface != WGL_AUX3_ARB ) {
00153          cerr << "PBuffer::setTarget(...) Error:\n\tInvalid face specification.\n";
00154          exit(1);
00155       }
00156 
00157       m_surface = surface;
00158 #endif
00159 }
00160 
00161 // Set mip level that is rendered to.
00162 // Default = 0
00163 void PBuffer::setMipLevel( int level )
00164 {
00165 #ifdef WIN32
00166    assert( level >= 0 );
00167 
00168    int attrib[3];
00169    attrib[0] = WGL_MIPMAP_LEVEL_ARB ;
00170    attrib[1] = level;
00171    attrib[2] = 0;
00172 
00173    wglSetPbufferAttribARB( m_buffer, attrib ); 
00174 #endif
00175 }
00176 
00177 // Set  WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,    WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 
00178 //              WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,    WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 
00179 //              WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,    WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
00180 // Default = POSITIVE_X
00181 void PBuffer::setCubeFace( GLenum cubeFace )
00182 {
00183 #ifdef WIN32
00184    assert( cubeFace == WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
00185       cubeFace == WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB ||
00186       cubeFace == WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB ||
00187       cubeFace == WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB ||
00188       cubeFace == WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB ||
00189       cubeFace == WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB );
00190 
00191    int attrib[3];
00192    attrib[0] = WGL_CUBE_MAP_FACE_ARB ;
00193    attrib[1] = cubeFace;
00194    attrib[2] = 0;
00195 
00196    wglSetPbufferAttribARB( m_buffer, attrib );
00197 #endif
00198 }
00199 
00200 void PBuffer::bind()
00201 {
00202 #ifdef WIN32
00203    wglBindTexImageARB(m_buffer, m_surface);
00204    //           m_curBoundSurface = m_surface;
00205 #endif
00206 }
00207 
00208 // WARNING: 'setSurface()' MUST be set to the correct surface!!!
00209 void PBuffer::release()
00210 {
00211 #ifdef WIN32
00212    wglReleaseTexImageARB(m_buffer, m_surface);
00213 #endif
00214 }
00215 
00216 void PBuffer::enable(bool saveState)
00217 {
00218    //   llong t0 = g_perfCounter.query();
00219 
00220    // DEBUGGING
00221    //HDC          curDC = wglGetCurrentDC();
00222    //HGLRC curRC = wglGetCurrentContext();
00223    // END DEBUG
00224    //cerr << "Pbuffer::enable(...) WARNING: Caching commented out\n\n";
00225    if( this != m_curPbuff ) { /// Avoid the ctxt switch if we are already current.
00226       //        if( curDC != m_devCTX ||
00227       //                curRC != m_renCTX ) {
00228       m_curPbuff = this;
00229       m_stateSaved = saveState;
00230 
00231       //handleModeSwitch();                     /// * \/\/\/\/ AEL 5/23/02
00232 
00233       /// Always-Saved state                            /// * \/\/\/\/ AEL 5/23/02 from here down based on Milan's code
00234       glGetIntegerv(GL_VIEWPORT,    &m_saveViewPort[0]);
00235       glGetIntegerv(GL_DRAW_BUFFER, &m_saveDrawBuff);
00236       glGetIntegerv(GL_READ_BUFFER, &m_saveReadBuff);
00237 
00238       // Conditionally saved state
00239       if( saveState ) {
00240 #ifdef WIN32
00241          //wglGetLastError("PBuffer::enable() 1");
00242          m_saveDevCTX = wglGetCurrentDC();        //Device context
00243          m_saveRenCTX = wglGetCurrentContext();//Render context
00244          //wglGetLastError("PBuffer::enable() 2");
00245 #endif
00246          //TODO: What about Linux?
00247       }
00248 
00249       /// set read/write context to pbuffer
00250       //wglGetLastError("PBuffer::enable() 3");
00251       glErr(cerr,"Pbuffer","enable() 2");
00252 #ifdef WIN32
00253       //                        #if WGL_ARB_make_current_read
00254       //                                if( wglMakeContextCurrentARB( m_devCTX, m_devCTX, m_renCTX ) == NULL ) {
00255       //                                        fprintf(stderr, "PBuffer:Enable() failed.\n"); }//exit(1); }
00256       //                        #else
00257       if( wglMakeCurrent( m_devCTX, m_renCTX ) == NULL) {
00258          fprintf(stderr, "PBuffer:Enable() failed.\n"); }//exit(1); }
00259       //                        #endif
00260       //                        DWORD err = GetLastError();
00261 #else //Linux
00262       //m_window = curWindow;
00263       glXMakeCurrent(glXGetCurrentDisplay(), 
00264          m_buffer, 
00265          glXGetCurrentContext());
00266 #endif
00267       //wglGetLastError("PBuffer::enable() 4");
00268       glErr(cerr,"Pbuffer","enable() 3");
00269 
00270       /// draw & read the front m_buffer of pbuffer
00271       glDrawBuffer(GL_FRONT);
00272       glReadBuffer(GL_FRONT);
00273 
00274       /// resize view port. generally you'll want to set this to the
00275       /// size of your pbuffer so that you render to the entire pbuffer
00276       /// but there are cases where you might want to render to just a
00277       /// sub-region of the pbuffer.
00278       /// TODO: Does this need to be here?
00279       //glViewport(0, 0, m_dimen.w, m_dimen.h );
00280 
00281       glErr(cerr,"Pbuffer","enable() 4");
00282    } 
00283 
00284    //   llong t1 = g_perfCounter.query();
00285    //   m_totEnableTime += (t1 - t0) / g_perfCounter.frequency();
00286 }
00287 
00288 void PBuffer::disable() //AEL 5/23/02
00289 {
00290    glDrawBuffer(m_saveDrawBuff);
00291    glReadBuffer(m_saveReadBuff);
00292    //glViewport(m_saveViewPort[0], m_saveViewPort[1], m_saveViewPort[2], m_saveViewPort[3]);
00293 
00294    /// make sure the pbuffer has been initialized
00295    if (m_buffer==0) return;
00296 
00297    if( m_stateSaved ) {
00298 #ifdef WIN32
00299       /// make sure we haven't lost our pbuffer due to a display mode change
00300       int flag = 0;
00301       wglQueryPbufferARB(m_buffer, WGL_PBUFFER_LOST_ARB, &flag);
00302       if (flag != 0) return;
00303 
00304       /// reset the saved state
00305       //#if WGL_ARB_make_current_read
00306       //        wglMakeContextCurrentARB(m_saveDevCTX, m_saveDevCTX, m_saveRenCTX);
00307       //#else
00308       wglMakeCurrent(m_saveDevCTX, m_saveRenCTX);
00309       //#endif
00310 #else /// Linux
00311       // TODO: Does this work?? Don't we need to save some state in "enable()"?
00312       glXMakeCurrent(glXGetCurrentDisplay(), m_window, glXGetCurrentContext());
00313 #endif
00314 
00315    }
00316 
00317    m_stateSaved = false;
00318    m_curPbuff = NULL; 
00319    glErr(cerr,"PBuffer", "disable()");
00320 }
00321 
00322 /// Check to see if the pbuffer was lost.
00323 /// If it was lost, destroy it and then recreate it.
00324 void PBuffer::handleModeSwitch()
00325 {
00326 #ifdef WIN32
00327    int lost = 0;
00328 
00329    wglQueryPbufferARB( m_buffer, WGL_PBUFFER_LOST_ARB, &lost );
00330 
00331    if( lost )
00332    {
00333       this->~PBuffer();
00334       create();
00335    }
00336 
00337    glErr(cerr,"PBuffer", "handleModeSwitch()");
00338 #else
00339    /// In GLX, this info is sent via an event generation, so
00340    /// we are not going to handle this for now.
00341 #endif
00342 }
00343 
00344 void PBuffer::create()
00345 {
00346 #ifdef WIN32
00347    /// Get the current context
00348    HDC   curDevCTX = wglGetCurrentDC();
00349    assert(curDevCTX);
00350 
00351    /// Attempt to match the pixel format of "m_mode"
00352    /// Returns 
00353    int format = GetPixelFormat( curDevCTX );
00354    int requestedFormat = setPixelFormat( curDevCTX );
00355 
00356 #ifndef NDEBUG
00357    cerr << "PBuffer::create: requestedFormat = " << requestedFormat << endl;
00358 #endif
00359 
00360    /// Create the pbuffer.
00361    int  iAttrib[2*MAX_ATTRIBS];
00362    iAttrib[0] = 0;
00363    if(m_mode & PBUFF_REND_TO_TEX){
00364       if( wglew.NV_float_buffer && (m_mode & PBUFF_FLOAT16 || m_mode & PBUFF_FLOAT32) ) {
00365          // Nvidia float buffer
00366          iAttrib[0] = WGL_TEXTURE_FORMAT_ARB;
00367          iAttrib[1] = WGL_TEXTURE_FLOAT_RGBA_NV;
00368       }
00369       else { // ATI or Nvidia fixed-point
00370          iAttrib[0] = WGL_TEXTURE_FORMAT_ARB;
00371          iAttrib[1] = WGL_TEXTURE_RGBA_ARB;
00372       }
00373 
00374       if( m_mode & PBUFF_CUBE ) {
00375          iAttrib[2] = WGL_TEXTURE_TARGET_ARB;
00376          iAttrib[3] = WGL_TEXTURE_CUBE_MAP_ARB;
00377       }
00378       else if( m_mode & PBUFF_RECT && wglew.NV_render_texture_rectangle ) {
00379          iAttrib[2] = WGL_TEXTURE_TARGET_ARB;
00380          iAttrib[3] = WGL_TEXTURE_RECTANGLE_NV;
00381       }
00382       else {
00383          iAttrib[2] = WGL_TEXTURE_TARGET_ARB;
00384          iAttrib[3] = WGL_TEXTURE_2D_ARB;
00385       }
00386 
00387       iAttrib[4] = WGL_MIPMAP_TEXTURE_ARB;
00388       iAttrib[5] = (m_mode & PBUFF_MIPMAP) > 0;
00389 
00390       iAttrib[6] = WGL_PBUFFER_LARGEST_ARB;
00391       iAttrib[7] = false;
00392 
00393       iAttrib[8] = 0;    //the last one in an attribute array must be zero!!!
00394 
00395 #if DEBUGGING
00396       fprintf(stderr, "Using Render To Texture P-Buffer\n");
00397 #endif
00398    }
00399 
00400    /// Finally...create the buffer!
00401    m_buffer = wglCreatePbufferARB( curDevCTX, requestedFormat, m_xDim, m_yDim, iAttrib );
00402    m_format = requestedFormat;
00403 
00404    /// If something went wrong, figure out what and report it.
00405    if ( !m_buffer )
00406    {
00407       DWORD err = GetLastError();
00408       fprintf( stderr, "pbuffer creation error:  wglCreatePbufferARB() failed\n" );
00409       if ( err == ERROR_INVALID_PIXEL_FORMAT )
00410       {
00411          fprintf( stderr, "error:  ERROR_INVALID_PIXEL_FORMAT\n" );
00412       }
00413       else if ( err == ERROR_NO_SYSTEM_RESOURCES )
00414       {
00415          fprintf( stderr, "error:  ERROR_NO_SYSTEM_RESOURCES\n" );
00416       }
00417       else if ( err == ERROR_INVALID_DATA )
00418       {
00419          fprintf( stderr, "error:  ERROR_INVALID_DATA\n" );
00420       }
00421       exit( -1 );
00422    }
00423 
00424    /// Get the device context.
00425    m_devCTX = wglGetPbufferDCARB( m_buffer );
00426    if ( !m_devCTX )
00427    {
00428       fprintf( stderr, "pbuffer creation error:  wglGetPbufferDCARB() failed\n" );
00429       exit( -1 );
00430    }
00431 
00432    /// Create a gl render-context for the pbuffer.
00433    if( m_renCTX == NULL ) {
00434       m_renCTX = wglCreateContext( m_devCTX );
00435 
00436       if( m_mode & PBUFF_SHARE )
00437       {
00438          HGLRC curRenCTX = wglGetCurrentContext();
00439 
00440          /// Share the textures/displayLists/etc between the current context and this pbuffer
00441          if( !wglShareLists( curRenCTX,  m_renCTX ) )
00442          {
00443             fprintf( stderr, "pbuffer: wglShareLists() failed\n" );
00444             exit( -1 );
00445          }
00446       }
00447    }
00448 
00449    if ( !m_renCTX ) {
00450       fprintf( stderr, "pbuffer creation error:  m_renCTX==NULL\n" );
00451       exit( -1 );
00452    }
00453 
00454    /// Determine the actual m_dimen.w and m_dimen.h we were able to create.
00455    wglQueryPbufferARB( m_buffer, WGL_PBUFFER_WIDTH_ARB, &m_xDim );
00456    wglQueryPbufferARB( m_buffer, WGL_PBUFFER_HEIGHT_ARB, &m_yDim);
00457 
00458    // Ensure that DC is correct by binding buffer once and releasing it.
00459    //this->enable(true);
00460    //m_devCTX = wglGetCurrentDC();
00461    //m_renCTX = wglGetCurrentContext();
00462    //this->disable();
00463 
00464 #else /// Linux
00465    int  iAttrib[2*MAX_ATTRIBS];
00466 
00467    GLXFBConfigID configid;
00468    if ( glXQueryContext( glXGetCurrentDisplay(), glXGetCurrentContext(), GLX_FBCONFIG_ID, (int*)&configid ) != Success )
00469    {
00470       cerr << "PBuffer::Create() Error: glXQueryContext failed.\n" << endl;
00471       exit(1);
00472    }
00473    //glXQueryDrawable( glXGetCurrentDisplay(), glXGetCurrentDrawable(), GLX_FBCONFIG_ID, (int*)&configid );
00474    iAttrib[0] = GLX_FBCONFIG_ID;
00475    iAttrib[1] = configid;
00476    iAttrib[2] = 0;
00477    int n;
00478    GLXFBConfig* config = glXChooseFBConfig(glXGetCurrentDisplay(), DefaultScreen(glXGetCurrentDisplay()), iAttrib, &n);
00479    if (config == NULL || n == 0)
00480    {
00481       cerr << "PBuffer::Create() Error: glXChooseFBConfig failed.\n" << endl;
00482       exit(1);
00483    }
00484    iAttrib[0] = GLX_PBUFFER_WIDTH;
00485    iAttrib[1] = m_xDim;
00486    iAttrib[2] = GLX_PBUFFER_HEIGHT;
00487    iAttrib[3] = m_yDim;
00488    iAttrib[4] = GLX_PRESERVED_CONTENTS; /// we don't want to lose the buffer
00489    iAttrib[5] = true;
00490    iAttrib[6] = GLX_LARGEST_PBUFFER; /// we need exact size or fail
00491    iAttrib[7] = false;
00492    iAttrib[8] = 0;    
00493    m_buffer = glXCreatePbuffer( glXGetCurrentDisplay(), *config, iAttrib);
00494    if (m_buffer == 0)
00495    {
00496       cerr << "PBuffer::Create() Error: glXCreatePbuffer failed.\n" << endl;
00497       exit(1);
00498    }            
00499 #endif
00500 }
00501 
00502 #ifdef WIN32
00503 
00504 ///////////////////////////////////////////////////////////
00505 ///////////////////////////////////////////////////////////
00506 /// Attempts to find a pixel format that matches "m_mode"
00507 int PBuffer::setPixelFormat( HDC curDevCTX )
00508 {
00509    /// Query for a suitable pixel format based on the specified m_mode.
00510    int iAttrib[MAX_ATTRIBS][2] = {0};
00511    int nI = 0;
00512 
00513    /// Since we are trying to create a pbuffer, the pixel format we
00514    /// request (and subsequently use) must be "p-m_buffer capable".
00515    iAttrib[nI][0] = WGL_DRAW_TO_PBUFFER_ARB;
00516    iAttrib[nI][1] = true;
00517    nI++;
00518 
00519    // Data Format Type: Fixed or floating point: Default is RGBA, fixed-point
00520 
00521    if ( (m_mode & PBUFF_FLOAT16) || (m_mode & PBUFF_FLOAT32) ) {// Floating point buffer
00522       if( wglew.ATI_pixel_format_float ) {
00523          iAttrib[nI][0] = WGL_PIXEL_TYPE_ARB;
00524          iAttrib[nI][1] = WGL_TYPE_RGBA_FLOAT_ATI;
00525          nI++;
00526       }
00527       else if( wglew.NV_float_buffer ) {
00528          iAttrib[nI][0] = WGL_FLOAT_COMPONENTS_NV;
00529          iAttrib[nI][1] = GL_TRUE;
00530          nI++;
00531       }
00532       else {
00533          cerr << "Pbuffer::setPixelFormat(...) Error:\n\t"
00534             "GPU not capable of floating point pbuffers.\n"
00535             "At least ATI 9500/9700 or Nvidia GeForceFX is required.\n";
00536          exit(1);
00537       }
00538    }
00539    else {                                                                                                               // Fixed-point
00540       iAttrib[nI][0] = WGL_PIXEL_TYPE_ARB;
00541       iAttrib[nI][1] = WGL_TYPE_RGBA_ARB;
00542       nI++;
00543    }
00544 
00545    // Data Format Size: 8, 16, or 32 bits per color channel: Default is 8
00546    int bitsPerChannel = 8;
00547    if (  (m_mode & PBUFF_FIXED16) ||
00548       (m_mode & PBUFF_FLOAT16)  ) { bitsPerChannel = 16; }
00549    else if( (m_mode & PBUFF_FLOAT32)  ) { bitsPerChannel = 32; }
00550    else                                                      { bitsPerChannel = 8;  }
00551 
00552    iAttrib[nI][0] = WGL_RED_BITS_ARB;
00553    iAttrib[nI][1] = bitsPerChannel;
00554    nI++;
00555    iAttrib[nI][0] = WGL_GREEN_BITS_ARB;
00556    iAttrib[nI][1] = bitsPerChannel;
00557    nI++;
00558    iAttrib[nI][0] = WGL_BLUE_BITS_ARB;
00559    iAttrib[nI][1] = bitsPerChannel;
00560    nI++;
00561    iAttrib[nI][0] = WGL_ALPHA_BITS_ARB;
00562    iAttrib[nI][1] = bitsPerChannel;
00563    nI++;
00564 
00565    if ( m_mode & PBUFF_DOUBLE )
00566    {
00567       iAttrib[nI][0] = WGL_DOUBLE_BUFFER_ARB;
00568       iAttrib[nI][1] = true;
00569       nI++;
00570    }
00571 
00572    // Depth buffer
00573    int depthBits = (m_mode & PBUFF_DEPTH24) ? 24 : (m_mode & PBUFF_DEPTH16) ? 16 : 0;
00574    iAttrib[nI][0] = WGL_DEPTH_BITS_ARB;
00575    iAttrib[nI][1] = depthBits;
00576    nI++;
00577 
00578    if ( m_mode & PBUFF_STENCIL )
00579    {
00580       iAttrib[nI][0] = WGL_STENCIL_BITS_ARB;
00581       iAttrib[nI][1] = 8;
00582       nI++;
00583    }
00584 
00585    if ( m_mode & PBUFF_ACCUM )
00586    {
00587       iAttrib[nI][0] = WGL_ACCUM_BITS_ARB;
00588       iAttrib[nI][1] = 24;
00589       nI++;
00590    }
00591 
00592    // AUX buffers
00593    if( m_mode & PBUFF_AUX1 ) {
00594       iAttrib[nI][0] = WGL_AUX_BUFFERS_ARB;
00595       iAttrib[nI][1] = 1;
00596       nI++;
00597    }
00598    else if( m_mode & PBUFF_AUX2 ) {
00599       iAttrib[nI][0] = WGL_AUX_BUFFERS_ARB;
00600       iAttrib[nI][1] = 2;
00601       nI++;
00602    }
00603    else if( m_mode & PBUFF_AUX3 ) {
00604       iAttrib[nI][0] = WGL_AUX_BUFFERS_ARB;
00605       iAttrib[nI][1] = 3;
00606       nI++;
00607    }
00608 
00609    iAttrib[nI][0] = WGL_SUPPORT_OPENGL_ARB;
00610    iAttrib[nI][1] = true;
00611    nI++;
00612 
00613    if( m_mode & PBUFF_REND_TO_TEX ){
00614       // Nvidia floating point RTT
00615       if( glew.NV_float_buffer && (m_mode & PBUFF_FLOAT16 || m_mode & PBUFF_FLOAT32)) {
00616          m_mode |= PBUFF_RECT;
00617          iAttrib[nI][0] = WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV;
00618          iAttrib[nI][1] = true;
00619          nI++;
00620       }
00621       else if( wglew.NV_render_texture_rectangle ) {
00622          // Nvidia fixed point RTT
00623          m_mode |= PBUFF_RECT;
00624          iAttrib[nI][0] = WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV;
00625          iAttrib[nI][1] = true;
00626          nI++;
00627       }
00628       else {
00629          // ATI all formats
00630          iAttrib[nI][0] = WGL_BIND_TO_TEXTURE_RGBA_ARB;
00631          iAttrib[nI][1] = true;
00632          nI++;
00633       }
00634    }
00635    iAttrib[nI][0] = 0;
00636 
00637    int format;
00638    int pformat[MAX_PFORMATS];
00639    unsigned int nformats;
00640    if ( !wglChoosePixelFormatARB( curDevCTX, &iAttrib[0][0], NULL, MAX_PFORMATS, pformat, &nformats ) )
00641    {
00642       fprintf( stderr, "pbuffer creation error:  Couldn't find a suitable pixel format.\n" );
00643       exit( -1 );
00644    }
00645    format = pformat[0];
00646 
00647 
00648 #if DEBUGGING
00649    FILE *fp = fopen( "debug.txt", "w" );
00650    if ( !fp )
00651    {
00652       fprintf( stderr, "Couldn't open file: debug.txt\n" );
00653       exit( -1 );
00654    }
00655 
00656    fprintf( fp, "nformats = %d\n\n", nformats );
00657    int values[MAX_ATTRIBS];
00658    int iatr[MAX_ATTRIBS] = { WGL_PIXEL_TYPE_ARB, WGL_COLOR_BITS_ARB,
00659       WGL_RED_BITS_ARB, WGL_GREEN_BITS_ARB, WGL_BLUE_BITS_ARB,
00660       WGL_ALPHA_BITS_ARB, WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB, WGL_ACCUM_BITS_ARB,
00661       WGL_DOUBLE_BUFFER_ARB, WGL_SUPPORT_OPENGL_ARB, WGL_ACCELERATION_ARB };
00662    int niatr = 12;
00663    for ( int j = 0; j < MAX_ATTRIBS; j++ )
00664    {
00665       values[j] = false;
00666       iAttrib[j] = iAttrib[2*j];
00667    }
00668    for ( unsigned int i = 0; i < nformats; i++ )
00669    {
00670       HDC   curDevCTX = wglGetCurrentDC();
00671       if ( !wglGetPixelFormatAttribivARB( curDevCTX, pformat[i], 0, niatr, iatr, values ) )
00672       {
00673          fprintf( stderr, "pbuffer creation error:  wglGetPixelFormatAttribiv() failed\n" );
00674          exit( -1 );
00675       }
00676       fprintf( fp, "%d. pformat = %d\n", i, pformat[i] );
00677       fprintf( fp, "--------------------\n" );
00678       for ( int k = 0; k < niatr; k++ )
00679       {
00680          if ( iatr[k] == WGL_PIXEL_TYPE_ARB )
00681          {
00682             if ( values[k] == WGL_TYPE_COLORINDEX_ARB )
00683                fprintf( fp, " Pixel type = WGL_TYPE_COLORINDEX_ARB\n" );
00684             if ( values[k] == WGL_TYPE_RGBA_ARB )
00685                fprintf( fp, " Pixel type = WGL_TYPE_RGBA_ARB\n" );
00686          }
00687          if ( iatr[k] == WGL_COLOR_BITS_ARB )
00688          {
00689             fprintf( fp, " Color bits = %d\n", values[k] );
00690          }
00691          if ( iatr[k] == WGL_RED_BITS_ARB )
00692          {
00693             fprintf( fp, "      red         %d\n", values[k] );
00694          }
00695          if ( iatr[k] == WGL_GREEN_BITS_ARB )
00696          {
00697             fprintf( fp, "      green       %d\n", values[k] );
00698          }
00699          if ( iatr[k] == WGL_BLUE_BITS_ARB )
00700          {
00701             fprintf( fp, "      blue        %d\n", values[k] );
00702          }
00703          if ( iatr[k] == WGL_ALPHA_BITS_ARB )
00704          {
00705             fprintf( fp, "      alpha       %d\n", values[k] );
00706          }
00707          if ( iatr[k] == WGL_DEPTH_BITS_ARB )
00708          {
00709             fprintf( fp, " Depth bits =   %d\n", values[k] );
00710          }
00711          if ( iatr[k] == WGL_STENCIL_BITS_ARB )
00712          {
00713             fprintf( fp, " Stencil bits = %d\n", values[k] );
00714          }
00715          if ( iatr[k] == WGL_ACCUM_BITS_ARB )
00716          {
00717             fprintf( fp, " Accum bits =   %d\n", values[k] );
00718          }
00719          if ( iatr[k] == WGL_DOUBLE_BUFFER_ARB )
00720          {
00721             fprintf( fp, " Double Buffer  = %d\n", values[k] );
00722          }
00723          if ( iatr[k] == WGL_SUPPORT_OPENGL_ARB )
00724          {
00725             fprintf( fp, " Support OpenGL = %d\n", values[k] );
00726          }
00727          if ( iatr[k] == WGL_ACCELERATION_ARB )
00728          {
00729             if ( values[k] == WGL_FULL_ACCELERATION_ARB ) {
00730                fprintf( fp, " Acceleration   = WGL_FULL_ACCELERATION_ARB\n" );
00731             }
00732             if ( values[k] == WGL_GENERIC_ACCELERATION_ARB ) {
00733                fprintf( fp, " Acceleration   = WGL_GENERIC_ACCELERATION_ARB\n" );
00734             }
00735          }
00736       }
00737       fprintf( fp, "\n" );
00738    }
00739    fprintf( fp, "selected pformat = %d\n", format );
00740    fprintf( stderr, "Created a %d x %d pbuffer\n", m_xDim, m_yDim );
00741    fclose( fp );
00742 #endif
00743 
00744    return format;
00745 }
00746 
00747 int PBuffer::setPixelFormatNV_HACK( HDC curDevCTX )
00748 {
00749    int iattributes[MAX_ATTRIBS*2] = {0};
00750    int niattribs= 0;
00751    int bitsPerChannel= 32;
00752 
00753 
00754    // This Pbuffer would have to be bound a WGL_TEXTURE_RECTANGLE_NV texture
00755    // with the format WGL_TEXTURE_RECTANGLE_FLOAT_RGBA_NV
00756    iattributes[niattribs] = WGL_RED_BITS_ARB;
00757    iattributes[++niattribs] = bitsPerChannel;
00758    iattributes[++niattribs] = WGL_GREEN_BITS_ARB;
00759    iattributes[++niattribs] = bitsPerChannel;
00760    iattributes[++niattribs] = WGL_BLUE_BITS_ARB;
00761    iattributes[++niattribs] = bitsPerChannel;
00762    iattributes[++niattribs] = WGL_ALPHA_BITS_ARB;
00763    iattributes[++niattribs] = bitsPerChannel;
00764    iattributes[++niattribs] = WGL_DRAW_TO_PBUFFER_ARB;
00765    iattributes[++niattribs] = GL_TRUE;
00766    iattributes[++niattribs] = WGL_FLOAT_COMPONENTS_NV;
00767    iattributes[++niattribs] = GL_TRUE;
00768    iattributes[++niattribs] = WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV;
00769    iattributes[++niattribs] = GL_TRUE;
00770 
00771    /*
00772    // 8 bit doesn't work with the rest of the code
00773    iattributes[niattribs] = WGL_DRAW_TO_PBUFFER_ARB;
00774    iattributes[++niattribs] = GL_TRUE;
00775    iattributes[++niattribs] = WGL_BIND_TO_TEXTURE_RGBA_ARB;
00776    iattributes[++niattribs] = GL_TRUE;
00777    */
00778    int format;
00779    int pformat[MAX_PFORMATS];
00780    unsigned int nformats;
00781    if ( !wglChoosePixelFormatARB( curDevCTX, &iattributes[0], NULL, MAX_PFORMATS, pformat, &nformats ) )
00782    {
00783       fprintf( stderr, "pbuffer creation error:  Couldn't find a suitable pixel format.\n" );
00784       exit( -1 );
00785    }
00786    format = pformat[0];
00787 
00788    return format;
00789 }
00790 #endif //WIN32
00791 
00792 

Send questions, comments, and bug reports to:
jmk