2003-05-22 05:28:37 +00:00
# include "global.h"
2006-07-24 05:48:21 +00:00
# include "RageDisplay_OGL.h"
# include "RageDisplay_OGL_Helpers.h"
using namespace RageDisplay_OGL_Helpers ;
2003-05-22 05:28:37 +00:00
2007-02-19 23:40:19 +00:00
# include "RageFile.h"
2004-06-14 00:51:00 +00:00
# include "RageSurface.h"
# include "RageSurfaceUtils.h"
2003-05-22 05:28:37 +00:00
# include "RageUtil.h"
# include "RageLog.h"
# include "RageTextureManager.h"
# include "RageMath.h"
# include "RageTypes.h"
# include "RageUtil.h"
2005-11-13 19:04:07 +00:00
# include "EnumHelper.h"
2005-12-04 17:58:25 +00:00
# include "Foreach.h"
2005-11-26 07:22:33 +00:00
# include "DisplayResolutions.h"
2006-02-06 20:41:05 +00:00
# include "LocalizedString.h"
2003-05-22 05:28:37 +00:00
# include "arch/LowLevelWindow/LowLevelWindow.h"
2006-07-24 05:48:21 +00:00
# include <set>
2005-05-11 04:43:54 +00:00
# if defined(_MSC_VER)
2003-05-27 00:25:46 +00:00
# pragma comment(lib, "opengl32.lib")
2004-01-23 06:20:28 +00:00
# pragma comment(lib, "glu32.lib")
2003-06-30 06:23:42 +00:00
# endif
2003-05-22 05:28:37 +00:00
//
// Globals
//
2003-10-09 06:33:11 +00:00
static bool g_bReversePackedPixelsWorks = true ;
2004-09-26 09:15:16 +00:00
static bool g_bColorIndexTableWorks = true ;
2003-07-09 03:16:28 +00:00
2003-05-22 05:28:37 +00:00
/* OpenGL system information that generally doesn't change at runtime. */
/* Range and granularity of points and lines: */
2005-12-11 05:30:02 +00:00
static float g_line_range [ 2 ] ;
static float g_point_range [ 2 ] ;
2003-05-22 05:28:37 +00:00
/* OpenGL version * 10: */
2005-12-11 05:30:02 +00:00
static int g_glVersion ;
2003-05-22 05:28:37 +00:00
2004-01-24 19:14:22 +00:00
/* GLU version * 10: */
2005-12-11 05:30:02 +00:00
static int g_gluVersion ;
2004-01-24 19:14:22 +00:00
2005-01-04 05:34:58 +00:00
static int g_iMaxTextureUnits = 0 ;
2005-05-28 03:50:07 +00:00
/* We don't actually use normals (we don't turn on lighting), there's just
2003-05-22 05:28:37 +00:00
* no GL_T2F_C4F_V3F. */
2005-12-11 05:30:02 +00:00
static const GLenum RageSpriteVertexFormat = GL_T2F_C4F_N3F_V3F ;
2003-05-22 05:28:37 +00:00
2005-02-01 03:04:32 +00:00
/* If we support texture matrix scaling, a handle to the vertex program: */
2005-02-11 04:06:52 +00:00
static GLhandleARB g_bTextureMatrixShader = 0 ;
2003-05-22 05:28:37 +00:00
2006-07-26 03:44:27 +00:00
static map < unsigned , RenderTarget * > g_mapRenderTargets ;
static RenderTarget * g_pCurrentRenderTarget = NULL ;
2005-11-13 18:22:52 +00:00
static LowLevelWindow * g_pWind ;
2003-05-22 05:28:37 +00:00
2006-07-26 03:44:27 +00:00
static bool g_bInvertY = false ;
2007-03-22 18:55:49 +00:00
static void InvalidateObjects ( ) ;
2003-05-30 20:16:30 +00:00
2005-09-29 17:15:12 +00:00
static RageDisplay : : PixelFormatDesc PIXEL_FORMAT_DESC [ NUM_PixelFormat ] = {
2003-05-30 20:16:30 +00:00
{
2003-06-29 08:13:18 +00:00
/* R8G8B8A8 */
2003-05-30 20:16:30 +00:00
32 ,
2003-06-28 01:45:44 +00:00
{ 0xFF000000 ,
2003-05-30 20:16:30 +00:00
0x00FF0000 ,
2003-06-28 01:45:44 +00:00
0x0000FF00 ,
0x000000FF }
2007-03-22 05:30:19 +00:00
} , {
/* B8G8R8A8 */
32 ,
{ 0x0000FF00 ,
0x00FF0000 ,
0xFF000000 ,
0x000000FF }
2003-05-30 20:16:30 +00:00
} , {
2003-06-28 01:45:44 +00:00
/* R4G4B4A4 */
2003-05-30 20:16:30 +00:00
16 ,
{ 0xF000 ,
0x0F00 ,
0x00F0 ,
0x000F } ,
} , {
2003-06-28 01:45:44 +00:00
/* R5G5B5A1 */
2003-05-30 20:16:30 +00:00
16 ,
{ 0xF800 ,
0x07C0 ,
0x003E ,
0x0001 } ,
} , {
2007-03-20 07:47:14 +00:00
/* R5G5B5X1 */
2003-05-30 20:16:30 +00:00
16 ,
{ 0xF800 ,
0x07C0 ,
0x003E ,
0x0000 } ,
} , {
2003-06-28 01:45:44 +00:00
/* R8G8B8 */
2003-05-30 20:16:30 +00:00
24 ,
2003-06-28 01:45:44 +00:00
{ 0xFF0000 ,
2003-05-30 20:16:30 +00:00
0x00FF00 ,
2003-06-28 01:45:44 +00:00
0x0000FF ,
2003-05-30 20:16:30 +00:00
0x000000 }
2003-06-30 03:13:53 +00:00
} , {
/* Paletted */
8 ,
{ 0 , 0 , 0 , 0 } /* N/A */
2003-06-29 08:13:18 +00:00
} , {
2007-03-20 07:47:14 +00:00
/* B8G8R8 */
2003-06-29 08:13:18 +00:00
24 ,
{ 0x0000FF ,
0x00FF00 ,
0xFF0000 ,
0x000000 }
2003-05-30 20:16:30 +00:00
} , {
2007-03-20 07:48:18 +00:00
/* A1R5G5B5 */
2003-06-30 03:13:53 +00:00
16 ,
{ 0x7C00 ,
0x03E0 ,
0x001F ,
0x8000 } ,
2007-03-20 07:51:56 +00:00
} , {
/* X1R5G5B5 */
16 ,
{ 0x7C00 ,
0x03E0 ,
0x001F ,
0x0000 } ,
2003-05-30 20:16:30 +00:00
}
} ;
2005-09-29 17:15:12 +00:00
/* g_GLPixFmtInfo is used for both texture formats and surface formats. For example,
* it's fine to ask for a PixelFormat_RGB5 texture, but to supply a surface matching
* PixelFormat_RGB8. OpenGL will simply discard the extra bits.
2003-07-09 03:16:28 +00:00
*
* It's possible for a format to be supported as a texture format but not as a
* surface format. For example, if packed pixels aren't supported, we can still
* use GL_RGB5_A1, but we'll have to convert to a supported surface pixel format
* first. It's not ideal, since we'll convert to RGBA8 and OGL will convert back,
* but it works fine.
*/
2003-05-30 20:16:30 +00:00
struct GLPixFmtInfo_t {
GLenum internalfmt ; /* target format */
GLenum format ; /* target format */
GLenum type ; /* data format */
2005-09-29 17:15:12 +00:00
} const g_GLPixFmtInfo [ NUM_PixelFormat ] = {
2003-05-30 20:16:30 +00:00
{
2003-06-29 08:13:18 +00:00
/* R8G8B8A8 */
2003-05-30 20:16:30 +00:00
GL_RGBA8 ,
GL_RGBA ,
GL_UNSIGNED_BYTE ,
2007-03-22 05:30:19 +00:00
} , {
/* R8G8B8A8 */
GL_RGBA8 ,
GL_BGRA ,
GL_UNSIGNED_BYTE ,
2003-05-30 20:16:30 +00:00
} , {
/* B4G4R4A4 */
GL_RGBA4 ,
GL_RGBA ,
GL_UNSIGNED_SHORT_4_4_4_4 ,
} , {
/* B5G5R5A1 */
GL_RGB5_A1 ,
GL_RGBA ,
GL_UNSIGNED_SHORT_5_5_5_1 ,
} , {
/* B5G5R5 */
GL_RGB5 ,
GL_RGBA ,
GL_UNSIGNED_SHORT_5_5_5_1 ,
} , {
/* B8G8R8 */
GL_RGB8 ,
GL_RGB ,
GL_UNSIGNED_BYTE ,
2003-06-30 03:13:53 +00:00
} , {
/* Paletted */
GL_COLOR_INDEX8_EXT ,
GL_COLOR_INDEX ,
GL_UNSIGNED_BYTE ,
2003-06-29 08:13:18 +00:00
} , {
/* B8G8R8 */
GL_RGB8 ,
GL_BGR ,
GL_UNSIGNED_BYTE ,
2003-05-30 20:16:30 +00:00
} , {
2003-06-30 03:13:53 +00:00
/* A1R5G5B5 (matches D3DFMT_A1R5G5B5) */
GL_RGB5_A1 ,
GL_BGRA ,
GL_UNSIGNED_SHORT_1_5_5_5_REV ,
2007-03-20 07:51:56 +00:00
} , {
/* X1R5G5B5 */
GL_RGB5 ,
GL_BGRA ,
GL_UNSIGNED_SHORT_1_5_5_5_REV ,
2003-05-30 20:16:30 +00:00
}
} ;
2005-05-28 03:50:28 +00:00
static void FixLittleEndian ( )
2003-06-11 01:19:02 +00:00
{
2004-06-13 07:35:08 +00:00
# if defined(ENDIAN_LITTLE)
2005-11-13 18:22:52 +00:00
static bool bInitialized = false ;
if ( bInitialized )
2003-06-11 01:19:02 +00:00
return ;
2005-11-13 18:22:52 +00:00
bInitialized = true ;
2003-06-11 01:19:02 +00:00
2005-09-29 17:15:12 +00:00
for ( int i = 0 ; i < NUM_PixelFormat ; + + i )
2003-06-11 01:19:02 +00:00
{
2003-10-03 21:38:38 +00:00
RageDisplay : : PixelFormatDesc & pf = PIXEL_FORMAT_DESC [ i ] ;
2003-06-11 01:19:02 +00:00
2004-06-14 05:48:28 +00:00
/* OpenGL and RageSurface handle byte formats differently; we need
2003-06-28 01:45:44 +00:00
* to flip non-paletted masks to make them line up. */
2005-09-29 17:15:12 +00:00
if ( g_GLPixFmtInfo [ i ] . type ! = GL_UNSIGNED_BYTE | | pf . bpp = = 8 )
2003-06-11 01:19:02 +00:00
continue ;
for ( int mask = 0 ; mask < 4 ; + + mask )
2003-06-11 01:22:14 +00:00
{
int m = pf . masks [ mask ] ;
switch ( pf . bpp )
{
2004-06-13 07:10:26 +00:00
case 24 : m = Swap24 ( m ) ; break ;
case 32 : m = Swap32 ( m ) ; break ;
2003-06-28 01:45:44 +00:00
default : ASSERT ( 0 ) ;
2003-06-11 01:22:14 +00:00
}
pf . masks [ mask ] = m ;
}
2003-06-11 01:19:02 +00:00
}
# endif
}
2003-05-30 20:16:30 +00:00
2008-01-02 12:17:49 +00:00
/* Making an OpenGL call doesn't also flush the error state; if we happen
* to have an error from a previous call, then the assert below will fail.
* Flush it. */
# define FlushGLErrors() do { } while( glGetError() != GL_NO_ERROR )
2004-04-16 21:34:58 +00:00
# define AssertNoGLError() \
{ \
GLenum error = glGetError(); \
2005-12-30 13:19:40 +00:00
ASSERT_M( error == GL_NO_ERROR, GLToString(error) ); \
2004-04-12 03:07:44 +00:00
}
2008-01-03 02:45:00 +00:00
# if defined(DEBUG) || !defined(GL_GET_ERROR_IS_SLOW)
2008-01-02 12:17:49 +00:00
# define DebugFlushGLErrors() FlushGLErrors()
# define DebugAssertNoGLError() AssertNoGLError()
# else
# define DebugFlushGLErrors()
# define DebugAssertNoGLError()
# endif
2004-04-16 05:31:08 +00:00
static void TurnOffHardwareVBO ( )
{
2004-05-24 03:41:49 +00:00
if ( GLExt . glBindBufferARB )
2004-04-16 05:31:08 +00:00
{
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , 0 ) ;
GLExt . glBindBufferARB ( GL_ELEMENT_ARRAY_BUFFER_ARB , 0 ) ;
2004-04-16 05:31:08 +00:00
}
}
2004-11-30 22:21:50 +00:00
RageDisplay_OGL : : RageDisplay_OGL ( )
2003-05-22 05:28:37 +00:00
{
2003-05-27 00:48:40 +00:00
LOG - > Trace ( " RageDisplay_OGL::RageDisplay_OGL() " ) ;
LOG - > MapLog ( " renderer " , " Current renderer: OpenGL " ) ;
2003-05-22 05:28:37 +00:00
2005-05-28 03:50:28 +00:00
FixLittleEndian ( ) ;
2006-07-24 05:48:21 +00:00
RageDisplay_OGL_Helpers : : Init ( ) ;
2003-06-11 01:19:02 +00:00
2005-11-13 18:22:52 +00:00
g_pWind = NULL ;
2005-05-06 14:41:46 +00:00
g_bTextureMatrixShader = 0 ;
2004-11-30 22:21:50 +00:00
}
2006-01-22 01:00:06 +00:00
RString GetInfoLog ( GLhandleARB h )
2005-02-01 03:04:32 +00:00
{
GLint iLength ;
GLExt . glGetObjectParameterivARB ( h , GL_OBJECT_INFO_LOG_LENGTH_ARB , & iLength ) ;
if ( ! iLength )
2006-01-22 01:00:06 +00:00
return RString ( ) ;
2005-02-01 03:04:32 +00:00
GLcharARB * pInfoLog = new GLcharARB [ iLength ] ;
GLExt . glGetInfoLogARB ( h , iLength , & iLength , pInfoLog ) ;
2006-01-22 01:00:06 +00:00
RString sRet = pInfoLog ;
2005-02-01 03:04:32 +00:00
delete [ ] pInfoLog ;
2007-02-19 23:40:19 +00:00
TrimRight ( sRet ) ;
2005-02-01 03:04:32 +00:00
return sRet ;
}
2007-02-19 23:40:19 +00:00
GLhandleARB CompileShader ( GLenum ShaderType , RString sFile , vector < RString > asDefines )
2005-02-01 03:04:32 +00:00
{
2007-02-19 23:40:19 +00:00
RString sBuffer ;
{
RageFile file ;
if ( ! file . Open ( sFile ) )
{
LOG - > Warn ( " Error compiling shader %s: %s " , sFile . c_str ( ) , file . GetError ( ) . c_str ( ) ) ;
return 0 ;
}
if ( file . Read ( sBuffer , file . GetFileSize ( ) ) = = - 1 )
{
LOG - > Warn ( " Error compiling shader %s: %s " , sFile . c_str ( ) , file . GetError ( ) . c_str ( ) ) ;
return 0 ;
}
}
2005-02-01 03:04:32 +00:00
2007-02-19 23:40:19 +00:00
LOG - > Trace ( " Compiling shader %s " , sFile . c_str ( ) ) ;
GLhandleARB hShader = GLExt . glCreateShaderObjectARB ( ShaderType ) ;
vector < const GLcharARB * > apData ;
vector < GLint > aiLength ;
FOREACH ( RString , asDefines , s )
{
* s = ssprintf ( " #define %s \n " , s - > c_str ( ) ) ;
apData . push_back ( s - > data ( ) ) ;
aiLength . push_back ( s - > size ( ) ) ;
}
apData . push_back ( " #line 1 \n " ) ;
aiLength . push_back ( 8 ) ;
2005-02-01 03:04:32 +00:00
2007-02-19 23:40:19 +00:00
apData . push_back ( sBuffer . data ( ) ) ;
aiLength . push_back ( sBuffer . size ( ) ) ;
GLExt . glShaderSourceARB ( hShader , apData . size ( ) , & apData [ 0 ] , & aiLength [ 0 ] ) ;
2005-02-01 03:04:32 +00:00
2007-02-19 23:40:19 +00:00
GLExt . glCompileShaderARB ( hShader ) ;
RString sInfo = GetInfoLog ( hShader ) ;
GLint bCompileStatus = GL_FALSE ;
GLExt . glGetObjectParameterivARB ( hShader , GL_OBJECT_COMPILE_STATUS_ARB , & bCompileStatus ) ;
2005-02-01 03:04:32 +00:00
if ( ! bCompileStatus )
{
2007-02-19 23:40:19 +00:00
LOG - > Warn ( " Error compiling shader %s: \n %s " , sFile . c_str ( ) , sInfo . c_str ( ) ) ;
GLExt . glDeleteObjectARB ( hShader ) ;
2005-02-11 04:06:52 +00:00
return 0 ;
2005-02-01 03:04:32 +00:00
}
2007-02-19 23:40:19 +00:00
if ( ! sInfo . empty ( ) )
LOG - > Trace ( " Messages compiling shader %s: \n %s " , sFile . c_str ( ) , sInfo . c_str ( ) ) ;
2005-02-01 03:04:32 +00:00
2007-02-19 23:40:19 +00:00
return hShader ;
}
2005-02-01 03:04:32 +00:00
2007-02-19 23:40:19 +00:00
GLhandleARB LoadShader ( GLenum ShaderType , RString sFile , vector < RString > asDefines )
2005-02-01 03:04:32 +00:00
{
2007-02-19 23:40:19 +00:00
if ( ! GLExt . m_bGL_ARB_fragment_shader & & ShaderType = = GL_FRAGMENT_SHADER_ARB )
return 0 ;
if ( ! GLExt . m_bGL_ARB_vertex_shader & & ShaderType = = GL_VERTEX_SHADER_ARB )
return 0 ;
2005-02-01 03:04:32 +00:00
2007-02-19 23:40:19 +00:00
GLhandleARB hShader = CompileShader ( ShaderType , sFile , asDefines ) ;
if ( hShader = = 0 )
return 0 ;
2005-02-01 03:04:32 +00:00
2007-02-19 23:40:19 +00:00
GLhandleARB hProgram = GLExt . glCreateProgramObjectARB ( ) ;
GLExt . glAttachObjectARB ( hProgram , hShader ) ;
GLExt . glDeleteObjectARB ( hShader ) ;
2005-02-01 03:04:32 +00:00
// Link the program.
2007-02-19 23:40:19 +00:00
GLExt . glLinkProgramARB ( hProgram ) ;
2005-02-01 03:04:32 +00:00
GLint bLinkStatus = false ;
2007-02-19 23:40:19 +00:00
GLExt . glGetObjectParameterivARB ( hProgram , GL_OBJECT_LINK_STATUS_ARB , & bLinkStatus ) ;
2005-02-01 03:04:32 +00:00
if ( ! bLinkStatus )
{
2007-02-19 23:40:19 +00:00
LOG - > Warn ( " Error linking shader %s: %s " , sFile . c_str ( ) , GetInfoLog ( hProgram ) . c_str ( ) ) ;
GLExt . glDeleteObjectARB ( hProgram ) ;
return 0 ;
2007-02-18 10:37:06 +00:00
}
2007-02-19 23:40:19 +00:00
return hProgram ;
2005-02-01 03:04:32 +00:00
}
2007-02-19 23:40:19 +00:00
static int g_iAttribTextureMatrixScale ;
2007-02-14 01:59:41 +00:00
2007-02-24 23:20:25 +00:00
static GLhandleARB g_bUnpremultiplyShader = 0 ;
2007-02-14 01:59:41 +00:00
static GLhandleARB g_bColorBurnShader = 0 ;
2007-02-19 23:40:19 +00:00
static GLhandleARB g_bColorDodgeShader = 0 ;
static GLhandleARB g_bVividLightShader = 0 ;
static GLhandleARB g_hHardMixShader = 0 ;
2007-03-21 04:38:17 +00:00
static GLhandleARB g_hYUYV422Shader = 0 ;
2007-02-14 01:59:41 +00:00
2007-02-19 23:40:19 +00:00
void InitShaders ( )
{
vector < RString > asDefines ;
g_bTextureMatrixShader = LoadShader ( GL_VERTEX_SHADER_ARB , " Data/Shaders/GLSL/Texture matrix scaling.vert " , asDefines ) ;
2007-02-24 23:20:25 +00:00
g_bUnpremultiplyShader = LoadShader ( GL_FRAGMENT_SHADER_ARB , " Data/Shaders/GLSL/Unpremultiply.frag " , asDefines ) ;
2007-02-19 23:40:19 +00:00
g_bColorBurnShader = LoadShader ( GL_FRAGMENT_SHADER_ARB , " Data/Shaders/GLSL/Color burn.frag " , asDefines ) ;
g_bColorDodgeShader = LoadShader ( GL_FRAGMENT_SHADER_ARB , " Data/Shaders/GLSL/Color dodge.frag " , asDefines ) ;
g_bVividLightShader = LoadShader ( GL_FRAGMENT_SHADER_ARB , " Data/Shaders/GLSL/Vivid light.frag " , asDefines ) ;
g_hHardMixShader = LoadShader ( GL_FRAGMENT_SHADER_ARB , " Data/Shaders/GLSL/Hard mix.frag " , asDefines ) ;
2007-03-21 04:38:17 +00:00
g_hYUYV422Shader = LoadShader ( GL_FRAGMENT_SHADER_ARB , " Data/Shaders/GLSL/YUYV422.frag " , asDefines ) ;
2007-02-14 01:59:41 +00:00
2007-02-19 23:40:19 +00:00
// Bind attributes.
if ( g_bTextureMatrixShader )
2007-02-14 01:59:41 +00:00
{
2007-03-07 20:08:55 +00:00
FlushGLErrors ( ) ;
2007-02-19 23:40:19 +00:00
g_iAttribTextureMatrixScale = GLExt . glGetAttribLocationARB ( g_bTextureMatrixShader , " TextureMatrixScale " ) ;
if ( g_iAttribTextureMatrixScale = = - 1 )
{
LOG - > Trace ( " Scaling shader link failed: couldn't bind attribute \" TextureMatrixScale \" " ) ;
GLExt . glDeleteObjectARB ( g_bTextureMatrixShader ) ;
g_bTextureMatrixShader = 0 ;
}
else
{
AssertNoGLError ( ) ;
2007-07-22 18:43:55 +00:00
/* Older Catalyst drivers seem to throw GL_INVALID_OPERATION here. */
GLExt . glVertexAttrib2fARB ( g_iAttribTextureMatrixScale , 1 , 1 ) ;
GLenum iError = glGetError ( ) ;
if ( iError = = GL_INVALID_OPERATION )
{
LOG - > Trace ( " Scaling shader failed: glVertexAttrib2fARB returned GL_INVALID_OPERATION " ) ;
GLExt . glDeleteObjectARB ( g_bTextureMatrixShader ) ;
g_bTextureMatrixShader = 0 ;
}
else
{
ASSERT_M ( iError = = GL_NO_ERROR , GLToString ( iError ) ) ;
}
2007-02-19 23:40:19 +00:00
}
2007-02-14 01:59:41 +00:00
}
}
2006-02-06 20:41:05 +00:00
static LocalizedString OBTAIN_AN_UPDATED_VIDEO_DRIVER ( " RageDisplay_OGL " , " Obtain an updated driver from your video card manufacturer. " ) ;
static LocalizedString GLDIRECT_IS_NOT_COMPATIBLE ( " RageDisplay_OGL " , " GLDirect was detected. GLDirect is not compatible with this game and should be disabled. " ) ;
2006-02-06 20:14:02 +00:00
RString RageDisplay_OGL : : Init ( const VideoModeParams & p , bool bAllowUnacceleratedRenderer )
2004-11-30 22:21:50 +00:00
{
2006-12-17 07:41:21 +00:00
g_pWind = LowLevelWindow : : Create ( ) ;
2003-05-22 05:28:37 +00:00
2004-11-30 20:01:07 +00:00
bool bIgnore = false ;
2006-01-22 01:00:06 +00:00
RString sError = SetVideoMode ( p , bIgnore ) ;
2004-11-30 20:01:07 +00:00
if ( sError ! = " " )
2004-11-30 22:21:50 +00:00
return sError ;
2003-05-22 05:28:37 +00:00
// Log driver details
2005-01-04 05:34:58 +00:00
LOG - > Info ( " OGL Vendor: %s " , glGetString ( GL_VENDOR ) ) ;
LOG - > Info ( " OGL Renderer: %s " , glGetString ( GL_RENDERER ) ) ;
LOG - > Info ( " OGL Version: %s " , glGetString ( GL_VERSION ) ) ;
LOG - > Info ( " OGL Max texture size: %i " , GetMaxTextureSize ( ) ) ;
LOG - > Info ( " OGL Texture units: %i " , g_iMaxTextureUnits ) ;
LOG - > Info ( " GLU Version: %s " , gluGetString ( GLU_VERSION ) ) ;
2003-06-25 20:44:49 +00:00
2007-02-17 14:14:44 +00:00
/* Pretty-print the extension string: */
LOG - > Info ( " OGL Extensions: " ) ;
{
const char * szExtensionString = ( const char * ) glGetString ( GL_EXTENSIONS ) ;
vector < RString > asExtensions ;
split ( szExtensionString , " " , asExtensions ) ;
2007-03-21 12:01:54 +00:00
sort ( asExtensions . begin ( ) , asExtensions . end ( ) ) ;
2007-02-17 14:14:44 +00:00
size_t iNextToPrint = 0 ;
while ( iNextToPrint < asExtensions . size ( ) )
{
size_t iLastToPrint = iNextToPrint ;
RString sType ;
for ( size_t i = iNextToPrint ; i < asExtensions . size ( ) ; + + i )
{
vector < RString > asBits ;
split ( asExtensions [ i ] , " _ " , asBits ) ;
RString sThisType ;
if ( asBits . size ( ) > 2 )
sThisType = join ( " _ " , asBits . begin ( ) , asBits . begin ( ) + 2 ) ;
if ( i > iNextToPrint & & sThisType ! = sType )
break ;
sType = sThisType ;
iLastToPrint = i ;
}
if ( iNextToPrint = = iLastToPrint )
{
LOG - > Info ( " %s " , asExtensions [ iNextToPrint ] . c_str ( ) ) ;
+ + iNextToPrint ;
continue ;
}
RString sList = ssprintf ( " %s: " , sType . c_str ( ) ) ;
while ( iNextToPrint < = iLastToPrint )
{
vector < RString > asBits ;
split ( asExtensions [ iNextToPrint ] , " _ " , asBits ) ;
RString sShortExt = join ( " _ " , asBits . begin ( ) + 2 , asBits . end ( ) ) ;
sList + = sShortExt ;
if ( iNextToPrint < iLastToPrint )
sList + = " , " ;
if ( iNextToPrint = = iLastToPrint | | sList . size ( ) + asExtensions [ iNextToPrint + 1 ] . size ( ) > 120 )
{
LOG - > Info ( " %s " , sList . c_str ( ) ) ;
sList = " " ;
}
+ + iNextToPrint ;
}
}
}
2005-11-13 18:54:09 +00:00
if ( g_pWind - > IsSoftwareRenderer ( sError ) )
2003-06-25 20:44:49 +00:00
{
if ( ! bAllowUnacceleratedRenderer )
2006-02-06 20:41:05 +00:00
return sError + " " + OBTAIN_AN_UPDATED_VIDEO_DRIVER . GetValue ( ) + " \n \n " ;
2005-11-13 18:54:09 +00:00
LOG - > Warn ( " Low-performance OpenGL renderer: " + sError ) ;
2003-06-25 20:44:49 +00:00
}
2003-05-22 05:28:37 +00:00
2004-04-03 00:09:16 +00:00
# if defined(_WINDOWS)
/* GLDirect is a Direct3D wrapper for OpenGL. It's rather buggy; and if in
* any case GLDirect can successfully render us, we should be able to do so
* too using Direct3D directly. (If we can't, it's a bug that we can work
* around--if GLDirect can do it, so can we!) */
if ( ! strncmp ( ( const char * ) glGetString ( GL_RENDERER ) , " GLDirect " , 8 ) )
2006-02-06 20:41:05 +00:00
return GLDIRECT_IS_NOT_COMPATIBLE . GetValue ( ) + " \n " ;
2004-04-03 00:09:16 +00:00
# endif
2003-05-22 05:28:37 +00:00
/* Log this, so if people complain that the radar looks bad on their
* system we can compare them: */
2005-11-13 18:22:52 +00:00
glGetFloatv ( GL_LINE_WIDTH_RANGE , g_line_range ) ;
glGetFloatv ( GL_POINT_SIZE_RANGE , g_point_range ) ;
2004-11-30 22:21:50 +00:00
2006-01-22 01:00:06 +00:00
return RString ( ) ;
2003-05-22 05:28:37 +00:00
}
2003-05-26 19:42:04 +00:00
RageDisplay_OGL : : ~ RageDisplay_OGL ( )
2003-05-22 05:28:37 +00:00
{
2005-11-13 18:22:52 +00:00
delete g_pWind ;
2003-05-22 05:28:37 +00:00
}
2005-11-26 07:22:33 +00:00
void RageDisplay_OGL : : GetDisplayResolutions ( DisplayResolutions & out ) const
{
2006-02-07 08:29:36 +00:00
out . clear ( ) ;
2005-11-26 07:22:33 +00:00
g_pWind - > GetDisplayResolutions ( out ) ;
}
2006-02-06 23:40:28 +00:00
float RageDisplay_OGL : : GetMonitorAspectRatio ( ) const
{
return g_pWind - > GetMonitorAspectRatio ( ) ;
}
2004-05-15 08:18:37 +00:00
static void CheckPalettedTextures ( )
2003-05-30 20:16:30 +00:00
{
2006-01-22 01:00:06 +00:00
RString sError ;
2004-03-13 07:38:46 +00:00
do
2004-03-13 06:42:07 +00:00
{
2005-05-28 03:54:33 +00:00
if ( ! GLExt . HasExtension ( " GL_EXT_paletted_texture " ) )
2004-05-10 01:06:37 +00:00
{
2005-11-13 18:22:52 +00:00
sError = " GL_EXT_paletted_texture missing " ;
2004-05-10 01:06:37 +00:00
break ;
}
2004-05-24 03:41:49 +00:00
if ( GLExt . glColorTableEXT = = NULL )
2004-03-13 07:38:46 +00:00
{
2005-11-13 18:22:52 +00:00
sError = " glColorTableEXT missing " ;
2004-03-13 07:38:46 +00:00
break ;
}
2004-03-13 06:42:07 +00:00
2004-05-24 03:41:49 +00:00
if ( GLExt . glGetColorTableParameterivEXT = = NULL )
2004-03-13 07:38:46 +00:00
{
2005-11-13 18:22:52 +00:00
sError = " glGetColorTableParameterivEXT missing " ;
2004-03-13 07:38:46 +00:00
break ;
}
2003-05-30 20:16:30 +00:00
2004-03-13 07:38:46 +00:00
/* Check to see if paletted textures really work. */
2005-09-29 17:15:12 +00:00
GLenum glTexFormat = g_GLPixFmtInfo [ PixelFormat_PAL ] . internalfmt ;
GLenum glImageFormat = g_GLPixFmtInfo [ PixelFormat_PAL ] . format ;
GLenum glImageType = g_GLPixFmtInfo [ PixelFormat_PAL ] . type ;
2003-05-30 20:16:30 +00:00
2005-11-13 18:22:52 +00:00
int iBits = 8 ;
2003-10-09 06:33:11 +00:00
2004-03-13 07:38:46 +00:00
FlushGLErrors ( ) ;
2003-11-13 18:04:31 +00:00
# define GL_CHECK_ERROR(f) \
2004-03-13 07:38:46 +00:00
{ \
GLenum glError = glGetError(); \
if( glError != GL_NO_ERROR ) { \
2005-11-13 18:22:52 +00:00
sError = ssprintf(f " failed (%s)", GLToString(glError).c_str() ); \
2004-03-13 07:38:46 +00:00
break; \
} \
}
2003-11-13 18:04:31 +00:00
2005-11-13 18:22:52 +00:00
glTexImage2D ( GL_PROXY_TEXTURE_2D ,
2003-05-30 20:16:30 +00:00
0 , glTexFormat ,
16 , 16 , 0 ,
2005-11-13 18:22:52 +00:00
glImageFormat , glImageType , NULL ) ;
2004-03-13 07:38:46 +00:00
GL_CHECK_ERROR ( " glTexImage2D " ) ;
2003-05-30 20:16:30 +00:00
2005-11-13 18:22:52 +00:00
GLuint iFormat = 0 ;
glGetTexLevelParameteriv ( GL_PROXY_TEXTURE_2D , 0 , GLenum ( GL_TEXTURE_INTERNAL_FORMAT ) , ( GLint * ) & iFormat ) ;
2004-04-03 21:33:10 +00:00
GL_CHECK_ERROR ( " glGetTexLevelParameteriv(GL_TEXTURE_INTERNAL_FORMAT) " ) ;
2005-11-13 18:22:52 +00:00
if ( iFormat ! = glTexFormat )
2003-10-09 06:33:11 +00:00
{
2005-11-13 18:22:52 +00:00
sError = ssprintf ( " Expected format %s, got %s instead " ,
GLToString ( glTexFormat ) . c_str ( ) , GLToString ( iFormat ) . c_str ( ) ) ;
2004-03-13 07:38:46 +00:00
break ;
2003-10-09 06:33:11 +00:00
}
2004-03-13 07:38:46 +00:00
GLubyte palette [ 256 * 4 ] ;
memset ( palette , 0 , sizeof ( palette ) ) ;
2004-05-24 03:41:49 +00:00
GLExt . glColorTableEXT ( GL_PROXY_TEXTURE_2D , GL_RGBA8 , 256 , GL_RGBA , GL_UNSIGNED_BYTE , palette ) ;
2004-03-13 07:38:46 +00:00
GL_CHECK_ERROR ( " glColorTableEXT " ) ;
2003-05-30 20:16:30 +00:00
2005-11-13 18:22:52 +00:00
GLint iSize = 0 ;
glGetTexLevelParameteriv ( GL_PROXY_TEXTURE_2D , 0 , GLenum ( GL_TEXTURE_INDEX_SIZE_EXT ) , & iSize ) ;
2004-03-13 06:42:07 +00:00
GL_CHECK_ERROR ( " glGetTexLevelParameteriv(GL_TEXTURE_INDEX_SIZE_EXT) " ) ;
2005-11-13 18:22:52 +00:00
if ( iBits > iSize | | iSize > 8 )
2003-05-30 23:15:53 +00:00
{
2005-11-13 18:22:52 +00:00
sError = ssprintf ( " Expected %i-bit palette, got a %i-bit one instead " , iBits , int ( iSize ) ) ;
2004-03-13 07:38:46 +00:00
break ;
2003-05-30 23:15:53 +00:00
}
2003-11-13 18:04:31 +00:00
2005-11-13 18:22:52 +00:00
GLint iRealWidth = 0 ;
GLExt . glGetColorTableParameterivEXT ( GL_PROXY_TEXTURE_2D , GL_COLOR_TABLE_WIDTH , & iRealWidth ) ;
2003-11-14 00:07:47 +00:00
GL_CHECK_ERROR ( " glGetColorTableParameterivEXT(GL_COLOR_TABLE_WIDTH) " ) ;
2005-11-13 18:22:52 +00:00
if ( iRealWidth ! = 1 < < iBits )
2003-11-13 18:04:31 +00:00
{
2005-11-13 18:22:52 +00:00
sError = ssprintf ( " GL_COLOR_TABLE_WIDTH returned %i instead of %i " , int ( iRealWidth ) , 1 < < iBits ) ;
2004-03-13 07:38:46 +00:00
break ;
2003-11-13 18:04:31 +00:00
}
2004-03-13 07:38:46 +00:00
2005-11-13 18:22:52 +00:00
GLint iRealFormat = 0 ;
GLExt . glGetColorTableParameterivEXT ( GL_PROXY_TEXTURE_2D , GL_COLOR_TABLE_FORMAT , & iRealFormat ) ;
2003-11-13 18:04:31 +00:00
GL_CHECK_ERROR ( " glGetColorTableParameterivEXT(GL_COLOR_TABLE_FORMAT) " ) ;
2005-11-13 18:22:52 +00:00
if ( iRealFormat ! = GL_RGBA8 )
2003-11-13 18:04:31 +00:00
{
2005-11-13 18:22:52 +00:00
sError = ssprintf ( " GL_COLOR_TABLE_FORMAT returned %s instead of GL_RGBA8 " , GLToString ( iRealFormat ) . c_str ( ) ) ;
2004-03-13 07:38:46 +00:00
break ;
2003-11-13 18:04:31 +00:00
}
2004-03-13 07:38:46 +00:00
} while ( 0 ) ;
# undef GL_CHECK_ERROR
2003-05-30 20:16:30 +00:00
2005-11-13 18:22:52 +00:00
if ( sError = = " " )
2004-03-13 07:38:46 +00:00
return ;
2003-05-30 20:16:30 +00:00
2004-05-15 08:18:37 +00:00
/* If 8-bit palettes don't work, disable them entirely--don't trust 4-bit
* palettes if it can't even get 8-bit ones right. */
2004-05-24 03:41:49 +00:00
GLExt . glColorTableEXT = NULL ;
GLExt . glGetColorTableParameterivEXT = NULL ;
2005-11-13 18:22:52 +00:00
LOG - > Info ( " Paletted textures disabled: %s. " , sError . c_str ( ) ) ;
2003-05-30 20:16:30 +00:00
}
2003-07-09 03:16:28 +00:00
static void CheckReversePackedPixels ( )
{
/* Try to create a texture. */
FlushGLErrors ( ) ;
2005-11-13 18:22:52 +00:00
glTexImage2D ( GL_PROXY_TEXTURE_2D ,
2003-07-09 03:16:28 +00:00
0 , GL_RGBA ,
16 , 16 , 0 ,
2005-11-13 18:22:52 +00:00
GL_BGRA , GL_UNSIGNED_SHORT_1_5_5_5_REV , NULL ) ;
2003-07-09 03:16:28 +00:00
const GLenum glError = glGetError ( ) ;
if ( glError = = GL_NO_ERROR )
2005-11-13 18:22:52 +00:00
{
2003-07-09 03:16:28 +00:00
g_bReversePackedPixelsWorks = true ;
2005-11-13 18:22:52 +00:00
}
2003-07-09 03:16:28 +00:00
else
{
g_bReversePackedPixelsWorks = false ;
2005-11-13 18:22:52 +00:00
LOG - > Info ( " GL_UNSIGNED_SHORT_1_5_5_5_REV failed (%s), disabled " ,
2003-07-09 03:16:28 +00:00
GLToString ( glError ) . c_str ( ) ) ;
}
}
2003-05-22 05:28:37 +00:00
void SetupExtensions ( )
{
2006-06-12 06:42:25 +00:00
const float fGLVersion = StringToFloat ( ( const char * ) glGetString ( GL_VERSION ) ) ;
2007-01-03 05:05:28 +00:00
g_glVersion = lrintf ( fGLVersion * 10 ) ;
2003-05-22 05:28:37 +00:00
2006-06-12 06:42:25 +00:00
const float fGLUVersion = StringToFloat ( ( const char * ) gluGetString ( GLU_VERSION ) ) ;
2007-01-03 05:05:28 +00:00
g_gluVersion = lrintf ( fGLUVersion * 10 ) ;
2004-01-24 19:14:22 +00:00
2005-11-13 18:22:52 +00:00
GLExt . Load ( g_pWind ) ;
2004-05-24 03:56:08 +00:00
2005-01-30 19:50:55 +00:00
g_iMaxTextureUnits = 1 ;
if ( GLExt . glActiveTextureARB ! = NULL )
glGetIntegerv ( GL_MAX_TEXTURE_UNITS_ARB , ( GLint * ) & g_iMaxTextureUnits ) ;
2004-05-24 03:56:08 +00:00
2004-05-15 08:18:37 +00:00
CheckPalettedTextures ( ) ;
2003-07-09 03:16:28 +00:00
CheckReversePackedPixels ( ) ;
2004-09-26 09:15:16 +00:00
{
GLint iMaxTableSize = 0 ;
glGetIntegerv ( GL_MAX_PIXEL_MAP_TABLE , & iMaxTableSize ) ;
if ( iMaxTableSize < 256 )
{
/* The minimum GL_MAX_PIXEL_MAP_TABLE is 32; if it's not at least 256,
* we can't fit a palette in it, so we can't send paletted data as input
* for a non-paletted texture. */
2004-10-05 10:36:11 +00:00
LOG - > Info ( " GL_MAX_PIXEL_MAP_TABLE is only %d " , int ( iMaxTableSize ) ) ;
2004-09-26 09:15:16 +00:00
g_bColorIndexTableWorks = false ;
}
else
2005-11-13 18:22:52 +00:00
{
2004-09-26 09:15:16 +00:00
g_bColorIndexTableWorks = true ;
2005-11-13 18:22:52 +00:00
}
2004-09-26 09:15:16 +00:00
}
2003-05-22 05:28:37 +00:00
}
2003-05-26 19:42:04 +00:00
void RageDisplay_OGL : : ResolutionChanged ( )
2003-05-22 05:28:37 +00:00
{
2005-11-24 10:40:23 +00:00
//LOG->Warn( "RageDisplay_OGL::ResolutionChanged" );
2003-05-22 05:28:37 +00:00
/* Clear any junk that's in the framebuffer. */
2004-09-19 01:38:12 +00:00
if ( BeginFrame ( ) )
EndFrame ( ) ;
2005-12-29 07:45:06 +00:00
RageDisplay : : ResolutionChanged ( ) ;
2003-05-22 05:28:37 +00:00
}
2003-06-05 19:29:27 +00:00
// Return true if mode change was successful.
// bNewDeviceOut is set true if a new device was created and textures
// need to be reloaded.
2006-01-22 01:00:06 +00:00
RString RageDisplay_OGL : : TryVideoMode ( const VideoModeParams & p , bool & bNewDeviceOut )
2003-05-22 05:28:37 +00:00
{
2005-11-24 10:40:23 +00:00
//LOG->Warn( "RageDisplay_OGL::TryVideoMode( %d, %d, %d, %d, %d, %d )", p.windowed, p.width, p.height, p.bpp, p.rate, p.vsync );
2006-01-22 01:00:06 +00:00
RString err ;
2005-11-13 18:22:52 +00:00
err = g_pWind - > TryVideoMode ( p , bNewDeviceOut ) ;
2003-08-28 00:08:01 +00:00
if ( err ! = " " )
return err ; // failed to set video mode
2003-05-22 05:28:37 +00:00
2007-03-22 18:55:49 +00:00
/* Now that we've initialized, we can search for extensions. Do this before InvalidateObjects,
2005-11-11 21:01:58 +00:00
* since AllocateBuffers needs it. */
SetupExtensions ( ) ;
2003-06-05 19:29:27 +00:00
if ( bNewDeviceOut )
2003-05-22 05:28:37 +00:00
{
/* We have a new OpenGL context, so we have to tell our textures that
* their OpenGL texture number is invalid. */
2005-11-13 18:22:52 +00:00
if ( TEXTUREMAN )
2003-05-22 05:28:37 +00:00
TEXTUREMAN - > InvalidateTextures ( ) ;
2004-04-16 21:34:58 +00:00
2006-07-26 03:44:27 +00:00
/* Delete all render targets. They may have associated resources other than
* the texture itself. */
2006-07-26 03:58:29 +00:00
FOREACHM ( unsigned , RenderTarget * , g_mapRenderTargets , rt )
2006-07-26 03:44:27 +00:00
delete rt - > second ;
g_mapRenderTargets . clear ( ) ;
2004-04-16 21:34:58 +00:00
/* Recreate all vertex buffers. */
2007-03-22 18:55:49 +00:00
InvalidateObjects ( ) ;
2005-11-28 23:11:34 +00:00
2007-02-19 23:40:19 +00:00
InitShaders ( ) ;
2003-05-22 05:28:37 +00:00
}
/* Set vsync the Windows way, if we can. (What other extensions are there
* to do this, for other archs?) */
2004-05-24 03:41:49 +00:00
if ( GLExt . wglSwapIntervalEXT )
2006-02-01 07:52:33 +00:00
GLExt . wglSwapIntervalEXT ( p . vsync ) ;
2003-05-22 05:28:37 +00:00
ResolutionChanged ( ) ;
2006-01-22 01:00:06 +00:00
return RString ( ) ; // successfully set mode
2003-05-22 05:28:37 +00:00
}
2003-05-26 19:42:04 +00:00
int RageDisplay_OGL : : GetMaxTextureSize ( ) const
2003-05-22 05:28:37 +00:00
{
GLint size ;
2005-11-13 18:22:52 +00:00
glGetIntegerv ( GL_MAX_TEXTURE_SIZE , & size ) ;
2003-05-22 05:28:37 +00:00
return size ;
}
2004-09-19 01:38:12 +00:00
bool RageDisplay_OGL : : BeginFrame ( )
2003-05-22 05:28:37 +00:00
{
2006-01-18 09:18:17 +00:00
/* We do this in here, rather than ResolutionChanged, or we won't update the
* viewport for the concurrent rendering context. */
int fWidth = g_pWind - > GetActualVideoModeParams ( ) . width ;
int fHeight = g_pWind - > GetActualVideoModeParams ( ) . height ;
glViewport ( 0 , 0 , fWidth , fHeight ) ;
2006-07-26 01:44:59 +00:00
glClearColor ( 0 , 0 , 0 , 0 ) ;
2003-11-18 20:33:18 +00:00
SetZWrite ( true ) ;
2005-11-13 18:58:54 +00:00
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
2006-07-25 20:10:56 +00:00
return RageDisplay : : BeginFrame ( ) ;
2003-05-22 05:28:37 +00:00
}
2003-05-26 19:42:04 +00:00
void RageDisplay_OGL : : EndFrame ( )
2003-05-22 05:28:37 +00:00
{
2005-03-22 01:32:05 +00:00
glFlush ( ) ;
2005-03-17 01:21:13 +00:00
2006-01-17 01:43:11 +00:00
FrameLimitBeforeVsync ( g_pWind - > GetActualVideoModeParams ( ) . rate ) ;
2005-11-13 18:22:52 +00:00
g_pWind - > SwapBuffers ( ) ;
2006-01-17 01:44:47 +00:00
FrameLimitAfterVsync ( ) ;
2005-07-13 00:01:46 +00:00
2005-11-13 18:22:52 +00:00
g_pWind - > Update ( ) ;
2005-07-13 00:01:46 +00:00
2005-07-13 00:37:43 +00:00
RageDisplay : : EndFrame ( ) ;
2003-05-22 05:28:37 +00:00
}
2004-06-14 00:51:00 +00:00
RageSurface * RageDisplay_OGL : : CreateScreenshot ( )
2003-05-22 05:28:37 +00:00
{
2005-11-13 18:22:52 +00:00
int width = g_pWind - > GetActualVideoModeParams ( ) . width ;
int height = g_pWind - > GetActualVideoModeParams ( ) . height ;
2003-06-05 19:29:27 +00:00
2005-09-29 17:15:12 +00:00
const PixelFormatDesc & desc = PIXEL_FORMAT_DESC [ PixelFormat_RGBA8 ] ;
2004-06-14 00:51:00 +00:00
RageSurface * image = CreateSurface ( width , height , desc . bpp ,
desc . masks [ 0 ] , desc . masks [ 1 ] , desc . masks [ 2 ] , 0 ) ;
2003-07-09 06:16:19 +00:00
2008-01-02 12:17:49 +00:00
DebugFlushGLErrors ( ) ;
2005-04-09 05:06:14 +00:00
glReadBuffer ( GL_FRONT ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-04-09 05:06:14 +00:00
2005-11-13 18:22:52 +00:00
glReadPixels ( 0 , 0 , g_pWind - > GetActualVideoModeParams ( ) . width , g_pWind - > GetActualVideoModeParams ( ) . height , GL_RGBA ,
2006-02-01 07:52:33 +00:00
GL_UNSIGNED_BYTE , image - > pixels ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2003-05-22 05:28:37 +00:00
2004-08-26 20:36:44 +00:00
RageSurfaceUtils : : FlipVertically ( image ) ;
2004-05-19 00:27:48 +00:00
return image ;
2003-05-22 05:28:37 +00:00
}
2007-02-24 23:17:34 +00:00
RageSurface * RageDisplay_OGL : : GetTexture ( unsigned iTexture )
{
if ( iTexture = = 0 )
return NULL ; // XXX
FlushGLErrors ( ) ;
glBindTexture ( GL_TEXTURE_2D , iTexture ) ;
GLint iHeight , iWidth , iAlphaBits ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_HEIGHT , & iHeight ) ;
2007-03-20 07:46:05 +00:00
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_WIDTH , & iWidth ) ;
2007-02-24 23:17:34 +00:00
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_ALPHA_SIZE , & iAlphaBits ) ;
int iFormat = iAlphaBits ? PixelFormat_RGBA8 : PixelFormat_RGB8 ;
const PixelFormatDesc & desc = PIXEL_FORMAT_DESC [ iFormat ] ;
RageSurface * pImage = CreateSurface ( iWidth , iHeight , desc . bpp ,
desc . masks [ 0 ] , desc . masks [ 1 ] , desc . masks [ 2 ] , desc . masks [ 3 ] ) ;
2007-03-20 07:46:05 +00:00
glGetTexImage ( GL_TEXTURE_2D , 0 , g_GLPixFmtInfo [ iFormat ] . format , GL_UNSIGNED_BYTE , pImage - > pixels ) ;
2007-02-24 23:17:34 +00:00
AssertNoGLError ( ) ;
return pImage ;
}
2005-11-11 21:16:48 +00:00
VideoModeParams RageDisplay_OGL : : GetActualVideoModeParams ( ) const
{
2005-11-13 18:22:52 +00:00
return g_pWind - > GetActualVideoModeParams ( ) ;
2005-11-11 21:16:48 +00:00
}
2003-05-22 05:28:37 +00:00
2003-07-07 01:29:18 +00:00
static void SetupVertices ( const RageSpriteVertex v [ ] , int iNumVerts )
2003-05-22 05:28:37 +00:00
{
2003-05-26 19:42:04 +00:00
static float * Vertex , * Texture , * Normal ;
static GLubyte * Color ;
2003-05-22 05:28:37 +00:00
static int Size = 0 ;
2005-11-13 18:22:52 +00:00
if ( iNumVerts > Size )
2003-05-22 05:28:37 +00:00
{
Size = iNumVerts ;
delete [ ] Vertex ;
delete [ ] Color ;
delete [ ] Texture ;
2003-05-26 19:42:04 +00:00
delete [ ] Normal ;
2003-05-22 05:28:37 +00:00
Vertex = new float [ Size * 3 ] ;
2003-05-26 19:42:04 +00:00
Color = new GLubyte [ Size * 4 ] ;
2003-05-22 05:28:37 +00:00
Texture = new float [ Size * 2 ] ;
2003-05-26 19:42:04 +00:00
Normal = new float [ Size * 3 ] ;
2003-05-22 05:28:37 +00:00
}
2005-11-13 18:22:52 +00:00
for ( unsigned i = 0 ; i < unsigned ( iNumVerts ) ; + + i )
2003-05-22 05:28:37 +00:00
{
Vertex [ i * 3 + 0 ] = v [ i ] . p [ 0 ] ;
Vertex [ i * 3 + 1 ] = v [ i ] . p [ 1 ] ;
Vertex [ i * 3 + 2 ] = v [ i ] . p [ 2 ] ;
2003-05-26 19:42:04 +00:00
Color [ i * 4 + 0 ] = v [ i ] . c . r ;
Color [ i * 4 + 1 ] = v [ i ] . c . g ;
Color [ i * 4 + 2 ] = v [ i ] . c . b ;
Color [ i * 4 + 3 ] = v [ i ] . c . a ;
2003-05-22 05:28:37 +00:00
Texture [ i * 2 + 0 ] = v [ i ] . t [ 0 ] ;
Texture [ i * 2 + 1 ] = v [ i ] . t [ 1 ] ;
2003-05-27 05:26:53 +00:00
Normal [ i * 3 + 0 ] = v [ i ] . n [ 0 ] ;
Normal [ i * 3 + 1 ] = v [ i ] . n [ 1 ] ;
2003-05-27 08:39:36 +00:00
Normal [ i * 3 + 2 ] = v [ i ] . n [ 2 ] ;
2003-05-22 05:28:37 +00:00
}
2005-11-13 18:22:52 +00:00
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glVertexPointer ( 3 , GL_FLOAT , 0 , Vertex ) ;
2003-05-22 05:28:37 +00:00
2005-11-13 18:22:52 +00:00
glEnableClientState ( GL_COLOR_ARRAY ) ;
glColorPointer ( 4 , GL_UNSIGNED_BYTE , 0 , Color ) ;
2003-05-22 05:28:37 +00:00
2005-11-13 18:22:52 +00:00
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glTexCoordPointer ( 2 , GL_FLOAT , 0 , Texture ) ;
2003-05-22 05:28:37 +00:00
2007-02-19 23:40:19 +00:00
if ( GLExt . glClientActiveTextureARB ! = NULL )
{
GLExt . glClientActiveTextureARB ( GL_TEXTURE1_ARB ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glTexCoordPointer ( 2 , GL_FLOAT , 0 , Texture ) ;
GLExt . glClientActiveTextureARB ( GL_TEXTURE0_ARB ) ;
}
2005-11-13 18:22:52 +00:00
glEnableClientState ( GL_NORMAL_ARRAY ) ;
glNormalPointer ( GL_FLOAT , 0 , Normal ) ;
2003-05-26 19:42:04 +00:00
}
2003-05-22 05:28:37 +00:00
2004-04-08 08:35:38 +00:00
void RageDisplay_OGL : : SendCurrentMatrices ( )
{
2004-10-24 22:59:10 +00:00
RageMatrix projection ;
RageMatrixMultiply ( & projection , GetCentering ( ) , GetProjectionTop ( ) ) ;
2006-07-26 03:44:27 +00:00
if ( g_bInvertY )
{
RageMatrix flip ;
RageMatrixScale ( & flip , + 1 , - 1 , + 1 ) ;
RageMatrixMultiply ( & projection , & flip , & projection ) ;
}
2004-04-08 08:35:38 +00:00
glMatrixMode ( GL_PROJECTION ) ;
2004-10-24 22:59:10 +00:00
glLoadMatrixf ( ( const float * ) & projection ) ;
// OpenGL has just "modelView", whereas D3D has "world" and "view"
2004-04-08 08:35:38 +00:00
RageMatrix modelView ;
2004-10-24 22:59:10 +00:00
RageMatrixMultiply ( & modelView , GetViewTop ( ) , GetWorldTop ( ) ) ;
2004-04-08 08:35:38 +00:00
glMatrixMode ( GL_MODELVIEW ) ;
glLoadMatrixf ( ( const float * ) & modelView ) ;
2004-10-24 22:59:10 +00:00
glMatrixMode ( GL_TEXTURE ) ;
2004-08-09 00:46:42 +00:00
glLoadMatrixf ( ( const float * ) GetTextureTop ( ) ) ;
2004-04-08 08:35:38 +00:00
}
2003-09-21 02:36:28 +00:00
2004-04-16 05:09:02 +00:00
class RageCompiledGeometrySWOGL : public RageCompiledGeometry
2003-07-07 01:29:18 +00:00
{
2004-04-08 08:35:38 +00:00
public :
2004-04-16 05:09:02 +00:00
void Allocate ( const vector < msMesh > & vMeshes )
2004-04-08 08:35:38 +00:00
{
2007-02-07 05:54:13 +00:00
/* Always allocate at least 1 entry, so &x[0] is valid. */
m_vPosition . resize ( max ( 1u , GetTotalVertices ( ) ) ) ;
m_vTexture . resize ( max ( 1u , GetTotalVertices ( ) ) ) ;
m_vNormal . resize ( max ( 1u , GetTotalVertices ( ) ) ) ;
m_vTexMatrixScale . resize ( max ( 1u , GetTotalVertices ( ) ) ) ;
m_vTriangles . resize ( max ( 1u , GetTotalTriangles ( ) ) ) ;
2004-04-08 08:35:38 +00:00
}
2004-04-16 05:09:02 +00:00
void Change ( const vector < msMesh > & vMeshes )
2004-04-08 08:35:38 +00:00
{
2004-04-16 05:09:02 +00:00
for ( unsigned i = 0 ; i < vMeshes . size ( ) ; i + + )
{
const MeshInfo & meshInfo = m_vMeshInfo [ i ] ;
const msMesh & mesh = vMeshes [ i ] ;
const vector < RageModelVertex > & Vertices = mesh . Vertices ;
const vector < msTriangle > & Triangles = mesh . Triangles ;
2003-07-07 01:29:18 +00:00
2004-08-19 00:36:11 +00:00
for ( unsigned j = 0 ; j < Vertices . size ( ) ; j + + )
2004-04-16 05:09:02 +00:00
{
2004-08-19 00:36:11 +00:00
m_vPosition [ meshInfo . iVertexStart + j ] = Vertices [ j ] . p ;
m_vTexture [ meshInfo . iVertexStart + j ] = Vertices [ j ] . t ;
m_vNormal [ meshInfo . iVertexStart + j ] = Vertices [ j ] . n ;
2005-02-01 03:04:32 +00:00
m_vTexMatrixScale [ meshInfo . iVertexStart + j ] = Vertices [ j ] . TextureMatrixScale ;
2004-04-16 05:09:02 +00:00
}
2004-04-08 08:35:38 +00:00
2004-08-19 00:36:11 +00:00
for ( unsigned j = 0 ; j < Triangles . size ( ) ; j + + )
for ( unsigned k = 0 ; k < 3 ; k + + )
{
int iVertexIndexInVBO = meshInfo . iVertexStart + Triangles [ j ] . nVertexIndices [ k ] ;
m_vTriangles [ meshInfo . iTriangleStart + j ] . nVertexIndices [ k ] = ( uint16_t ) iVertexIndexInVBO ;
}
2004-04-16 05:09:02 +00:00
}
2004-04-12 03:07:44 +00:00
}
2004-04-16 05:09:02 +00:00
void Draw ( int iMeshIndex ) const
2004-04-08 08:35:38 +00:00
{
2004-04-16 05:31:08 +00:00
TurnOffHardwareVBO ( ) ;
2004-04-16 05:09:02 +00:00
const MeshInfo & meshInfo = m_vMeshInfo [ iMeshIndex ] ;
2004-04-08 08:35:38 +00:00
glEnableClientState ( GL_VERTEX_ARRAY ) ;
2004-04-16 05:09:02 +00:00
glVertexPointer ( 3 , GL_FLOAT , 0 , & m_vPosition [ 0 ] ) ;
2004-04-08 08:35:38 +00:00
glDisableClientState ( GL_COLOR_ARRAY ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
2004-04-16 05:09:02 +00:00
glTexCoordPointer ( 2 , GL_FLOAT , 0 , & m_vTexture [ 0 ] ) ;
2004-04-08 08:35:38 +00:00
glEnableClientState ( GL_NORMAL_ARRAY ) ;
2004-04-16 05:09:02 +00:00
glNormalPointer ( GL_FLOAT , 0 , & m_vNormal [ 0 ] ) ;
2004-04-08 08:35:38 +00:00
2005-10-20 19:18:32 +00:00
if ( meshInfo . m_bNeedsTextureMatrixScale )
{
// Kill the texture translation.
// XXX: Change me to scale the translation by the TextureTranslationScale of the first vertex.
RageMatrix mat ;
glGetFloatv ( GL_TEXTURE_MATRIX , ( float * ) mat ) ;
/*
for( int i=0; i<4; i++ )
{
2006-01-22 01:00:06 +00:00
RString s;
2005-10-20 19:18:32 +00:00
for( int j=0; j<4; j++ )
s += ssprintf( "%f ", mat.m[i][j] );
LOG->Trace( s );
}
*/
mat . m [ 3 ] [ 0 ] = 0 ;
mat . m [ 3 ] [ 1 ] = 0 ;
mat . m [ 3 ] [ 2 ] = 0 ;
glMatrixMode ( GL_TEXTURE ) ;
glLoadMatrixf ( ( const float * ) mat ) ;
}
2004-04-16 05:09:02 +00:00
glDrawElements (
GL_TRIANGLES ,
meshInfo . iTriangleCount * 3 ,
GL_UNSIGNED_SHORT ,
& m_vTriangles [ 0 ] + meshInfo . iTriangleStart ) ;
2004-04-08 08:35:38 +00:00
}
2004-04-16 05:09:02 +00:00
2004-04-08 08:35:38 +00:00
protected :
2004-04-16 05:09:02 +00:00
vector < RageVector3 > m_vPosition ;
vector < RageVector2 > m_vTexture ;
vector < RageVector3 > m_vNormal ;
vector < msTriangle > m_vTriangles ;
2005-02-01 03:04:32 +00:00
vector < RageVector2 > m_vTexMatrixScale ;
2004-04-08 08:35:38 +00:00
} ;
2007-03-22 18:55:49 +00:00
class InvalidateObject ;
static set < InvalidateObject * > g_InvalidateList ;
class InvalidateObject
{
public :
InvalidateObject ( ) { g_InvalidateList . insert ( this ) ; }
virtual ~ InvalidateObject ( ) { g_InvalidateList . erase ( this ) ; }
virtual void Invalidate ( ) = 0 ;
} ;
static void InvalidateObjects ( )
{
FOREACHS ( InvalidateObject * , g_InvalidateList , it )
( * it ) - > Invalidate ( ) ;
}
class RageCompiledGeometryHWOGL : public RageCompiledGeometrySWOGL , public InvalidateObject
2004-04-12 03:07:44 +00:00
{
protected :
// vertex buffer object names
GLuint m_nPositions ;
GLuint m_nTextureCoords ;
GLuint m_nNormals ;
GLuint m_nTriangles ;
2005-02-01 03:04:32 +00:00
GLuint m_nTextureMatrixScale ;
2004-04-16 21:34:58 +00:00
void AllocateBuffers ( ) ;
void UploadData ( ) ;
2004-04-12 03:07:44 +00:00
public :
2004-04-16 21:34:58 +00:00
RageCompiledGeometryHWOGL ( ) ;
~ RageCompiledGeometryHWOGL ( ) ;
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
/* This is called when our OpenGL context is invalidated. */
void Invalidate ( ) ;
void Allocate ( const vector < msMesh > & vMeshes ) ;
void Change ( const vector < msMesh > & vMeshes ) ;
void Draw ( int iMeshIndex ) const ;
} ;
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
RageCompiledGeometryHWOGL : : RageCompiledGeometryHWOGL ( )
{
2005-11-28 23:26:22 +00:00
m_nPositions = 0 ;
m_nTextureCoords = 0 ;
m_nNormals = 0 ;
m_nTriangles = 0 ;
m_nTextureMatrixScale = 0 ;
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
AllocateBuffers ( ) ;
}
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
RageCompiledGeometryHWOGL : : ~ RageCompiledGeometryHWOGL ( )
{
2008-01-02 12:17:49 +00:00
DebugFlushGLErrors ( ) ;
2004-04-12 03:07:44 +00:00
2004-05-24 03:41:49 +00:00
GLExt . glDeleteBuffersARB ( 1 , & m_nPositions ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glDeleteBuffersARB ( 1 , & m_nTextureCoords ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glDeleteBuffersARB ( 1 , & m_nNormals ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glDeleteBuffersARB ( 1 , & m_nTriangles ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-02-01 03:04:32 +00:00
GLExt . glDeleteBuffersARB ( 1 , & m_nTextureMatrixScale ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
}
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
void RageCompiledGeometryHWOGL : : AllocateBuffers ( )
{
2008-01-02 12:17:49 +00:00
DebugFlushGLErrors ( ) ;
2004-04-16 21:34:58 +00:00
if ( ! m_nPositions )
2004-04-12 03:07:44 +00:00
{
2004-05-24 03:41:49 +00:00
GLExt . glGenBuffersARB ( 1 , & m_nPositions ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
}
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
if ( ! m_nTextureCoords )
{
2004-05-24 03:41:49 +00:00
GLExt . glGenBuffersARB ( 1 , & m_nTextureCoords ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
}
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
if ( ! m_nNormals )
{
2004-05-24 03:41:49 +00:00
GLExt . glGenBuffersARB ( 1 , & m_nNormals ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
}
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
if ( ! m_nTriangles )
{
2004-05-24 03:41:49 +00:00
GLExt . glGenBuffersARB ( 1 , & m_nTriangles ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-12 03:07:44 +00:00
}
2005-02-01 03:04:32 +00:00
if ( ! m_nTextureMatrixScale )
{
GLExt . glGenBuffersARB ( 1 , & m_nTextureMatrixScale ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-02-01 03:04:32 +00:00
}
2004-04-16 21:34:58 +00:00
}
2004-04-16 05:09:02 +00:00
2004-04-16 21:34:58 +00:00
void RageCompiledGeometryHWOGL : : UploadData ( )
{
2008-01-02 12:17:49 +00:00
DebugFlushGLErrors ( ) ;
2005-11-28 23:35:21 +00:00
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , m_nPositions ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glBufferDataARB (
2004-04-16 21:34:58 +00:00
GL_ARRAY_BUFFER_ARB ,
GetTotalVertices ( ) * sizeof ( RageVector3 ) ,
& m_vPosition [ 0 ] ,
GL_STATIC_DRAW_ARB ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 05:09:02 +00:00
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , m_nTextureCoords ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glBufferDataARB (
2004-04-16 21:34:58 +00:00
GL_ARRAY_BUFFER_ARB ,
GetTotalVertices ( ) * sizeof ( RageVector2 ) ,
& m_vTexture [ 0 ] ,
GL_STATIC_DRAW_ARB ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 05:09:02 +00:00
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , m_nNormals ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glBufferDataARB (
2004-04-16 21:34:58 +00:00
GL_ARRAY_BUFFER_ARB ,
GetTotalVertices ( ) * sizeof ( RageVector3 ) ,
& m_vNormal [ 0 ] ,
GL_STATIC_DRAW_ARB ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 05:09:02 +00:00
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ELEMENT_ARRAY_BUFFER_ARB , m_nTriangles ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glBufferDataARB (
2004-04-16 21:34:58 +00:00
GL_ELEMENT_ARRAY_BUFFER_ARB ,
GetTotalTriangles ( ) * sizeof ( msTriangle ) ,
& m_vTriangles [ 0 ] ,
GL_STATIC_DRAW_ARB ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-02-01 03:04:32 +00:00
2005-10-20 14:15:13 +00:00
if ( m_bAnyNeedsTextureMatrixScale )
2005-02-01 03:04:32 +00:00
{
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , m_nTextureMatrixScale ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-02-01 03:04:32 +00:00
GLExt . glBufferDataARB (
GL_ARRAY_BUFFER_ARB ,
GetTotalVertices ( ) * sizeof ( RageVector2 ) ,
& m_vTexMatrixScale [ 0 ] ,
GL_STATIC_DRAW_ARB ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-02-01 03:04:32 +00:00
}
2004-04-16 21:34:58 +00:00
}
void RageCompiledGeometryHWOGL : : Invalidate ( )
{
/* Our vertex buffers no longer exist. Reallocate and reupload. */
2005-11-28 23:26:22 +00:00
m_nPositions = 0 ;
m_nTextureCoords = 0 ;
m_nNormals = 0 ;
m_nTriangles = 0 ;
m_nTextureMatrixScale = 0 ;
2004-04-16 21:34:58 +00:00
AllocateBuffers ( ) ;
UploadData ( ) ;
}
void RageCompiledGeometryHWOGL : : Allocate ( const vector < msMesh > & vMeshes )
{
2008-01-02 12:17:49 +00:00
DebugFlushGLErrors ( ) ;
2005-11-28 23:35:21 +00:00
2004-04-16 21:34:58 +00:00
RageCompiledGeometrySWOGL : : Allocate ( vMeshes ) ;
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , m_nPositions ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glBufferDataARB (
2004-04-16 21:34:58 +00:00
GL_ARRAY_BUFFER_ARB ,
GetTotalVertices ( ) * sizeof ( RageVector3 ) ,
NULL ,
GL_STATIC_DRAW_ARB ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , m_nTextureCoords ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glBufferDataARB (
2004-04-16 21:34:58 +00:00
GL_ARRAY_BUFFER_ARB ,
GetTotalVertices ( ) * sizeof ( RageVector2 ) ,
NULL ,
GL_STATIC_DRAW_ARB ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , m_nNormals ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glBufferDataARB (
2004-04-16 21:34:58 +00:00
GL_ARRAY_BUFFER_ARB ,
GetTotalVertices ( ) * sizeof ( RageVector3 ) ,
NULL ,
GL_STATIC_DRAW_ARB ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ELEMENT_ARRAY_BUFFER_ARB , m_nTriangles ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glBufferDataARB (
2004-04-16 21:34:58 +00:00
GL_ELEMENT_ARRAY_BUFFER_ARB ,
GetTotalTriangles ( ) * sizeof ( msTriangle ) ,
NULL ,
GL_STATIC_DRAW_ARB ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-02-01 03:04:32 +00:00
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , m_nTextureMatrixScale ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-02-01 03:04:32 +00:00
GLExt . glBufferDataARB (
GL_ARRAY_BUFFER_ARB ,
GetTotalVertices ( ) * sizeof ( RageVector2 ) ,
NULL ,
GL_STATIC_DRAW_ARB ) ;
2004-04-16 21:34:58 +00:00
}
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
void RageCompiledGeometryHWOGL : : Change ( const vector < msMesh > & vMeshes )
{
RageCompiledGeometrySWOGL : : Change ( vMeshes ) ;
2004-04-16 05:09:02 +00:00
2004-04-16 21:34:58 +00:00
UploadData ( ) ;
}
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
void RageCompiledGeometryHWOGL : : Draw ( int iMeshIndex ) const
{
2008-01-02 12:17:49 +00:00
DebugFlushGLErrors ( ) ;
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
const MeshInfo & meshInfo = m_vMeshInfo [ iMeshIndex ] ;
2004-04-16 22:10:25 +00:00
if ( ! meshInfo . iVertexCount | | ! meshInfo . iTriangleCount )
return ;
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
glEnableClientState ( GL_VERTEX_ARRAY ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , m_nPositions ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
glVertexPointer ( 3 , GL_FLOAT , 0 , NULL ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-12 03:07:44 +00:00
2004-04-16 21:34:58 +00:00
glDisableClientState ( GL_COLOR_ARRAY ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , m_nTextureCoords ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
glTexCoordPointer ( 2 , GL_FLOAT , 0 , NULL ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
// TRICKY: Don't bind and send normals if lighting is disabled. This
// will save some effort transforming these values.
2008-01-02 12:17:49 +00:00
// XXX: We should keep track of these ourself and avoid glGet*()
2004-04-16 21:34:58 +00:00
GLboolean bLighting ;
glGetBooleanv ( GL_LIGHTING , & bLighting ) ;
2004-04-17 18:11:03 +00:00
GLboolean bTextureGenS ;
2004-04-17 20:07:39 +00:00
glGetBooleanv ( GL_TEXTURE_GEN_S , & bTextureGenS ) ;
2004-04-17 18:11:03 +00:00
GLboolean bTextureGenT ;
2004-04-17 20:07:39 +00:00
glGetBooleanv ( GL_TEXTURE_GEN_T , & bTextureGenT ) ;
2004-04-17 18:11:03 +00:00
if ( bLighting | | bTextureGenS | | bTextureGenT )
2004-04-16 21:34:58 +00:00
{
glEnableClientState ( GL_NORMAL_ARRAY ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , m_nNormals ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
glNormalPointer ( GL_FLOAT , 0 , NULL ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
}
else
{
glDisableClientState ( GL_NORMAL_ARRAY ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-16 21:34:58 +00:00
}
2005-10-20 14:15:13 +00:00
if ( meshInfo . m_bNeedsTextureMatrixScale )
2005-02-01 03:04:32 +00:00
{
2005-10-21 06:36:08 +00:00
if ( g_bTextureMatrixShader ! = 0 )
2005-10-20 14:15:13 +00:00
{
/* If we're using texture matrix scales, set up that buffer, too, and enable the
* vertex shader. This shader doesn't support all OpenGL state, so only enable it
* if we're using it. */
2007-02-18 10:37:06 +00:00
GLExt . glEnableVertexAttribArrayARB ( g_iAttribTextureMatrixScale ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-10-20 14:15:13 +00:00
GLExt . glBindBufferARB ( GL_ARRAY_BUFFER_ARB , m_nTextureMatrixScale ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2007-02-18 10:37:06 +00:00
GLExt . glVertexAttribPointerARB ( g_iAttribTextureMatrixScale , 2 , GL_FLOAT , false , 0 , NULL ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-10-20 14:15:13 +00:00
GLExt . glUseProgramObjectARB ( g_bTextureMatrixShader ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-10-20 14:15:13 +00:00
}
else
{
2005-10-20 18:19:44 +00:00
// Kill the texture translation.
// XXX: Change me to scale the translation by the TextureTranslationScale of the first vertex.
RageMatrix mat ;
glGetFloatv ( GL_TEXTURE_MATRIX , ( float * ) mat ) ;
/*
for( int i=0; i<4; i++ )
{
2006-01-22 01:00:06 +00:00
RString s;
2005-10-20 18:19:44 +00:00
for( int j=0; j<4; j++ )
s += ssprintf( "%f ", mat.m[i][j] );
LOG->Trace( s );
}
*/
mat . m [ 3 ] [ 0 ] = 0 ;
mat . m [ 3 ] [ 1 ] = 0 ;
mat . m [ 3 ] [ 2 ] = 0 ;
2005-10-20 14:15:13 +00:00
glMatrixMode ( GL_TEXTURE ) ;
2005-10-20 18:19:44 +00:00
glLoadMatrixf ( ( const float * ) mat ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-10-20 14:15:13 +00:00
}
2005-02-01 03:04:32 +00:00
}
2004-05-24 03:41:49 +00:00
GLExt . glBindBufferARB ( GL_ELEMENT_ARRAY_BUFFER_ARB , m_nTriangles ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-04-15 05:02:35 +00:00
2004-04-16 05:09:02 +00:00
# define BUFFER_OFFSET(o) ((char*)(o))
2004-04-15 05:02:35 +00:00
2004-05-24 03:41:49 +00:00
ASSERT ( GLExt . glDrawRangeElements ) ;
GLExt . glDrawRangeElements (
2004-04-16 21:34:58 +00:00
GL_TRIANGLES ,
meshInfo . iVertexStart , // minimum array index contained in indices
meshInfo . iVertexStart + meshInfo . iVertexCount - 1 ,
// maximum array index contained in indices
meshInfo . iTriangleCount * 3 , // number of elements to be rendered
GL_UNSIGNED_SHORT ,
BUFFER_OFFSET ( meshInfo . iTriangleStart * sizeof ( msTriangle ) ) ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2005-02-01 03:04:32 +00:00
2005-10-20 14:15:13 +00:00
if ( meshInfo . m_bNeedsTextureMatrixScale & & g_bTextureMatrixShader ! = 0 )
2005-02-01 03:04:32 +00:00
{
2007-02-18 10:37:06 +00:00
GLExt . glDisableVertexAttribArrayARB ( g_iAttribTextureMatrixScale ) ;
2005-02-11 04:06:52 +00:00
GLExt . glUseProgramObjectARB ( 0 ) ;
2005-02-01 03:04:32 +00:00
}
2004-04-16 21:34:58 +00:00
}
2004-04-12 03:07:44 +00:00
2004-04-16 05:09:02 +00:00
RageCompiledGeometry * RageDisplay_OGL : : CreateCompiledGeometry ( )
2004-04-08 08:35:38 +00:00
{
2004-05-24 03:41:49 +00:00
if ( GLExt . glGenBuffersARB )
2004-04-16 05:09:02 +00:00
return new RageCompiledGeometryHWOGL ;
2004-04-12 03:07:44 +00:00
else
2004-04-16 05:09:02 +00:00
return new RageCompiledGeometrySWOGL ;
2004-04-08 08:35:38 +00:00
}
2004-04-16 05:09:02 +00:00
void RageDisplay_OGL : : DeleteCompiledGeometry ( RageCompiledGeometry * p )
2004-04-08 08:35:38 +00:00
{
delete p ;
2003-07-07 01:29:18 +00:00
}
2004-04-15 05:24:28 +00:00
void RageDisplay_OGL : : DrawQuadsInternal ( const RageSpriteVertex v [ ] , int iNumVerts )
2003-05-26 19:42:04 +00:00
{
2004-04-16 05:31:08 +00:00
TurnOffHardwareVBO ( ) ;
2004-04-08 08:35:38 +00:00
SendCurrentMatrices ( ) ;
2003-05-26 19:42:04 +00:00
SetupVertices ( v , iNumVerts ) ;
2003-05-22 05:28:37 +00:00
glDrawArrays ( GL_QUADS , 0 , iNumVerts ) ;
}
2003-05-26 19:42:04 +00:00
2004-04-15 05:24:28 +00:00
void RageDisplay_OGL : : DrawQuadStripInternal ( const RageSpriteVertex v [ ] , int iNumVerts )
2004-04-13 07:28:25 +00:00
{
2004-04-16 05:31:08 +00:00
TurnOffHardwareVBO ( ) ;
2004-04-13 07:28:25 +00:00
SendCurrentMatrices ( ) ;
SetupVertices ( v , iNumVerts ) ;
glDrawArrays ( GL_QUAD_STRIP , 0 , iNumVerts ) ;
}
2007-01-15 08:08:57 +00:00
void RageDisplay_OGL : : DrawSymmetricQuadStripInternal ( const RageSpriteVertex v [ ] , int iNumVerts )
{
int iNumPieces = ( iNumVerts - 3 ) / 3 ;
int iNumTriangles = iNumPieces * 4 ;
int iNumIndices = iNumTriangles * 3 ;
// make a temporary index buffer
static vector < uint16_t > vIndices ;
unsigned uOldSize = vIndices . size ( ) ;
unsigned uNewSize = max ( uOldSize , ( unsigned ) iNumIndices ) ;
vIndices . resize ( uNewSize ) ;
for ( uint16_t i = ( uint16_t ) uOldSize / 12 ; i < ( uint16_t ) iNumPieces ; i + + )
{
// { 1, 3, 0 } { 1, 4, 3 } { 1, 5, 4 } { 1, 2, 5 }
vIndices [ i * 12 + 0 ] = i * 3 + 1 ;
vIndices [ i * 12 + 1 ] = i * 3 + 3 ;
vIndices [ i * 12 + 2 ] = i * 3 + 0 ;
vIndices [ i * 12 + 3 ] = i * 3 + 1 ;
vIndices [ i * 12 + 4 ] = i * 3 + 4 ;
vIndices [ i * 12 + 5 ] = i * 3 + 3 ;
vIndices [ i * 12 + 6 ] = i * 3 + 1 ;
vIndices [ i * 12 + 7 ] = i * 3 + 5 ;
vIndices [ i * 12 + 8 ] = i * 3 + 4 ;
vIndices [ i * 12 + 9 ] = i * 3 + 1 ;
vIndices [ i * 12 + 10 ] = i * 3 + 2 ;
vIndices [ i * 12 + 11 ] = i * 3 + 5 ;
}
TurnOffHardwareVBO ( ) ;
SendCurrentMatrices ( ) ;
SetupVertices ( v , iNumVerts ) ;
glDrawElements (
GL_TRIANGLES ,
iNumIndices ,
GL_UNSIGNED_SHORT ,
& vIndices [ 0 ] ) ;
}
2004-04-15 05:24:28 +00:00
void RageDisplay_OGL : : DrawFanInternal ( const RageSpriteVertex v [ ] , int iNumVerts )
2003-05-22 05:28:37 +00:00
{
2004-04-16 05:31:08 +00:00
TurnOffHardwareVBO ( ) ;
2004-04-08 08:35:38 +00:00
SendCurrentMatrices ( ) ;
2003-09-21 02:36:28 +00:00
2003-05-26 19:42:04 +00:00
SetupVertices ( v , iNumVerts ) ;
2003-05-22 05:28:37 +00:00
glDrawArrays ( GL_TRIANGLE_FAN , 0 , iNumVerts ) ;
}
2004-04-15 05:24:28 +00:00
void RageDisplay_OGL : : DrawStripInternal ( const RageSpriteVertex v [ ] , int iNumVerts )
2003-05-22 05:28:37 +00:00
{
2004-04-16 05:31:08 +00:00
TurnOffHardwareVBO ( ) ;
2004-04-08 08:35:38 +00:00
SendCurrentMatrices ( ) ;
2003-09-21 02:36:28 +00:00
2003-05-26 19:42:04 +00:00
SetupVertices ( v , iNumVerts ) ;
2003-05-22 05:28:37 +00:00
glDrawArrays ( GL_TRIANGLE_STRIP , 0 , iNumVerts ) ;
}
2004-04-15 05:24:28 +00:00
void RageDisplay_OGL : : DrawTrianglesInternal ( const RageSpriteVertex v [ ] , int iNumVerts )
2003-05-22 05:28:37 +00:00
{
2004-04-16 05:31:08 +00:00
TurnOffHardwareVBO ( ) ;
2004-04-08 08:35:38 +00:00
SendCurrentMatrices ( ) ;
2003-09-21 02:36:28 +00:00
2003-05-26 19:42:04 +00:00
SetupVertices ( v , iNumVerts ) ;
2003-05-22 05:28:37 +00:00
glDrawArrays ( GL_TRIANGLES , 0 , iNumVerts ) ;
}
2004-04-16 05:09:02 +00:00
void RageDisplay_OGL : : DrawCompiledGeometryInternal ( const RageCompiledGeometry * p , int iMeshIndex )
2003-05-22 05:28:37 +00:00
{
2004-04-16 05:31:08 +00:00
TurnOffHardwareVBO ( ) ;
2004-04-08 08:35:38 +00:00
SendCurrentMatrices ( ) ;
2003-09-21 02:36:28 +00:00
2004-04-16 05:09:02 +00:00
p - > Draw ( iMeshIndex ) ;
2003-05-22 05:28:37 +00:00
}
2005-11-13 18:22:52 +00:00
void RageDisplay_OGL : : DrawLineStripInternal ( const RageSpriteVertex v [ ] , int iNumVerts , float fLineWidth )
2003-05-22 05:28:37 +00:00
{
2004-04-16 05:31:08 +00:00
TurnOffHardwareVBO ( ) ;
2005-11-11 21:16:48 +00:00
if ( ! GetActualVideoModeParams ( ) . bSmoothLines )
2003-05-27 00:20:54 +00:00
{
2004-04-16 05:06:31 +00:00
/* Fall back on the generic polygon-based line strip. */
2005-11-13 18:22:52 +00:00
RageDisplay : : DrawLineStripInternal ( v , iNumVerts , fLineWidth ) ;
2003-05-27 00:20:54 +00:00
return ;
}
2004-04-08 08:35:38 +00:00
SendCurrentMatrices ( ) ;
2003-05-22 05:28:37 +00:00
2003-05-27 00:20:54 +00:00
/* Draw a nice AA'd line loop. One problem with this is that point and line
* sizes don't always precisely match, which doesn't look quite right.
* It's worth it for the AA, though. */
2005-11-13 18:22:52 +00:00
glEnable ( GL_LINE_SMOOTH ) ;
2003-05-27 00:20:54 +00:00
2005-12-04 17:58:25 +00:00
/* fLineWidth is in units relative to object space, but OpenGL line and point sizes
* are in raster units (actual pixels). Scale the line width by the average ratio;
* if object space is 640x480, and we have a 1280x960 window, we'll double the
* width. */
{
const RageMatrix * pMat = GetProjectionTop ( ) ;
float fW = 2 / pMat - > m [ 0 ] [ 0 ] ;
float fH = - 2 / pMat - > m [ 1 ] [ 1 ] ;
float fWidthVal = float ( g_pWind - > GetActualVideoModeParams ( ) . width ) / fW ;
float fHeightVal = float ( g_pWind - > GetActualVideoModeParams ( ) . height ) / fH ;
fLineWidth * = ( fWidthVal + fHeightVal ) / 2 ;
}
2003-05-27 00:20:54 +00:00
/* Clamp the width to the hardware max for both lines and points (whichever
* is more restrictive). */
2005-11-13 18:22:52 +00:00
fLineWidth = clamp ( fLineWidth , g_line_range [ 0 ] , g_line_range [ 1 ] ) ;
fLineWidth = clamp ( fLineWidth , g_point_range [ 0 ] , g_point_range [ 1 ] ) ;
2003-05-27 00:20:54 +00:00
/* Hmm. The granularity of lines and points might be different; for example,
* if lines are .5 and points are .25, we might want to snap the width to the
* nearest .5, so the hardware doesn't snap them to different sizes. Does it
* matter? */
2005-11-13 18:22:52 +00:00
glLineWidth ( fLineWidth ) ;
2003-05-27 00:20:54 +00:00
/* Draw the line loop: */
SetupVertices ( v , iNumVerts ) ;
glDrawArrays ( GL_LINE_STRIP , 0 , iNumVerts ) ;
2005-11-13 18:22:52 +00:00
glDisable ( GL_LINE_SMOOTH ) ;
2003-05-27 00:20:54 +00:00
/* Round off the corners. This isn't perfect; the point is sometimes a little
* larger than the line, causing a small bump on the edge. Not sure how to fix
* that. */
2005-11-13 18:22:52 +00:00
glPointSize ( fLineWidth ) ;
2003-05-27 00:20:54 +00:00
/* Hack: if the points will all be the same, we don't want to draw
* any points at all, since there's nothing to connect. That'll happen
* if both scale factors in the matrix are ~0. (Actually, I think
* it's true if two of the three scale factors are ~0, but we don't
* use this for anything 3d at the moment anyway ...) This is needed
* because points aren't scaled like regular polys--a zero-size point
* will still be drawn. */
RageMatrix mat ;
glGetFloatv ( GL_MODELVIEW_MATRIX , ( float * ) mat ) ;
2005-11-13 18:22:52 +00:00
if ( mat . m [ 0 ] [ 0 ] < 1e-5 & & mat . m [ 1 ] [ 1 ] < 1e-5 )
2003-05-27 00:20:54 +00:00
return ;
2005-11-13 18:22:52 +00:00
glEnable ( GL_POINT_SMOOTH ) ;
2003-05-27 00:20:54 +00:00
SetupVertices ( v , iNumVerts ) ;
glDrawArrays ( GL_POINTS , 0 , iNumVerts ) ;
2005-11-13 18:22:52 +00:00
glDisable ( GL_POINT_SMOOTH ) ;
2003-05-22 05:28:37 +00:00
}
2007-02-13 04:59:05 +00:00
static bool SetTextureUnit ( TextureUnit tu )
{
// If multitexture isn't supported, ignore all textures except for 0.
if ( GLExt . glActiveTextureARB = = NULL )
return false ;
if ( ( int ) tu > g_iMaxTextureUnits )
return false ;
GLExt . glActiveTextureARB ( enum_add2 ( GL_TEXTURE0_ARB , tu ) ) ;
return true ;
}
2004-02-04 09:55:18 +00:00
void RageDisplay_OGL : : ClearAllTextures ( )
2003-05-22 05:28:37 +00:00
{
2006-10-07 08:56:58 +00:00
FOREACH_ENUM ( TextureUnit , i )
2006-07-23 03:19:49 +00:00
SetTexture ( i , 0 ) ;
2004-02-04 09:55:18 +00:00
// HACK: Reset the active texture to 0.
// TODO: Change all texture functions to take a stage number.
2004-05-24 03:41:49 +00:00
if ( GLExt . glActiveTextureARB )
GLExt . glActiveTextureARB ( GL_TEXTURE0_ARB ) ;
2004-02-04 09:55:18 +00:00
}
2005-01-04 05:34:58 +00:00
int RageDisplay_OGL : : GetNumTextureUnits ( )
{
if ( GLExt . glActiveTextureARB = = NULL )
return 1 ;
else
return g_iMaxTextureUnits ;
}
2006-07-23 03:19:49 +00:00
void RageDisplay_OGL : : SetTexture ( TextureUnit tu , unsigned iTexture )
2004-02-04 09:55:18 +00:00
{
2007-02-13 04:59:05 +00:00
if ( ! SetTextureUnit ( tu ) )
return ;
2004-02-04 09:55:18 +00:00
2006-07-23 03:19:49 +00:00
if ( iTexture )
2003-07-07 01:29:18 +00:00
{
glEnable ( GL_TEXTURE_2D ) ;
2006-07-23 03:19:49 +00:00
glBindTexture ( GL_TEXTURE_2D , iTexture ) ;
2003-07-07 01:29:18 +00:00
}
else
{
glDisable ( GL_TEXTURE_2D ) ;
}
2003-05-22 05:28:37 +00:00
}
2005-11-13 18:22:52 +00:00
2007-02-13 04:59:05 +00:00
void RageDisplay_OGL : : SetTextureMode ( TextureUnit tu , TextureMode tm )
2003-05-22 05:28:37 +00:00
{
2007-02-13 04:59:05 +00:00
if ( ! SetTextureUnit ( tu ) )
return ;
2007-02-13 04:02:08 +00:00
switch ( tm )
2003-05-22 05:28:37 +00:00
{
2007-02-13 04:02:08 +00:00
case TextureMode_Modulate :
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
break ;
case TextureMode_Add :
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_ADD ) ;
break ;
case TextureMode_Glow :
if ( ! GLExt . m_bARB_texture_env_combine & & ! GLExt . m_bEXT_texture_env_combine )
{
/* This is changing blend state, instead of texture state, which isn't
* great, but it's better than doing nothing. */
glBlendFunc ( GL_SRC_ALPHA , GL_ONE ) ;
return ;
}
2004-02-04 09:55:18 +00:00
2007-02-13 04:02:08 +00:00
/* Source color is the diffuse color only: */
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_COMBINE_EXT ) ;
glTexEnvi ( GL_TEXTURE_ENV , GLenum ( GL_COMBINE_RGB_EXT ) , GL_REPLACE ) ;
glTexEnvi ( GL_TEXTURE_ENV , GLenum ( GL_SOURCE0_RGB_EXT ) , GL_PRIMARY_COLOR_EXT ) ;
/* Source alpha is texture alpha * diffuse alpha: */
glTexEnvi ( GL_TEXTURE_ENV , GLenum ( GL_COMBINE_ALPHA_EXT ) , GL_MODULATE ) ;
glTexEnvi ( GL_TEXTURE_ENV , GLenum ( GL_OPERAND0_ALPHA_EXT ) , GL_SRC_ALPHA ) ;
glTexEnvi ( GL_TEXTURE_ENV , GLenum ( GL_SOURCE0_ALPHA_EXT ) , GL_PRIMARY_COLOR_EXT ) ;
glTexEnvi ( GL_TEXTURE_ENV , GLenum ( GL_OPERAND1_ALPHA_EXT ) , GL_SRC_ALPHA ) ;
glTexEnvi ( GL_TEXTURE_ENV , GLenum ( GL_SOURCE1_ALPHA_EXT ) , GL_TEXTURE ) ;
break ;
}
2004-02-04 09:55:18 +00:00
}
2007-02-13 05:09:54 +00:00
void RageDisplay_OGL : : SetTextureFiltering ( TextureUnit tu , bool b )
2003-05-22 05:28:37 +00:00
{
2007-03-23 07:59:33 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , b ? GL_LINEAR : GL_NEAREST ) ;
GLint iMinFilter ;
if ( b )
{
GLint iWidth1 = - 1 ;
GLint iWidth2 = - 1 ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_WIDTH , & iWidth1 ) ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 1 , GL_TEXTURE_WIDTH , & iWidth2 ) ;
if ( iWidth1 > 1 & & iWidth2 ! = 0 )
{
/* Mipmaps are enabled. */
if ( g_pWind - > GetActualVideoModeParams ( ) . bTrilinearFiltering )
iMinFilter = GL_LINEAR_MIPMAP_LINEAR ;
else
iMinFilter = GL_LINEAR_MIPMAP_NEAREST ;
}
else
{
iMinFilter = GL_LINEAR ;
}
}
else
{
iMinFilter = GL_NEAREST ;
}
2003-05-22 05:28:37 +00:00
2007-03-23 07:59:33 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , iMinFilter ) ;
2003-05-22 05:28:37 +00:00
}
2007-02-14 01:59:41 +00:00
void RageDisplay_OGL : : SetEffectMode ( EffectMode effect )
{
2007-02-19 23:40:19 +00:00
if ( GLExt . glUseProgramObjectARB = = NULL )
return ;
GLhandleARB hShader = 0 ;
2007-02-14 01:59:41 +00:00
switch ( effect )
{
2007-02-19 23:40:19 +00:00
case EffectMode_Normal : hShader = 0 ; break ;
2007-02-24 23:20:25 +00:00
case EffectMode_Unpremultiply : hShader = g_bUnpremultiplyShader ; break ;
2007-02-19 23:40:19 +00:00
case EffectMode_ColorBurn : hShader = g_bColorBurnShader ; break ;
case EffectMode_ColorDodge : hShader = g_bColorDodgeShader ; break ;
case EffectMode_VividLight : hShader = g_bVividLightShader ; break ;
case EffectMode_HardMix : hShader = g_hHardMixShader ; break ;
2007-03-21 04:38:17 +00:00
case EffectMode_YUYV422 : hShader = g_hYUYV422Shader ; break ;
2007-02-14 01:59:41 +00:00
}
2007-02-19 23:40:19 +00:00
2008-01-02 12:17:49 +00:00
DebugFlushGLErrors ( ) ;
2007-02-19 23:40:19 +00:00
GLExt . glUseProgramObjectARB ( hShader ) ;
if ( hShader = = 0 )
return ;
GLint iTexture1 = GLExt . glGetUniformLocationARB ( hShader , " Texture1 " ) ;
GLint iTexture2 = GLExt . glGetUniformLocationARB ( hShader , " Texture2 " ) ;
GLExt . glUniform1iARB ( iTexture1 , 0 ) ;
GLExt . glUniform1iARB ( iTexture2 , 1 ) ;
2007-03-21 04:38:17 +00:00
if ( effect = = EffectMode_YUYV422 )
{
GLint iTextureWidthUniform = GLExt . glGetUniformLocationARB ( hShader , " TextureWidth " ) ;
GLint iWidth ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_WIDTH , & iWidth ) ;
GLExt . glUniform1iARB ( iTextureWidthUniform , iWidth ) ;
}
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2007-02-14 01:59:41 +00:00
}
bool RageDisplay_OGL : : IsEffectModeSupported ( EffectMode effect )
{
switch ( effect )
{
2007-02-19 23:40:19 +00:00
case EffectMode_Normal : return true ;
2007-02-24 23:20:25 +00:00
case EffectMode_Unpremultiply : return g_bUnpremultiplyShader ! = 0 ;
2007-02-19 23:40:19 +00:00
case EffectMode_ColorBurn : return g_bColorBurnShader ! = 0 ;
case EffectMode_ColorDodge : return g_bColorDodgeShader ! = 0 ;
case EffectMode_VividLight : return g_bVividLightShader ! = 0 ;
case EffectMode_HardMix : return g_hHardMixShader ! = 0 ;
2007-03-21 04:38:17 +00:00
case EffectMode_YUYV422 : return g_hYUYV422Shader ! = 0 ;
2007-02-14 01:59:41 +00:00
}
return false ;
}
2003-05-26 19:42:04 +00:00
void RageDisplay_OGL : : SetBlendMode ( BlendMode mode )
2003-05-22 05:28:37 +00:00
{
glEnable ( GL_BLEND ) ;
2006-07-27 01:34:57 +00:00
if ( GLExt . glBlendEquation ! = NULL )
{
if ( mode = = BLEND_INVERT_DEST )
GLExt . glBlendEquation ( GL_FUNC_SUBTRACT ) ;
else
GLExt . glBlendEquation ( GL_FUNC_ADD ) ;
}
2007-02-13 05:01:25 +00:00
int iSourceRGB , iDestRGB ;
2007-02-24 13:03:35 +00:00
int iSourceAlpha = GL_ONE , iDestAlpha = GL_ONE_MINUS_SRC_ALPHA ;
2003-05-22 05:28:37 +00:00
switch ( mode )
{
case BLEND_NORMAL :
2007-02-13 05:01:25 +00:00
iSourceRGB = GL_SRC_ALPHA ; iDestRGB = GL_ONE_MINUS_SRC_ALPHA ;
2003-05-22 05:28:37 +00:00
break ;
case BLEND_ADD :
2007-02-13 05:01:25 +00:00
iSourceRGB = GL_SRC_ALPHA ; iDestRGB = GL_ONE ;
2003-05-22 05:28:37 +00:00
break ;
2007-02-24 23:30:29 +00:00
case BLEND_COPY_SRC :
iSourceRGB = GL_ONE ; iDestRGB = GL_ZERO ;
iSourceAlpha = GL_ONE ; iDestAlpha = GL_ZERO ;
break ;
2007-02-25 00:32:39 +00:00
case BLEND_ALPHA_MASK :
iSourceRGB = GL_ZERO ; iDestRGB = GL_ONE ;
iSourceAlpha = GL_ZERO ; iDestAlpha = GL_SRC_ALPHA ;
break ;
case BLEND_ALPHA_KNOCK_OUT :
iSourceRGB = GL_ZERO ; iDestRGB = GL_ONE ;
iSourceAlpha = GL_ZERO ; iDestAlpha = GL_ONE_MINUS_SRC_ALPHA ;
break ;
2006-07-27 01:34:57 +00:00
case BLEND_WEIGHTED_MULTIPLY :
/* output = 2*(dst*src). 0.5,0.5,0.5 is identity; darker colors darken the image,
* and brighter colors lighten the image. */
2007-02-13 05:01:25 +00:00
iSourceRGB = GL_DST_COLOR ; iDestRGB = GL_SRC_COLOR ;
2006-07-27 01:34:57 +00:00
break ;
case BLEND_INVERT_DEST :
/* out = src - dst. The source color should almost always be #FFFFFF, to make it "1 - dst". */
2007-02-13 05:01:25 +00:00
iSourceRGB = GL_ONE ; iDestRGB = GL_ONE ;
2006-07-27 01:34:57 +00:00
break ;
2003-05-22 05:28:37 +00:00
case BLEND_NO_EFFECT :
2007-02-13 05:01:25 +00:00
iSourceRGB = GL_ZERO ; iDestRGB = GL_ONE ;
2007-02-24 13:03:35 +00:00
iSourceAlpha = GL_ZERO ; iSourceAlpha = GL_ONE ;
2003-05-22 05:28:37 +00:00
break ;
2006-10-01 04:01:37 +00:00
DEFAULT_FAIL ( mode ) ;
2003-05-22 05:28:37 +00:00
}
2007-02-13 05:01:25 +00:00
2007-02-24 23:19:07 +00:00
if ( GLExt . glBlendFuncSeparateEXT ! = NULL )
GLExt . glBlendFuncSeparateEXT ( iSourceRGB , iDestRGB , iSourceAlpha , iDestAlpha ) ;
2007-02-24 13:03:35 +00:00
else
glBlendFunc ( iSourceRGB , iDestRGB ) ;
2003-05-22 05:28:37 +00:00
}
2003-11-18 20:33:18 +00:00
bool RageDisplay_OGL : : IsZWriteEnabled ( ) const
2003-05-22 05:28:37 +00:00
{
bool a ;
2003-11-18 20:33:18 +00:00
glGetBooleanv ( GL_DEPTH_WRITEMASK , ( unsigned char * ) & a ) ;
2003-05-22 05:28:37 +00:00
return a ;
}
2003-11-18 20:33:18 +00:00
bool RageDisplay_OGL : : IsZTestEnabled ( ) const
2003-05-22 05:28:37 +00:00
{
2003-11-18 20:33:18 +00:00
GLenum a ;
2003-12-10 16:42:02 +00:00
glGetIntegerv ( GL_DEPTH_FUNC , ( GLint * ) & a ) ;
2003-11-18 20:33:18 +00:00
return a ! = GL_ALWAYS ;
2003-05-22 05:28:37 +00:00
}
2003-11-18 20:33:18 +00:00
2003-05-26 19:42:04 +00:00
void RageDisplay_OGL : : ClearZBuffer ( )
2003-05-22 05:28:37 +00:00
{
2003-11-18 20:33:18 +00:00
bool write = IsZWriteEnabled ( ) ;
SetZWrite ( true ) ;
2006-02-01 07:52:33 +00:00
glClear ( GL_DEPTH_BUFFER_BIT ) ;
2003-11-18 20:33:18 +00:00
SetZWrite ( write ) ;
}
void RageDisplay_OGL : : SetZWrite ( bool b )
{
glDepthMask ( b ) ;
}
2005-05-06 04:05:02 +00:00
void RageDisplay_OGL : : SetZBias ( float f )
2005-05-06 03:24:41 +00:00
{
2005-05-06 04:05:02 +00:00
float fNear = SCALE ( f , 0.0f , 1.0f , 0.05f , 0.0f ) ;
float fFar = SCALE ( f , 0.0f , 1.0f , 1.0f , 0.95f ) ;
glDepthRange ( fNear , fFar ) ;
2005-05-06 03:24:41 +00:00
}
2004-05-15 09:26:21 +00:00
void RageDisplay_OGL : : SetZTestMode ( ZTestMode mode )
2003-11-18 20:33:18 +00:00
{
glEnable ( GL_DEPTH_TEST ) ;
2004-05-15 09:26:21 +00:00
switch ( mode )
{
2006-02-01 07:52:33 +00:00
case ZTEST_OFF : glDepthFunc ( GL_ALWAYS ) ; break ;
2004-05-15 09:26:21 +00:00
case ZTEST_WRITE_ON_PASS : glDepthFunc ( GL_LEQUAL ) ; break ;
case ZTEST_WRITE_ON_FAIL : glDepthFunc ( GL_GREATER ) ; break ;
default : ASSERT ( 0 ) ;
}
2003-05-22 05:28:37 +00:00
}
2007-02-13 05:56:24 +00:00
void RageDisplay_OGL : : SetTextureWrapping ( TextureUnit tu , bool b )
2003-05-22 05:28:37 +00:00
{
2007-02-13 05:56:24 +00:00
/* This should be per-texture-unit state, but it's per-texture state in OpenGl,
* so we'll behave incorrectly if the same texture is used in more than one texture
* unit simultaneously with different wrapping. */
SetTextureUnit ( tu ) ;
2003-09-06 05:32:42 +00:00
GLenum mode = b ? GL_REPEAT : GL_CLAMP_TO_EDGE ;
2003-05-22 05:28:37 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , mode ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , mode ) ;
}
2003-05-26 19:42:04 +00:00
void RageDisplay_OGL : : SetMaterial (
2004-01-06 21:25:46 +00:00
const RageColor & emissive ,
const RageColor & ambient ,
const RageColor & diffuse ,
const RageColor & specular ,
2003-05-22 05:28:37 +00:00
float shininess
)
{
2004-04-24 10:18:15 +00:00
// TRICKY: If lighting is off, then setting the material
// will have no effect. Even if lighting is off, we still
// want Models to have basic color and transparency.
// We can do this fake lighting by setting the vertex color.
2005-01-30 19:50:55 +00:00
// XXX: unintended: SetLighting must be called before SetMaterial
2004-04-24 10:18:15 +00:00
GLboolean bLighting ;
glGetBooleanv ( GL_LIGHTING , & bLighting ) ;
if ( bLighting )
{
glMaterialfv ( GL_FRONT , GL_EMISSION , emissive ) ;
glMaterialfv ( GL_FRONT , GL_AMBIENT , ambient ) ;
glMaterialfv ( GL_FRONT , GL_DIFFUSE , diffuse ) ;
glMaterialfv ( GL_FRONT , GL_SPECULAR , specular ) ;
glMaterialf ( GL_FRONT , GL_SHININESS , shininess ) ;
}
else
{
2005-07-07 22:07:13 +00:00
RageColor c = diffuse ;
c . r + = emissive . r + ambient . r ;
c . g + = emissive . g + ambient . g ;
c . b + = emissive . b + ambient . b ;
glColor4fv ( c ) ;
2004-04-24 10:18:15 +00:00
}
2003-05-22 05:28:37 +00:00
}
2003-05-26 19:42:04 +00:00
void RageDisplay_OGL : : SetLighting ( bool b )
2003-05-22 05:28:37 +00:00
{
if ( b ) glEnable ( GL_LIGHTING ) ;
else glDisable ( GL_LIGHTING ) ;
}
2003-05-26 19:42:04 +00:00
void RageDisplay_OGL : : SetLightOff ( int index )
2003-05-22 05:28:37 +00:00
{
glDisable ( GL_LIGHT0 + index ) ;
}
2005-11-13 18:22:52 +00:00
2003-05-26 19:42:04 +00:00
void RageDisplay_OGL : : SetLightDirectional (
2003-05-22 05:28:37 +00:00
int index ,
2004-01-06 21:25:46 +00:00
const RageColor & ambient ,
const RageColor & diffuse ,
const RageColor & specular ,
const RageVector3 & dir )
2003-05-22 05:28:37 +00:00
{
// Light coordinates are transformed by the modelview matrix, but
// we are being passed in world-space coords.
glPushMatrix ( ) ;
glLoadIdentity ( ) ;
glEnable ( GL_LIGHT0 + index ) ;
2005-11-13 18:22:52 +00:00
glLightfv ( GL_LIGHT0 + index , GL_AMBIENT , ambient ) ;
glLightfv ( GL_LIGHT0 + index , GL_DIFFUSE , diffuse ) ;
glLightfv ( GL_LIGHT0 + index , GL_SPECULAR , specular ) ;
2003-05-22 05:28:37 +00:00
float position [ 4 ] = { dir . x , dir . y , dir . z , 0 } ;
2005-11-13 18:22:52 +00:00
glLightfv ( GL_LIGHT0 + index , GL_POSITION , position ) ;
2003-05-22 05:28:37 +00:00
glPopMatrix ( ) ;
}
2004-02-04 11:05:33 +00:00
void RageDisplay_OGL : : SetCullMode ( CullMode mode )
2003-05-22 05:28:37 +00:00
{
2004-02-04 11:05:33 +00:00
switch ( mode )
{
case CULL_BACK :
2003-05-22 05:28:37 +00:00
glEnable ( GL_CULL_FACE ) ;
2004-02-04 11:05:33 +00:00
glCullFace ( GL_BACK ) ;
break ;
case CULL_FRONT :
glEnable ( GL_CULL_FACE ) ;
glCullFace ( GL_FRONT ) ;
break ;
case CULL_NONE :
2006-02-01 07:52:33 +00:00
glDisable ( GL_CULL_FACE ) ;
2004-02-04 11:05:33 +00:00
break ;
default :
ASSERT ( 0 ) ;
}
2003-05-22 05:28:37 +00:00
}
2003-10-03 21:38:38 +00:00
const RageDisplay : : PixelFormatDesc * RageDisplay_OGL : : GetPixelFormatDesc ( PixelFormat pf ) const
2003-05-26 03:12:12 +00:00
{
2005-09-29 17:15:12 +00:00
ASSERT ( pf < NUM_PixelFormat ) ;
2003-05-26 03:12:12 +00:00
return & PIXEL_FORMAT_DESC [ pf ] ;
}
2006-01-17 01:24:40 +00:00
bool RageDisplay_OGL : : SupportsThreadedRendering ( )
{
return g_pWind - > SupportsThreadedRendering ( ) ;
}
2006-01-27 09:13:03 +00:00
void RageDisplay_OGL : : BeginConcurrentRenderingMainThread ( )
{
g_pWind - > BeginConcurrentRenderingMainThread ( ) ;
}
void RageDisplay_OGL : : EndConcurrentRenderingMainThread ( )
{
g_pWind - > EndConcurrentRenderingMainThread ( ) ;
}
2006-01-17 01:24:40 +00:00
void RageDisplay_OGL : : BeginConcurrentRendering ( )
{
g_pWind - > BeginConcurrentRendering ( ) ;
2006-07-25 20:10:56 +00:00
RageDisplay : : BeginConcurrentRendering ( ) ;
2006-01-17 01:24:40 +00:00
}
void RageDisplay_OGL : : EndConcurrentRendering ( )
{
g_pWind - > EndConcurrentRendering ( ) ;
}
2006-07-24 05:53:57 +00:00
void RageDisplay_OGL : : DeleteTexture ( unsigned iTexture )
2003-05-22 05:28:37 +00:00
{
2007-02-14 00:07:55 +00:00
if ( iTexture = = 0 )
return ;
2006-07-26 03:44:27 +00:00
if ( g_mapRenderTargets . find ( iTexture ) ! = g_mapRenderTargets . end ( ) )
{
delete g_mapRenderTargets [ iTexture ] ;
g_mapRenderTargets . erase ( iTexture ) ;
return ;
}
2008-01-02 12:17:49 +00:00
DebugFlushGLErrors ( ) ;
2006-07-24 05:53:57 +00:00
glDeleteTextures ( 1 , reinterpret_cast < GLuint * > ( & iTexture ) ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2003-05-22 05:28:37 +00:00
}
2005-11-13 18:22:52 +00:00
PixelFormat RageDisplay_OGL : : GetImgPixelFormat ( RageSurface * & img , bool & bFreeImg , int width , int height , bool bPalettedTexture )
2003-06-30 02:39:56 +00:00
{
PixelFormat pixfmt = FindPixelFormat ( img - > format - > BitsPerPixel , img - > format - > Rmask , img - > format - > Gmask , img - > format - > Bmask , img - > format - > Amask ) ;
2004-09-26 09:15:16 +00:00
/* If img is paletted, we're setting up a non-paletted texture, and color indexes
* are too small, depalettize. */
bool bSupported = true ;
if ( ! bPalettedTexture & & img - > fmt . BytesPerPixel = = 1 & & ! g_bColorIndexTableWorks )
bSupported = false ;
2006-10-07 04:25:28 +00:00
if ( pixfmt = = PixelFormat_Invalid | | ! SupportsSurfaceFormat ( pixfmt ) )
2004-09-26 09:15:16 +00:00
bSupported = false ;
if ( ! bSupported )
2003-06-30 02:39:56 +00:00
{
/* The source isn't in a supported, known pixel format. We need to convert
* it ourself. Just convert it to RGBA8, and let OpenGL convert it back
* down to whatever the actual pixel format is. This is a very slow code
* path, which should almost never be used. */
2005-09-29 17:15:12 +00:00
pixfmt = PixelFormat_RGBA8 ;
2003-07-09 03:16:28 +00:00
ASSERT ( SupportsSurfaceFormat ( pixfmt ) ) ;
2003-06-30 02:39:56 +00:00
const PixelFormatDesc * pfd = DISPLAY - > GetPixelFormatDesc ( pixfmt ) ;
2007-07-24 18:37:12 +00:00
RageSurface * imgconv = CreateSurface ( img - > w , img - > h ,
2004-06-14 00:51:00 +00:00
pfd - > bpp , pfd - > masks [ 0 ] , pfd - > masks [ 1 ] , pfd - > masks [ 2 ] , pfd - > masks [ 3 ] ) ;
2004-08-31 01:15:12 +00:00
RageSurfaceUtils : : Blit ( img , imgconv , width , height ) ;
2003-06-30 02:39:56 +00:00
img = imgconv ;
2005-11-13 18:22:52 +00:00
bFreeImg = true ;
2003-06-30 02:39:56 +00:00
}
else
2005-10-02 03:35:56 +00:00
{
2005-11-13 18:22:52 +00:00
bFreeImg = false ;
2005-10-02 03:35:56 +00:00
}
2003-06-30 02:39:56 +00:00
return pixfmt ;
}
2004-09-26 09:15:16 +00:00
/* If we're sending a paletted surface to a non-paletted texture, set the palette. */
void SetPixelMapForSurface ( int glImageFormat , int glTexFormat , const RageSurfacePalette * palette )
{
if ( glImageFormat ! = GL_COLOR_INDEX | | glTexFormat = = GL_COLOR_INDEX8_EXT )
{
2004-09-30 04:52:06 +00:00
glPixelTransferi ( GL_MAP_COLOR , false ) ;
2004-09-26 09:15:16 +00:00
return ;
}
GLushort buf [ 4 ] [ 256 ] ;
memset ( buf , 0 , sizeof ( buf ) ) ;
for ( int i = 0 ; i < palette - > ncolors ; + + i )
{
buf [ 0 ] [ i ] = SCALE ( palette - > colors [ i ] . r , 0 , 255 , 0 , 65535 ) ;
buf [ 1 ] [ i ] = SCALE ( palette - > colors [ i ] . g , 0 , 255 , 0 , 65535 ) ;
buf [ 2 ] [ i ] = SCALE ( palette - > colors [ i ] . b , 0 , 255 , 0 , 65535 ) ;
buf [ 3 ] [ i ] = SCALE ( palette - > colors [ i ] . a , 0 , 255 , 0 , 65535 ) ;
}
2008-01-02 12:17:49 +00:00
DebugFlushGLErrors ( ) ;
2004-09-26 09:15:16 +00:00
glPixelMapusv ( GL_PIXEL_MAP_I_TO_R , 256 , buf [ 0 ] ) ;
glPixelMapusv ( GL_PIXEL_MAP_I_TO_G , 256 , buf [ 1 ] ) ;
glPixelMapusv ( GL_PIXEL_MAP_I_TO_B , 256 , buf [ 2 ] ) ;
glPixelMapusv ( GL_PIXEL_MAP_I_TO_A , 256 , buf [ 3 ] ) ;
2004-09-30 04:52:06 +00:00
glPixelTransferi ( GL_MAP_COLOR , true ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-09-26 09:15:16 +00:00
}
2003-05-26 19:42:04 +00:00
unsigned RageDisplay_OGL : : CreateTexture (
2003-05-22 05:28:37 +00:00
PixelFormat pixfmt ,
2005-11-13 18:22:52 +00:00
RageSurface * pImg ,
2004-01-23 06:20:28 +00:00
bool bGenerateMipMaps )
2003-05-22 05:28:37 +00:00
{
2005-09-29 17:15:12 +00:00
ASSERT ( pixfmt < NUM_PixelFormat ) ;
2003-08-29 03:03:29 +00:00
2004-01-24 19:14:22 +00:00
2006-02-01 07:44:33 +00:00
/* Find the pixel format of the surface we've been given. */
2005-11-13 18:22:52 +00:00
bool bFreeImg ;
2006-02-01 07:44:33 +00:00
PixelFormat SurfacePixFmt = GetImgPixelFormat ( pImg , bFreeImg , pImg - > w , pImg - > h , pixfmt = = PixelFormat_PAL ) ;
2006-10-07 04:25:28 +00:00
ASSERT ( SurfacePixFmt ! = PixelFormat_Invalid ) ;
2003-06-30 02:39:56 +00:00
2005-09-29 17:15:12 +00:00
GLenum glTexFormat = g_GLPixFmtInfo [ pixfmt ] . internalfmt ;
2006-02-01 07:44:33 +00:00
GLenum glImageFormat = g_GLPixFmtInfo [ SurfacePixFmt ] . format ;
GLenum glImageType = g_GLPixFmtInfo [ SurfacePixFmt ] . type ;
2003-05-22 05:28:37 +00:00
2004-09-26 09:15:16 +00:00
/* If the image is paletted, but we're not sending it to a paletted image,
* set up glPixelMap. */
2005-11-13 18:22:52 +00:00
SetPixelMapForSurface ( glImageFormat , glTexFormat , pImg - > format - > palette ) ;
2004-09-26 09:15:16 +00:00
2004-01-24 19:35:53 +00:00
// HACK: OpenGL 1.2 types aren't available in GLU 1.3. Don't call GLU for mip
// mapping if we're using an OGL 1.2 type and don't have >= GLU 1.3.
// http://pyopengl.sourceforge.net/documentation/manual/gluBuild2DMipmaps.3G.html
2004-01-24 22:46:06 +00:00
if ( bGenerateMipMaps & & g_gluVersion < 13 )
2004-01-24 19:35:53 +00:00
{
switch ( pixfmt )
{
// OpenGL 1.1 types
2005-09-29 17:15:12 +00:00
case PixelFormat_RGBA8 :
case PixelFormat_RGB8 :
case PixelFormat_PAL :
case PixelFormat_BGR8 :
2004-01-24 19:35:53 +00:00
break ;
// OpenGL 1.2 types
default :
LOG - > Trace ( " Can't generate mipmaps for type %s because GLU version %.1f is too old. " , GLToString ( glImageType ) . c_str ( ) , g_gluVersion / 10.f ) ;
bGenerateMipMaps = false ;
break ;
}
}
2007-02-13 05:56:24 +00:00
SetTextureUnit ( TextureUnit_1 ) ;
2004-01-24 19:35:53 +00:00
// allocate OpenGL texture resource
2006-07-24 06:11:37 +00:00
unsigned int iTexHandle ;
glGenTextures ( 1 , reinterpret_cast < GLuint * > ( & iTexHandle ) ) ;
ASSERT ( iTexHandle ) ;
2004-01-24 19:35:53 +00:00
2006-07-24 06:11:37 +00:00
glBindTexture ( GL_TEXTURE_2D , iTexHandle ) ;
2004-05-18 08:43:21 +00:00
2005-11-13 18:22:52 +00:00
if ( g_pWind - > GetActualVideoModeParams ( ) . bAnisotropicFiltering & &
2005-05-28 03:54:33 +00:00
GLExt . HasExtension ( " GL_EXT_texture_filter_anisotropic " ) )
2004-05-18 08:43:21 +00:00
{
2005-11-13 18:22:52 +00:00
GLfloat fLargestSupportedAnisotropy ;
glGetFloatv ( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT , & fLargestSupportedAnisotropy ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAX_ANISOTROPY_EXT , fLargestSupportedAnisotropy ) ;
2004-05-18 08:43:21 +00:00
}
2007-03-23 07:59:33 +00:00
SetTextureFiltering ( TextureUnit_1 , true ) ;
2007-02-13 05:56:24 +00:00
SetTextureWrapping ( TextureUnit_1 , false ) ;
2004-01-24 19:35:53 +00:00
2005-11-13 18:22:52 +00:00
glPixelStorei ( GL_UNPACK_ROW_LENGTH , pImg - > pitch / pImg - > format - > BytesPerPixel ) ;
2004-01-24 19:35:53 +00:00
2005-09-29 17:15:12 +00:00
if ( pixfmt = = PixelFormat_PAL )
2004-01-24 22:18:12 +00:00
{
2004-09-26 08:56:32 +00:00
/* The texture is paletted; set the texture palette. */
2004-01-24 22:18:12 +00:00
GLubyte palette [ 256 * 4 ] ;
2005-11-13 18:22:52 +00:00
memset ( palette , 0 , sizeof ( palette ) ) ;
2004-01-24 22:18:12 +00:00
int p = 0 ;
2004-09-26 08:56:32 +00:00
/* Copy the palette to the format OpenGL expects. */
2005-11-13 18:22:52 +00:00
for ( int i = 0 ; i < pImg - > format - > palette - > ncolors ; + + i )
2004-01-24 22:18:12 +00:00
{
2005-11-13 18:22:52 +00:00
palette [ p + + ] = pImg - > format - > palette - > colors [ i ] . r ;
palette [ p + + ] = pImg - > format - > palette - > colors [ i ] . g ;
palette [ p + + ] = pImg - > format - > palette - > colors [ i ] . b ;
palette [ p + + ] = pImg - > format - > palette - > colors [ i ] . a ;
2004-01-24 22:18:12 +00:00
}
/* Set the palette. */
2005-11-13 18:22:52 +00:00
GLExt . glColorTableEXT ( GL_TEXTURE_2D , GL_RGBA8 , 256 , GL_RGBA , GL_UNSIGNED_BYTE , palette ) ;
2004-01-24 22:18:12 +00:00
2005-11-13 18:22:52 +00:00
GLint iRealFormat = 0 ;
GLExt . glGetColorTableParameterivEXT ( GL_TEXTURE_2D , GL_COLOR_TABLE_FORMAT , & iRealFormat ) ;
ASSERT ( iRealFormat = = GL_RGBA8 ) ;
2004-01-24 22:18:12 +00:00
}
2007-05-06 02:43:05 +00:00
LOG - > Trace ( " %s (format %s, %ix%i, format %s, type %s, pixfmt %i, imgpixfmt %i) " ,
bGenerateMipMaps ? " gluBuild2DMipmaps " : " glTexImage2D " ,
GLToString ( glTexFormat ) . c_str ( ) ,
pImg - > w , pImg - > h ,
GLToString ( glImageFormat ) . c_str ( ) ,
GLToString ( glImageType ) . c_str ( ) , pixfmt , SurfacePixFmt ) ;
2004-09-26 08:53:01 +00:00
2008-01-02 12:17:49 +00:00
DebugFlushGLErrors ( ) ;
2003-05-31 09:10:18 +00:00
2004-01-23 06:20:28 +00:00
if ( bGenerateMipMaps )
{
2004-01-24 19:14:22 +00:00
GLenum error = gluBuild2DMipmaps (
2004-01-23 06:20:28 +00:00
GL_TEXTURE_2D , glTexFormat ,
2005-11-13 18:22:52 +00:00
pImg - > w , pImg - > h ,
glImageFormat , glImageType , pImg - > pixels ) ;
2004-09-26 08:53:01 +00:00
ASSERT_M ( error = = 0 , ( char * ) gluErrorString ( error ) ) ;
2004-01-23 06:20:28 +00:00
}
else
{
glTexImage2D (
GL_TEXTURE_2D , 0 , glTexFormat ,
2007-03-21 04:51:47 +00:00
power_of_two ( pImg - > w ) , power_of_two ( pImg - > h ) , 0 ,
glImageFormat , glImageType , NULL ) ;
if ( pImg - > pixels )
glTexSubImage2D ( GL_TEXTURE_2D , 0 ,
0 , 0 ,
pImg - > w , pImg - > h ,
glImageFormat , glImageType , pImg - > pixels ) ;
2004-01-24 19:14:22 +00:00
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2004-01-23 06:20:28 +00:00
}
2003-05-22 05:28:37 +00:00
2003-06-28 02:19:31 +00:00
/* Sanity check: */
2005-09-29 17:15:12 +00:00
if ( pixfmt = = PixelFormat_PAL )
2003-05-22 05:28:37 +00:00
{
2005-11-13 18:22:52 +00:00
GLint iSize = 0 ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GLenum ( GL_TEXTURE_INDEX_SIZE_EXT ) , & iSize ) ;
if ( iSize ! = 8 )
RageException : : Throw ( " Thought paletted textures worked, but they don't. " ) ;
2003-05-22 05:28:37 +00:00
}
2005-11-13 18:22:52 +00:00
glPixelStorei ( GL_UNPACK_ROW_LENGTH , 0 ) ;
2003-05-22 05:28:37 +00:00
glFlush ( ) ;
2005-11-13 18:22:52 +00:00
if ( bFreeImg )
delete pImg ;
2006-07-24 06:11:37 +00:00
return iTexHandle ;
2003-05-22 05:28:37 +00:00
}
2007-03-22 19:03:31 +00:00
struct RageTextureLock_OGL : public RageTextureLock , public InvalidateObject
{
public :
RageTextureLock_OGL ( )
{
m_iTexHandle = 0 ;
m_iBuffer = 0 ;
CreateObject ( ) ;
}
~ RageTextureLock_OGL ( )
{
ASSERT ( m_iTexHandle = = 0 ) ; // locked!
GLExt . glDeleteBuffersARB ( 1 , & m_iBuffer ) ;
}
/* This is called when our OpenGL context is invalidated. */
void Invalidate ( )
{
m_iTexHandle = 0 ;
}
void Lock ( unsigned iTexHandle , RageSurface * pSurface )
{
ASSERT ( m_iTexHandle = = 0 ) ;
ASSERT ( pSurface - > pixels = = NULL ) ;
CreateObject ( ) ;
m_iTexHandle = iTexHandle ;
GLExt . glBindBufferARB ( GL_PIXEL_UNPACK_BUFFER_ARB , m_iBuffer ) ;
int iSize = pSurface - > h * pSurface - > pitch ;
GLExt . glBufferDataARB ( GL_PIXEL_UNPACK_BUFFER_ARB , iSize , NULL , GL_STREAM_DRAW ) ;
void * pSurfaceMemory = GLExt . glMapBufferARB ( GL_PIXEL_UNPACK_BUFFER_ARB , GL_WRITE_ONLY ) ;
pSurface - > pixels = ( uint8_t * ) pSurfaceMemory ;
pSurface - > pixels_owned = false ;
}
void Unlock ( RageSurface * pSurface , bool bChanged )
{
GLExt . glUnmapBufferARB ( GL_PIXEL_UNPACK_BUFFER_ARB ) ;
pSurface - > pixels = ( uint8_t * ) BUFFER_OFFSET ( 0 ) ;
if ( bChanged )
DISPLAY - > UpdateTexture ( m_iTexHandle , pSurface , 0 , 0 , pSurface - > w , pSurface - > h ) ;
pSurface - > pixels = NULL ;
m_iTexHandle = 0 ;
GLExt . glBindBufferARB ( GL_PIXEL_UNPACK_BUFFER_ARB , 0 ) ;
}
private :
void CreateObject ( )
{
if ( m_iBuffer ! = 0 )
return ;
2008-01-02 12:17:49 +00:00
DebugFlushGLErrors ( ) ;
2007-03-22 19:03:31 +00:00
GLExt . glGenBuffersARB ( 1 , & m_iBuffer ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2007-03-22 19:03:31 +00:00
}
GLuint m_iBuffer ;
unsigned m_iTexHandle ;
} ;
RageTextureLock * RageDisplay_OGL : : CreateTextureLock ( )
{
2007-03-27 00:24:56 +00:00
if ( ! GLExt . HasExtension ( " GL_ARB_pixel_buffer_object " ) )
return NULL ;
2007-03-22 19:03:31 +00:00
return new RageTextureLock_OGL ;
}
2003-05-26 19:42:04 +00:00
void RageDisplay_OGL : : UpdateTexture (
2006-07-24 06:11:37 +00:00
unsigned iTexHandle ,
2005-11-13 18:22:52 +00:00
RageSurface * pImg ,
int iXOffset , int iYOffset , int iWidth , int iHeight )
2003-05-22 05:28:37 +00:00
{
2006-07-24 06:11:37 +00:00
glBindTexture ( GL_TEXTURE_2D , iTexHandle ) ;
2003-05-22 05:28:37 +00:00
2005-11-13 18:22:52 +00:00
bool bFreeImg ;
2006-02-01 07:44:33 +00:00
PixelFormat SurfacePixFmt = GetImgPixelFormat ( pImg , bFreeImg , iWidth , iHeight , false ) ;
2003-06-29 08:13:18 +00:00
2005-11-13 18:22:52 +00:00
glPixelStorei ( GL_UNPACK_ROW_LENGTH , pImg - > pitch / pImg - > format - > BytesPerPixel ) ;
2003-08-29 04:46:54 +00:00
2006-02-01 07:44:33 +00:00
GLenum glImageFormat = g_GLPixFmtInfo [ SurfacePixFmt ] . format ;
GLenum glImageType = g_GLPixFmtInfo [ SurfacePixFmt ] . type ;
2003-05-22 05:28:37 +00:00
2006-04-06 09:43:44 +00:00
/* If the image is paletted, but we're not sending it to a paletted image,
* set up glPixelMap. */
if ( pImg - > format - > palette )
{
GLenum glTexFormat = 0 ;
glGetTexLevelParameteriv ( GL_PROXY_TEXTURE_2D , 0 , GLenum ( GL_TEXTURE_INTERNAL_FORMAT ) , ( GLint * ) & glTexFormat ) ;
SetPixelMapForSurface ( glImageFormat , glTexFormat , pImg - > format - > palette ) ;
}
2005-11-13 18:22:52 +00:00
glTexSubImage2D ( GL_TEXTURE_2D , 0 ,
iXOffset , iYOffset ,
iWidth , iHeight ,
glImageFormat , glImageType , pImg - > pixels ) ;
2003-05-22 05:28:37 +00:00
/* Must unset PixelStore when we're done! */
2005-11-13 18:22:52 +00:00
glPixelStorei ( GL_UNPACK_ROW_LENGTH , 0 ) ;
2003-05-22 05:28:37 +00:00
glFlush ( ) ;
2003-06-29 08:13:18 +00:00
2005-11-13 18:22:52 +00:00
if ( bFreeImg )
delete pImg ;
2003-05-22 05:28:37 +00:00
}
2006-07-26 19:18:21 +00:00
class RenderTarget_FramebufferObject : public RenderTarget
{
public :
RenderTarget_FramebufferObject ( ) ;
~ RenderTarget_FramebufferObject ( ) ;
void Create ( const RenderTargetParam & param , int & iTextureWidthOut , int & iTextureHeightOut ) ;
unsigned GetTexture ( ) const { return m_iTexHandle ; }
void StartRenderingTo ( ) ;
void FinishRenderingTo ( ) ;
2006-07-29 00:23:44 +00:00
virtual bool InvertY ( ) const { return true ; }
2006-07-26 19:18:21 +00:00
private :
unsigned int m_iFrameBufferHandle ;
unsigned int m_iTexHandle ;
unsigned int m_iDepthBufferHandle ;
} ;
RenderTarget_FramebufferObject : : RenderTarget_FramebufferObject ( )
{
m_iFrameBufferHandle = 0 ;
m_iTexHandle = 0 ;
m_iDepthBufferHandle = 0 ;
}
RenderTarget_FramebufferObject : : ~ RenderTarget_FramebufferObject ( )
{
if ( m_iDepthBufferHandle )
GLExt . glDeleteRenderbuffersEXT ( 1 , reinterpret_cast < GLuint * > ( & m_iDepthBufferHandle ) ) ;
if ( m_iFrameBufferHandle )
GLExt . glDeleteFramebuffersEXT ( 1 , reinterpret_cast < GLuint * > ( & m_iFrameBufferHandle ) ) ;
if ( m_iTexHandle )
glDeleteTextures ( 1 , reinterpret_cast < GLuint * > ( & m_iTexHandle ) ) ;
}
void RenderTarget_FramebufferObject : : Create ( const RenderTargetParam & param , int & iTextureWidthOut , int & iTextureHeightOut )
{
2006-07-29 00:23:44 +00:00
m_Param = param ;
2008-01-02 12:17:49 +00:00
DebugFlushGLErrors ( ) ;
2006-07-26 19:18:21 +00:00
// Allocate OpenGL texture resource
glGenTextures ( 1 , reinterpret_cast < GLuint * > ( & m_iTexHandle ) ) ;
ASSERT ( m_iTexHandle ) ;
int iTextureWidth = power_of_two ( param . iWidth ) ;
int iTextureHeight = power_of_two ( param . iHeight ) ;
iTextureWidthOut = iTextureWidth ;
iTextureHeightOut = iTextureHeight ;
glBindTexture ( GL_TEXTURE_2D , m_iTexHandle ) ;
2007-02-24 12:33:16 +00:00
GLenum internalformat ;
GLenum type = param . bWithAlpha ? GL_RGBA : GL_RGB ;
if ( param . bFloat & & GLExt . m_bGL_ARB_texture_float )
internalformat = param . bWithAlpha ? GL_RGBA16F_ARB : GL_RGB16F_ARB ;
else
internalformat = param . bWithAlpha ? GL_RGBA8 : GL_RGB8 ;
glTexImage2D ( GL_TEXTURE_2D , 0 , internalformat ,
iTextureWidth , iTextureHeight , 0 , type , GL_UNSIGNED_BYTE , NULL ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2006-07-26 19:18:21 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
/* Create the framebuffer object. */
GLExt . glGenFramebuffersEXT ( 1 , reinterpret_cast < GLuint * > ( & m_iFrameBufferHandle ) ) ;
ASSERT ( m_iFrameBufferHandle ) ;
/* Attach the texture to it. */
GLExt . glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT , m_iFrameBufferHandle ) ;
GLExt . glFramebufferTexture2DEXT ( GL_FRAMEBUFFER_EXT , GL_COLOR_ATTACHMENT0_EXT , GL_TEXTURE_2D , m_iTexHandle , 0 ) ;
2008-01-02 12:17:49 +00:00
DebugAssertNoGLError ( ) ;
2006-07-26 19:18:21 +00:00
/* Attach a depth buffer, if requested. */
if ( param . bWithDepthBuffer )
{
GLExt . glGenRenderbuffersEXT ( 1 , reinterpret_cast < GLuint * > ( & m_iDepthBufferHandle ) ) ;
ASSERT ( m_iDepthBufferHandle ) ;
GLExt . glRenderbufferStorageEXT ( GL_RENDERBUFFER_EXT , GL_DEPTH_COMPONENT16 , iTextureWidth , iTextureHeight ) ;
GLExt . glFramebufferRenderbufferEXT ( GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , m_iDepthBufferHandle ) ;
}
GLenum status = GLExt . glCheckFramebufferStatusEXT ( GL_FRAMEBUFFER_EXT ) ;
switch ( status )
{
case GL_FRAMEBUFFER_COMPLETE_EXT :
break ;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT :
FAIL_M ( " GL_FRAMEBUFFER_UNSUPPORTED_EXT " ) ;
break ;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT : FAIL_M ( " GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT " ) ; break ;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT : FAIL_M ( " GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT " ) ; break ;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT : FAIL_M ( " GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT " ) ; break ;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT : FAIL_M ( " GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT " ) ; break ;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT : FAIL_M ( " GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT " ) ; break ;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT : FAIL_M ( " GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT " ) ; break ;
default :
ASSERT ( 0 ) ;
}
2006-07-27 01:30:55 +00:00
GLExt . glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT , 0 ) ;
2006-07-26 19:18:21 +00:00
}
void RenderTarget_FramebufferObject : : StartRenderingTo ( )
{
GLExt . glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT , m_iFrameBufferHandle ) ;
}
void RenderTarget_FramebufferObject : : FinishRenderingTo ( )
{
GLExt . glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT , 0 ) ;
}
2006-07-26 03:44:27 +00:00
bool RageDisplay_OGL : : SupportsRenderToTexture ( ) const
{
2006-07-26 19:18:21 +00:00
return GLExt . m_bGL_EXT_framebuffer_object | | g_pWind - > SupportsRenderToTexture ( ) ;
2006-07-26 03:44:27 +00:00
}
/*
* Render-to-texture can be implemented in several ways: the generic GL_ARB_pixel_buffer_object,
* or platform-specifically. PBO is not available on all hardware that supports RTT,
* particularly GeForce 2, but is simpler and faster when available.
*/
unsigned RageDisplay_OGL : : CreateRenderTarget ( const RenderTargetParam & param , int & iTextureWidthOut , int & iTextureHeightOut )
{
2006-07-26 19:18:21 +00:00
RenderTarget * pTarget ;
if ( GLExt . m_bGL_EXT_framebuffer_object )
2006-07-28 21:03:57 +00:00
pTarget = new RenderTarget_FramebufferObject ;
2006-07-26 19:18:21 +00:00
else
2006-07-28 21:06:13 +00:00
pTarget = g_pWind - > CreateRenderTarget ( ) ;
2006-07-28 21:03:57 +00:00
pTarget - > Create ( param , iTextureWidthOut , iTextureHeightOut ) ;
2006-07-26 19:18:21 +00:00
2006-07-26 03:44:27 +00:00
unsigned iTexture = pTarget - > GetTexture ( ) ;
ASSERT ( g_mapRenderTargets . find ( iTexture ) = = g_mapRenderTargets . end ( ) ) ;
g_mapRenderTargets [ iTexture ] = pTarget ;
return iTexture ;
}
void RageDisplay_OGL : : SetRenderTarget ( unsigned iTexture , bool bPreserveTexture )
{
if ( iTexture = = 0 )
{
g_bInvertY = false ;
glFrontFace ( GL_CCW ) ;
2007-02-28 05:03:15 +00:00
/* Pop matrixes affected by SetDefaultRenderStates. */
DISPLAY - > CameraPopMatrix ( ) ;
2006-07-29 00:23:44 +00:00
/* Reset the viewport. */
int fWidth = g_pWind - > GetActualVideoModeParams ( ) . width ;
int fHeight = g_pWind - > GetActualVideoModeParams ( ) . height ;
glViewport ( 0 , 0 , fWidth , fHeight ) ;
2006-07-26 03:44:27 +00:00
if ( g_pCurrentRenderTarget )
g_pCurrentRenderTarget - > FinishRenderingTo ( ) ;
g_pCurrentRenderTarget = NULL ;
return ;
}
/* If we already had a render target, disable it. */
if ( g_pCurrentRenderTarget ! = NULL )
SetRenderTarget ( 0 , true ) ;
/* Enable the new render target. */
ASSERT ( g_mapRenderTargets . find ( iTexture ) ! = g_mapRenderTargets . end ( ) ) ;
RenderTarget * pTarget = g_mapRenderTargets [ iTexture ] ;
pTarget - > StartRenderingTo ( ) ;
g_pCurrentRenderTarget = pTarget ;
2006-07-29 00:23:44 +00:00
/* Set the viewport to the size of the render target. */
glViewport ( 0 , 0 , pTarget - > GetParam ( ) . iWidth , pTarget - > GetParam ( ) . iHeight ) ;
2006-07-26 03:44:27 +00:00
/* If this render target implementation flips Y, compensate. Inverting will
* switch the winding order. */
g_bInvertY = pTarget - > InvertY ( ) ;
if ( g_bInvertY )
glFrontFace ( GL_CW ) ;
/* The render target may be in a different OpenGL context, so re-send
2007-02-28 05:03:15 +00:00
* state. Push matrixes affected by SetDefaultRenderStates. */
DISPLAY - > CameraPushMatrix ( ) ;
2006-07-26 03:44:27 +00:00
SetDefaultRenderStates ( ) ;
/* Clear the texture, if requested. Always set the associated state, for
* consistency. */
glClearColor ( 0 , 0 , 0 , 0 ) ;
SetZWrite ( true ) ;
2006-08-15 00:39:41 +00:00
/* If bPreserveTexture is false, clear the render target. Only clear the depth
* buffer if the target has one; otherwise we're clearing the real depth buffer. */
2006-07-26 03:44:27 +00:00
if ( ! bPreserveTexture )
2006-08-15 00:39:41 +00:00
{
int iBit = GL_COLOR_BUFFER_BIT ;
if ( pTarget - > GetParam ( ) . bWithDepthBuffer )
iBit | = GL_DEPTH_BUFFER_BIT ;
glClear ( iBit ) ;
}
2006-07-26 03:44:27 +00:00
}
2004-06-19 21:00:38 +00:00
void RageDisplay_OGL : : SetPolygonMode ( PolygonMode pm )
{
GLenum m ;
switch ( pm )
{
case POLYGON_FILL : m = GL_FILL ; break ;
case POLYGON_LINE : m = GL_LINE ; break ;
2006-02-01 07:52:33 +00:00
default : ASSERT ( 0 ) ; return ;
2004-06-19 21:00:38 +00:00
}
glPolygonMode ( GL_FRONT_AND_BACK , m ) ;
}
2004-06-20 01:26:28 +00:00
void RageDisplay_OGL : : SetLineWidth ( float fWidth )
2004-06-19 21:00:38 +00:00
{
2004-06-20 01:26:28 +00:00
glLineWidth ( fWidth ) ;
2004-06-19 21:00:38 +00:00
}
2007-05-06 02:43:05 +00:00
RString RageDisplay_OGL : : GetTextureDiagnostics ( unsigned iTexture ) const
2003-06-22 01:53:04 +00:00
{
2007-05-06 02:43:05 +00:00
/*
s << (bGenerateMipMaps? "gluBuild2DMipmaps":"glTexImage2D");
s << "(format " << GLToString(glTexFormat) <<
", " << pImg->w << "x" << pImg->h <<
", format " << GLToString(iFormat) <<
", type " << GLToString(glImageType) <<
", pixfmt " << pixfmt <<
", imgpixfmt " << SurfacePixFmt <<
")";
LOG->Trace( "%s", s.str().c_str() );
glBindTexture( GL_TEXTURE_2D, iTexture );
GLint iWidth;
glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GLenum(GL_TEXTURE_WIDTH), (GLint *) &iWidth );
GLint iHeight;
glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GLenum(GL_TEXTURE_HEIGHT), (GLint *) &iHeight );
GLint iFormat;
glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GLenum(GL_TEXTURE_INTERNAL_FORMAT), (GLint *) &iFormat );
GL_CHECK_ERROR( "glGetTexLevelParameteriv(GL_TEXTURE_INTERNAL_FORMAT)" );
if( iFormat != glTexFormat )
{
sError = ssprintf( "Expected format %s, got %s instead",
GLToString(glTexFormat).c_str(), GLToString(iFormat).c_str() );
break;
}
*/
2006-01-22 01:00:06 +00:00
return RString ( ) ;
2003-06-22 01:53:04 +00:00
}
2003-05-26 19:42:04 +00:00
void RageDisplay_OGL : : SetAlphaTest ( bool b )
2003-05-22 05:28:37 +00:00
{
glAlphaFunc ( GL_GREATER , 0.01f ) ;
if ( b )
glEnable ( GL_ALPHA_TEST ) ;
else
glDisable ( GL_ALPHA_TEST ) ;
}
2003-05-25 00:43:44 +00:00
2003-09-21 18:07:29 +00:00
2003-07-09 03:16:28 +00:00
/*
* Although we pair texture formats (eg. GL_RGB8) and surface formats
* (pairs of eg. GL_RGB8,GL_UNSIGNED_SHORT_5_5_5_1), it's possible for
* a format to be supported for a texture format but not a surface
* format. This is abstracted, so you don't need to know about this
* as a user calling CreateTexture.
*
* One case of this is if packed pixels aren't supported. We can still
* use 16-bit color modes, but we have to send it in 32-bit. Almost
* everything supports packed pixels.
*
* Another case of this is incomplete packed pixels support. Some implementations
* neglect GL_UNSIGNED_SHORT_*_REV.
*/
bool RageDisplay_OGL : : SupportsSurfaceFormat ( PixelFormat pixfmt )
{
2005-09-29 17:15:12 +00:00
switch ( g_GLPixFmtInfo [ pixfmt ] . type )
2003-07-09 03:16:28 +00:00
{
case GL_UNSIGNED_SHORT_1_5_5_5_REV :
2005-01-30 19:50:55 +00:00
return GLExt . m_bGL_EXT_bgra & & g_bReversePackedPixelsWorks ;
2003-07-09 03:16:28 +00:00
default :
return true ;
}
}
2003-11-29 17:56:09 +00:00
2005-10-19 23:52:16 +00:00
bool RageDisplay_OGL : : SupportsTextureFormat ( PixelFormat pixfmt , bool bRealtime )
2003-11-29 17:56:09 +00:00
{
/* If we support a pixfmt for texture formats but not for surface formats, then
* we'll have to convert the texture to a supported surface format before uploading.
* This is too slow for dynamic textures. */
2005-10-19 23:52:16 +00:00
if ( bRealtime & & ! SupportsSurfaceFormat ( pixfmt ) )
2003-11-29 17:56:09 +00:00
return false ;
2005-09-29 17:15:12 +00:00
switch ( g_GLPixFmtInfo [ pixfmt ] . format )
2003-11-29 17:56:09 +00:00
{
case GL_COLOR_INDEX :
2004-05-24 03:41:49 +00:00
return GLExt . glColorTableEXT & & GLExt . glGetColorTableParameterivEXT ;
2003-11-29 17:56:09 +00:00
case GL_BGR :
case GL_BGRA :
2005-01-30 19:50:55 +00:00
return GLExt . m_bGL_EXT_bgra ;
2003-11-29 17:56:09 +00:00
default :
return true ;
}
}
2004-01-06 19:54:13 +00:00
2005-10-21 06:36:08 +00:00
bool RageDisplay_OGL : : SupportsPerVertexMatrixScale ( )
{
2006-02-22 21:22:33 +00:00
// Intel i915 on OSX 10.4.4 supports vertex programs but not hardware vertex buffers.
// Our software vertex rendering doesn't support vertex programs.
return GLExt . glGenBuffersARB & & g_bTextureMatrixShader ! = 0 ;
2005-10-21 06:36:08 +00:00
}
2007-02-13 06:04:30 +00:00
void RageDisplay_OGL : : SetSphereEnvironmentMapping ( TextureUnit tu , bool b )
2004-01-06 19:54:13 +00:00
{
2007-02-13 06:04:30 +00:00
if ( ! SetTextureUnit ( tu ) )
return ;
2004-01-06 19:54:13 +00:00
if ( b )
{
2005-11-13 18:22:52 +00:00
glTexGeni ( GL_S , GL_TEXTURE_GEN_MODE , GL_SPHERE_MAP ) ;
glTexGeni ( GL_T , GL_TEXTURE_GEN_MODE , GL_SPHERE_MAP ) ;
glEnable ( GL_TEXTURE_GEN_S ) ;
glEnable ( GL_TEXTURE_GEN_T ) ;
2004-01-06 19:54:13 +00:00
}
else
{
2005-11-13 18:22:52 +00:00
glDisable ( GL_TEXTURE_GEN_S ) ;
glDisable ( GL_TEXTURE_GEN_T ) ;
2004-01-06 19:54:13 +00:00
}
}
2004-05-06 00:42:06 +00:00
/*
* Copyright (c) 2001-2004 Chris Danford, Glenn Maynard
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/