Back to index

nux  3.0.0
GLPBuffer.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 #ifndef NUX_OPENGLES_20
00023 
00024 #include "NuxCore/NuxCore.h"
00025 #include "GLResource.h"
00026 #include "GLPBuffer.h"
00027 
00028 namespace nux
00029 {
00030 
00031 #if defined(NUX_OS_WINDOWS)
00032 
00033   PBuffer::PBuffer (const char *strMode, bool managed)
00034     : m_hDC (0), m_hGLRC (0), m_hPBuffer (0), m_hOldGLRC (0), m_hOldDC (0),
00035       m_bIsTexture (false), m_iWidth (0), m_iHeight (0), m_strMode (strMode),
00036       m_bSharedContext (false), m_bShareObjects (false), m_bIsBound (false),
00037       m_bIsActive (false), m_bManaged (managed)
00038   {
00039     m_pfAttribList.push_back (WGL_DRAW_TO_PBUFFER_ARB);
00040     m_pfAttribList.push_back (true);
00041     m_pfAttribList.push_back (WGL_SUPPORT_OPENGL_ARB);
00042     m_pfAttribList.push_back (true);
00043 
00044     m_pbAttribList.push_back (WGL_PBUFFER_LARGEST_ARB);
00045     m_pbAttribList.push_back (true);
00046 
00047     nuxDebugMsg (TEXT ("Declare a Pbuffer with \"%s\" parameters\n"), strMode);
00048     m_strMode = strMode;
00049     parseModeString (m_strMode, &m_pfAttribList, &m_pbAttribList);
00050 
00051     m_pfAttribList.push_back (0);
00052     m_pbAttribList.push_back (0);
00053   }
00054 
00055   PBuffer::~PBuffer()
00056   {
00057     if (m_bManaged)
00058       Destroy();
00059   }
00060 
00061 // This function actually does the creation of the p-buffer.
00062 // It can only be called once a window has already been created.
00063   bool PBuffer::Initialize (int iWidth, int iHeight, bool bShareContexts, bool bShareObjects)
00064   {
00065     HDC hdc = wglGetCurrentDC();
00066     HGLRC hglrc = wglGetCurrentContext();
00067     int format = 0;
00068     int nfattribs = 0;
00069     int niattribs = 0;
00070 
00071     m_iWidth = iWidth;
00072     m_iHeight = iHeight;
00073 
00074     m_bSharedContext = bShareContexts;
00075     m_bShareObjects = bShareObjects;
00076 
00077     if (m_bSharedContext)
00078     {
00079       // Get the pixel format for the on-screen window.
00080       format = GetPixelFormat (hdc);
00081 
00082       if (format == 0)
00083       {
00084         nuxDebugMsg (TEXT ("pbuffer creation error:  GetPixelFormat() failed") );
00085         return false;
00086       }
00087     }
00088     else
00089     {
00090       unsigned int nformats;
00091       wglChoosePixelFormatARB (hdc, &m_pfAttribList[0], NULL, 1, &format, &nformats);
00092 
00093       if (nformats == 0)
00094       {
00095         nuxDebugMsg (TEXT ("pbuffer creation error:  Couldn't find a suitable pixel format.") );
00096         return false;
00097       }
00098     }
00099 
00100     m_hPBuffer = wglCreatePbufferARB (hdc, format, m_iWidth, m_iHeight, &m_pbAttribList[0]);
00101 
00102     if (!m_hPBuffer)
00103     {
00104       DWORD err = GetLastError();
00105       nuxDebugMsg (TEXT ("pbuffer creation error:  wglCreatePbufferARB() failed") );
00106 
00107       if (err == ERROR_INVALID_PIXEL_FORMAT)
00108       {
00109         nuxDebugMsg (TEXT ("error:  ERROR_INVALID_PIXEL_FORMAT") );
00110       }
00111       else if (err == ERROR_NO_SYSTEM_RESOURCES)
00112       {
00113         nuxDebugMsg (TEXT ("error:  ERROR_NO_SYSTEM_RESOURCES") );
00114       }
00115       else if (err == ERROR_INVALID_DATA)
00116       {
00117         nuxDebugMsg (TEXT ("error:  ERROR_INVALID_DATA") );
00118       }
00119 
00120       return false;
00121     }
00122 
00123     // Get the device context.
00124     m_hDC = wglGetPbufferDCARB (m_hPBuffer);
00125 
00126     if (!m_hDC)
00127     {
00128       nuxDebugMsg (TEXT ("pbuffer creation error:  wglGetPbufferDCARB() failed") );
00129       return false;
00130     }
00131 
00132     if (m_bSharedContext)
00133     {
00134       // Let's use the same gl context..
00135       // Since the device contexts are compatible (i.e. same pixelformat),
00136       // we should be able to use the same gl rendering context.
00137       m_hGLRC = hglrc;
00138     }
00139     else
00140     {
00141       // Create a new gl context for the p-buffer.
00142       m_hGLRC = wglCreateContext (m_hDC);
00143 
00144       if (!m_hGLRC)
00145       {
00146         nuxDebugMsg (TEXT ("pbuffer creation error:  wglCreateContext() failed") );
00147         return false;
00148       }
00149 
00150       if (m_bShareObjects)
00151       {
00152         if (!wglShareLists (hglrc, m_hGLRC) )
00153         {
00154           nuxDebugMsg (TEXT ("pbuffer: wglShareLists() failed") );
00155           return false;
00156         }
00157       }
00158     }
00159 
00160     GLint texFormat = WGL_NO_TEXTURE_ARB;
00161     wglQueryPbufferARB (m_hPBuffer, WGL_TEXTURE_FORMAT_ARB, &texFormat);
00162 
00163     if (texFormat != WGL_NO_TEXTURE_ARB)
00164       m_bIsTexture = true;
00165 
00166     // Determine the actual width and height we were able to create.
00167     wglQueryPbufferARB (m_hPBuffer, WGL_PBUFFER_WIDTH_ARB, &m_iWidth);
00168     wglQueryPbufferARB (m_hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &m_iHeight);
00169 
00170     nuxDebugMsg ("Created a %d x %d pbuffer\n", m_iWidth, m_iHeight);
00171 
00172 #ifdef _DEBUG
00173     // query pixel format
00174     int iattributes[] =
00175     {
00176       WGL_RED_BITS_ARB,
00177       WGL_GREEN_BITS_ARB,
00178       WGL_BLUE_BITS_ARB,
00179       WGL_ALPHA_BITS_ARB,
00180       WGL_FLOAT_COMPONENTS_NV,
00181       WGL_DEPTH_BITS_ARB,
00182       WGL_SAMPLES_EXT,
00183       WGL_AUX_BUFFERS_ARB
00184     };
00185     int ivalues[sizeof (iattributes) / sizeof (int) ];
00186 
00187     if (wglGetPixelFormatAttribivARB (m_hDC, format, 0, sizeof (iattributes) / sizeof (int), iattributes, ivalues) )
00188     {
00189       nuxDebugMsg ("r:%d g:%d b:%d a:%d float:%d depth:%d samples:%d aux:%d\n",
00190                    ivalues[0], ivalues[1], ivalues[2], ivalues[3], ivalues[4], ivalues[5], ivalues[6], ivalues[7]);
00191     }
00192 
00193 #endif
00194 
00195     return true;
00196   }
00197 
00198   void PBuffer::Destroy()
00199   {
00200     if (m_hPBuffer)
00201     {
00202       if (!m_bSharedContext) wglDeleteContext (m_hGLRC);
00203 
00204       wglReleasePbufferDCARB (m_hPBuffer, m_hDC);
00205       wglDestroyPbufferARB (m_hPBuffer);
00206     }
00207   }
00208 
00209   void PBuffer::parseModeString (const char *modeString, std::vector<int> *pfAttribList, std::vector<int> *pbAttribList)
00210   {
00211     if (!modeString || strcmp (modeString, "") == 0)
00212       return;
00213 
00214     m_iBitsPerComponent = 8;
00215     m_iNComponents = 0;
00216     bool bIsFloatBuffer = false;
00217     bool bIsATIFloatBuffer = false;
00218     bool bIsTexture = false;
00219     bool bNeedAlpha = false;
00220 
00221     char *mode = _strdup (modeString);
00222 
00223     std::vector<std::string> tokens;
00224     char *next_token = NULL;
00225 #ifdef WIN32_SECURE
00226     char *buf = strtok_s (mode, " ", &next_token);
00227 #else
00228     char *buf = strtok (mode, " ");
00229 #endif
00230 
00231     while (buf != NULL)
00232     {
00233       if (strstr (buf, "ati_float") != NULL)
00234         bIsATIFloatBuffer = true;
00235       else if (strstr (buf, "float") != NULL)
00236         bIsFloatBuffer = true;
00237 
00238       if (strstr (buf, "texture") != NULL)
00239         bIsTexture = true;
00240 
00241       if (strstr (buf, "alpha") != NULL)
00242         bNeedAlpha = true;
00243 
00244       tokens.push_back (buf);
00245 #ifdef WIN32_SECURE
00246       buf = strtok_s (NULL, " ", &next_token);
00247 #else
00248       buf = strtok (NULL, " ");
00249 #endif
00250     }
00251 
00252     pfAttribList->push_back (WGL_PIXEL_TYPE_ARB);
00253 #ifdef WGL_ATI_pixel_format_float
00254 
00255     if (bIsATIFloatBuffer)
00256     {
00257       pfAttribList->push_back (WGL_TYPE_RGBA_FLOAT_ATI);
00258     }
00259     else
00260 #endif
00261     {
00262       pfAttribList->push_back (WGL_TYPE_RGBA_ARB);
00263     }
00264 
00265     for (unsigned int i = 0; i < tokens.size(); i++)
00266     {
00267       std::string token = tokens[i];
00268 
00269       if (token == "rgb" && (m_iNComponents <= 1) )
00270       {
00271         /*            pfAttribList->push_back(WGL_RED_BITS_ARB);
00272                     pfAttribList->push_back(m_iBitsPerComponent);
00273                     pfAttribList->push_back(WGL_GREEN_BITS_ARB);
00274                     pfAttribList->push_back(m_iBitsPerComponent);
00275                     pfAttribList->push_back(WGL_BLUE_BITS_ARB);
00276                     pfAttribList->push_back(m_iBitsPerComponent);*/
00277         m_iNComponents += 3;
00278         continue;
00279       }
00280       else if (token == "rgb") nuxDebugMsg ("warning : mistake in components definition (rgb + %d)\n", m_iNComponents);
00281 
00282 
00283       if (token == "rgba" && (m_iNComponents == 0) )
00284       {
00285         /*pfAttribList->push_back(WGL_RED_BITS_ARB);
00286         pfAttribList->push_back(m_iBitsPerComponent);
00287         pfAttribList->push_back(WGL_GREEN_BITS_ARB);
00288         pfAttribList->push_back(m_iBitsPerComponent);
00289         pfAttribList->push_back(WGL_BLUE_BITS_ARB);
00290         pfAttribList->push_back(m_iBitsPerComponent);
00291         pfAttribList->push_back(WGL_ALPHA_BITS_ARB);
00292         pfAttribList->push_back(m_iBitsPerComponent);*/
00293         m_iNComponents = 4;
00294         continue;
00295       }
00296       else if (token == "rgba") nuxDebugMsg ("warning : mistake in components definition (rgba + %d)\n", m_iNComponents);
00297 
00298       if (token == "alpha" && (m_iNComponents <= 3) )
00299       {
00300         /*pfAttribList->push_back(WGL_ALPHA_BITS_ARB);
00301         pfAttribList->push_back(m_iBitsPerComponent);*/
00302         m_iNComponents++;
00303         continue;
00304       }
00305       else if (token == "alpha") nuxDebugMsg ("warning : mistake in components definition (alpha + %d)\n", m_iNComponents);
00306 
00307 
00308       if (token == "r" && (m_iNComponents <= 1) ) // && bIsFloatBuffer)
00309       {
00310         /*pfAttribList->push_back(WGL_RED_BITS_ARB);
00311         pfAttribList->push_back(m_iBitsPerComponent);*/
00312         m_iNComponents++;
00313         continue;
00314       }
00315       else if (token == "r") nuxDebugMsg ("warning : mistake in components definition (r + %d)\n", m_iNComponents);
00316 
00317       if (token == "rg" && (m_iNComponents <= 1) ) // && bIsFloatBuffer)
00318       {
00319         /*pfAttribList->push_back(WGL_RED_BITS_ARB);
00320         pfAttribList->push_back(m_iBitsPerComponent);
00321         pfAttribList->push_back(WGL_GREEN_BITS_ARB);
00322         pfAttribList->push_back(m_iBitsPerComponent);*/
00323         m_iNComponents += 2;
00324         continue;
00325       }
00326       else if (token == "r") nuxDebugMsg ("warning : mistake in components definition (rg + %d)\n", m_iNComponents);
00327 
00328       if (token.find ("depth") == 0)
00329       {
00330         pfAttribList->push_back (WGL_DEPTH_BITS_ARB);
00331         pfAttribList->push_back (getIntegerValue (token) );
00332 
00333         continue;
00334       }
00335 
00336       if (token.find ("stencil") == 0)
00337       {
00338         pfAttribList->push_back (WGL_STENCIL_BITS_ARB);
00339         pfAttribList->push_back (8);
00340 
00341         continue;
00342       }
00343 
00344       if (token.find ("samples") == 0)
00345       {
00346         pfAttribList->push_back (WGL_SAMPLE_BUFFERS_ARB);
00347         pfAttribList->push_back (1);
00348         pfAttribList->push_back (WGL_SAMPLES_ARB);
00349         pfAttribList->push_back (getIntegerValue (token) );
00350 
00351         continue;
00352       }
00353 
00354       if (token.find ("aux") == 0)
00355       {
00356         pfAttribList->push_back (WGL_AUX_BUFFERS_ARB);
00357         pfAttribList->push_back (getIntegerValue (token) );
00358         continue;
00359       }
00360 
00361       if (token == "double")
00362       {
00363         pfAttribList->push_back (WGL_DOUBLE_BUFFER_ARB);
00364         pfAttribList->push_back (true);
00365 
00366         continue;
00367       }
00368 
00369       if (token.find ("ati_float") == 0)
00370       {
00371         m_iBitsPerComponent = getIntegerValue (token);
00372         // type already set above
00373         continue;
00374 
00375       }
00376       else if (token.find ("float") == 0)
00377       {
00378         m_iBitsPerComponent = getIntegerValue (token);
00379         //bIsFloatBuffer = true; done previously
00380         pfAttribList->push_back (WGL_FLOAT_COMPONENTS_NV);
00381         pfAttribList->push_back (true);
00382 
00383         continue;
00384       }
00385 
00386       if (token.find ("texture") == 0)
00387       {
00388         if (token.find ("textureRECT") == 0 || bIsFloatBuffer)
00389         {
00390           pbAttribList->push_back (WGL_TEXTURE_TARGET_ARB);
00391           pbAttribList->push_back (WGL_TEXTURE_RECTANGLE_NV);
00392         }
00393         else if (token.find ("textureCUBE") == 0)
00394         {
00395           pbAttribList->push_back (WGL_TEXTURE_TARGET_ARB);
00396           pbAttribList->push_back (WGL_TEXTURE_CUBE_MAP_ARB);
00397         }
00398         else
00399         {
00400           pbAttribList->push_back (WGL_TEXTURE_TARGET_ARB);
00401           pbAttribList->push_back (WGL_TEXTURE_2D_ARB);
00402         }
00403 
00404         if (bIsFloatBuffer || bIsATIFloatBuffer)
00405         {
00406           if (m_iNComponents == 0)
00407           {
00408             nuxDebugMsg ("components not specified. assuming rgba...\n");
00409             pfAttribList->push_back (WGL_RED_BITS_ARB);
00410             pfAttribList->push_back (m_iBitsPerComponent);
00411             pfAttribList->push_back (WGL_GREEN_BITS_ARB);
00412             pfAttribList->push_back (m_iBitsPerComponent);
00413             pfAttribList->push_back (WGL_BLUE_BITS_ARB);
00414             pfAttribList->push_back (m_iBitsPerComponent);
00415             pfAttribList->push_back (WGL_ALPHA_BITS_ARB);
00416             pfAttribList->push_back (m_iBitsPerComponent);
00417             m_iNComponents = 4;
00418           }
00419         }
00420 
00421         if (bIsFloatBuffer)
00422         {
00423           switch (m_iNComponents)
00424           {
00425             case 1:
00426               pfAttribList->push_back (WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV);
00427               pfAttribList->push_back (true);
00428 
00429               pbAttribList->push_back (WGL_TEXTURE_FORMAT_ARB);
00430               pbAttribList->push_back (WGL_TEXTURE_FLOAT_R_NV);
00431               break;
00432             case 2:
00433               pfAttribList->push_back (WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV);
00434               pfAttribList->push_back (true);
00435 
00436               pbAttribList->push_back (WGL_TEXTURE_FORMAT_ARB);
00437               pbAttribList->push_back (WGL_TEXTURE_FLOAT_RG_NV);
00438               break;
00439             case 3:
00440               pfAttribList->push_back (WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
00441               pfAttribList->push_back (true);
00442 
00443               pbAttribList->push_back (WGL_TEXTURE_FORMAT_ARB);
00444               pbAttribList->push_back (WGL_TEXTURE_FLOAT_RGB_NV);
00445               break;
00446             case 4:
00447               pfAttribList->push_back (WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV);
00448               pfAttribList->push_back (true);
00449 
00450               pbAttribList->push_back (WGL_TEXTURE_FORMAT_ARB);
00451               pbAttribList->push_back (WGL_TEXTURE_FLOAT_RGBA_NV);
00452               break;
00453             default:
00454               nuxDebugMsg ("Bad number of components (r=1,rg=2,rgb=3,rgba=4): %d\n", m_iNComponents);
00455               break;
00456           }
00457         }
00458         else
00459         {
00460           switch (m_iNComponents)
00461           {
00462             case 3:
00463               pfAttribList->push_back (WGL_BIND_TO_TEXTURE_RGB_ARB);
00464               pfAttribList->push_back (true);
00465 
00466               pbAttribList->push_back (WGL_TEXTURE_FORMAT_ARB);
00467               pbAttribList->push_back (WGL_TEXTURE_RGB_ARB);
00468               break;
00469             case 4:
00470               pfAttribList->push_back (WGL_BIND_TO_TEXTURE_RGBA_ARB);
00471               pfAttribList->push_back (true);
00472 
00473               pbAttribList->push_back (WGL_TEXTURE_FORMAT_ARB);
00474               pbAttribList->push_back (WGL_TEXTURE_RGBA_ARB);
00475               break;
00476             default:
00477               nuxDebugMsg ("Bad number of components (r=1,rg=2,rgb=3,rgba=4): %d\n", m_iNComponents);
00478               break;
00479           }
00480         }
00481 
00482         std::string option = getStringValue (token);
00483 
00484         if (option == "depth")
00485         {
00486           pfAttribList->push_back (WGL_BIND_TO_TEXTURE_DEPTH_NV);
00487           pfAttribList->push_back (true);
00488 
00489           pbAttribList->push_back (WGL_DEPTH_TEXTURE_FORMAT_NV);
00490           pbAttribList->push_back (WGL_TEXTURE_DEPTH_COMPONENT_NV);
00491         }
00492 
00493         continue;
00494       }
00495 
00496       if (token.find ("mipmap") == 0 && bIsTexture)
00497       {
00498         pbAttribList->push_back (WGL_MIPMAP_TEXTURE_ARB);
00499         pbAttribList->push_back (true);
00500 
00501         continue;
00502       }
00503 
00504       nuxDebugMsg ("unknown pbuffer attribute: %s\n", token.c_str() );
00505     }
00506 
00507     if (m_iNComponents > 0)
00508     {
00509       pfAttribList->push_back (WGL_RED_BITS_ARB);
00510       pfAttribList->push_back (m_iBitsPerComponent);
00511     }
00512 
00513     if (m_iNComponents > 1)
00514     {
00515       pfAttribList->push_back (WGL_GREEN_BITS_ARB);
00516       pfAttribList->push_back (m_iBitsPerComponent);
00517     }
00518 
00519     if (m_iNComponents > 2)
00520     {
00521       pfAttribList->push_back (WGL_BLUE_BITS_ARB);
00522       pfAttribList->push_back (m_iBitsPerComponent);
00523     }
00524 
00525     if (m_iNComponents > 3)
00526     {
00527       pfAttribList->push_back (WGL_ALPHA_BITS_ARB);
00528       pfAttribList->push_back (m_iBitsPerComponent);
00529     }
00530   }
00531 
00532 // Check to see if the pbuffer was lost.
00533 // If it was lost, destroy it and then recreate it.
00534   void PBuffer::HandleModeSwitch()
00535   {
00536     int lost = 0;
00537 
00538     wglQueryPbufferARB (m_hPBuffer, WGL_PBUFFER_LOST_ARB, &lost);
00539 
00540     if (lost)
00541     {
00542       this->~PBuffer();
00543       Initialize (m_iWidth, m_iHeight, m_bSharedContext, m_bShareObjects);
00544     }
00545   }
00546 
00547   int PBuffer::Bind (int iBuffer)
00548   {
00549     if (!m_bIsTexture)
00550     {
00551       nuxDebugMsg ("PBuffer::Bind() failed - pbuffer format does not support render to texture!\n");
00552       return 0;
00553     }
00554 
00555 #if 0
00556 
00557     // SGG - with MRT it is legal to bind different buffers of a pbuffer simultaneously
00558     if (m_bIsBound)
00559     {
00560       nuxDebugMsg ("PBuffer::Bind() failed - pbuffer is already bound.\n");
00561       return 0;
00562     }
00563 
00564 #endif
00565 
00566     int ret = wglBindTexImageARB (m_hPBuffer, iBuffer);
00567 
00568     if (!ret)
00569       nuxDebugMsg ("PBuffer::Bind() failed.\n");
00570 
00571     m_bIsBound = true;
00572 
00573     return ret;
00574   }
00575 
00576   int PBuffer::Release (int iBuffer)
00577   {
00578     if (!m_bIsTexture)
00579     {
00580       nuxDebugMsg ("PBuffer::Release() failed - pbuffer format does not support render to texture!\n");
00581       return 0;
00582     }
00583 
00584 #if 0
00585 
00586     // SGG - with MRT it is legal to bind different buffers of a pbuffer simultaneously
00587     if (!m_bIsBound)
00588     {
00589       nuxDebugMsg ("PBuffer::Release() failed - pbuffer is not bound.\n");
00590       return 0;
00591     }
00592 
00593 #endif
00594 
00595     int ret = wglReleaseTexImageARB (m_hPBuffer, iBuffer);
00596 
00597     if (!ret)
00598       nuxDebugMsg ("PBuffer::Release() failed.\n");
00599 
00600     m_bIsBound = false;
00601 
00602     return ret;
00603   }
00604 
00605 
00606   void PBuffer::Activate (PBuffer *current /* = NULL */)
00607   {
00608     if (current == this)
00609     {
00610       return; // no switch necessary
00611     }
00612 
00613     if (NULL == current || !current->m_bIsActive)
00614     {
00615       if (m_bIsActive)
00616         return;
00617 
00618       m_hOldGLRC = wglGetCurrentContext();
00619       m_hOldDC = wglGetCurrentDC();
00620     }
00621     else
00622     {
00623       m_hOldGLRC = current->m_hOldGLRC;
00624       m_hOldDC = current->m_hOldDC;
00625       current->m_hOldGLRC = 0;
00626       current->m_hOldDC = 0;
00627       current->m_bIsActive = false;
00628     }
00629 
00630     if (!wglMakeCurrent (m_hDC, m_hGLRC) )
00631       nuxDebugMsg ("PBuffer::Activate() failed.\n");
00632 
00633     m_bIsActive = true;
00634   }
00635 
00636   void PBuffer::Deactivate()
00637   {
00638     if (!m_bIsActive)
00639       return;
00640 
00641     if (!wglMakeCurrent (m_hOldDC, m_hOldGLRC) )
00642       nuxDebugMsg ("PBuffer::Deactivate() failed.\n");
00643 
00644     m_hOldGLRC = 0;
00645     m_hOldDC = 0;
00646     m_bIsActive = false;
00647   }
00648 
00649 #elif defined(NUX_OS_LINUX)
00650 
00651   PBuffer::PBuffer (const char *strMode, bool managed)
00652     : m_pDisplay (0), m_glxPbuffer (0), m_glxContext (0), m_pOldDisplay (0), m_glxOldDrawable (0),
00653       m_glxOldContext (0), m_iWidth (0), m_iHeight (0), m_strMode (strMode),
00654       m_bSharedContext (false), m_bShareObjects (false), m_bManaged (managed)
00655   {
00656     m_pfAttribList.push_back (GLX_DRAWABLE_TYPE);
00657     m_pfAttribList.push_back (GLX_PBUFFER_BIT);
00658     m_pfAttribList.push_back (GLX_RENDER_TYPE);
00659     m_pfAttribList.push_back (GLX_RGBA_BIT);
00660 
00661     m_pbAttribList.push_back (GLX_LARGEST_PBUFFER);
00662     m_pbAttribList.push_back (true);
00663     m_pbAttribList.push_back (GLX_PRESERVED_CONTENTS);
00664     m_pbAttribList.push_back (true);
00665 
00666     m_strMode = strMode;
00667     parseModeString (m_strMode, &m_pfAttribList, &m_pbAttribList);
00668 
00669     m_pfAttribList.push_back (0);
00670     m_pbAttribList.push_back (0);
00671   }
00672 
00673   PBuffer::~PBuffer()
00674   {
00675     if (m_bManaged)
00676       Destroy();
00677   }
00678 
00679   bool PBuffer::Initialize (int iWidth, int iHeight, bool bShareContexts, bool bShareObjects)
00680   {
00681     Display *pDisplay = glXGetCurrentDisplay();
00682     int iScreen = DefaultScreen (pDisplay);
00683     GLXContext glxContext = glXGetCurrentContext();
00684 
00685     GLXFBConfig *glxConfig;
00686     int iConfigCount;
00687 
00688     m_bSharedContext = bShareContexts;
00689     m_bShareObjects = bShareObjects;
00690 
00691     m_iWidth = iWidth;
00692     m_iHeight = iHeight;
00693 
00694     if (m_bSharedContext)
00695     {
00696       glxConfig = glXGetFBConfigs (pDisplay, iScreen, &iConfigCount);
00697 
00698       if (!glxConfig)
00699       {
00700         nuxDebugMsg ("pbuffer creation error:  glXGetFBConfigs() failed\n");
00701         return false;
00702       }
00703     }
00704     else
00705     {
00706       glxConfig = glXChooseFBConfigSGIX (pDisplay, iScreen, &m_pfAttribList[0], &iConfigCount);
00707 
00708       if (!glxConfig)
00709       {
00710         nuxDebugMsg ("pbuffer creation error:  glXChooseFBConfig() failed\n");
00711         return false;
00712       }
00713     }
00714 
00715     m_glxPbuffer = glXCreateGLXPbufferSGIX (pDisplay, glxConfig[0], m_iWidth, m_iHeight, &m_pbAttribList[0]);
00716 
00717     if (!m_glxPbuffer)
00718     {
00719       nuxDebugMsg ("pbuffer creation error:  glXCreatePbuffer() failed\n");
00720       return false;
00721     }
00722 
00723     if (m_bSharedContext)
00724     {
00725       m_glxContext = glxContext;
00726     }
00727     else
00728     {
00729       if (m_bShareObjects)
00730         m_glxContext = glXCreateContextWithConfigSGIX (pDisplay, glxConfig[0], GLX_RGBA_TYPE, glxContext, true);
00731       else
00732         m_glxContext = glXCreateContextWithConfigSGIX (pDisplay, glxConfig[0], GLX_RGBA_TYPE, NULL, true);
00733 
00734       if (!glxConfig)
00735       {
00736         nuxDebugMsg ("pbuffer creation error:  glXCreateNewContext() failed\n");
00737         return false;
00738       }
00739     }
00740 
00741     m_pDisplay = pDisplay;
00742 
00743     unsigned int w, h;
00744     w = h = 0;
00745 
00746     glXQueryGLXPbufferSGIX (m_pDisplay, m_glxPbuffer, GLX_WIDTH, &w);
00747     glXQueryGLXPbufferSGIX (m_pDisplay, m_glxPbuffer, GLX_HEIGHT, &h);
00748     m_iWidth = w;
00749     m_iHeight = h;
00750 
00751     nuxDebugMsg ("Created a %d x %d pbuffer\n", m_iWidth, m_iHeight);
00752 
00753     return true;
00754   }
00755 
00756   void PBuffer::Destroy()
00757   {
00758     if (m_glxContext && !m_bSharedContext)
00759       glXDestroyContext (m_pDisplay, m_glxContext);
00760 
00761     if (m_glxPbuffer)
00762       glXDestroyGLXPbufferSGIX (m_pDisplay, m_glxPbuffer);
00763 
00764     m_glxContext = 0;
00765     m_glxPbuffer = 0;
00766     m_pDisplay = 0;
00767   }
00768 
00769   void PBuffer::parseModeString (const char *modeString, std::vector<int> *pfAttribList, std::vector<int> *pbAttribList)
00770   {
00771     if (!modeString || strcmp (modeString, "") == 0)
00772       return;
00773 
00774     m_iBitsPerComponent = 8;
00775     m_iNComponents = 0;
00776     bool bIsFloatBuffer = false;
00777 
00778     char *mode = strdup (modeString);
00779 
00780     std::vector<std::string> tokens;
00781     char *buf = strtok (mode, " ");
00782 
00783     while (buf != NULL)
00784     {
00785       if (strstr (buf, "float") != NULL)
00786         bIsFloatBuffer = true;
00787 
00788       tokens.push_back (buf);
00789       buf = strtok (NULL, " ");
00790     }
00791 
00792     for (unsigned int i = 0; i < tokens.size(); i++)
00793     {
00794       std::string token = tokens[i];
00795 
00796       if (token == "rgb" && !bIsFloatBuffer)
00797       {
00798         pfAttribList->push_back (GLX_RED_SIZE);
00799         pfAttribList->push_back (m_iBitsPerComponent);
00800         pfAttribList->push_back (GLX_GREEN_SIZE);
00801         pfAttribList->push_back (m_iBitsPerComponent);
00802         pfAttribList->push_back (GLX_BLUE_SIZE);
00803         pfAttribList->push_back (m_iBitsPerComponent);
00804         m_iNComponents += 3;
00805         continue;
00806       }
00807       else if (token == "rgb")
00808       {
00809         nuxDebugMsg ("warning : mistake in components definition (rgb + %d)\n", m_iNComponents);
00810       }
00811 
00812       if (token == "rgba" && (m_iNComponents == 0) )
00813       {
00814         pfAttribList->push_back (GLX_RED_SIZE);
00815         pfAttribList->push_back (m_iBitsPerComponent);
00816         pfAttribList->push_back (GLX_GREEN_SIZE);
00817         pfAttribList->push_back (m_iBitsPerComponent);
00818         pfAttribList->push_back (GLX_BLUE_SIZE);
00819         pfAttribList->push_back (m_iBitsPerComponent);
00820         pfAttribList->push_back (GLX_ALPHA_SIZE);
00821         pfAttribList->push_back (m_iBitsPerComponent);
00822         m_iNComponents = 4;
00823         continue;
00824       }
00825       else if (token == "rgba")
00826       {
00827         nuxDebugMsg ("warning : mistake in components definition (rgba + %d)\n", m_iNComponents);
00828       }
00829 
00830       if (token.find ("alpha") != token.npos)
00831       {
00832         pfAttribList->push_back (GLX_ALPHA_SIZE);
00833         pfAttribList->push_back (m_iBitsPerComponent);
00834         m_iNComponents++;
00835         continue;
00836       }
00837       else if (token == "alpha")
00838       {
00839         nuxDebugMsg ("warning : mistake in components definition (alpha + %d)\n", m_iNComponents);
00840       }
00841 
00842       if (token.find ("depth") != token.npos)
00843       {
00844         pfAttribList->push_back (GLX_DEPTH_SIZE);
00845         pfAttribList->push_back (getIntegerValue (token) );
00846 
00847         continue;
00848       }
00849 
00850       if (token.find ("stencil") != token.npos)
00851       {
00852         pfAttribList->push_back (GLX_STENCIL_SIZE);
00853         pfAttribList->push_back (getIntegerValue (token) );
00854 
00855         continue;
00856       }
00857 
00858       if (token.find ("samples") != token.npos)
00859       {
00860         pfAttribList->push_back (GLX_SAMPLE_BUFFERS_ARB);
00861         pfAttribList->push_back (1);
00862         pfAttribList->push_back (GLX_SAMPLES_ARB);
00863         pfAttribList->push_back (getIntegerValue (token) );
00864 
00865         continue;
00866       }
00867 
00868       if (token == "double")
00869       {
00870         pfAttribList->push_back (GLX_DOUBLEBUFFER);
00871         pfAttribList->push_back (true);
00872 
00873         continue;
00874       }
00875 
00876       if (token.find ("float") == 0)
00877       {
00878         m_iBitsPerComponent = getIntegerValue (token);
00879         pfAttribList->push_back (GLX_FLOAT_COMPONENTS_NV);
00880         pfAttribList->push_back (true);
00881         continue;
00882       }
00883 
00884       nuxDebugMsg ("unknown pbuffer attribute: %s\n", token.c_str() );
00885     }
00886   }
00887 
00888   void PBuffer::Activate (PBuffer *current /* = NULL */)
00889   {
00890     if (current == this)
00891     {
00892       return; // no switch necessary
00893     }
00894 
00895     if (NULL == current || !current->m_bIsActive)
00896     {
00897       m_pOldDisplay = glXGetCurrentDisplay();
00898       m_glxOldDrawable = glXGetCurrentDrawable();
00899       m_glxOldContext = glXGetCurrentContext();
00900     }
00901     else
00902     {
00903       m_pOldDisplay = current->m_pOldDisplay;
00904       m_glxOldDrawable = current->m_glxOldDrawable;
00905       m_glxOldContext = current->m_glxOldContext;
00906       current->m_pOldDisplay = 0;
00907       current->m_glxOldDrawable = 0;
00908       current->m_glxOldContext = 0;
00909     }
00910 
00911     if (!glXMakeCurrent (m_pDisplay, m_glxPbuffer, m_glxContext) )
00912     {
00913       nuxDebugMsg ("PBuffer::Activate() failed.\n");
00914     }
00915   }
00916 
00917   void PBuffer::Deactivate()
00918   {
00919     if (!glXMakeCurrent (m_pOldDisplay, m_glxOldDrawable, m_glxOldContext) )
00920     {
00921       nuxDebugMsg ("PBuffer::Deactivate() failed.\n");
00922     }
00923 
00924     m_pOldDisplay = 0;
00925     m_glxOldDrawable = 0;
00926     m_glxOldContext = 0;
00927   }
00928 
00929 #elif defined(NUX_OS_MACOSX)
00930 
00931   PBuffer::PBuffer (const char *strMode)
00932     :
00933     m_iWidth (0), m_iHeight (0), m_strMode (strMode),
00934     m_bSharedContext (false), m_bShareObjects (false)
00935   {
00936     nuxDebugMsg ("pbuffer not implemented under Mac OS X yet\n");
00937   }
00938 
00939   PBuffer::~PBuffer()
00940   {
00941     nuxDebugMsg ("pbuffer not implemented under Mac OS X yet\n");
00942   }
00943 
00944   bool PBuffer::Initialize (int iWidth, int iHeight, bool bShareContexts, bool bShareObjects)
00945   {
00946     nuxDebugMsg ("pbuffer not implemented under Mac OS X yet\n");
00947 
00948     return false;
00949   }
00950 
00951   void PBuffer::Activate()
00952   {
00953     nuxDebugMsg ("pbuffer not implemented under Mac OS X yet\n");
00954   }
00955 
00956   void PBuffer::Deactivate()
00957   {
00958     nuxDebugMsg ("pbuffer not implemented under Mac OS X yet\n");
00959   }
00960 
00961 #endif
00962 
00963   std::string PBuffer::getStringValue (std::string token)
00964   {
00965     size_t pos;
00966 
00967     if ( (pos = token.find ("=") ) != token.npos)
00968     {
00969       std::string value = token.substr (pos + 1, token.length() - pos + 1);
00970       return value;
00971     }
00972     else
00973       return "";
00974   }
00975 
00976   int PBuffer::getIntegerValue (std::string token)
00977   {
00978     size_t pos;
00979 
00980     if ( (pos = token.find ("=") ) != token.npos)
00981     {
00982       std::string value = token.substr (pos + 1, token.length() - pos + 1);
00983 
00984       if (value.empty() )
00985         return 1;
00986 
00987       return atoi (value.c_str() );
00988     }
00989     else
00990       return 1;
00991   }
00992 
00993 //----------------------------------------------------------------------------------
00994 //
00996 //
00997 //----------------------------------------------------------------------------------
00998   unsigned int PBuffer::GetSizeInBytes()
00999   {
01000     return m_iWidth * m_iHeight * (m_iNComponents / 8);
01001   }
01002   /*************************************************************************/  /*********************************************************************/
01008   unsigned int PBuffer::CopyToBuffer (void *ptr, int w, int h)
01009   {
01010     GLenum format = 0;
01011     GLenum type = 0;
01012 
01013     switch (m_iNComponents)
01014     {
01015       case 1: //
01016         format = GL_LUMINANCE; // is it right to ask for Red only component ?
01017         break;
01018       case 2:
01019         format = GL_LUMINANCE_ALPHA; //How to ask for GL_RG ??
01020         break;
01021       case 3:
01022         format = GL_RGB;
01023         break;
01024       case 4:
01025         format = GL_RGBA;
01026         break;
01027     }
01028 
01029     switch (m_iBitsPerComponent)
01030     {
01031       case 8:
01032         type = GL_UNSIGNED_BYTE;
01033         break;
01034       case 32:
01035         type = GL_FLOAT;
01036         break;
01037 #ifdef GL_NV_half_float
01038       case 16:
01039         type = GL_HALF_FLOAT_NV;
01040         break;
01041 #endif
01042       default:
01043         nuxDebugMsg ("unknown m_iBitsPerComponent\n");
01044 #      if defined(WIN32)
01045         __debugbreak();
01046 #      endif
01047     }
01048 
01049     Activate();
01050 
01051     if ( (w < 0) || (w > m_iWidth) )
01052       w = m_iWidth;
01053 
01054     if ( (h < 0) || (h > m_iHeight) )
01055       h = m_iHeight;
01056 
01057     glReadPixels (0, 0, w, h, format, type, ptr);
01058     Deactivate();
01059     return w * h * (m_iNComponents / 8);
01060   }
01061 
01062 }
01063 
01064 #endif // NUX_OPENGLES_20
01065