nux-1.16.0
|
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 }