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