2003-05-22 05:28:37 +00:00
|
|
|
#include "global.h"
|
|
|
|
|
|
2004-06-14 05:54:01 +00:00
|
|
|
/* ours may be more up-to-date */
|
|
|
|
|
#define __glext_h_
|
2003-05-22 05:28:37 +00:00
|
|
|
|
2004-06-14 05:54:01 +00:00
|
|
|
#if defined(WIN32)
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-10-24 10:37:56 +00:00
|
|
|
#if !defined(MACOSX)
|
2004-06-14 11:14:16 +00:00
|
|
|
# include <GL/gl.h>
|
|
|
|
|
# include <GL/glu.h>
|
|
|
|
|
#else
|
|
|
|
|
# include <OpenGL/gl.h>
|
|
|
|
|
# include <OpenGL/glu.h>
|
|
|
|
|
#endif
|
2003-05-22 05:28:37 +00:00
|
|
|
|
2004-06-14 05:54:01 +00:00
|
|
|
#undef __glext_h_
|
2003-05-22 05:28:37 +00:00
|
|
|
#include "glext.h"
|
|
|
|
|
|
2004-06-14 00:51:00 +00:00
|
|
|
#include "RageSurface.h"
|
|
|
|
|
#include "RageSurfaceUtils.h"
|
2004-02-17 08:47:27 +00:00
|
|
|
#include "PrefsManager.h" // XXX
|
2004-09-21 06:07:12 +00:00
|
|
|
#include "ScreenDimensions.h" // XXX
|
2003-12-21 02:06:40 +00:00
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
/* Windows's broken gl.h defines GL_EXT_paletted_texture incompletely: */
|
|
|
|
|
#ifndef GL_TEXTURE_INDEX_SIZE_EXT
|
|
|
|
|
#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED
|
|
|
|
|
#endif
|
|
|
|
|
#include <set>
|
2003-08-03 05:40:40 +00:00
|
|
|
#include <sstream>
|
2003-05-22 05:28:37 +00:00
|
|
|
|
2005-10-24 10:37:56 +00:00
|
|
|
#if defined(MACOSX)
|
2003-09-22 11:14:31 +00:00
|
|
|
#include "archutils/Darwin/Vsync.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
#include "RageDisplay.h"
|
2003-05-26 19:42:04 +00:00
|
|
|
#include "RageDisplay_OGL.h"
|
2005-01-30 19:50:55 +00:00
|
|
|
#include "RageDisplay_OGL_Extensions.h"
|
2003-05-22 05:28:37 +00:00
|
|
|
#include "RageUtil.h"
|
|
|
|
|
#include "RageLog.h"
|
|
|
|
|
#include "RageTimer.h"
|
|
|
|
|
#include "RageException.h"
|
|
|
|
|
#include "RageTexture.h"
|
|
|
|
|
#include "RageTextureManager.h"
|
|
|
|
|
#include "RageMath.h"
|
|
|
|
|
#include "RageTypes.h"
|
|
|
|
|
#include "RageUtil.h"
|
2005-10-28 03:10:48 +00:00
|
|
|
#include "ProductInfo.h"
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
#include "arch/LowLevelWindow/LowLevelWindow.h"
|
|
|
|
|
|
2005-03-15 00:30:26 +00:00
|
|
|
#include "arch/arch.h"
|
|
|
|
|
|
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: */
|
|
|
|
|
float g_line_range[2];
|
|
|
|
|
float g_point_range[2];
|
|
|
|
|
|
|
|
|
|
/* OpenGL version * 10: */
|
|
|
|
|
int g_glVersion;
|
|
|
|
|
|
2004-01-24 19:14:22 +00:00
|
|
|
/* GLU version * 10: */
|
|
|
|
|
int g_gluVersion;
|
|
|
|
|
|
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. */
|
2003-07-07 01:29:18 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
LowLevelWindow *wind;
|
|
|
|
|
|
2004-04-16 21:34:58 +00:00
|
|
|
static void InvalidateAllGeometry();
|
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 }
|
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 },
|
|
|
|
|
}, {
|
2003-06-28 01:45:44 +00:00
|
|
|
/* R5G5B5 */
|
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
|
|
|
}, {
|
|
|
|
|
/* B8G8R8A8 */
|
|
|
|
|
24,
|
|
|
|
|
{ 0x0000FF,
|
|
|
|
|
0x00FF00,
|
|
|
|
|
0xFF0000,
|
|
|
|
|
0x000000 }
|
2003-05-30 20:16:30 +00:00
|
|
|
}, {
|
2003-06-30 03:13:53 +00:00
|
|
|
/* A1B5G5R5 */
|
|
|
|
|
16,
|
|
|
|
|
{ 0x7C00,
|
|
|
|
|
0x03E0,
|
|
|
|
|
0x001F,
|
|
|
|
|
0x8000 },
|
2003-05-30 20:16:30 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2003-07-03 02:42:44 +00:00
|
|
|
static map<GLenum, CString> g_Strings;
|
|
|
|
|
static void InitStringMap()
|
|
|
|
|
{
|
|
|
|
|
static bool Initialized = false;
|
|
|
|
|
if(Initialized) return;
|
|
|
|
|
Initialized = true;
|
|
|
|
|
#define X(a) g_Strings[a] = #a;
|
|
|
|
|
X(GL_RGBA8); X(GL_RGBA4); X(GL_RGB5_A1); X(GL_RGB5); X(GL_RGBA); X(GL_RGB);
|
|
|
|
|
X(GL_BGR); X(GL_BGRA);
|
2003-10-09 06:33:11 +00:00
|
|
|
X(GL_COLOR_INDEX8_EXT); X(GL_COLOR_INDEX4_EXT); X(GL_COLOR_INDEX);
|
2003-07-03 02:42:44 +00:00
|
|
|
X(GL_UNSIGNED_BYTE); X(GL_UNSIGNED_SHORT_4_4_4_4); X(GL_UNSIGNED_SHORT_5_5_5_1);
|
|
|
|
|
X(GL_UNSIGNED_SHORT_1_5_5_5_REV);
|
2003-07-07 22:56:02 +00:00
|
|
|
X(GL_INVALID_ENUM); X(GL_INVALID_VALUE); X(GL_INVALID_OPERATION);
|
|
|
|
|
X(GL_STACK_OVERFLOW); X(GL_STACK_UNDERFLOW); X(GL_OUT_OF_MEMORY);
|
2003-07-03 02:42:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static CString GLToString( GLenum e )
|
|
|
|
|
{
|
|
|
|
|
if( g_Strings.find(e) != g_Strings.end() )
|
|
|
|
|
return g_Strings[e];
|
|
|
|
|
|
2003-12-24 20:32:20 +00:00
|
|
|
return ssprintf( "%i", int(e) );
|
2003-07-03 02:42:44 +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,
|
|
|
|
|
}, {
|
|
|
|
|
/* 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,
|
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)
|
2003-06-11 01:19:02 +00:00
|
|
|
static bool Initialized = false;
|
|
|
|
|
if( Initialized )
|
|
|
|
|
return;
|
|
|
|
|
Initialized = true;
|
|
|
|
|
|
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
|
|
|
|
2003-06-12 19:40:44 +00:00
|
|
|
static void FlushGLErrors()
|
|
|
|
|
{
|
|
|
|
|
/* 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. */
|
|
|
|
|
while( glGetError() != GL_NO_ERROR )
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-16 21:34:58 +00:00
|
|
|
#define AssertNoGLError() \
|
|
|
|
|
{ \
|
|
|
|
|
GLenum error = glGetError(); \
|
|
|
|
|
ASSERT_M( error == GL_NO_ERROR, GLToString(error) ) \
|
2004-04-12 03:07:44 +00:00
|
|
|
}
|
|
|
|
|
|
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-06-14 23:59:14 +00:00
|
|
|
#if defined(UNIX)
|
2003-11-13 18:02:00 +00:00
|
|
|
#define Font X11___Font
|
|
|
|
|
#define Screen X11___Screen
|
|
|
|
|
#include "GL/glx.h"
|
|
|
|
|
#undef Font
|
|
|
|
|
#undef Screen
|
|
|
|
|
|
2004-06-14 05:48:28 +00:00
|
|
|
Display *g_X11Display = NULL;
|
2003-12-24 06:23:59 +00:00
|
|
|
#endif
|
|
|
|
|
|
2003-11-13 18:02:00 +00:00
|
|
|
static void LogGLXDebugInformation()
|
|
|
|
|
{
|
2004-06-14 23:59:14 +00:00
|
|
|
#if defined(UNIX)
|
2003-12-24 06:23:59 +00:00
|
|
|
ASSERT( g_X11Display );
|
2003-11-13 18:02:00 +00:00
|
|
|
|
2003-12-24 06:23:59 +00:00
|
|
|
const int scr = DefaultScreen( g_X11Display );
|
2003-11-13 18:02:00 +00:00
|
|
|
|
2004-05-23 22:32:10 +00:00
|
|
|
LOG->Info( "Display: %s (screen %i)", DisplayString(g_X11Display), scr );
|
2003-12-24 06:23:59 +00:00
|
|
|
LOG->Info( "Direct rendering: %s", glXIsDirect( g_X11Display, glXGetCurrentContext() )? "yes":"no" );
|
2004-03-06 02:47:31 +00:00
|
|
|
|
|
|
|
|
int XServerVersion = XVendorRelease( g_X11Display ); /* eg. 40201001 */
|
|
|
|
|
int major = XServerVersion / 10000000; XServerVersion %= 10000000;
|
|
|
|
|
int minor = XServerVersion / 100000; XServerVersion %= 100000;
|
|
|
|
|
int revision = XServerVersion / 1000; XServerVersion %= 1000;
|
|
|
|
|
int patch = XServerVersion;
|
|
|
|
|
|
2004-05-23 22:32:10 +00:00
|
|
|
LOG->Info( "X server vendor: %s [%i.%i.%i.%i]", XServerVendor( g_X11Display ), major, minor, revision, patch );
|
|
|
|
|
LOG->Info( "Server GLX vendor: %s [%s]", glXQueryServerString( g_X11Display, scr, GLX_VENDOR ), glXQueryServerString( g_X11Display, scr, GLX_VERSION ) );
|
|
|
|
|
LOG->Info( "Client GLX vendor: %s [%s]", glXGetClientString( g_X11Display, GLX_VENDOR ), glXGetClientString( g_X11Display, GLX_VERSION ) );
|
2003-11-13 18:02:00 +00:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
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();
|
2003-07-03 02:42:44 +00:00
|
|
|
InitStringMap();
|
2003-06-11 01:19:02 +00:00
|
|
|
|
2004-11-30 22:21:50 +00:00
|
|
|
wind = NULL;
|
2005-05-06 14:41:46 +00:00
|
|
|
g_bTextureMatrixShader = 0;
|
2004-11-30 22:21:50 +00:00
|
|
|
}
|
|
|
|
|
|
2005-02-01 03:04:32 +00:00
|
|
|
CString GetInfoLog( GLhandleARB h )
|
|
|
|
|
{
|
|
|
|
|
GLint iLength;
|
|
|
|
|
GLExt.glGetObjectParameterivARB( h, GL_OBJECT_INFO_LOG_LENGTH_ARB, &iLength );
|
|
|
|
|
if( !iLength )
|
2005-09-04 16:55:21 +00:00
|
|
|
return CString();
|
2005-02-01 03:04:32 +00:00
|
|
|
|
|
|
|
|
GLcharARB *pInfoLog = new GLcharARB[iLength];
|
|
|
|
|
GLExt.glGetInfoLogARB( h, iLength, &iLength, pInfoLog );
|
|
|
|
|
CString sRet = pInfoLog;
|
|
|
|
|
delete [] pInfoLog;
|
|
|
|
|
return sRet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GLhandleARB CompileShader( GLenum ShaderType, CString sBuffer )
|
|
|
|
|
{
|
|
|
|
|
GLhandleARB VertexShader = GLExt.glCreateShaderObjectARB( GL_VERTEX_SHADER_ARB );
|
|
|
|
|
const GLcharARB *pData = sBuffer.data();
|
|
|
|
|
int iLength = sBuffer.size();
|
2005-03-23 21:04:40 +00:00
|
|
|
GLExt.glShaderSourceARB( VertexShader, 1, &pData, (GLint*)&iLength );
|
2005-02-01 03:04:32 +00:00
|
|
|
|
|
|
|
|
GLExt.glCompileShaderARB( VertexShader );
|
|
|
|
|
|
|
|
|
|
GLint bCompileStatus = GL_FALSE;
|
|
|
|
|
GLExt.glGetObjectParameterivARB( VertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &bCompileStatus );
|
|
|
|
|
|
|
|
|
|
if( !bCompileStatus )
|
|
|
|
|
{
|
|
|
|
|
LOG->Trace( "Compile failure: %s", GetInfoLog( VertexShader ).c_str() );
|
2005-02-11 04:06:52 +00:00
|
|
|
return 0;
|
2005-02-01 03:04:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return VertexShader;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
ATTRIB_TEXTURE_MATRIX_SCALE = 1
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* XXX: How should we include these? Doing them like this is ugly. Linking them in
|
|
|
|
|
* from another file as a text symbol would be ideal, but that's completely different
|
|
|
|
|
* on each platform, so it'd be a maintenance nightmare. Reading them from a file would
|
|
|
|
|
* be annoying, too. */
|
|
|
|
|
const GLcharARB *g_TextureMatrixScaleShader =
|
|
|
|
|
" \
|
|
|
|
|
attribute vec4 TextureMatrixScale; \
|
|
|
|
|
void main( void ) \
|
|
|
|
|
{ \
|
|
|
|
|
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \
|
|
|
|
|
vec4 multiplied_tex_coord = gl_TextureMatrix[0] * gl_MultiTexCoord0; \
|
|
|
|
|
gl_TexCoord[0] = (multiplied_tex_coord * TextureMatrixScale) + \
|
2005-02-05 06:43:35 +00:00
|
|
|
(gl_MultiTexCoord0 * (vec4(1)-TextureMatrixScale)); \
|
2005-02-01 03:04:32 +00:00
|
|
|
gl_FrontColor = gl_Color; \
|
|
|
|
|
} \
|
|
|
|
|
";
|
|
|
|
|
|
|
|
|
|
void InitScalingScript()
|
|
|
|
|
{
|
2005-02-11 04:06:52 +00:00
|
|
|
g_bTextureMatrixShader = 0;
|
2005-02-01 03:04:32 +00:00
|
|
|
|
|
|
|
|
if( !GLExt.m_bGL_ARB_shader_objects ||
|
|
|
|
|
!GLExt.m_bGL_ARB_vertex_shader ||
|
|
|
|
|
!GLExt.m_bGL_ARB_shading_language_100 )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
GLhandleARB VertexShader = CompileShader( GL_VERTEX_SHADER_ARB, g_TextureMatrixScaleShader );
|
2005-02-11 04:06:52 +00:00
|
|
|
if( VertexShader == 0 )
|
2005-02-01 03:04:32 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
g_bTextureMatrixShader = GLExt.glCreateProgramObjectARB();
|
|
|
|
|
GLExt.glAttachObjectARB( g_bTextureMatrixShader, VertexShader );
|
|
|
|
|
GLExt.glDeleteObjectARB( VertexShader );
|
|
|
|
|
|
|
|
|
|
// Bind attributes.
|
|
|
|
|
GLExt.glBindAttribLocationARB( g_bTextureMatrixShader, ATTRIB_TEXTURE_MATRIX_SCALE, "TextureMatrixScale" );
|
|
|
|
|
|
|
|
|
|
// Link the program.
|
|
|
|
|
GLExt.glLinkProgramARB( g_bTextureMatrixShader );
|
|
|
|
|
GLint bLinkStatus = false;
|
|
|
|
|
GLExt.glGetObjectParameterivARB( g_bTextureMatrixShader, GL_OBJECT_LINK_STATUS_ARB, &bLinkStatus );
|
|
|
|
|
|
|
|
|
|
if( !bLinkStatus )
|
|
|
|
|
{
|
|
|
|
|
LOG->Trace( "Scaling shader link failed: %s", GetInfoLog(g_bTextureMatrixShader).c_str() );
|
|
|
|
|
GLExt.glDeleteObjectARB( g_bTextureMatrixShader );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GLExt.glVertexAttrib2fARB( ATTRIB_TEXTURE_MATRIX_SCALE, 1, 1 );
|
|
|
|
|
}
|
|
|
|
|
|
2004-11-30 22:21:50 +00:00
|
|
|
CString RageDisplay_OGL::Init( VideoModeParams p, bool bAllowUnacceleratedRenderer )
|
|
|
|
|
{
|
2003-05-22 05:28:37 +00:00
|
|
|
wind = MakeLowLevelWindow();
|
|
|
|
|
|
2004-11-30 20:01:07 +00:00
|
|
|
bool bIgnore = false;
|
|
|
|
|
CString sError = SetVideoMode( p, bIgnore );
|
|
|
|
|
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( "OGL Extensions: %s", glGetString(GL_EXTENSIONS) );
|
|
|
|
|
LOG->Info( "GLU Version: %s", gluGetString(GLU_VERSION) );
|
2003-06-25 20:44:49 +00:00
|
|
|
|
2003-11-13 18:02:00 +00:00
|
|
|
LogGLXDebugInformation();
|
|
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
if( IsSoftwareRenderer() )
|
2003-06-25 20:44:49 +00:00
|
|
|
{
|
|
|
|
|
if( !bAllowUnacceleratedRenderer )
|
2004-11-30 22:21:50 +00:00
|
|
|
return
|
2003-06-25 20:44:49 +00:00
|
|
|
"Your system is reporting that OpenGL hardware acceleration is not available. "
|
2004-11-30 22:21:50 +00:00
|
|
|
"Please obtain an updated driver from your video card manufacturer.\n\n";
|
2003-05-22 05:28:37 +00:00
|
|
|
LOG->Warn("This is a software renderer!");
|
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 ) )
|
2005-10-28 03:10:48 +00:00
|
|
|
return "GLDirect was detected. GLDirect is not compatible with " PRODUCT_NAME ", and should be disabled.\n";
|
2004-04-03 00:09:16 +00:00
|
|
|
#endif
|
|
|
|
|
|
2004-06-14 23:59:14 +00:00
|
|
|
#if defined(UNIX)
|
2003-12-24 06:23:59 +00:00
|
|
|
if( !glXIsDirect( g_X11Display, glXGetCurrentContext() ) )
|
|
|
|
|
{
|
|
|
|
|
if( !bAllowUnacceleratedRenderer )
|
2004-11-30 22:21:50 +00:00
|
|
|
return "Your system is reporting that direct rendering is not available. "
|
2004-12-01 01:09:20 +00:00
|
|
|
"Please obtain an updated driver from your video card manufacturer.";
|
2004-11-30 22:21:50 +00:00
|
|
|
|
2003-12-24 06:23:59 +00:00
|
|
|
LOG->Warn("Direct rendering is not enabled!");
|
|
|
|
|
}
|
|
|
|
|
#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: */
|
|
|
|
|
glGetFloatv(GL_LINE_WIDTH_RANGE, g_line_range);
|
|
|
|
|
glGetFloatv(GL_POINT_SIZE_RANGE, g_point_range);
|
2004-11-30 22:21:50 +00:00
|
|
|
|
2005-02-01 03:04:32 +00:00
|
|
|
InitScalingScript();
|
|
|
|
|
|
2005-09-04 16:55:21 +00:00
|
|
|
return CString();
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
2004-06-14 23:59:14 +00:00
|
|
|
#if defined(UNIX) && defined(HAVE_LIBXTST)
|
2004-03-15 02:29:53 +00:00
|
|
|
#include <X11/extensions/XTest.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
bool RageDisplay_OGL::IsSoftwareRenderer()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-12-24 06:23:59 +00:00
|
|
|
#if defined(WIN32)
|
2003-05-22 05:28:37 +00:00
|
|
|
return
|
|
|
|
|
( strcmp((const char*)glGetString(GL_VENDOR),"Microsoft Corporation")==0 ) &&
|
|
|
|
|
( strcmp((const char*)glGetString(GL_RENDERER),"GDI Generic")==0 );
|
2003-12-24 06:23:59 +00:00
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
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
|
|
|
{
|
|
|
|
|
delete wind;
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-15 08:18:37 +00:00
|
|
|
static void CheckPalettedTextures()
|
2003-05-30 20:16:30 +00:00
|
|
|
{
|
2004-03-13 06:42:07 +00:00
|
|
|
CString error;
|
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
|
|
|
{
|
|
|
|
|
error = "GL_EXT_paletted_texture missing";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-24 03:41:49 +00:00
|
|
|
if( GLExt.glColorTableEXT == NULL )
|
2004-03-13 07:38:46 +00:00
|
|
|
{
|
|
|
|
|
error = "glColorTableEXT missing";
|
|
|
|
|
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
|
|
|
{
|
|
|
|
|
error = "glGetColorTableParameterivEXT missing";
|
|
|
|
|
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
|
|
|
|
2004-03-13 07:38:46 +00:00
|
|
|
int bits = 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 ) { \
|
|
|
|
|
error = ssprintf(f " failed (%s)", GLToString(glError).c_str() ); \
|
|
|
|
|
break; \
|
|
|
|
|
} \
|
|
|
|
|
}
|
2003-11-13 18:04:31 +00:00
|
|
|
|
2004-03-13 07:38:46 +00:00
|
|
|
glTexImage2D(GL_PROXY_TEXTURE_2D,
|
2003-05-30 20:16:30 +00:00
|
|
|
0, glTexFormat,
|
|
|
|
|
16, 16, 0,
|
|
|
|
|
glImageFormat, glImageType, NULL);
|
2004-03-13 07:38:46 +00:00
|
|
|
GL_CHECK_ERROR( "glTexImage2D" );
|
2003-05-30 20:16:30 +00:00
|
|
|
|
2003-10-09 06:33:11 +00:00
|
|
|
GLuint ifmt = 0;
|
|
|
|
|
glGetTexLevelParameteriv( GL_PROXY_TEXTURE_2D, 0, GLenum(GL_TEXTURE_INTERNAL_FORMAT), (GLint *)&ifmt );
|
2004-04-03 21:33:10 +00:00
|
|
|
GL_CHECK_ERROR( "glGetTexLevelParameteriv(GL_TEXTURE_INTERNAL_FORMAT)" );
|
2003-10-09 06:33:11 +00:00
|
|
|
if( ifmt != glTexFormat )
|
|
|
|
|
{
|
|
|
|
|
error = ssprintf( "Expected format %s, got %s instead",
|
2004-03-13 07:38:46 +00:00
|
|
|
GLToString(glTexFormat).c_str(),
|
|
|
|
|
GLToString(ifmt).c_str() );
|
|
|
|
|
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
|
|
|
|
2003-05-30 23:15:53 +00:00
|
|
|
GLint size = 0;
|
|
|
|
|
glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GLenum(GL_TEXTURE_INDEX_SIZE_EXT), &size);
|
2004-03-13 06:42:07 +00:00
|
|
|
GL_CHECK_ERROR( "glGetTexLevelParameteriv(GL_TEXTURE_INDEX_SIZE_EXT)" );
|
2003-10-09 06:33:11 +00:00
|
|
|
if( bits > size || size > 8 )
|
2003-05-30 23:15:53 +00:00
|
|
|
{
|
2003-12-24 20:32:20 +00:00
|
|
|
error = ssprintf("Expected %i-bit palette, got a %i-bit one instead", bits, int(size));
|
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
|
|
|
|
|
|
|
|
GLint RealWidth = 0;
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glGetColorTableParameterivEXT(GL_PROXY_TEXTURE_2D, GL_COLOR_TABLE_WIDTH, &RealWidth);
|
2003-11-14 00:07:47 +00:00
|
|
|
GL_CHECK_ERROR( "glGetColorTableParameterivEXT(GL_COLOR_TABLE_WIDTH)" );
|
2003-11-13 18:04:31 +00:00
|
|
|
if( RealWidth != 1 << bits )
|
|
|
|
|
{
|
2003-12-24 20:32:20 +00:00
|
|
|
error = ssprintf("GL_COLOR_TABLE_WIDTH returned %i instead of %i", int(RealWidth), 1 << bits );
|
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
|
|
|
|
2003-11-13 18:04:31 +00:00
|
|
|
GLint RealFormat = 0;
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glGetColorTableParameterivEXT(GL_PROXY_TEXTURE_2D, GL_COLOR_TABLE_FORMAT, &RealFormat);
|
2003-11-13 18:04:31 +00:00
|
|
|
GL_CHECK_ERROR( "glGetColorTableParameterivEXT(GL_COLOR_TABLE_FORMAT)" );
|
|
|
|
|
if( RealFormat != GL_RGBA8 )
|
|
|
|
|
{
|
|
|
|
|
error = ssprintf("GL_COLOR_TABLE_FORMAT returned %s instead of GL_RGBA8", GLToString(RealFormat).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
|
|
|
|
2004-03-13 07:38:46 +00:00
|
|
|
if( error == "" )
|
|
|
|
|
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;
|
2004-05-15 08:18:37 +00:00
|
|
|
LOG->Info("Paletted textures disabled: %s.", error.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();
|
|
|
|
|
glTexImage2D(GL_PROXY_TEXTURE_2D,
|
|
|
|
|
0, GL_RGBA,
|
|
|
|
|
16, 16, 0,
|
2003-07-09 04:18:01 +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 )
|
|
|
|
|
g_bReversePackedPixelsWorks = true;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
g_bReversePackedPixelsWorks = false;
|
|
|
|
|
LOG->Info("GL_UNSIGNED_SHORT_1_5_5_5_REV failed (%s), disabled",
|
|
|
|
|
GLToString(glError).c_str() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
void SetupExtensions()
|
|
|
|
|
{
|
2004-08-10 20:57:59 +00:00
|
|
|
const float fGLVersion = strtof( (const char *) glGetString(GL_VERSION), NULL );
|
2003-05-22 05:28:37 +00:00
|
|
|
g_glVersion = int(roundf(fGLVersion * 10));
|
|
|
|
|
|
2004-08-10 20:57:59 +00:00
|
|
|
const float fGLUVersion = strtof( (const char *) gluGetString(GLU_VERSION), NULL );
|
2004-01-24 19:14:22 +00:00
|
|
|
g_gluVersion = int(roundf(fGLUVersion * 10));
|
|
|
|
|
|
2005-01-30 19:50:55 +00:00
|
|
|
GLExt.Load( wind );
|
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
|
|
|
|
|
g_bColorIndexTableWorks = true;
|
|
|
|
|
}
|
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
|
|
|
{
|
2003-06-05 19:29:27 +00:00
|
|
|
SetViewport(0,0);
|
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();
|
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.
|
2003-08-27 23:36:09 +00:00
|
|
|
CString RageDisplay_OGL::TryVideoMode( VideoModeParams p, bool &bNewDeviceOut )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2003-05-26 19:42:04 +00:00
|
|
|
// LOG->Trace( "RageDisplay_OGL::SetVideoMode( %d, %d, %d, %d, %d, %d )", windowed, width, height, bpp, rate, vsync );
|
2003-08-28 00:08:01 +00:00
|
|
|
CString err;
|
|
|
|
|
err = wind->TryVideoMode( p, bNewDeviceOut );
|
|
|
|
|
if( err != "" )
|
|
|
|
|
return err; // failed to set video mode
|
2003-05-22 05:28:37 +00:00
|
|
|
|
2005-11-11 21:01:58 +00:00
|
|
|
/* Now that we've initialized, we can search for extensions. Do this before InvalidateAllGeometry,
|
|
|
|
|
* 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. */
|
|
|
|
|
if(TEXTUREMAN)
|
|
|
|
|
TEXTUREMAN->InvalidateTextures();
|
2004-04-16 21:34:58 +00:00
|
|
|
|
|
|
|
|
/* Recreate all vertex buffers. */
|
|
|
|
|
InvalidateAllGeometry();
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->SetDefaultRenderStates();
|
|
|
|
|
|
|
|
|
|
/* 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 )
|
|
|
|
|
GLExt.wglSwapIntervalEXT(p.vsync);
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
ResolutionChanged();
|
|
|
|
|
|
2005-09-04 16:55:21 +00:00
|
|
|
return CString(); // successfully set mode
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_OGL::SetViewport(int shift_left, int shift_down)
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
/* left and down are on a 0..SCREEN_WIDTH, 0..SCREEN_HEIGHT scale.
|
|
|
|
|
* Scale them to the actual viewport range. */
|
2005-11-11 21:16:48 +00:00
|
|
|
shift_left = int( shift_left * float(wind->GetActualVideoModeParams().width) / SCREEN_WIDTH );
|
|
|
|
|
shift_down = int( shift_down * float(wind->GetActualVideoModeParams().height) / SCREEN_HEIGHT );
|
2003-05-22 05:28:37 +00:00
|
|
|
|
2005-11-11 21:16:48 +00:00
|
|
|
glViewport(shift_left, -shift_down, wind->GetActualVideoModeParams().width, wind->GetActualVideoModeParams().height);
|
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;
|
|
|
|
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size);
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-19 01:38:12 +00:00
|
|
|
bool RageDisplay_OGL::BeginFrame()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
glClearColor( 0,0,0,1 );
|
2003-11-18 20:33:18 +00:00
|
|
|
SetZWrite( true );
|
2003-05-22 05:28:37 +00:00
|
|
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
2004-09-19 01:38:12 +00:00
|
|
|
return true;
|
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(), not glFinish(); NVIDIA_GLX's glFinish()'s behavior is
|
|
|
|
|
// nowhere near performance-friendly and uses unholy amounts of CPU for
|
|
|
|
|
// Gog-knows-what.
|
|
|
|
|
glFlush();
|
2005-03-17 01:21:13 +00:00
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
wind->SwapBuffers();
|
2005-07-13 00:01:46 +00:00
|
|
|
|
|
|
|
|
wind->Update();
|
|
|
|
|
|
|
|
|
|
if( PREFSMAN->m_bDisableScreenSaver )
|
|
|
|
|
{
|
|
|
|
|
/* Disable the screensaver. */
|
|
|
|
|
#if defined(UNIX) && defined(HAVE_LIBXTST)
|
|
|
|
|
ASSERT( g_X11Display );
|
|
|
|
|
|
|
|
|
|
/* This causes flicker. */
|
|
|
|
|
// XForceScreenSaver( g_X11Display, ScreenSaverReset );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Instead, send a null relative mouse motion, to trick X into thinking there has been
|
|
|
|
|
* user activity.
|
|
|
|
|
*
|
|
|
|
|
* This also handles XScreenSaver; XForceScreenSaver only handles the internal X11
|
|
|
|
|
* screen blanker.
|
|
|
|
|
*
|
|
|
|
|
* This will delay the X blanker, DPMS and XScreenSaver from activating, and will
|
|
|
|
|
* disable the blanker and XScreenSaver if they're already active (unless XSS is
|
|
|
|
|
* locked). For some reason, it doesn't un-blank DPMS if it's already active.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
XLockDisplay( g_X11Display );
|
|
|
|
|
|
|
|
|
|
int event_base, error_base, major, minor;
|
|
|
|
|
if( XTestQueryExtension( g_X11Display, &event_base, &error_base, &major, &minor ) )
|
|
|
|
|
{
|
|
|
|
|
XTestFakeRelativeMotionEvent( g_X11Display, 0, 0, 0 );
|
|
|
|
|
XSync( g_X11Display, False );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
XUnlockDisplay( g_X11Display );
|
|
|
|
|
#endif
|
|
|
|
|
}
|
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-11 21:16:48 +00:00
|
|
|
int width = wind->GetActualVideoModeParams().width;
|
|
|
|
|
int height = wind->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
|
|
|
|
2004-08-26 20:26:03 +00:00
|
|
|
FlushGLErrors();
|
2005-04-09 05:06:14 +00:00
|
|
|
|
|
|
|
|
glReadBuffer( GL_FRONT );
|
|
|
|
|
AssertNoGLError();
|
|
|
|
|
|
2005-11-11 21:16:48 +00:00
|
|
|
glReadPixels(0, 0, wind->GetActualVideoModeParams().width, wind->GetActualVideoModeParams().height, GL_RGBA,
|
2003-05-22 05:28:37 +00:00
|
|
|
GL_UNSIGNED_BYTE, image->pixels);
|
2004-08-09 07:32:49 +00:00
|
|
|
AssertNoGLError();
|
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
|
|
|
}
|
|
|
|
|
|
2005-11-11 21:16:48 +00:00
|
|
|
VideoModeParams RageDisplay_OGL::GetActualVideoModeParams() const
|
|
|
|
|
{
|
|
|
|
|
return wind->GetActualVideoModeParams();
|
|
|
|
|
}
|
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;
|
|
|
|
|
if(iNumVerts > Size)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(unsigned i = 0; i < unsigned(iNumVerts); ++i)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, Vertex);
|
|
|
|
|
|
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
2003-05-26 19:42:04 +00:00
|
|
|
glColorPointer(4, GL_UNSIGNED_BYTE, 0, Color);
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
|
glTexCoordPointer(2, GL_FLOAT, 0, Texture);
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
2003-05-27 08:39:35 +00:00
|
|
|
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() );
|
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
|
|
|
{
|
2004-04-16 05:09:02 +00:00
|
|
|
m_vPosition.resize( GetTotalVertices() );
|
|
|
|
|
m_vTexture.resize( GetTotalVertices() );
|
|
|
|
|
m_vNormal.resize( GetTotalVertices() );
|
2005-02-01 03:04:32 +00:00
|
|
|
m_vTexMatrixScale.resize( GetTotalVertices() );
|
2004-04-16 05:09:02 +00:00
|
|
|
m_vTriangles.resize( 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++ )
|
|
|
|
|
{
|
|
|
|
|
CString s;
|
|
|
|
|
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
|
|
|
};
|
|
|
|
|
|
2004-04-16 05:09:02 +00:00
|
|
|
class RageCompiledGeometryHWOGL : public RageCompiledGeometrySWOGL
|
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
|
|
|
static set<RageCompiledGeometryHWOGL *> g_GeometryList;
|
|
|
|
|
static void InvalidateAllGeometry()
|
|
|
|
|
{
|
2005-11-11 21:01:58 +00:00
|
|
|
FOREACHS( RageCompiledGeometryHWOGL*, g_GeometryList, it )
|
2004-04-16 21:34:58 +00:00
|
|
|
(*it)->Invalidate();
|
|
|
|
|
}
|
2004-04-12 03:07:44 +00:00
|
|
|
|
2004-04-16 21:34:58 +00:00
|
|
|
RageCompiledGeometryHWOGL::RageCompiledGeometryHWOGL()
|
|
|
|
|
{
|
|
|
|
|
g_GeometryList.insert( this );
|
2005-02-01 03:04:32 +00:00
|
|
|
m_nPositions = m_nTextureCoords = m_nNormals = m_nTriangles = 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()
|
|
|
|
|
{
|
|
|
|
|
g_GeometryList.erase( this );
|
|
|
|
|
FlushGLErrors();
|
2004-04-12 03:07:44 +00:00
|
|
|
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glDeleteBuffersARB( 1, &m_nPositions );
|
2004-04-16 21:34:58 +00:00
|
|
|
AssertNoGLError();
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glDeleteBuffersARB( 1, &m_nTextureCoords );
|
2004-04-16 21:34:58 +00:00
|
|
|
AssertNoGLError();
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glDeleteBuffersARB( 1, &m_nNormals );
|
2004-04-16 21:34:58 +00:00
|
|
|
AssertNoGLError();
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glDeleteBuffersARB( 1, &m_nTriangles );
|
2004-04-16 21:34:58 +00:00
|
|
|
AssertNoGLError();
|
2005-02-01 03:04:32 +00:00
|
|
|
GLExt.glDeleteBuffersARB( 1, &m_nTextureMatrixScale );
|
|
|
|
|
AssertNoGLError();
|
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()
|
|
|
|
|
{
|
|
|
|
|
FlushGLErrors();
|
|
|
|
|
|
|
|
|
|
if( !m_nPositions )
|
2004-04-12 03:07:44 +00:00
|
|
|
{
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glGenBuffersARB( 1, &m_nPositions );
|
2004-04-16 05:09:02 +00:00
|
|
|
AssertNoGLError();
|
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 );
|
2004-04-16 05:09:02 +00:00
|
|
|
AssertNoGLError();
|
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 );
|
2004-04-16 05:09:02 +00:00
|
|
|
AssertNoGLError();
|
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 );
|
2004-04-16 05:09:02 +00:00
|
|
|
AssertNoGLError();
|
2004-04-12 03:07:44 +00:00
|
|
|
}
|
2005-02-01 03:04:32 +00:00
|
|
|
|
|
|
|
|
if( !m_nTextureMatrixScale )
|
|
|
|
|
{
|
|
|
|
|
GLExt.glGenBuffersARB( 1, &m_nTextureMatrixScale );
|
|
|
|
|
AssertNoGLError();
|
|
|
|
|
}
|
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()
|
|
|
|
|
{
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nPositions );
|
|
|
|
|
GLExt.glBufferDataARB(
|
2004-04-16 21:34:58 +00:00
|
|
|
GL_ARRAY_BUFFER_ARB,
|
|
|
|
|
GetTotalVertices()*sizeof(RageVector3),
|
|
|
|
|
&m_vPosition[0],
|
|
|
|
|
GL_STATIC_DRAW_ARB );
|
2004-04-16 05:31:08 +00:00
|
|
|
// AssertNoGLError();
|
2004-04-16 05:09:02 +00:00
|
|
|
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nTextureCoords );
|
|
|
|
|
GLExt.glBufferDataARB(
|
2004-04-16 21:34:58 +00:00
|
|
|
GL_ARRAY_BUFFER_ARB,
|
|
|
|
|
GetTotalVertices()*sizeof(RageVector2),
|
|
|
|
|
&m_vTexture[0],
|
|
|
|
|
GL_STATIC_DRAW_ARB );
|
2004-04-16 05:31:08 +00:00
|
|
|
// AssertNoGLError();
|
2004-04-16 05:09:02 +00:00
|
|
|
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nNormals );
|
|
|
|
|
GLExt.glBufferDataARB(
|
2004-04-16 21:34:58 +00:00
|
|
|
GL_ARRAY_BUFFER_ARB,
|
|
|
|
|
GetTotalVertices()*sizeof(RageVector3),
|
|
|
|
|
&m_vNormal[0],
|
|
|
|
|
GL_STATIC_DRAW_ARB );
|
2004-04-16 05:31:08 +00:00
|
|
|
// AssertNoGLError();
|
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 );
|
|
|
|
|
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 );
|
2004-04-16 05:31:08 +00:00
|
|
|
// AssertNoGLError();
|
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 );
|
|
|
|
|
GLExt.glBufferDataARB(
|
|
|
|
|
GL_ARRAY_BUFFER_ARB,
|
|
|
|
|
GetTotalVertices()*sizeof(RageVector2),
|
|
|
|
|
&m_vTexMatrixScale[0],
|
|
|
|
|
GL_STATIC_DRAW_ARB );
|
|
|
|
|
}
|
2004-04-16 21:34:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RageCompiledGeometryHWOGL::Invalidate()
|
|
|
|
|
{
|
|
|
|
|
/* Our vertex buffers no longer exist. Reallocate and reupload. */
|
2005-02-01 03:04:32 +00:00
|
|
|
m_nPositions = m_nTextureCoords = m_nNormals = m_nTriangles = m_nTextureMatrixScale = 0;
|
2004-04-16 21:34:58 +00:00
|
|
|
AllocateBuffers();
|
|
|
|
|
UploadData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RageCompiledGeometryHWOGL::Allocate( const vector<msMesh> &vMeshes )
|
|
|
|
|
{
|
|
|
|
|
RageCompiledGeometrySWOGL::Allocate( vMeshes );
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nPositions );
|
|
|
|
|
GLExt.glBufferDataARB(
|
2004-04-16 21:34:58 +00:00
|
|
|
GL_ARRAY_BUFFER_ARB,
|
|
|
|
|
GetTotalVertices()*sizeof(RageVector3),
|
|
|
|
|
NULL,
|
|
|
|
|
GL_STATIC_DRAW_ARB );
|
|
|
|
|
AssertNoGLError();
|
|
|
|
|
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nTextureCoords );
|
|
|
|
|
GLExt.glBufferDataARB(
|
2004-04-16 21:34:58 +00:00
|
|
|
GL_ARRAY_BUFFER_ARB,
|
|
|
|
|
GetTotalVertices()*sizeof(RageVector2),
|
|
|
|
|
NULL,
|
|
|
|
|
GL_STATIC_DRAW_ARB );
|
|
|
|
|
AssertNoGLError();
|
|
|
|
|
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nNormals );
|
|
|
|
|
GLExt.glBufferDataARB(
|
2004-04-16 21:34:58 +00:00
|
|
|
GL_ARRAY_BUFFER_ARB,
|
|
|
|
|
GetTotalVertices()*sizeof(RageVector3),
|
|
|
|
|
NULL,
|
|
|
|
|
GL_STATIC_DRAW_ARB );
|
|
|
|
|
AssertNoGLError();
|
|
|
|
|
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, m_nTriangles );
|
|
|
|
|
GLExt.glBufferDataARB(
|
2004-04-16 21:34:58 +00:00
|
|
|
GL_ELEMENT_ARRAY_BUFFER_ARB,
|
|
|
|
|
GetTotalTriangles()*sizeof(msTriangle),
|
|
|
|
|
NULL,
|
|
|
|
|
GL_STATIC_DRAW_ARB );
|
|
|
|
|
AssertNoGLError();
|
2005-02-01 03:04:32 +00:00
|
|
|
|
|
|
|
|
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nTextureMatrixScale );
|
|
|
|
|
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
|
|
|
|
|
{
|
|
|
|
|
FlushGLErrors();
|
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);
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nPositions );
|
2004-04-16 21:34:58 +00:00
|
|
|
AssertNoGLError();
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, NULL );
|
|
|
|
|
AssertNoGLError();
|
2004-04-12 03:07:44 +00:00
|
|
|
|
2004-04-16 21:34:58 +00:00
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
|
|
|
|
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nTextureCoords );
|
2004-04-16 21:34:58 +00:00
|
|
|
AssertNoGLError();
|
|
|
|
|
glTexCoordPointer(2, GL_FLOAT, 0, NULL);
|
|
|
|
|
AssertNoGLError();
|
|
|
|
|
|
|
|
|
|
// TRICKY: Don't bind and send normals if lighting is disabled. This
|
|
|
|
|
// will save some effort transforming these values.
|
|
|
|
|
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);
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nNormals );
|
2004-04-16 21:34:58 +00:00
|
|
|
AssertNoGLError();
|
|
|
|
|
glNormalPointer(GL_FLOAT, 0, NULL);
|
|
|
|
|
AssertNoGLError();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
|
|
|
}
|
|
|
|
|
|
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. */
|
|
|
|
|
GLExt.glEnableVertexAttribArrayARB( ATTRIB_TEXTURE_MATRIX_SCALE );
|
|
|
|
|
AssertNoGLError();
|
|
|
|
|
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nTextureMatrixScale );
|
|
|
|
|
AssertNoGLError();
|
|
|
|
|
GLExt.glVertexAttribPointerARB( ATTRIB_TEXTURE_MATRIX_SCALE, 2, GL_FLOAT, false, 0, NULL );
|
|
|
|
|
AssertNoGLError();
|
|
|
|
|
|
|
|
|
|
GLExt.glUseProgramObjectARB( g_bTextureMatrixShader );
|
|
|
|
|
}
|
|
|
|
|
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++ )
|
|
|
|
|
{
|
|
|
|
|
CString s;
|
|
|
|
|
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 );
|
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 );
|
2004-04-16 21:34:58 +00:00
|
|
|
AssertNoGLError();
|
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)) );
|
|
|
|
|
AssertNoGLError();
|
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
|
|
|
{
|
|
|
|
|
GLExt.glDisableVertexAttribArrayARB( ATTRIB_TEXTURE_MATRIX_SCALE );
|
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 );
|
|
|
|
|
}
|
|
|
|
|
|
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();
|
|
|
|
|
|
2003-05-22 05:28:37 +00:00
|
|
|
glMatrixMode( GL_PROJECTION );
|
2003-09-21 02:36:28 +00:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2004-04-15 05:24:28 +00:00
|
|
|
void RageDisplay_OGL::DrawLineStripInternal( const RageSpriteVertex v[], int iNumVerts, float LineWidth )
|
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. */
|
|
|
|
|
RageDisplay::DrawLineStripInternal(v, iNumVerts, LineWidth );
|
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. */
|
|
|
|
|
glEnable(GL_LINE_SMOOTH);
|
|
|
|
|
|
|
|
|
|
/* Our line width is wrt the regular internal SCREEN_WIDTHxSCREEN_HEIGHT screen,
|
|
|
|
|
* but these width functions actually want raster sizes (that is, actual pixels).
|
|
|
|
|
* Scale the line width and point size by the average ratio of the scale. */
|
2005-11-11 21:16:48 +00:00
|
|
|
float WidthVal = float(wind->GetActualVideoModeParams().width) / SCREEN_WIDTH;
|
|
|
|
|
float HeightVal = float(wind->GetActualVideoModeParams().height) / SCREEN_HEIGHT;
|
2003-05-27 00:20:54 +00:00
|
|
|
LineWidth *= (WidthVal + HeightVal) / 2;
|
|
|
|
|
|
|
|
|
|
/* Clamp the width to the hardware max for both lines and points (whichever
|
|
|
|
|
* is more restrictive). */
|
|
|
|
|
LineWidth = clamp(LineWidth, g_line_range[0], g_line_range[1]);
|
|
|
|
|
LineWidth = clamp(LineWidth, g_point_range[0], g_point_range[1]);
|
|
|
|
|
|
|
|
|
|
/* 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? */
|
|
|
|
|
glLineWidth(LineWidth);
|
|
|
|
|
|
|
|
|
|
/* Draw the line loop: */
|
|
|
|
|
SetupVertices( v, iNumVerts );
|
|
|
|
|
glDrawArrays( GL_LINE_STRIP, 0, iNumVerts );
|
|
|
|
|
|
|
|
|
|
glDisable(GL_LINE_SMOOTH);
|
|
|
|
|
|
|
|
|
|
/* 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. */
|
|
|
|
|
glPointSize(LineWidth);
|
|
|
|
|
|
|
|
|
|
/* 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 );
|
|
|
|
|
|
|
|
|
|
if(mat.m[0][0] < 1e-5 && mat.m[1][1] < 1e-5)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
glEnable(GL_POINT_SMOOTH);
|
|
|
|
|
|
|
|
|
|
SetupVertices( v, iNumVerts );
|
|
|
|
|
glDrawArrays( GL_POINTS, 0, iNumVerts );
|
|
|
|
|
|
|
|
|
|
glDisable(GL_POINT_SMOOTH);
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-04 09:55:18 +00:00
|
|
|
void RageDisplay_OGL::ClearAllTextures()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2005-11-05 03:08:09 +00:00
|
|
|
FOREACH_ENUM2( TextureUnit, i )
|
2004-02-04 09:55:18 +00:00
|
|
|
SetTexture( i, NULL );
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
|
2005-11-05 03:08:09 +00:00
|
|
|
void RageDisplay_OGL::SetTexture( TextureUnit tu, RageTexture* pTexture )
|
2004-02-04 09:55:18 +00:00
|
|
|
{
|
2004-05-24 03:41:49 +00:00
|
|
|
if( GLExt.glActiveTextureARB == NULL )
|
2004-02-04 09:55:18 +00:00
|
|
|
{
|
|
|
|
|
// multitexture isn't supported. Ignore all textures except for 0.
|
2005-11-05 03:08:09 +00:00
|
|
|
if( tu != 0 )
|
2004-02-04 09:55:18 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-11-05 03:08:09 +00:00
|
|
|
switch( tu )
|
2004-02-04 09:55:18 +00:00
|
|
|
{
|
|
|
|
|
case 0:
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glActiveTextureARB(GL_TEXTURE0_ARB);
|
2004-02-04 09:55:18 +00:00
|
|
|
break;
|
|
|
|
|
case 1:
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glActiveTextureARB(GL_TEXTURE1_ARB);
|
2004-02-04 09:55:18 +00:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-07 01:29:18 +00:00
|
|
|
if( pTexture )
|
|
|
|
|
{
|
|
|
|
|
glEnable( GL_TEXTURE_2D );
|
|
|
|
|
glBindTexture( GL_TEXTURE_2D, pTexture->GetTexHandle() );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
glDisable( GL_TEXTURE_2D );
|
|
|
|
|
}
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_OGL::SetTextureModeModulate()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-08 22:14:08 +00:00
|
|
|
void RageDisplay_OGL::SetTextureModeGlow()
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2005-01-30 19:50:55 +00:00
|
|
|
if( !GLExt.m_bEXT_texture_env_combine )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
2005-01-08 22:14:08 +00:00
|
|
|
/* This is changing blend state, instead of texture state, which isn't
|
|
|
|
|
* great, but it's better than doing nothing. */
|
2003-05-22 05:28:37 +00:00
|
|
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
|
|
|
|
return;
|
|
|
|
|
}
|
2005-01-08 22:14: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);
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
2004-02-04 09:55:18 +00:00
|
|
|
|
|
|
|
|
void RageDisplay_OGL::SetTextureModeAdd()
|
|
|
|
|
{
|
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_OGL::SetTextureFiltering( bool b )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
switch( mode )
|
|
|
|
|
{
|
|
|
|
|
case BLEND_NORMAL:
|
|
|
|
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
|
|
|
|
break;
|
|
|
|
|
case BLEND_ADD:
|
2003-10-22 01:47:40 +00:00
|
|
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
2003-05-22 05:28:37 +00:00
|
|
|
break;
|
|
|
|
|
case BLEND_NO_EFFECT:
|
2003-11-18 20:33:18 +00:00
|
|
|
/* XXX: Would it be faster and have the same effect to say glDisable(GL_COLOR_WRITEMASK)? */
|
2003-05-22 05:28:37 +00:00
|
|
|
glBlendFunc( GL_ZERO, GL_ONE );
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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 );
|
2003-05-22 05:28:37 +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 )
|
|
|
|
|
{
|
|
|
|
|
case ZTEST_OFF: glDepthFunc( GL_ALWAYS ); break;
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_OGL::SetTextureWrapping( bool b )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
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 );
|
|
|
|
|
}
|
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 );
|
2003-06-27 02:11:13 +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};
|
2003-06-27 02:11:13 +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:
|
2003-05-22 05:28:37 +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];
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_OGL::DeleteTexture( unsigned uTexHandle )
|
2003-05-22 05:28:37 +00:00
|
|
|
{
|
|
|
|
|
unsigned int uTexID = uTexHandle;
|
2003-06-12 19:40:44 +00:00
|
|
|
|
|
|
|
|
FlushGLErrors();
|
2003-05-22 05:28:37 +00:00
|
|
|
glDeleteTextures(1,reinterpret_cast<GLuint*>(&uTexID));
|
|
|
|
|
|
2004-04-12 03:07:44 +00:00
|
|
|
AssertNoGLError();
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-09-29 17:15:12 +00:00
|
|
|
PixelFormat RageDisplay_OGL::GetImgPixelFormat( RageSurface* &img, bool &FreeImg, 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;
|
|
|
|
|
|
2005-10-02 03:35:56 +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);
|
|
|
|
|
|
2004-06-14 00:51:00 +00:00
|
|
|
RageSurface *imgconv = CreateSurface( width, height,
|
|
|
|
|
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;
|
|
|
|
|
FreeImg = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
2005-10-02 03:35:56 +00:00
|
|
|
{
|
2003-06-30 02:39:56 +00:00
|
|
|
FreeImg = 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 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FlushGLErrors();
|
|
|
|
|
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 );
|
2004-09-26 09:15:16 +00:00
|
|
|
GLenum error = glGetError();
|
|
|
|
|
ASSERT_M( error == GL_NO_ERROR, GLToString(error) );
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-26 19:42:04 +00:00
|
|
|
unsigned RageDisplay_OGL::CreateTexture(
|
2003-05-22 05:28:37 +00:00
|
|
|
PixelFormat pixfmt,
|
2004-06-14 00:51:00 +00:00
|
|
|
RageSurface* img,
|
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 );
|
2004-01-24 19:35:53 +00:00
|
|
|
ASSERT( img->w == power_of_two(img->w) && img->h == power_of_two(img->h) );
|
2003-08-29 03:03:29 +00:00
|
|
|
|
2004-01-24 19:14:22 +00:00
|
|
|
|
2003-06-30 02:39:56 +00:00
|
|
|
/* Find the pixel format of the image we've been given. */
|
|
|
|
|
bool FreeImg;
|
2005-09-29 17:15:12 +00:00
|
|
|
PixelFormat imgpixfmt = GetImgPixelFormat( img, FreeImg, img->w, img->h, pixfmt == PixelFormat_PAL );
|
2005-10-02 03:35:56 +00:00
|
|
|
ASSERT( imgpixfmt != PixelFormat_INVALID );
|
2003-06-30 02:39:56 +00:00
|
|
|
|
2005-09-29 17:15:12 +00:00
|
|
|
GLenum glTexFormat = g_GLPixFmtInfo[pixfmt].internalfmt;
|
|
|
|
|
GLenum glImageFormat = g_GLPixFmtInfo[imgpixfmt].format;
|
|
|
|
|
GLenum glImageType = g_GLPixFmtInfo[imgpixfmt].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. */
|
|
|
|
|
SetPixelMapForSurface( glImageFormat, glTexFormat, img->format->palette );
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// allocate OpenGL texture resource
|
|
|
|
|
unsigned int uTexHandle;
|
|
|
|
|
glGenTextures(1, reinterpret_cast<GLuint*>(&uTexHandle));
|
|
|
|
|
ASSERT(uTexHandle);
|
|
|
|
|
|
|
|
|
|
glBindTexture( GL_TEXTURE_2D, uTexHandle );
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
2004-05-18 09:05:21 +00:00
|
|
|
GLint minFilter;
|
|
|
|
|
if( bGenerateMipMaps )
|
|
|
|
|
{
|
2005-11-11 21:16:48 +00:00
|
|
|
if( wind->GetActualVideoModeParams().bTrilinearFiltering )
|
2004-05-18 09:05:21 +00:00
|
|
|
minFilter = GL_LINEAR_MIPMAP_LINEAR;
|
|
|
|
|
else
|
|
|
|
|
minFilter = GL_LINEAR_MIPMAP_NEAREST;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
minFilter = GL_LINEAR;
|
|
|
|
|
}
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
|
2004-05-18 08:43:21 +00:00
|
|
|
|
2005-11-11 21:16:48 +00:00
|
|
|
if( wind->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
|
|
|
{
|
|
|
|
|
GLfloat largest_supported_anisotropy;
|
|
|
|
|
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
|
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-24 19:35:53 +00:00
|
|
|
SetTextureWrapping( false );
|
|
|
|
|
|
|
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, img->pitch / img->format->BytesPerPixel);
|
|
|
|
|
|
|
|
|
|
|
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];
|
|
|
|
|
memset(palette, 0, sizeof(palette));
|
|
|
|
|
int p = 0;
|
2004-09-26 08:56:32 +00:00
|
|
|
/* Copy the palette to the format OpenGL expects. */
|
2004-01-24 22:18:12 +00:00
|
|
|
for(int i = 0; i < img->format->palette->ncolors; ++i)
|
|
|
|
|
{
|
|
|
|
|
palette[p++] = img->format->palette->colors[i].r;
|
|
|
|
|
palette[p++] = img->format->palette->colors[i].g;
|
|
|
|
|
palette[p++] = img->format->palette->colors[i].b;
|
2004-06-14 00:51:00 +00:00
|
|
|
palette[p++] = img->format->palette->colors[i].a;
|
2004-01-24 22:18:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set the palette. */
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 256, GL_RGBA, GL_UNSIGNED_BYTE, palette);
|
2004-01-24 22:18:12 +00:00
|
|
|
|
|
|
|
|
GLint RealFormat = 0;
|
2004-05-24 03:41:49 +00:00
|
|
|
GLExt.glGetColorTableParameterivEXT(GL_TEXTURE_2D, GL_COLOR_TABLE_FORMAT, &RealFormat);
|
2004-01-24 22:18:12 +00:00
|
|
|
ASSERT( RealFormat == GL_RGBA8); /* This is a case I don't expect to happen. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-09-26 08:53:01 +00:00
|
|
|
{
|
|
|
|
|
ostringstream s;
|
|
|
|
|
|
2004-10-16 21:12:29 +00:00
|
|
|
s << (bGenerateMipMaps? "gluBuild2DMipmaps":"glTexImage2D");
|
2004-09-26 08:53:01 +00:00
|
|
|
s << "(format " << GLToString(glTexFormat) <<
|
|
|
|
|
", " << img->w << "x" << img->h <<
|
|
|
|
|
", format " << GLToString(glImageFormat) <<
|
|
|
|
|
", type " << GLToString(glImageType) <<
|
|
|
|
|
", pixfmt " << pixfmt <<
|
2004-10-23 02:18:17 +00:00
|
|
|
", imgpixfmt " << imgpixfmt <<
|
|
|
|
|
")";
|
2004-09-26 08:53:01 +00:00
|
|
|
LOG->Trace( "%s", s.str().c_str() );
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-12 19:40:44 +00:00
|
|
|
FlushGLErrors();
|
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,
|
|
|
|
|
img->w, img->h,
|
|
|
|
|
glImageFormat, glImageType, img->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,
|
2003-05-22 05:28:37 +00:00
|
|
|
img->w, img->h, 0,
|
|
|
|
|
glImageFormat, glImageType, img->pixels);
|
2004-01-24 19:14:22 +00:00
|
|
|
|
|
|
|
|
GLenum error = glGetError();
|
2004-09-26 08:53:01 +00:00
|
|
|
ASSERT_M( error == GL_NO_ERROR, GLToString(error) );
|
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
|
|
|
{
|
|
|
|
|
GLint size = 0;
|
|
|
|
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GLenum(GL_TEXTURE_INDEX_SIZE_EXT), &size);
|
|
|
|
|
if(size != 8)
|
2003-05-30 20:16:30 +00:00
|
|
|
RageException::Throw("Thought paletted textures worked, but they don't.");
|
2003-05-22 05:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
|
|
|
glFlush();
|
|
|
|
|
|
2003-06-30 02:39:56 +00:00
|
|
|
if( FreeImg )
|
2004-06-14 00:51:00 +00:00
|
|
|
delete img;
|
2003-05-22 05:28:37 +00:00
|
|
|
return uTexHandle;
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-26 09:15:16 +00:00
|
|
|
/* This doesn't support img being paletted if the surface itself isn't paletted.
|
|
|
|
|
* This is only used for movies anyway, which are never paletted. */
|
2003-05-26 19:42:04 +00:00
|
|
|
void RageDisplay_OGL::UpdateTexture(
|
2003-05-22 05:28:37 +00:00
|
|
|
unsigned uTexHandle,
|
2004-06-14 00:51:00 +00:00
|
|
|
RageSurface* img,
|
2003-05-22 05:28:37 +00:00
|
|
|
int xoffset, int yoffset, int width, int height )
|
|
|
|
|
{
|
|
|
|
|
glBindTexture( GL_TEXTURE_2D, uTexHandle );
|
|
|
|
|
|
2003-06-30 02:39:56 +00:00
|
|
|
bool FreeImg;
|
2004-09-26 09:15:16 +00:00
|
|
|
PixelFormat pixfmt = GetImgPixelFormat( img, FreeImg, width, height, false );
|
2003-06-29 08:13:18 +00:00
|
|
|
|
2003-08-29 04:46:54 +00:00
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, img->pitch / img->format->BytesPerPixel);
|
|
|
|
|
|
2005-09-29 17:15:12 +00:00
|
|
|
// GLenum glTexFormat = g_GLPixFmtInfo[pixfmt].internalfmt;
|
|
|
|
|
GLenum glImageFormat = g_GLPixFmtInfo[pixfmt].format;
|
|
|
|
|
GLenum glImageType = g_GLPixFmtInfo[pixfmt].type;
|
2003-05-22 05:28:37 +00:00
|
|
|
|
|
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
|
|
|
|
xoffset, yoffset,
|
|
|
|
|
width, height,
|
|
|
|
|
glImageFormat, glImageType, img->pixels);
|
|
|
|
|
|
|
|
|
|
/* Must unset PixelStore when we're done! */
|
|
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
|
|
|
glFlush();
|
2003-06-29 08:13:18 +00:00
|
|
|
|
2003-06-30 02:39:56 +00:00
|
|
|
if( FreeImg )
|
2004-06-14 00:51:00 +00:00
|
|
|
delete img;
|
2003-05-22 05:28:37 +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;
|
|
|
|
|
default: ASSERT(0); return;
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2003-06-22 01:53:04 +00:00
|
|
|
CString RageDisplay_OGL::GetTextureDiagnostics( unsigned id ) const
|
|
|
|
|
{
|
2005-09-04 16:55:21 +00:00
|
|
|
return CString();
|
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()
|
|
|
|
|
{
|
|
|
|
|
return g_bTextureMatrixShader != 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-22 03:39:39 +00:00
|
|
|
void RageDisplay_OGL::SetSphereEnvironmentMapping( bool b )
|
2004-01-06 19:54:13 +00:00
|
|
|
{
|
|
|
|
|
if( b )
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
glDisable(GL_TEXTURE_GEN_S);
|
|
|
|
|
glDisable(GL_TEXTURE_GEN_T);
|
|
|
|
|
}
|
|
|
|
|
}
|
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.
|
|
|
|
|
*/
|
|
|
|
|
|