source: GTP/trunk/Lib/Vis/Preprocessing/src/RenderTexture.cpp @ 1940

Revision 1940, 38.5 KB checked in by mattausch, 17 years ago (diff)
Line 
1//------------------------------------------------------------------------------
2// File : RenderTexture.cpp
3//------------------------------------------------------------------------------
4// Copyright 2002 Mark J. Harris and
5// The University of North Carolina at Chapel Hill
6//------------------------------------------------------------------------------
7// Permission to use, copy, modify, distribute and sell this software and its
8// documentation for any purpose is hereby granted without fee, provided that
9// the above copyright notice appear in all copies and that both that copyright
10// notice and this permission notice appear in supporting documentation.
11// Binaries may be compiled with this software without any royalties or
12// restrictions.
13//
14// The author(s) and The University of North Carolina at Chapel Hill make no
15// representations about the suitability of this software for any purpose.
16// It is provided "as is" without express or implied warranty.
17//
18// -----------------------------------------------------------------------------
19// Credits:
20// Original RenderTexture class: Mark J. Harris
21// Original Render-to-depth-texture support: Thorsten Scheuermann
22// Linux Copy-to-texture: Eric Werness
23// Various Bug Fixes: Daniel (Redge) Sperl
24//                    Bill Baxter
25//
26// -----------------------------------------------------------------------------
27/**
28 * @file RenderTexture.cpp
29 *
30 * Implementation of class RenderTexture.  A multi-format render to
31 * texture wrapper.
32 */
33#include "RenderTexture.h"
34#include <GL/glut.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <stdarg.h>
38#include <assert.h>
39
40//------------------------------------------------------------------------------
41// Function               : IsPowerOfTwo
42// Description      :
43//------------------------------------------------------------------------------
44/**
45 * @fn IsPowerOfTwo(int n)
46 * @brief Returns true if /param n is an integer power of 2.
47 *
48 * Taken from Steve Baker's Cute Code Collection.
49 */
50bool IsPowerOfTwo(int n)
51{
52  return ((n&(n-1))==0);
53}
54
55//------------------------------------------------------------------------------
56// Function      : RenderTexture::RenderTexture
57// Description   :
58//------------------------------------------------------------------------------
59/**
60 * @fn RenderTexture::RenderTexture()
61 * @brief Constructor.
62 */
63RenderTexture::RenderTexture(int iWidth, int iHeight, bool bIsTexture /* = true */,
64                                                         bool bIsDepthTexture /* = false */)
65: _iWidth(iWidth),
66  _iHeight(iHeight),
67  _bIsTexture(bIsTexture),
68  _bIsDepthTexture(bIsDepthTexture),
69  _bHasArbDepthTexture(true),            // [Redge]
70  _eUpdateMode(RT_RENDER_TO_TEXTURE),
71  _bInitialized(false),
72  _bFloat(false),
73  _bRectangle(false),
74  _bHasDepth(false),
75  _bHasStencil(false),
76  _bMipmap(false),
77  _bAnisoFilter(false),
78#ifdef _WIN32
79  _hDC(NULL),
80  _hGLContext(NULL),
81  _hPBuffer(NULL),
82  _hPreviousDC(0),
83  _hPreviousContext(0),
84#else
85  _pDpy(NULL),
86  _hGLContext(NULL),
87  _hPBuffer(0),
88  _hPreviousContext(0),
89  _hPreviousDrawable(0),
90#endif
91  _iTextureTarget(GL_NONE),
92  _iTextureID(0),
93  _pPoorDepthTexture(0) // [Redge]
94{
95  assert(iWidth > 0 && iHeight > 0);
96  _iBits[0] = _iBits[1] = _iBits[2] = _iBits[3] = 0;
97  _bRectangle = !(IsPowerOfTwo(iWidth) && IsPowerOfTwo(iHeight));
98}
99
100
101//------------------------------------------------------------------------------
102// Function               : RenderTexture::~RenderTexture
103// Description      :
104//------------------------------------------------------------------------------
105/**
106 * @fn RenderTexture::~RenderTexture()
107 * @brief Destructor.
108 */
109RenderTexture::~RenderTexture()
110{
111  _Invalidate();
112}
113
114
115//------------------------------------------------------------------------------
116// Function               : wglGetLastError
117// Description      :
118//------------------------------------------------------------------------------
119/**
120 * @fn wglGetLastError()
121 * @brief Returns the last windows error generated.
122 */
123#ifdef _WIN32
124void RenderTexture::_wglGetLastError()
125{
126#ifdef _DEBUG
127
128  DWORD err = GetLastError();
129  switch(err)
130  {
131  case ERROR_INVALID_PIXEL_FORMAT:
132    fprintf(stderr, "Win32 Error:  ERROR_INVALID_PIXEL_FORMAT\n");
133    break;
134  case ERROR_NO_SYSTEM_RESOURCES:
135    fprintf(stderr, "Win32 Error:  ERROR_NO_SYSTEM_RESOURCES\n");
136    break;
137  case ERROR_INVALID_DATA:
138    fprintf(stderr, "Win32 Error:  ERROR_INVALID_DATA\n");
139    break;
140  case ERROR_INVALID_WINDOW_HANDLE:
141    fprintf(stderr, "Win32 Error:  ERROR_INVALID_WINDOW_HANDLE\n");
142    break;
143  case ERROR_RESOURCE_TYPE_NOT_FOUND:
144    fprintf(stderr, "Win32 Error:  ERROR_RESOURCE_TYPE_NOT_FOUND\n");
145    break;
146  case ERROR_SUCCESS:
147    // no error
148    break;
149  default:
150    LPVOID lpMsgBuf;
151    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
152                  FORMAT_MESSAGE_FROM_SYSTEM |
153                  FORMAT_MESSAGE_IGNORE_INSERTS,
154                  NULL,
155                  err,
156                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
157                  (LPTSTR) &lpMsgBuf,
158                  0,
159                  NULL);
160   
161    fprintf(stderr, "Win32 Error %d: %s\n", err, lpMsgBuf);
162    LocalFree( lpMsgBuf );
163    break;
164  }
165  SetLastError(0);
166
167#endif // _DEBUG
168}
169#endif
170
171//------------------------------------------------------------------------------
172// Function               : PrintExtensionError
173// Description      :
174//------------------------------------------------------------------------------
175/**
176 * @fn PrintExtensionError( char* strMsg, ... )
177 * @brief Prints an error about missing OpenGL extensions.
178 */
179void PrintExtensionError( char* strMsg, ... )
180{
181  fprintf(stderr, "Error: RenderTexture requires the following unsupported "
182                  "OpenGL extensions: \n");
183  char strBuffer[512];
184  va_list args;
185  va_start(args, strMsg);
186#ifdef _WIN32
187  _vsnprintf( strBuffer, 512, strMsg, args );
188#else
189  vsnprintf( strBuffer, 512, strMsg, args );
190#endif
191  va_end(args);
192 
193  fprintf(stderr, strMsg);
194
195  exit(1);
196}
197
198
199//------------------------------------------------------------------------------
200// Function               : RenderTexture::Initialize
201// Description      :
202//------------------------------------------------------------------------------
203/**
204 * @fn RenderTexture::Initialize(bool bShare, bool bDepth, bool bStencil, bool bMipmap, bool bAnisoFilter, unsigned int iRBits, unsigned int iGBits, unsigned int iBBits, unsigned int iABits);
205 * @brief Initializes the RenderTexture, sharing display lists and textures if specified.
206 *
207 * This function actually does the creation of the p-buffer.  It can only be called
208 * once a GL context has already been created.  Note that if the texture is not
209 * power of two dimensioned, or has more than 8 bits per channel, enabling mipmapping
210 * or aniso filtering will cause an error.
211 */
212bool RenderTexture::Initialize(bool         bShare       /* = true */,
213                               bool         bDepth       /* = false */,
214                               bool         bStencil     /* = false */,
215                               bool         bMipmap      /* = false */,
216                               bool         bAnisoFilter /* = false */,
217                               unsigned int iRBits       /* = 8 */,
218                               unsigned int iGBits       /* = 8 */,
219                               unsigned int iBBits       /* = 8 */,
220                               unsigned int iABits       /* = 8 */,
221                               UpdateMode   updateMode   /* = RT_RENDER_TO_TEXTURE */)
222{
223#ifdef _WIN32
224  if (!WGLEW_ARB_pbuffer)
225  {
226    PrintExtensionError("WGL_ARB_pbuffer");
227    return false;
228  }
229  if (!WGLEW_ARB_pixel_format)
230  {
231    PrintExtensionError("WGL_ARB_pixel_format");
232    return false;
233  }
234  if (_bIsTexture && !WGLEW_ARB_render_texture)
235  {
236    PrintExtensionError("WGL_ARB_render_texture");
237    return false;
238  }
239  if (_bIsDepthTexture && !GLEW_ARB_depth_texture)
240  {
241    // [Redge]
242#if defined(_DEBUG) | defined(DEBUG)
243    fprintf(stderr, "Warning: OpenGL extension GL_ARB_depth_texture not available.\n"
244                    "         Using glReadPixels() to emulate behavior.\n");
245#endif   
246    _bHasArbDepthTexture = false;
247    //PrintExtensionError("GL_ARB_depth_texture");
248    //return false;
249    // [/Redge]
250  }
251  SetLastError(0);
252#else
253  if (!GLXEW_SGIX_pbuffer)
254  {
255    PrintExtensionError("GLX_SGIX_pbuffer");
256    return false;
257  }
258  if (!GLXEW_SGIX_fbconfig)
259  {
260    PrintExtensionError("GLX_SGIX_fbconfig");
261    return false;
262  }
263  if (_bIsDepthTexture)
264  {
265    PrintExtensionError("I don't know");
266    return false;
267  }
268  if (updateMode == RT_RENDER_TO_TEXTURE)
269  {
270    PrintExtensionError("Some GLX render texture extension");
271  }
272#endif
273
274  if (_bInitialized)
275    _Invalidate();
276 
277  _bFloat = (iRBits > 8 || iGBits > 8 || iBBits > 8 || iABits > 8);
278 
279  bool bNVIDIA = true;
280#ifdef _WIN32
281  if (_bFloat && !GLEW_NV_float_buffer)
282  {
283    bNVIDIA = false;
284    if (!WGLEW_ATI_pixel_format_float)
285    {
286      PrintExtensionError("GL_NV_float_buffer or GL_ATI_pixel_format_float");
287      return false;
288    }
289  }
290  if (_bFloat && _bIsTexture && !bNVIDIA && !GLEW_ATI_texture_float)
291  {
292          PrintExtensionError("NV_float_buffer or ATI_texture_float");
293  }
294#else
295  if (_bFloat && _bIsTexture && !GLXEW_NV_float_buffer)
296  {
297    PrintExtensionError("GLX_NV_float_buffer");
298    return false;
299  }
300#endif 
301  if (!_bFloat && !GLEW_NV_texture_rectangle)
302  {
303    bNVIDIA = false;
304  }
305 
306  _bRectangle = _bRectangle || (_bFloat && bNVIDIA);
307
308  if(_bIsDepthTexture)
309    _bHasDepth  = true;    // we need depth for a depth texture...
310  else
311    _bHasDepth  = bDepth;
312
313  _bHasStencil  = bStencil;
314  _bMipmap      = false;   // until it is enabled.
315  _bAnisoFilter = false;   // until it is enabled.
316  _eUpdateMode  = updateMode;
317
318  GLuint iWGLTextureTarget = 0;
319  GLuint iBindTarget = 0;
320  GLuint iTextureFormat = 0;
321  GLuint iDepthBindTarget = 0;
322  GLuint iDepthTextureFormat = 0;
323
324  if (_bIsTexture)
325    glGenTextures(1, &_iTextureID);
326  if (_bIsDepthTexture)
327    glGenTextures(1, &_iDepthTextureID);
328 
329  // Determine the appropriate texture formats and filtering modes.
330  if (_bIsTexture)
331  {
332    if (_bFloat)
333    {     
334      if (!bNVIDIA && _bRectangle)
335      {
336        fprintf(stderr,
337                "RenderTexture Error: ATI textures must be power-of-two-dimensioned.\n");
338        return false;
339      }
340
341      if (bNVIDIA)
342        _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
343      else
344        _iTextureTarget = GL_TEXTURE_2D;
345   
346      glBindTexture(_iTextureTarget, _iTextureID); 
347   
348      // We'll use clamp to edge as the default texture wrap mode for all tex types
349      glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
350      glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
351      glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
352      glTexParameteri( _iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
353   
354      if (bMipmap)
355      {
356        fprintf(stderr,
357                "RenderTexture Error: float textures do not support mipmaps\n");
358        return false;
359      }
360
361      if (RT_COPY_TO_TEXTURE == _eUpdateMode)
362      {
363        GLuint iInternalFormat;
364        GLuint iFormat;
365        if (iABits > 0)
366        {
367          if (bNVIDIA)
368            iInternalFormat = (iABits > 16) ? GL_FLOAT_RGBA32_NV : GL_FLOAT_RGBA16_NV;
369          else
370            iInternalFormat = (iABits > 16) ? GL_RGBA_FLOAT32_ATI : GL_RGBA_FLOAT16_ATI;
371          iFormat = GL_RGBA;
372        }
373        else if (iBBits > 0)
374        {
375          if (bNVIDIA)
376            iInternalFormat = (iBBits > 16) ? GL_FLOAT_RGB32_NV : GL_FLOAT_RGB16_NV;
377          else
378            iInternalFormat = (iBBits > 16) ? GL_RGB_FLOAT32_ATI : GL_RGB_FLOAT16_ATI;
379          iFormat = GL_RGB;
380        }
381        else if (iGBits > 0)
382        {
383          if (bNVIDIA)
384            iInternalFormat = (iGBits > 16) ? GL_FLOAT_RG32_NV : GL_FLOAT_RG16_NV;
385          else
386            iInternalFormat = (iGBits > 16) ? GL_LUMINANCE_ALPHA_FLOAT32_ATI :
387                                              GL_LUMINANCE_ALPHA_FLOAT16_ATI;
388          iFormat = GL_LUMINANCE_ALPHA;
389        }
390        else
391        {
392          if (bNVIDIA)
393            iInternalFormat = (iRBits > 16) ? GL_FLOAT_R32_NV : GL_FLOAT_R16_NV;
394          else
395            iInternalFormat = (iRBits > 16) ? GL_LUMINANCE_FLOAT32_ATI :
396                                              GL_LUMINANCE_FLOAT16_ATI;
397          iFormat = GL_LUMINANCE;
398        }
399        // Allocate the texture image (but pass it no data for now).
400        glTexImage2D(_iTextureTarget, 0, iInternalFormat, _iWidth, _iHeight,
401                     0, iFormat, GL_FLOAT, NULL);
402      }
403      else
404      {
405#ifdef _WIN32
406        if (bNVIDIA)
407          iWGLTextureTarget = WGL_TEXTURE_RECTANGLE_NV;
408        else
409          iWGLTextureTarget = WGL_TEXTURE_2D_ARB;
410
411        if (iABits > 0)
412        {
413          if (bNVIDIA)
414          {
415            iBindTarget    = WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV; 
416            iTextureFormat = WGL_TEXTURE_FLOAT_RGBA_NV;
417          }
418          else
419          {
420            iBindTarget    = WGL_BIND_TO_TEXTURE_RGBA_ARB; 
421            iTextureFormat = WGL_TEXTURE_RGBA_ARB;
422          }
423        }
424        else if (iBBits > 0)
425        {
426          if (bNVIDIA)
427          {
428            iBindTarget    = WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV; 
429            iTextureFormat = WGL_TEXTURE_FLOAT_RGB_NV;
430          }
431          else
432          {
433            iBindTarget    = WGL_BIND_TO_TEXTURE_RGB_ARB; 
434            iTextureFormat = WGL_TEXTURE_RGB_ARB;
435          }
436        }
437        else if (iGBits > 0)
438        {
439          if (bNVIDIA)
440          {
441            iBindTarget    = WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV; 
442            iTextureFormat = WGL_TEXTURE_FLOAT_RG_NV;
443          }
444          else
445          {
446            iBindTarget    = WGL_BIND_TO_TEXTURE_RGB_ARB; 
447            iTextureFormat = WGL_TEXTURE_RGB_ARB;
448          }
449        }
450        else
451        {
452          if (bNVIDIA)
453          {
454            iBindTarget    = WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV; 
455            iTextureFormat = WGL_TEXTURE_FLOAT_R_NV;
456          }
457          else
458          {
459            iBindTarget    = WGL_BIND_TO_TEXTURE_RGB_ARB; 
460            iTextureFormat = WGL_TEXTURE_RGB_ARB;
461          }
462        }
463#else if defined(DEBUG) || defined(_DEBUG)
464        printf("RenderTexture Error: Render-to-Texture not supported in Linux\n");
465#endif   
466      }
467    }
468    else
469    {
470      if (!_bRectangle)
471      {
472        _iTextureTarget = GL_TEXTURE_2D;
473        glBindTexture(_iTextureTarget, _iTextureID);
474           
475        // We'll use clamp to edge as the default texture wrap mode for all tex types
476        glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
477        glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
478        glTexParameteri( _iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
479     
480        if (bMipmap)
481        {
482          _bMipmap = true;
483          glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
484       
485          // Generate mipmap automatically if supported
486          if (GLEW_SGIS_generate_mipmap)
487          {
488            glTexParameteri( _iTextureTarget, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
489          }
490          else
491          {
492            PrintExtensionError("GL_SGIS_generate_mipmap");
493          }
494        }
495        else
496        {
497          glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
498        }
499     
500        // Set anisotropic filter to the max ratio
501        if (bAnisoFilter)
502        {
503          if (GLEW_EXT_texture_filter_anisotropic)
504          {
505            _bAnisoFilter = true;
506            float rMaxAniso;
507            glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &rMaxAniso);
508            glTexParameterf( _iTextureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, rMaxAniso);
509          }
510        }
511
512        if (RT_COPY_TO_TEXTURE == _eUpdateMode)
513        {
514          GLuint iInternalFormat;
515          GLuint iFormat;
516          if (iABits > 0)
517          {
518            iInternalFormat = GL_RGBA8;
519            iFormat = GL_RGBA;
520          }
521          else
522          {
523            iInternalFormat = GL_RGB8;
524            iFormat = GL_RGB;
525          }
526          // Allocate the texture image (but pass it no data for now).
527          glTexImage2D(_iTextureTarget, 0, iInternalFormat, _iWidth, _iHeight,
528                       0, iFormat, GL_FLOAT, NULL);
529        }
530        else
531        {
532#ifdef _WIN32   
533          iWGLTextureTarget = WGL_TEXTURE_2D_ARB;
534          if (iABits > 0)
535          {
536            iBindTarget    = WGL_BIND_TO_TEXTURE_RGBA_ARB;
537            iTextureFormat = WGL_TEXTURE_RGBA_ARB;
538          }
539          else
540          {
541            iBindTarget    = WGL_BIND_TO_TEXTURE_RGB_ARB; 
542            iTextureFormat = WGL_TEXTURE_RGB_ARB;
543          }
544#endif
545        }
546      }
547      else
548      {
549        if (!bNVIDIA)
550        {
551          fprintf(stderr,
552                  "RenderTexture Error: ATI textures must be power-of-two-dimensioned.\n");
553          return false;
554        }
555       
556        _iTextureTarget = GL_TEXTURE_RECTANGLE_NV;
557       
558        glBindTexture(_iTextureTarget, _iTextureID);
559     
560        glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
561        glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
562        glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
563        glTexParameteri( _iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
564       
565        if (bMipmap)
566        {
567
568          fprintf(stderr,
569                  "RenderTexture Error: rectangle textures do not support mipmaps\n");
570          return false;
571        }
572
573        if (RT_COPY_TO_TEXTURE == _eUpdateMode)
574        {
575          GLuint iInternalFormat;
576          GLuint iFormat;
577          if (iABits > 0)
578          {
579            iInternalFormat = GL_RGBA8;
580            iFormat = GL_RGBA;
581          }
582          else
583          {
584            iInternalFormat = GL_RGB8;
585            iFormat = GL_RGB;
586          }
587          // Allocate the texture image (but pass it no data for now).
588          glTexImage2D(_iTextureTarget, 0, iInternalFormat, _iWidth, _iHeight,
589                       0, iFormat, GL_FLOAT, NULL);
590        }
591        else
592        {
593#ifdef _WIN32
594          iWGLTextureTarget = WGL_TEXTURE_RECTANGLE_NV;
595          if (iABits > 0)
596          {
597            iBindTarget    = WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV;
598            iTextureFormat = WGL_TEXTURE_RGBA_ARB;
599          }
600          else
601          {
602            iBindTarget   = WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV;
603            iTextureFormat= WGL_TEXTURE_RGB_ARB;
604          }
605#endif
606        }
607      }
608    }
609  }
610
611  if (_bIsDepthTexture)
612  {
613    if (!bNVIDIA && _bRectangle)
614    {
615      fprintf(stderr,
616        "RenderTexture Error: ATI textures must be power-of-two-dimensioned.\n");
617      return false;
618    }
619
620    if (!_iTextureTarget)
621      _iTextureTarget = _bRectangle ? GL_TEXTURE_RECTANGLE_NV : GL_TEXTURE_2D;
622   
623    glBindTexture(_iTextureTarget, _iDepthTextureID); 
624   
625    // We'll use clamp to edge as the default texture wrap mode for all tex types
626    glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
627    glTexParameteri( _iTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
628    glTexParameteri( _iTextureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
629    glTexParameteri( _iTextureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
630   
631    // user will need to set up hardware shadow mapping himself (using ARB_shadow)
632       
633    if (RT_COPY_TO_TEXTURE == _eUpdateMode)
634    {
635      // [Redge]
636      if (_bHasArbDepthTexture)
637      {
638        // Allocate the texture image (but pass it no data for now).
639        glTexImage2D(_iTextureTarget, 0, GL_DEPTH_COMPONENT, _iWidth, _iHeight,
640                     0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
641      }
642      else
643      {
644        // allocate memory for depth texture
645        // Since this is slow, we warn the user in debug mode. (above)
646        _pPoorDepthTexture = new unsigned short[_iWidth * _iHeight];
647        glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16, _iWidth, _iHeight,
648                   0, GL_LUMINANCE, GL_UNSIGNED_SHORT, _pPoorDepthTexture);
649      }
650      // [/Redge]
651    }
652    else  // RENDER_TO_TEXTURE
653    {
654#ifdef _WIN32
655      if(_bRectangle)
656      {
657        if (!iWGLTextureTarget)  iWGLTextureTarget = WGL_TEXTURE_RECTANGLE_NV;
658        iDepthBindTarget    = WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV;
659        iDepthTextureFormat = WGL_TEXTURE_DEPTH_COMPONENT_NV;
660      }
661      else
662      {
663        if (!iWGLTextureTarget)  iWGLTextureTarget = WGL_TEXTURE_2D_ARB;
664        iDepthBindTarget    = WGL_BIND_TO_TEXTURE_DEPTH_NV;
665        iDepthTextureFormat = WGL_TEXTURE_DEPTH_COMPONENT_NV;
666      }
667#endif
668    }
669  }
670
671#if _WIN32
672  // Get the current context.
673  HDC hdc = wglGetCurrentDC();
674  if (NULL == hdc)
675    _wglGetLastError();
676  HGLRC hglrc = wglGetCurrentContext();
677  if (NULL == hglrc)
678    _wglGetLastError();
679 
680  int iFormat = 0;
681  unsigned int iNumFormats;
682  int attribChooseList[50];
683  int attribCreateList[50];
684  int attribChoose = 0;
685  int attribCreate = 0;
686 
687  // Setup the attrib list for wglChoosePixelFormat()
688 
689  attribChooseList[attribChoose++] = WGL_RED_BITS_ARB;
690  attribChooseList[attribChoose++] = iRBits;
691  attribChooseList[attribChoose++] = WGL_GREEN_BITS_ARB;
692  attribChooseList[attribChoose++] = iGBits;
693  attribChooseList[attribChoose++] = WGL_BLUE_BITS_ARB;
694  attribChooseList[attribChoose++] = iBBits;
695  attribChooseList[attribChoose++] = WGL_ALPHA_BITS_ARB;
696  attribChooseList[attribChoose++] = iABits;
697  if (_bFloat)
698  {
699    if (bNVIDIA)
700    {
701      attribChooseList[attribChoose++] = WGL_FLOAT_COMPONENTS_NV;
702      attribChooseList[attribChoose++] = GL_TRUE;
703    }
704    else
705    {
706      attribChooseList[attribChoose++] = WGL_PIXEL_TYPE_ARB;
707      attribChooseList[attribChoose++] = WGL_TYPE_RGBA_FLOAT_ATI;
708    }
709  }
710   
711  attribChooseList[attribChoose++] = WGL_STENCIL_BITS_ARB;
712  attribChooseList[attribChoose++] = (bStencil) ? 8 : 0;
713  attribChooseList[attribChoose++] = WGL_DEPTH_BITS_ARB;
714  attribChooseList[attribChoose++] = (bDepth) ? 24 : 0;
715  attribChooseList[attribChoose++] = WGL_DRAW_TO_PBUFFER_ARB;
716  attribChooseList[attribChoose++] = GL_TRUE;
717
718  if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
719  {
720    attribChooseList[attribChoose++] = iBindTarget;
721    attribChooseList[attribChoose++] = GL_TRUE;
722  }
723  if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
724  {
725    attribChooseList[attribChoose++] = iDepthBindTarget;
726    attribChooseList[attribChoose++] = GL_TRUE;
727  }
728
729  attribChooseList[attribChoose++] = 0;
730
731  // Setup the attrib list for wglCreatePbuffer()
732  if ((_bIsTexture || _bIsDepthTexture) && RT_RENDER_TO_TEXTURE == _eUpdateMode)
733  {
734    attribCreateList[attribCreate++] = WGL_TEXTURE_TARGET_ARB;
735    attribCreateList[attribCreate++] = iWGLTextureTarget;
736  }
737  if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
738  {
739    attribCreateList[attribCreate++] = WGL_TEXTURE_FORMAT_ARB;
740    attribCreateList[attribCreate++] = iTextureFormat;
741    /*attribCreateList[attribCreate++] = WGL_TEXTURE_TARGET_ARB;
742    attribCreateList[attribCreate++] = iWGLTextureTarget;*/
743    attribCreateList[attribCreate++] = WGL_MIPMAP_TEXTURE_ARB;
744    attribCreateList[attribCreate++] = (bMipmap) ? GL_TRUE : GL_FALSE; 
745  }
746  if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
747  {
748    attribCreateList[attribCreate++] = WGL_DEPTH_TEXTURE_FORMAT_NV;
749    attribCreateList[attribCreate++] = iDepthTextureFormat;
750  }
751  attribCreateList[attribCreate++] = WGL_PBUFFER_LARGEST_ARB;
752  attribCreateList[attribCreate++] = GL_FALSE;
753  attribCreateList[attribCreate++] = 0;
754
755  if (!wglChoosePixelFormatARB( hdc, attribChooseList, NULL, 1, &iFormat, &iNumFormats))
756  {
757    fprintf(stderr,
758            "RenderTexture::Initialize() creation error: wglChoosePixelFormatARB() failed.\n");
759    _wglGetLastError();
760    return false;
761  }
762  if ( iNumFormats <= 0 )
763  {
764    fprintf(stderr,
765            "RenderTexture::Initialize() creation error: Couldn't find a suitable pixel format.\n");
766    _wglGetLastError();
767    return false;
768  }
769
770  // Create the p-buffer.   
771  _hPBuffer = wglCreatePbufferARB( hdc, iFormat, _iWidth, _iHeight, attribCreateList );
772  if (!_hPBuffer)
773  {
774    fprintf(stderr, "RenderTexture::Initialize() pbuffer creation error: wglCreatePbufferARB() failed\n");
775    _wglGetLastError();
776    return false;
777  }
778 
779   // Get the device context.
780  _hDC = wglGetPbufferDCARB( _hPBuffer);
781  if ( !_hDC )
782  {
783    fprintf(stderr,
784            "RenderTexture::Initialize() creation error: wglGetGetPbufferDCARB() failed\n");
785    _wglGetLastError();
786    return false;
787  }
788 
789  // Create a gl context for the p-buffer.
790
791 
792  _hGLContext = wglCreateContext( _hDC );
793  if ( !_hGLContext )
794  {
795    fprintf(stderr, "RenderTexture::Initialize() creation error:  wglCreateContext() failed\n");
796    _wglGetLastError();
797    return false;
798  }
799 
800  // Share lists, texture objects, and program objects.
801  if( bShare )
802  {
803    if( !wglShareLists(hglrc, _hGLContext) )
804    {
805      fprintf(stderr, "RenderTexture::Initialize() creation error: wglShareLists() failed\n" );
806      _wglGetLastError();
807      return false;
808    }
809  }
810
811  // bind the pbuffer to the render texture object
812  if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
813  {
814    glBindTexture(_iTextureTarget, _iTextureID);
815    if (wglBindTexImageARB(_hPBuffer, WGL_FRONT_LEFT_ARB) == FALSE)
816    {
817      _wglGetLastError();
818      return false;
819    }
820  }
821  if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
822  {
823    glBindTexture(_iTextureTarget, _iDepthTextureID);
824    if (wglBindTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV) == FALSE)
825    {
826      _wglGetLastError();
827      return false;
828    }
829  }
830
831   // Determine the actual width and height we were able to create.
832  wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_iWidth );
833  wglQueryPbufferARB( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_iHeight );
834
835  _bInitialized = true;
836 
837  // get the actual number of bits allocated:
838  int attrib = WGL_RED_BITS_ARB;
839  int value;
840  _iBits[0] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : iRBits;
841  attrib = WGL_GREEN_BITS_ARB;
842  _iBits[1] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : iGBits;
843  attrib = WGL_BLUE_BITS_ARB;
844  _iBits[2] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : iBBits;
845  attrib = WGL_ALPHA_BITS_ARB;
846  _iBits[3] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : iABits;
847  attrib = WGL_DEPTH_BITS_ARB;
848  _iBits[4] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : 0;
849  attrib = WGL_STENCIL_BITS_ARB;
850  _iBits[5] = (wglGetPixelFormatAttribivARB(_hDC, iFormat, 0, 1, &attrib, &value)) ? value : 0;
851 
852#if defined(_DEBUG) | defined(DEBUG)
853  fprintf(stderr, "Created a %dx%d RenderTexture with BPP(%d, %d, %d, %d)",
854          _iWidth, _iHeight, _iBits[0], _iBits[1], _iBits[2], _iBits[3]);
855  if (_iBits[4]) fprintf(stderr, " depth=%d", _iBits[4]);
856  if (_iBits[5]) fprintf(stderr, " stencil=%d", _iBits[5]);
857  fprintf(stderr, "\n");
858#endif
859#else
860  _pDpy = glXGetCurrentDisplay();
861  GLXContext context = glXGetCurrentContext();
862  int screen = DefaultScreen(_pDpy);
863  XVisualInfo *visInfo;
864
865  int iFormat = 0;
866  int iNumFormats;
867  int fbAttribs[50];
868  int attrib = 0;
869
870  fbAttribs[attrib++] = GLX_RENDER_TYPE_SGIX;
871  fbAttribs[attrib++] = GLX_RGBA_BIT_SGIX;
872  fbAttribs[attrib++] = GLX_DRAWABLE_TYPE_SGIX;
873  fbAttribs[attrib++] = GLX_PBUFFER_BIT_SGIX;
874  fbAttribs[attrib++] = GLX_STENCIL_SIZE;
875  fbAttribs[attrib++] = (bStencil) ? 8 : 0;
876  fbAttribs[attrib++] = GLX_DEPTH_SIZE;
877  fbAttribs[attrib++] = (bDepth) ? 24 : 0;
878  if (_bFloat)
879  {
880    fbAttribs[attrib++] = GLX_RED_SIZE;
881    fbAttribs[attrib++] = iRBits;
882    fbAttribs[attrib++] = GLX_GREEN_SIZE;
883    fbAttribs[attrib++] = iGBits;
884    fbAttribs[attrib++] = GLX_BLUE_SIZE;
885    fbAttribs[attrib++] = iBBits;
886    fbAttribs[attrib++] = GLX_ALPHA_SIZE;
887    fbAttribs[attrib++] = iABits;
888    fbAttribs[attrib++] = GLX_FLOAT_COMPONENTS_NV;
889    fbAttribs[attrib++] = 1;   
890  }
891  fbAttribs[attrib++] = None;
892
893  GLXFBConfigSGIX *fbConfigs;
894  int nConfigs;
895
896  fbConfigs = glXChooseFBConfigSGIX(_pDpy, screen, fbAttribs, &nConfigs);
897
898  if (nConfigs == 0 || !fbConfigs) {
899    fprintf(stderr,
900            "RenderTexture::Initialize() creation error: Couldn't find a suitable pixel format\n");
901    return false;
902  }
903
904  // Pick the first returned format that will return a pbuffer
905  for (int i=0;i<nConfigs;i++)
906  {
907    _hPBuffer = glXCreateGLXPbufferSGIX(_pDpy, fbConfigs[i], _iWidth, _iHeight, NULL);
908    if (_hPBuffer) {
909      _hGLContext = glXCreateContextWithConfigSGIX(_pDpy, fbConfigs[i], GLX_RGBA_TYPE, bShare?context:NULL, True);
910      break;
911    }
912  }
913
914  if (!_hPBuffer)
915  {
916    fprintf(stderr, "RenderTexture::Initialize() pbuffer creation error: glXCreateGLXPbufferSGIX() failed\n");
917    return false;
918  }
919
920  if(!_hGLContext)
921  {
922      // Try indirect
923      _hGLContext = glXCreateContext(_pDpy, visInfo, bShare?context:NULL, False);
924      if ( !_hGLContext )
925      {
926        fprintf(stderr, "RenderTexture::Initialize() creation error:  glXCreateContext() failed\n");
927        return false;
928      }
929  }
930
931  glXQueryGLXPbufferSGIX(_pDpy, _hPBuffer, GLX_WIDTH_SGIX, (GLuint*)&_iWidth);
932  glXQueryGLXPbufferSGIX(_pDpy, _hPBuffer, GLX_HEIGHT_SGIX, (GLuint*)&_iHeight);
933
934  _bInitialized = true;
935
936  // XXX Query the color format
937
938#endif
939 
940  return true;
941}
942
943//------------------------------------------------------------------------------
944// Function               : RenderTexture::_Invalidate
945// Description      :
946//------------------------------------------------------------------------------
947/**
948 * @fn RenderTexture::_Invalidate()
949 * @brief Returns the pbuffer memory to the graphics device.
950 *
951 */
952bool RenderTexture::_Invalidate()
953{
954  _bFloat       = false;
955  _bRectangle   = false;
956  _bInitialized = false;
957  _bHasDepth    = false;
958  _bHasStencil  = false;
959  _bMipmap      = false;
960  _bAnisoFilter = false;
961  _iBits[0] = _iBits[1] = _iBits[2] = _iBits[3] = 0;
962
963  if (_bIsTexture)
964    glDeleteTextures(1, &_iTextureID);
965  if (_bIsDepthTexture) {
966      // [Redge]
967      if (!_bHasArbDepthTexture) delete[] _pPoorDepthTexture;
968      // [/Redge]
969      glDeleteTextures(1, &_iDepthTextureID);
970  }
971
972#if _WIN32
973  if ( _hPBuffer )
974  {
975    // Check if we are currently rendering in the pbuffer
976    if (wglGetCurrentContext() == _hGLContext)
977      wglMakeCurrent(0,0);
978    wglDeleteContext( _hGLContext);
979    wglReleasePbufferDCARB( _hPBuffer, _hDC);
980    wglDestroyPbufferARB( _hPBuffer );
981    _hPBuffer = 0;
982    return true;
983  }
984#else
985  if ( _hPBuffer )
986  {
987    if(glXGetCurrentContext() == _hGLContext)
988      // XXX I don't know if this is right at all
989      glXMakeCurrent(_pDpy, _hPBuffer, 0);
990    glXDestroyGLXPbufferSGIX(_pDpy, _hPBuffer);
991    _hPBuffer = 0;
992    return true;
993  }
994#endif
995  return false;
996}
997
998
999//------------------------------------------------------------------------------
1000// Function               : RenderTexture::Reset
1001// Description      :
1002//------------------------------------------------------------------------------
1003/**
1004 * @fn RenderTexture::Reset(int iWidth, int iHeight, unsigned int iMode, bool bIsTexture, bool bIsDepthTexture)
1005 * @brief Resets the resolution of the offscreen buffer.
1006 *
1007 * Causes the buffer to delete itself.  User must call Initialize() again
1008 * before use.
1009 */
1010bool RenderTexture::Reset(int iWidth, int iHeight, bool bIsTexture /* = true */,
1011                           bool bIsDepthTexture /* = false */)
1012{
1013  if (!_Invalidate())
1014  {
1015    fprintf(stderr, "RenderTexture::Reset(): failed to invalidate.\n");
1016    return false;
1017  }
1018  _iWidth     = iWidth;
1019  _iHeight    = iHeight;
1020  _bIsTexture = bIsTexture;
1021  _bIsDepthTexture = bIsDepthTexture;
1022 
1023  return true;
1024}
1025
1026
1027//------------------------------------------------------------------------------
1028// Function               : RenderTexture::BeginCapture
1029// Description      :
1030//------------------------------------------------------------------------------
1031/**
1032 * @fn RenderTexture::BeginCapture()
1033 * @brief Activates rendering to the RenderTexture.
1034 */
1035bool RenderTexture::BeginCapture()
1036{
1037  if (!_bInitialized)
1038  {
1039    fprintf(stderr, "RenderTexture::BeginCapture(): Texture is not initialized!\n");
1040    exit(1);
1041    return false;
1042  }
1043#ifdef _WIN32
1044  // cache the current context so we can reset it when EndCapture() is called.
1045  _hPreviousDC      = wglGetCurrentDC();
1046  if (NULL == _hPreviousDC)
1047    _wglGetLastError();
1048  _hPreviousContext = wglGetCurrentContext();
1049  if (NULL == _hPreviousContext)
1050    _wglGetLastError();
1051
1052  if (_bIsTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
1053  {
1054    glBindTexture(_iTextureTarget, _iTextureID);
1055
1056          // release the pbuffer from the render texture object
1057    if (FALSE == wglReleaseTexImageARB(_hPBuffer, WGL_FRONT_LEFT_ARB))
1058    {
1059      _wglGetLastError();
1060      return false;
1061    }
1062  }
1063
1064  if (_bIsDepthTexture && RT_RENDER_TO_TEXTURE == _eUpdateMode)
1065  {
1066    glBindTexture(_iTextureTarget, _iDepthTextureID);
1067
1068          // release the pbuffer from the render texture object
1069    if (FALSE == wglReleaseTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1070    {
1071      _wglGetLastError();
1072      return false;
1073    }
1074  }
1075
1076  // make the pbuffer's rendering context current.
1077  if (FALSE == wglMakeCurrent( _hDC, _hGLContext))
1078  {
1079    _wglGetLastError();
1080    return false;
1081  }
1082#else
1083  _hPreviousContext = glXGetCurrentContext();
1084  _hPreviousDrawable = glXGetCurrentDrawable();
1085
1086  if (False == glXMakeCurrent(_pDpy, _hPBuffer, _hGLContext)) {
1087    return false;
1088  }
1089#endif
1090 
1091  return true;
1092}
1093
1094
1095//------------------------------------------------------------------------------
1096// Function               : RenderTexture::EndCapture
1097// Description      :
1098//------------------------------------------------------------------------------
1099/**
1100 * @fn RenderTexture::EndCapture()
1101 * @brief Ends rendering to the RenderTexture.
1102 */
1103bool RenderTexture::EndCapture()
1104{
1105  bool bContextReset = false;
1106
1107  if (!_bInitialized)
1108  {
1109    fprintf(stderr, "RenderTexture::EndCapture(): Texture is not initialized!\n");
1110    return false;
1111  }
1112#ifdef _WIN32 
1113  if (_bIsTexture)
1114  {
1115    if (RT_RENDER_TO_TEXTURE == _eUpdateMode)
1116    {
1117      // make the previous rendering context current
1118      if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
1119      {
1120        _wglGetLastError();
1121        return false;
1122      }
1123      bContextReset = true;
1124   
1125      // [Redge] moved binding completely to Bind()
1126      // [Mark] Can't do that, because it makes things difficult for Cg users.
1127      // bind the pbuffer to the render texture object     
1128      glBindTexture(_iTextureTarget, _iTextureID);
1129      if (FALSE == wglBindTexImageARB(_hPBuffer, WGL_FRONT_LEFT_ARB))
1130      {
1131        _wglGetLastError();
1132        return false;
1133      }
1134    }
1135    else
1136    {
1137      glBindTexture(_iTextureTarget, _iTextureID);
1138      glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
1139    }
1140  }
1141  if (_bIsDepthTexture)
1142  {
1143    if (RT_RENDER_TO_TEXTURE == _eUpdateMode)
1144    {
1145      // make the previous rendering context current
1146      if(!bContextReset)
1147      {
1148        if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
1149        {
1150          _wglGetLastError();
1151          return false;
1152        }
1153        bContextReset = true;
1154      }
1155
1156      // [Redge] moved binding completely to Bind()
1157      // [Mark] Can't do that, because it makes things difficult for Cg users.
1158      // bind the pbuffer to the render texture object
1159      glBindTexture(_iTextureTarget, _iDepthTextureID);
1160      if (FALSE == wglBindTexImageARB(_hPBuffer, WGL_DEPTH_COMPONENT_NV))
1161      {
1162        _wglGetLastError();
1163        return false;
1164      }
1165    }
1166    else
1167    {
1168      glBindTexture(_iTextureTarget, _iDepthTextureID);
1169      // HOW TO COPY DEPTH TEXTURE??? Supposedly this just magically works...
1170      // [Redge]
1171      if (_bHasArbDepthTexture)
1172      {
1173        glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
1174      }
1175      else
1176      {
1177        // no 'real' depth texture available, so behavior has to be emulated
1178        // using glReadPixels (beware, this is (naturally) slow ...)
1179        glReadPixels(0, 0, _iWidth, _iHeight,
1180                     GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, _pPoorDepthTexture);
1181        glTexImage2D(_iTextureTarget, 0, GL_LUMINANCE16,
1182                     _iWidth, _iHeight,
1183                     0, GL_LUMINANCE, GL_UNSIGNED_SHORT, _pPoorDepthTexture);
1184      }
1185      // [/Redge]
1186    }
1187  }
1188 
1189  if(!bContextReset)
1190  {
1191    // make the previous rendering context current
1192    if (FALSE == wglMakeCurrent( _hPreviousDC, _hPreviousContext))
1193    {
1194      _wglGetLastError();
1195      return false;
1196    }
1197  }
1198#else
1199  assert(_bIsTexture);
1200  glBindTexture(_iTextureTarget, _iTextureID);
1201  glCopyTexSubImage2D(_iTextureTarget, 0, 0, 0, 0, 0, _iWidth, _iHeight);
1202
1203  if(!bContextReset)
1204  {
1205    if (False == glXMakeCurrent(_pDpy, _hPreviousDrawable, _hPreviousContext))
1206    {
1207      return false;
1208    }
1209  }
1210#endif
1211  return true;
1212}
1213
1214
1215
1216//------------------------------------------------------------------------------
1217// Function               : RenderTexture::Bind
1218// Description      :
1219//------------------------------------------------------------------------------
1220/**
1221 * @fn RenderTexture::Bind()
1222 * @brief Binds RGB texture.
1223 */
1224void RenderTexture::Bind() const
1225{
1226  if (_bInitialized) {
1227    glBindTexture(_iTextureTarget, _iTextureID);   
1228  }   
1229}
1230
1231
1232//------------------------------------------------------------------------------
1233// Function               : RenderTexture::BindDepth
1234// Description      :
1235//------------------------------------------------------------------------------
1236/**
1237 * @fn RenderTexture::BindDepth()
1238 * @brief Binds depth texture.
1239 */
1240void RenderTexture::BindDepth() const
1241{
1242  if (_bInitialized && _bIsDepthTexture) {
1243    glBindTexture(_iTextureTarget, _iDepthTextureID);
1244  }
1245}
Note: See TracBrowser for help on using the repository browser.