2007-01-15 12:09:25 -08:00
|
|
|
/*
|
|
|
|
This file is part of Warzone 2100.
|
|
|
|
Copyright (C) 1999-2004 Eidos Interactive
|
2009-02-10 10:01:48 -08:00
|
|
|
Copyright (C) 2005-2009 Warzone Resurrection Project
|
2007-01-15 12:09:25 -08:00
|
|
|
|
|
|
|
Warzone 2100 is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Warzone 2100 is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Warzone 2100; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
2007-06-28 10:47:08 -07:00
|
|
|
/*
|
|
|
|
* Screen.c
|
|
|
|
*
|
|
|
|
* Basic double buffered display using direct draw.
|
|
|
|
*
|
|
|
|
*/
|
2006-06-02 12:34:58 -07:00
|
|
|
|
2008-04-20 05:52:19 -07:00
|
|
|
#include "lib/ivis_opengl/GLee.h"
|
2007-04-11 07:21:45 -07:00
|
|
|
#include "lib/framework/frame.h"
|
|
|
|
|
2007-11-24 03:49:51 -08:00
|
|
|
#include <SDL.h>
|
2007-04-11 07:21:45 -07:00
|
|
|
#include <physfs.h>
|
2007-04-17 09:53:28 -07:00
|
|
|
#include <png.h>
|
2007-04-30 07:09:33 -07:00
|
|
|
#include "lib/ivis_common/png_util.h"
|
2007-05-01 13:34:54 -07:00
|
|
|
#include "lib/ivis_common/tex.h"
|
2007-04-17 09:53:28 -07:00
|
|
|
|
2006-06-02 12:34:58 -07:00
|
|
|
#include "lib/framework/frameint.h"
|
|
|
|
#include "lib/ivis_common/piestate.h"
|
2007-02-25 04:34:18 -08:00
|
|
|
#include "lib/ivis_common/pieblitfunc.h"
|
2008-08-27 08:24:21 -07:00
|
|
|
#if defined(WZ_OS_MAC)
|
2008-08-01 21:28:58 -07:00
|
|
|
#include <OpenGL/glu.h>
|
|
|
|
#else
|
|
|
|
#include <GL/glu.h>
|
|
|
|
#endif
|
2007-06-28 10:47:08 -07:00
|
|
|
#include "screen.h"
|
2008-10-03 20:31:18 -07:00
|
|
|
#include "src/console.h"
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
/* The Current screen size and bit depth */
|
|
|
|
UDWORD screenWidth = 0;
|
|
|
|
UDWORD screenHeight = 0;
|
|
|
|
UDWORD screenDepth = 0;
|
|
|
|
|
2007-03-28 08:08:57 -07:00
|
|
|
/* global used to indicate preferred internal OpenGL format */
|
|
|
|
int wz_texture_compression;
|
|
|
|
|
2007-11-14 14:29:19 -08:00
|
|
|
static SDL_Surface *screen = NULL;
|
2008-03-24 09:51:17 -07:00
|
|
|
static BOOL bBackDrop = false;
|
2007-11-14 14:29:19 -08:00
|
|
|
static char screendump_filename[PATH_MAX];
|
2008-03-24 09:51:17 -07:00
|
|
|
static BOOL screendump_required = false;
|
2007-11-14 14:29:19 -08:00
|
|
|
static GLuint backDropTexture = ~0;
|
2006-12-31 10:19:19 -08:00
|
|
|
|
2008-08-01 21:28:58 -07:00
|
|
|
// Variables needed for our FBO
|
|
|
|
GLuint fbo; // Our handle to the FBO
|
|
|
|
GLuint FBOtexture; // The texture we are going to use
|
|
|
|
GLuint FBOdepthbuffer; // Our handle to the depth render buffer
|
2008-08-03 14:06:39 -07:00
|
|
|
static BOOL FBOinit = false;
|
2008-08-17 11:35:22 -07:00
|
|
|
BOOL bFboProblem = false; // hack to work around people with bad drivers. (*cough*intel*cough*)
|
2008-08-01 21:28:58 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
/* Initialise the double buffered display */
|
2006-11-03 17:11:26 -08:00
|
|
|
BOOL screenInitialise(
|
|
|
|
UDWORD width, // Display width
|
2007-06-28 10:47:08 -07:00
|
|
|
UDWORD height, // Display height
|
|
|
|
UDWORD bitDepth, // Display bit depth
|
2009-04-18 08:01:56 -07:00
|
|
|
unsigned int fsaa, // FSAA anti aliasing level
|
2008-08-25 11:01:49 -07:00
|
|
|
BOOL fullScreen, // Whether to start windowed
|
2006-11-03 17:11:26 -08:00
|
|
|
// or full screen
|
2008-08-25 11:01:49 -07:00
|
|
|
BOOL vsync) // If to sync to vblank or not
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2006-11-03 17:11:26 -08:00
|
|
|
static int video_flags = 0;
|
2007-02-21 12:20:26 -08:00
|
|
|
int bpp = 0, value;
|
2006-11-03 17:11:26 -08:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
/* Store the screen information */
|
|
|
|
screenWidth = width;
|
|
|
|
screenHeight = height;
|
2006-11-03 17:11:26 -08:00
|
|
|
screenDepth = bitDepth;
|
|
|
|
|
|
|
|
// Calculate the common flags for windowed and fullscreen modes.
|
|
|
|
if (video_flags == 0) {
|
|
|
|
// Fetch the video info.
|
|
|
|
const SDL_VideoInfo* video_info = SDL_GetVideoInfo();
|
|
|
|
|
|
|
|
if (!video_info) {
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2006-11-03 17:11:26 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// The flags to pass to SDL_SetVideoMode.
|
|
|
|
video_flags = SDL_OPENGL; // Enable OpenGL in SDL.
|
|
|
|
video_flags |= SDL_ANYFORMAT; // Don't emulate requested BPP if not available.
|
|
|
|
video_flags |= SDL_HWPALETTE; // Store the palette in hardware.
|
|
|
|
|
|
|
|
// This checks to see if surfaces can be stored in memory.
|
|
|
|
if (video_info->hw_available) {
|
|
|
|
video_flags |= SDL_HWSURFACE;
|
|
|
|
} else {
|
|
|
|
video_flags |= SDL_SWSURFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This checks if hardware blits can be done.
|
|
|
|
if (video_info->blit_hw) {
|
|
|
|
video_flags |= SDL_HWACCEL;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fullScreen) {
|
|
|
|
video_flags |= SDL_FULLSCREEN;
|
|
|
|
}
|
2006-06-02 12:34:58 -07:00
|
|
|
|
2006-11-03 17:11:26 -08:00
|
|
|
// Set the double buffer OpenGL attribute.
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
|
|
|
|
2008-08-25 11:01:49 -07:00
|
|
|
// Enable vsync if requested by the user
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, vsync);
|
|
|
|
|
2009-04-18 08:01:56 -07:00
|
|
|
// Enable FSAA anti-aliasing if and at the level requested by the user
|
|
|
|
if (fsaa)
|
|
|
|
{
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, fsaa);
|
|
|
|
}
|
|
|
|
|
2006-11-03 17:11:26 -08:00
|
|
|
bpp = SDL_VideoModeOK(width, height, bitDepth, video_flags);
|
|
|
|
if (!bpp) {
|
|
|
|
debug( LOG_ERROR, "Error: Video mode %dx%d@%dbpp is not supported!\n", width, height, bitDepth );
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2006-11-03 17:11:26 -08:00
|
|
|
switch ( bpp )
|
|
|
|
{
|
|
|
|
case 32:
|
|
|
|
case 24:
|
|
|
|
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
|
|
|
|
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
|
|
|
|
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
|
|
|
|
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
|
|
|
|
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
|
|
|
|
SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8 );
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
debug( LOG_ERROR, "Warning: Using colour depth of %i instead of %i.", bpp, screenDepth );
|
|
|
|
debug( LOG_ERROR, " You will experience graphics glitches!" );
|
|
|
|
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
|
|
|
|
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 6 );
|
|
|
|
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
|
|
|
|
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
|
|
|
|
SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8 );
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
debug( LOG_ERROR, "Error: You don't want to play Warzone with a bit depth of %i, do you?", bpp );
|
|
|
|
exit( 1 );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
debug( LOG_ERROR, "Error: Unsupported bit depth: %i", bpp );
|
|
|
|
exit( 1 );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
screen = SDL_SetVideoMode(width, height, bpp, video_flags);
|
2007-02-21 12:20:26 -08:00
|
|
|
if ( !screen ) {
|
|
|
|
debug( LOG_ERROR, "Error: SDL_SetVideoMode failed (%s).", SDL_GetError() );
|
2008-03-24 09:51:17 -07:00
|
|
|
return false;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2007-03-16 09:20:16 -07:00
|
|
|
if ( SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &value) == -1)
|
2007-02-21 12:20:26 -08:00
|
|
|
{
|
|
|
|
debug( LOG_ERROR, "OpenGL initialization did not give double buffering!" );
|
|
|
|
}
|
2008-04-20 05:52:19 -07:00
|
|
|
// Note that no initialisation of GLee is required, since this is handled automatically.
|
|
|
|
|
2008-05-15 10:32:39 -07:00
|
|
|
/* Dump information about OpenGL implementation to the console */
|
|
|
|
debug(LOG_3D, "OpenGL Vendor : %s", glGetString(GL_VENDOR));
|
|
|
|
debug(LOG_3D, "OpenGL Renderer : %s", glGetString(GL_RENDERER));
|
|
|
|
debug(LOG_3D, "OpenGL Version : %s", glGetString(GL_VERSION));
|
|
|
|
debug(LOG_3D, "OpenGL Extensions : %s", glGetString(GL_EXTENSIONS)); // FIXME This is too much for MAX_LEN_LOG_LINE
|
|
|
|
debug(LOG_3D, "Supported OpenGL extensions:");
|
|
|
|
debug(LOG_3D, " * OpenGL 1.2 %s supported!", GLEE_VERSION_1_2 ? "is" : "is NOT");
|
|
|
|
debug(LOG_3D, " * OpenGL 1.3 %s supported!", GLEE_VERSION_1_3 ? "is" : "is NOT");
|
|
|
|
debug(LOG_3D, " * OpenGL 1.4 %s supported!", GLEE_VERSION_1_4 ? "is" : "is NOT");
|
|
|
|
debug(LOG_3D, " * OpenGL 1.5 %s supported!", GLEE_VERSION_1_5 ? "is" : "is NOT");
|
|
|
|
debug(LOG_3D, " * OpenGL 2.0 %s supported!", GLEE_VERSION_2_0 ? "is" : "is NOT");
|
|
|
|
debug(LOG_3D, " * OpenGL 2.1 %s supported!", GLEE_VERSION_2_1 ? "is" : "is NOT");
|
2009-03-06 06:40:27 -08:00
|
|
|
debug(LOG_3D, " * OpenGL 3.0 %s supported!", GLEE_VERSION_3_0 ? "is" : "is NOT");
|
2008-05-15 10:32:39 -07:00
|
|
|
debug(LOG_3D, " * Texture compression %s supported.", GLEE_ARB_texture_compression ? "is" : "is NOT");
|
|
|
|
debug(LOG_3D, " * Two side stencil %s supported.", GLEE_EXT_stencil_two_side ? "is" : "is NOT");
|
|
|
|
debug(LOG_3D, " * Stencil wrap %s supported.", GLEE_EXT_stencil_wrap ? "is" : "is NOT");
|
|
|
|
debug(LOG_3D, " * Anisotropic filtering %s supported.", GLEE_EXT_texture_filter_anisotropic ? "is" : "is NOT");
|
2008-07-15 13:06:09 -07:00
|
|
|
debug(LOG_3D, " * Rectangular texture %s supported.", GLEE_ARB_texture_rectangle ? "is" : "is NOT");
|
2008-08-01 21:28:58 -07:00
|
|
|
debug(LOG_3D, " * FrameBuffer Object (FBO) %s supported.", GLEE_EXT_framebuffer_object ? "is" : "is NOT");
|
2008-07-15 13:06:09 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
glViewport(0, 0, width, height);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
2009-06-04 10:56:56 -07:00
|
|
|
glOrtho(0.0f, (double)width, (double)height, 0.0f, 1.0f, -1.0f);
|
2007-05-01 13:34:54 -07:00
|
|
|
|
2007-07-30 13:20:06 -07:00
|
|
|
glMatrixMode(GL_TEXTURE);
|
2007-11-09 09:43:50 -08:00
|
|
|
glScalef(1.0f/OLD_TEXTURE_SIZE_FIX, 1.0f/OLD_TEXTURE_SIZE_FIX, 1.0f); // FIXME Scaling texture coords to 256x256!
|
2007-07-30 13:20:06 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glCullFace(GL_FRONT);
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
|
2008-03-12 12:29:24 -07:00
|
|
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
|
2008-03-24 09:51:17 -07:00
|
|
|
return true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Release the DD objects */
|
|
|
|
void screenShutDown(void)
|
|
|
|
{
|
|
|
|
if (screen != NULL)
|
|
|
|
{
|
|
|
|
SDL_FreeSurface(screen);
|
2007-11-14 14:29:19 -08:00
|
|
|
screen = NULL;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-04-16 12:22:01 -07:00
|
|
|
void screen_SetBackDropFromFile(const char* filename)
|
2006-12-31 10:19:19 -08:00
|
|
|
{
|
2007-02-20 16:10:03 -08:00
|
|
|
// HACK : We should use a resource handler here!
|
2007-04-16 12:22:01 -07:00
|
|
|
const char *extension = strrchr(filename, '.');// determine the filetype
|
2007-05-01 13:34:54 -07:00
|
|
|
iV_Image image;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-02-20 16:10:03 -08:00
|
|
|
if(!extension)
|
2007-02-07 07:27:17 -08:00
|
|
|
{
|
2007-02-20 16:10:03 -08:00
|
|
|
debug(LOG_ERROR, "Image without extension: \"%s\"!", filename);
|
|
|
|
return; // filename without extension... don't bother
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure the current texture page is reloaded after we are finished
|
|
|
|
// Otherwise WZ will think it is still loaded and not load it again
|
2008-03-21 07:34:30 -07:00
|
|
|
pie_SetTexturePage(TEXPAGE_NONE);
|
2007-02-10 06:34:12 -08:00
|
|
|
|
2007-04-17 11:24:31 -07:00
|
|
|
if( strcmp(extension,".png") == 0 )
|
2007-02-10 06:34:12 -08:00
|
|
|
{
|
2007-05-01 13:34:54 -07:00
|
|
|
if (iV_loadImage_PNG( filename, &image ) )
|
2007-02-20 16:10:03 -08:00
|
|
|
{
|
|
|
|
if (~backDropTexture == 0)
|
|
|
|
glGenTextures(1, &backDropTexture);
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, backDropTexture);
|
2007-06-02 16:01:29 -07:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
|
2007-05-01 13:34:54 -07:00
|
|
|
image.width, image.height,
|
|
|
|
0, iV_getPixelFormat(&image), GL_UNSIGNED_BYTE, image.bmp);
|
2007-02-20 16:10:03 -08:00
|
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
|
|
|
2007-05-01 13:34:54 -07:00
|
|
|
iV_unloadImage(&image);
|
2007-02-20 16:10:03 -08:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2007-02-10 06:34:12 -08:00
|
|
|
else
|
2007-02-20 16:10:03 -08:00
|
|
|
debug(LOG_ERROR, "Unknown extension \"%s\" for image \"%s\"!", extension, filename);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
//===================================================================
|
|
|
|
|
|
|
|
void screen_StopBackDrop(void)
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
bBackDrop = false; //checking [movie]
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void screen_RestartBackDrop(void)
|
|
|
|
{
|
2008-03-24 09:51:17 -07:00
|
|
|
bBackDrop = true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL screen_GetBackDrop(void)
|
|
|
|
{
|
|
|
|
return bBackDrop;
|
|
|
|
}
|
2007-11-14 14:29:19 -08:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
//******************************************************************
|
|
|
|
//slight hack to display maps (or whatever) in background.
|
2007-02-25 04:57:04 -08:00
|
|
|
//bitmap MUST be (BACKDROP_HACK_WIDTH * BACKDROP_HACK_HEIGHT) for now.
|
2007-04-16 12:22:01 -07:00
|
|
|
void screen_Upload(const char *newBackDropBmp)
|
2006-06-02 12:34:58 -07:00
|
|
|
{
|
2008-04-18 11:04:55 -07:00
|
|
|
static bool processed = false;
|
|
|
|
|
2007-02-07 07:27:17 -08:00
|
|
|
if(newBackDropBmp != NULL)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2008-04-18 11:04:55 -07:00
|
|
|
if (processed) // lets free a texture when we use a new one.
|
|
|
|
{
|
|
|
|
glDeleteTextures( 1, &backDropTexture );
|
|
|
|
}
|
|
|
|
|
2007-02-07 07:27:17 -08:00
|
|
|
glGenTextures(1, &backDropTexture);
|
2008-03-21 07:34:30 -07:00
|
|
|
pie_SetTexturePage(TEXPAGE_NONE);
|
2007-02-07 07:27:17 -08:00
|
|
|
glBindTexture(GL_TEXTURE_2D, backDropTexture);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
|
2007-02-25 04:57:04 -08:00
|
|
|
BACKDROP_HACK_WIDTH, BACKDROP_HACK_HEIGHT,
|
2006-03-27 03:03:10 -08:00
|
|
|
0, GL_RGB, GL_UNSIGNED_BYTE, newBackDropBmp);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2007-02-07 07:27:17 -08:00
|
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
2008-04-18 11:04:55 -07:00
|
|
|
processed = true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2006-06-02 12:34:58 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDepthMask(GL_FALSE);
|
2007-02-20 15:46:34 -08:00
|
|
|
|
2007-02-20 16:10:03 -08:00
|
|
|
// Make sure the current texture page is reloaded after we are finished
|
|
|
|
// Otherwise WZ will think it is still loaded and not load it again
|
2008-03-21 07:34:30 -07:00
|
|
|
pie_SetTexturePage(TEXPAGE_NONE);
|
2007-02-20 15:46:34 -08:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, backDropTexture);
|
2007-02-07 07:27:17 -08:00
|
|
|
glColor3f(1, 1, 1);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
glBegin(GL_TRIANGLE_STRIP);
|
2007-07-30 13:20:06 -07:00
|
|
|
glTexCoord2f(0, 0);
|
|
|
|
glVertex2f(0, 0);
|
|
|
|
glTexCoord2f(255, 0);
|
|
|
|
glVertex2f(screenWidth, 0);
|
|
|
|
glTexCoord2f(0, 255);
|
|
|
|
glVertex2f(0, screenHeight);
|
|
|
|
glTexCoord2f(255, 255);
|
2007-02-07 07:27:17 -08:00
|
|
|
glVertex2f(screenWidth, screenHeight);
|
2007-06-28 10:47:08 -07:00
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Swap between windowed and full screen mode */
|
|
|
|
void screenToggleMode(void)
|
|
|
|
{
|
2006-08-08 13:58:32 -07:00
|
|
|
(void) SDL_WM_ToggleFullScreen(screen);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2007-04-17 09:53:28 -07:00
|
|
|
// Screenshot code goes below this
|
|
|
|
static const unsigned int channelsPerPixel = 3;
|
|
|
|
|
2008-08-15 13:27:18 -07:00
|
|
|
/** Writes a screenshot of the current frame to file.
|
|
|
|
*
|
|
|
|
* Performs the actual work of writing the frame currently displayed on screen
|
|
|
|
* to the filename specified by screenDumpToDisk().
|
|
|
|
*
|
|
|
|
* @NOTE This function will only dump a screenshot to file if it was requested
|
|
|
|
* by screenDumpToDisk().
|
|
|
|
*
|
|
|
|
* \sa screenDumpToDisk()
|
|
|
|
*/
|
2007-04-29 16:00:38 -07:00
|
|
|
void screenDoDumpToDiskIfRequired(void)
|
2007-04-17 09:53:28 -07:00
|
|
|
{
|
2007-04-29 16:00:38 -07:00
|
|
|
const char* fileName = screendump_filename;
|
2007-05-01 13:34:54 -07:00
|
|
|
static iV_Image image = { 0, 0, 0, NULL };
|
2007-04-17 09:53:28 -07:00
|
|
|
|
2007-04-29 16:00:38 -07:00
|
|
|
if (!screendump_required) return;
|
|
|
|
debug( LOG_3D, "Saving screenshot %s\n", fileName );
|
2007-05-01 13:34:54 -07:00
|
|
|
|
2007-04-29 16:00:38 -07:00
|
|
|
// Dump the currently displayed screen in a buffer
|
2007-12-10 15:15:46 -08:00
|
|
|
// Casting to unsigned int here to prevent GCC from warning about a
|
|
|
|
// comparison between unsigned and signed integers. Why does SDL use
|
|
|
|
// a signed integer anyway? When will your screen ever have a negative
|
|
|
|
// width or height for your screen? Assert it to be sure though. -- Giel
|
2008-08-15 13:27:18 -07:00
|
|
|
ASSERT(screen->w >= 0 && screen->h >= 0, "Somehow our screen has negative dimensions! Width = %d; Height = %d", screen->w, screen->h);
|
2007-12-10 15:15:46 -08:00
|
|
|
if (image.width != (unsigned int)screen->w || image.height != (unsigned int)screen->h)
|
2007-04-17 09:53:28 -07:00
|
|
|
{
|
2007-04-29 16:00:38 -07:00
|
|
|
if (image.bmp != NULL)
|
2007-04-23 07:28:04 -07:00
|
|
|
{
|
2007-04-29 16:00:38 -07:00
|
|
|
free(image.bmp);
|
2007-04-23 07:28:04 -07:00
|
|
|
}
|
2007-05-01 13:34:54 -07:00
|
|
|
|
2007-04-29 16:00:38 -07:00
|
|
|
image.width = screen->w;
|
|
|
|
image.height = screen->h;
|
2007-05-01 13:34:54 -07:00
|
|
|
image.bmp = malloc(channelsPerPixel * image.width * image.height);
|
2007-04-29 16:00:38 -07:00
|
|
|
if (image.bmp == NULL)
|
2007-04-17 09:53:28 -07:00
|
|
|
{
|
2007-04-29 16:00:38 -07:00
|
|
|
image.width = 0; image.height = 0;
|
2008-08-15 13:27:18 -07:00
|
|
|
debug(LOG_ERROR, "Couldn't allocate memory");
|
2007-04-29 16:00:38 -07:00
|
|
|
return;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
}
|
2007-04-29 16:00:38 -07:00
|
|
|
glReadPixels(0, 0, image.width, image.height, GL_RGB, GL_UNSIGNED_BYTE, image.bmp);
|
2007-04-16 12:22:01 -07:00
|
|
|
|
2007-04-17 11:24:31 -07:00
|
|
|
// Write the screen to a PNG
|
2007-05-01 13:34:54 -07:00
|
|
|
iV_saveImage_PNG(fileName, &image);
|
2007-04-16 12:22:01 -07:00
|
|
|
|
2008-10-03 20:31:18 -07:00
|
|
|
// display message to user about screenshot
|
|
|
|
snprintf(ConsoleString,sizeof(ConsoleString),"Screenshot %s saved!",fileName);
|
|
|
|
addConsoleMessage(ConsoleString, LEFT_JUSTIFY,SYSTEM_MESSAGE);
|
|
|
|
|
2008-03-24 09:51:17 -07:00
|
|
|
screendump_required = false;
|
2007-04-16 12:22:01 -07:00
|
|
|
}
|
|
|
|
|
2008-08-15 13:27:18 -07:00
|
|
|
/** Registers the currently displayed frame for making a screen shot.
|
|
|
|
*
|
|
|
|
* The filename will be suffixed with a number, such that no files are
|
|
|
|
* overwritten.
|
|
|
|
*
|
|
|
|
* \param path The directory path to save the screenshot in.
|
|
|
|
*/
|
2008-08-03 15:56:38 -07:00
|
|
|
void screenDumpToDisk(const char* path)
|
|
|
|
{
|
2007-04-16 12:22:01 -07:00
|
|
|
static unsigned int screendump_num = 0;
|
|
|
|
|
|
|
|
while (++screendump_num != 0) {
|
|
|
|
// We can safely use '/' as path separator here since PHYSFS uses that as its default separator
|
2008-08-03 15:56:38 -07:00
|
|
|
ssprintf(screendump_filename, "%s/wz2100_shot_%03i.png", path, screendump_num);
|
2007-04-16 12:22:01 -07:00
|
|
|
if (!PHYSFS_exists(screendump_filename)) {
|
|
|
|
// Found a usable filename, so we'll stop searching.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-16 13:07:56 -07:00
|
|
|
ASSERT( screendump_num != 0, "screenDumpToDisk: integer overflow; no more filenumbers available.\n" );
|
2007-04-16 13:00:12 -07:00
|
|
|
|
|
|
|
// If we have an integer overflow, we don't want to go about and overwrite files
|
|
|
|
if (screendump_num != 0)
|
2008-03-24 09:51:17 -07:00
|
|
|
screendump_required = true;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
2008-08-03 14:06:39 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if an OpenGL error has occurred.
|
|
|
|
* \param label Label to print when an OpenGL occurred.
|
|
|
|
*/
|
2008-08-01 21:28:58 -07:00
|
|
|
void checkGLErrors(const char *label)
|
|
|
|
{
|
2008-08-03 14:06:39 -07:00
|
|
|
const GLenum errCode = glGetError();
|
2008-08-01 21:28:58 -07:00
|
|
|
|
2008-08-03 14:06:39 -07:00
|
|
|
if (errCode == GL_NO_ERROR)
|
|
|
|
return;
|
|
|
|
|
|
|
|
debug(LOG_ERROR, "OpenGL ERROR in %s: %s, (0x%0x)", label, gluErrorString(errCode), errCode);
|
2008-08-17 11:35:22 -07:00
|
|
|
bFboProblem = true; // we have a issue with the FBO, fallback to normal routine
|
2008-08-01 21:28:58 -07:00
|
|
|
}
|
2008-08-03 14:06:39 -07:00
|
|
|
|
2008-08-03 15:56:38 -07:00
|
|
|
BOOL Init_FBO(unsigned int width, unsigned int height)
|
2008-08-01 21:28:58 -07:00
|
|
|
{
|
2008-08-03 14:06:39 -07:00
|
|
|
GLenum status;
|
2008-08-03 15:56:38 -07:00
|
|
|
|
|
|
|
// Bail out if FBOs aren't supported
|
|
|
|
if (!GLEE_EXT_framebuffer_object)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// No need to create two FBOs
|
|
|
|
if (FBOinit)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Create the FBO
|
|
|
|
glGenFramebuffersEXT(1, &fbo);
|
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
|
|
|
|
|
|
|
|
// create depthbuffer
|
|
|
|
glGenRenderbuffersEXT(1, &FBOdepthbuffer);
|
|
|
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, FBOdepthbuffer);
|
|
|
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
|
|
|
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, FBOdepthbuffer);
|
|
|
|
|
|
|
|
// Now setup a texture to render to
|
|
|
|
glGenTextures(1, &FBOtexture);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, FBOtexture);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
|
|
|
|
// attach that texture to the color
|
|
|
|
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
|
|
|
GL_TEXTURE_2D, FBOtexture, 0);
|
|
|
|
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); // unbind FBO
|
|
|
|
|
|
|
|
// make sure everything went OK
|
|
|
|
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
|
|
|
if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
2008-08-01 21:28:58 -07:00
|
|
|
{
|
2008-08-03 15:56:38 -07:00
|
|
|
switch (status)
|
2008-08-01 21:28:58 -07:00
|
|
|
{
|
2008-08-03 15:56:38 -07:00
|
|
|
case GL_FRAMEBUFFER_COMPLETE_EXT:
|
|
|
|
break;
|
|
|
|
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
|
|
|
debug(LOG_ERROR, "Error: FBO missing a required image/buffer attachment!");
|
|
|
|
break;
|
|
|
|
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
|
|
|
debug(LOG_ERROR, "Error: FBO has no images/buffers attached!");
|
|
|
|
break;
|
|
|
|
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
|
|
|
debug(LOG_ERROR, "Error: FBO has mismatched image/buffer dimensions!");
|
|
|
|
break;
|
|
|
|
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
|
|
|
debug(LOG_ERROR, "Error: FBO colorbuffer attachments have different types!");
|
|
|
|
break;
|
|
|
|
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
|
|
|
debug(LOG_ERROR, "Error: FBO trying to draw to non-attached color buffer!");
|
|
|
|
break;
|
|
|
|
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
|
|
|
debug(LOG_ERROR, "Error: FBO trying to read from a non-attached color buffer!");
|
|
|
|
break;
|
|
|
|
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
|
|
|
debug(LOG_ERROR, "Error: FBO format is not supported by current graphics card/driver!");
|
|
|
|
break;
|
|
|
|
case GL_INVALID_FRAMEBUFFER_OPERATION_EXT :
|
|
|
|
debug(LOG_ERROR, "Error: FBO Non-framebuffer passed to glCheckFramebufferStatusEXT()!");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
debug(LOG_ERROR, "*UNKNOWN FBO ERROR* reported from glCheckFramebufferStatusEXT() for %x!", status);
|
|
|
|
break;
|
2008-08-01 21:28:58 -07:00
|
|
|
}
|
2008-08-03 15:56:38 -07:00
|
|
|
FBOinit = false; //we have a error with the FBO setup
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FBOinit = true; //everything is OK with FBO setup.
|
2008-08-01 21:28:58 -07:00
|
|
|
}
|
2008-08-03 15:56:38 -07:00
|
|
|
|
2008-08-01 21:28:58 -07:00
|
|
|
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); // unbind it for now.
|
|
|
|
checkGLErrors("Init_FBO() Completed");
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
2008-08-03 14:06:39 -07:00
|
|
|
|
2008-08-01 21:28:58 -07:00
|
|
|
void Delete_FBO(void)
|
|
|
|
{
|
|
|
|
if(FBOinit)
|
|
|
|
{
|
|
|
|
glDeleteFramebuffersEXT(1, &fbo);
|
|
|
|
checkGLErrors("Deleting FBO");
|
|
|
|
glDeleteRenderbuffersEXT(1, &FBOdepthbuffer);
|
|
|
|
checkGLErrors("deleting FBOdepthbuffer");
|
|
|
|
glDeleteTextures(1,&FBOtexture);
|
|
|
|
checkGLErrors("deleting FBOtexture");
|
|
|
|
fbo = FBOdepthbuffer = FBOtexture = FBOinit = 0; //reset everything.
|
|
|
|
}
|
|
|
|
}
|