Skip to content

Commit

Permalink
Add an option for scanlines when playing videos.
Browse files Browse the repository at this point in the history
Shows either no, 50% dimmed or black scanlines. Disabled if the video texture
is too small (needs 2 * video height), or the video is shown so small that the
scanlines can't be noticed.

Closes #2095.
  • Loading branch information
cybersphinx committed May 4, 2011
1 parent 7019d7e commit 9698470
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 19 deletions.
53 changes: 46 additions & 7 deletions lib/sequence/sequence.c
Expand Up @@ -65,6 +65,7 @@
#include "lib/sound/audio.h"
#include "lib/sound/openal_error.h"
#include "lib/sound/mixer.h"
#include "src/warzoneconfig.h"

#include <theora/theora.h>
#include <physfs.h>
Expand Down Expand Up @@ -178,6 +179,8 @@ static int videoY2 = 0;
static int ScrnvidXpos = 0;
static int ScrnvidYpos = 0;

static SCANLINE_MODE use_scanlines;

// Helper; just grab some more compressed bitstream and sync it for page extraction
static int buffer_data(PHYSFS_file* in, ogg_sync_state* oy)
{
Expand Down Expand Up @@ -292,7 +295,12 @@ static GLuint video_texture;
*/
static void Allocate_videoFrame(void)
{
RGBAframe = malloc(videodata.ti.frame_width * videodata.ti.frame_height * 4);
int size = videodata.ti.frame_width * videodata.ti.frame_height * 4;
if (use_scanlines)
size *= 2;

RGBAframe = malloc(size);
memset(RGBAframe, 0, size);
glGenTextures(1, &video_texture);
}

Expand All @@ -310,6 +318,8 @@ static void video_write(bool update)
unsigned int x = 0, y = 0;
const int video_width = videodata.ti.frame_width;
const int video_height = videodata.ti.frame_height;
// when using scanlines we need to double the height
const int height_factor = (use_scanlines ? 2 : 1);
yuv_buffer yuv;
glErrors();

Expand All @@ -323,7 +333,7 @@ static void video_write(bool update)
int rgb_offset = 0;
int y_offset = 0;
int uv_offset = 0;
int half_width = video_width / 2;
const int half_width = video_width / 2;

theora_decode_YUVout(&videodata.td, &yuv);

Expand All @@ -347,6 +357,18 @@ static void video_write(bool update)
int B = Vclip((A + 516 * U + 128) >> 8);

RGBAframe[rgb_offset] = (B << 16) | (G << 8) | (R << 0) | (0xFF << 24);
if (use_scanlines == SCANLINES_50)
{
// halve the rgb values for a dimmed scanline
R /= 2;
G /= 2;
B /= 2;
RGBAframe[rgb_offset + video_width] = (B << 16) | (G << 8) | (R << 0) | (0xff << 24);
}
else if (use_scanlines == SCANLINES_BLACK)
{
RGBAframe[rgb_offset + video_width] = (0xFF << 24);
}
rgb_offset++;

// second pixel, U and V (and thus C) are the same as before.
Expand All @@ -358,12 +380,26 @@ static void video_write(bool update)
B = Vclip((A + 516 * U + 128) >> 8);

RGBAframe[rgb_offset] = (B << 16) | (G << 8) | (R << 0) | (0xFF << 24);
if (use_scanlines == SCANLINES_50)
{
// halve the rgb values for a dimmed scanline
R /= 2;
G /= 2;
B /= 2;
RGBAframe[rgb_offset + video_width] = (B << 16) | (G << 8) | (R << 0) | (0xff << 24);
}
else if (use_scanlines == SCANLINES_BLACK)
{
RGBAframe[rgb_offset + video_width] = (0xFF << 24);
}
rgb_offset++;
}
if (use_scanlines)
rgb_offset += video_width;
}

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, video_width,
video_height, GL_RGBA, GL_UNSIGNED_BYTE, RGBAframe);
video_height * height_factor, GL_RGBA, GL_UNSIGNED_BYTE, RGBAframe);
glErrors();
}

Expand All @@ -380,9 +416,9 @@ static void video_write(bool update)
glVertex2f(videoX1, videoY1);
glTexCoord2f(256 * video_width / texture_width, 0);
glVertex2f(videoX2, videoY1); //screenWidth
glTexCoord2f(256 * video_width / texture_width, 256 * video_height / texture_height);
glTexCoord2f(256 * video_width / texture_width, 256 * video_height * height_factor / texture_height);
glVertex2f(videoX2, videoY2); //screenWidth,screenHeight
glTexCoord2f(0, 256 * video_height / texture_height);
glTexCoord2f(0, 256 * video_height * height_factor / texture_height);
glVertex2f(videoX1, videoY2); //screenHeight
glEnd();

Expand Down Expand Up @@ -716,6 +752,11 @@ bool seq_Play(const char* filename)
debug(LOG_ERROR, "Video not in YUV420 format!");
return false;
}
// disable scanlines if the video is too large for the texture or shown too small
use_scanlines = war_getScanlineMode();
if (videodata.ti.frame_height * 2 > texture_height || videoY2 < videodata.ti.frame_height * 2)
use_scanlines = SCANLINES_OFF;

Allocate_videoFrame();

glBindTexture(GL_TEXTURE_2D, video_texture);
Expand Down Expand Up @@ -1024,8 +1065,6 @@ void seq_SetDisplaySize(int sizeX, int sizeY, int posX, int posY)
videoY1 += offset;
videoY2 -= offset;
}


}

ScrnvidXpos = posX;
Expand Down
6 changes: 6 additions & 0 deletions lib/sequence/sequence.h
Expand Up @@ -29,4 +29,10 @@ extern void seq_Shutdown(void);
extern int seq_GetFrameNumber(void);
extern void seq_SetDisplaySize(int sizeX, int sizeY, int posX, int posY);

typedef enum {
SCANLINES_OFF,
SCANLINES_50,
SCANLINES_BLACK
} SCANLINE_MODE;

#endif // __INCLUDED_LIB_SEQUENCE_SEQUENCE_H__
10 changes: 10 additions & 0 deletions src/configuration.c
Expand Up @@ -356,6 +356,15 @@ BOOL loadConfig(void)
war_SetFMVmode(FMV_2X);
}

if (getWarzoneKeyNumeric("scanlines", &val))
{
war_setScanlineMode(val);
}
else
{
war_setScanlineMode(SCANLINES_OFF);
}

// //////////////////////////
// subtitles
if(getWarzoneKeyNumeric("subtitles", &val))
Expand Down Expand Up @@ -724,6 +733,7 @@ BOOL saveConfig(void)
setWarzoneKeyNumeric("shadows",(SDWORD)(getDrawShadows())); // shadows
setWarzoneKeyNumeric("sound", (SDWORD)war_getSoundEnabled());
setWarzoneKeyNumeric("FMVmode",(SDWORD)(war_GetFMVmode())); // sequences
setWarzoneKeyNumeric("scanlines", (SDWORD)war_getScanlineMode());
setWarzoneKeyNumeric("subtitles",(SDWORD)(seq_GetSubtitles())); // subtitles
setWarzoneKeyNumeric("radarObjectMode",(SDWORD)bEnemyAllyRadarColor); // enemy/allies radar view
setWarzoneKeyNumeric("radarTerrainMode",(SDWORD)radarDrawMode);
Expand Down
61 changes: 49 additions & 12 deletions src/frontend.c
Expand Up @@ -499,52 +499,69 @@ static BOOL startGraphicsOptionsMenu(void)
break;
}

// Scanlines
addTextButton(FRONTEND_SCANLINES, FRONTEND_POS3X - 35, FRONTEND_POS3Y, _("Scanlines"), 0);
switch (war_getScanlineMode())
{
case SCANLINES_OFF:
addTextButton(FRONTEND_SCANLINES_R, FRONTEND_POS3M - 55, FRONTEND_POS3Y, _("Off"), 0);
break;

case SCANLINES_50:
addTextButton(FRONTEND_SCANLINES_R, FRONTEND_POS3M - 55, FRONTEND_POS3Y, _("50%"), 0);
break;

case SCANLINES_BLACK:
addTextButton(FRONTEND_SCANLINES_R, FRONTEND_POS3M - 55, FRONTEND_POS3Y, _("Black"), 0);
break;
}

////////////
// screenshake
addTextButton(FRONTEND_SSHAKE, FRONTEND_POS3X-35, FRONTEND_POS3Y, _("Screen Shake"), 0);
addTextButton(FRONTEND_SSHAKE, FRONTEND_POS4X-35, FRONTEND_POS4Y, _("Screen Shake"), 0);
if(getShakeStatus())
{// shaking on
addTextButton(FRONTEND_SSHAKE_R, FRONTEND_POS3M-55, FRONTEND_POS3Y, _("On"), 0);
addTextButton(FRONTEND_SSHAKE_R, FRONTEND_POS4M-55, FRONTEND_POS4Y, _("On"), 0);
}
else
{//shaking off.
addTextButton(FRONTEND_SSHAKE_R, FRONTEND_POS3M-55, FRONTEND_POS3Y, _("Off"), 0);
addTextButton(FRONTEND_SSHAKE_R, FRONTEND_POS4M-55, FRONTEND_POS4Y, _("Off"), 0);
}

////////////
// fog
addTextButton(FRONTEND_FOGTYPE, FRONTEND_POS4X-35, FRONTEND_POS4Y, _("Fog"), 0);
addTextButton(FRONTEND_FOGTYPE, FRONTEND_POS5X-35, FRONTEND_POS5Y, _("Fog"), 0);
if(war_GetFog())
{
addTextButton(FRONTEND_FOGTYPE_R,FRONTEND_POS4M-55,FRONTEND_POS4Y, _("Mist"), 0);
addTextButton(FRONTEND_FOGTYPE_R,FRONTEND_POS5M-55,FRONTEND_POS5Y, _("Mist"), 0);
}
else
{
addTextButton(FRONTEND_FOGTYPE_R,FRONTEND_POS4M-55,FRONTEND_POS4Y, _("Fog Of War"), 0);
addTextButton(FRONTEND_FOGTYPE_R,FRONTEND_POS5M-55,FRONTEND_POS5Y, _("Fog Of War"), 0);
}

////////////
//subtitle mode.
addTextButton(FRONTEND_SUBTITLES, FRONTEND_POS5X - 35, FRONTEND_POS5Y, _("Subtitles"), 0);
addTextButton(FRONTEND_SUBTITLES, FRONTEND_POS6X - 35, FRONTEND_POS6Y, _("Subtitles"), 0);
if (!seq_GetSubtitles())
{
addTextButton(FRONTEND_SUBTITLES_R, FRONTEND_POS5M - 55, FRONTEND_POS5Y, _("Off"), 0);
addTextButton(FRONTEND_SUBTITLES_R, FRONTEND_POS6M - 55, FRONTEND_POS6Y, _("Off"), 0);
}
else
{
addTextButton(FRONTEND_SUBTITLES_R, FRONTEND_POS5M - 55, FRONTEND_POS5Y, _("On"), 0);
addTextButton(FRONTEND_SUBTITLES_R, FRONTEND_POS6M - 55, FRONTEND_POS6Y, _("On"), 0);
}

////////////
//shadows
addTextButton(FRONTEND_SHADOWS, FRONTEND_POS6X - 35, FRONTEND_POS6Y, _("Shadows"), 0);
addTextButton(FRONTEND_SHADOWS, FRONTEND_POS7X - 35, FRONTEND_POS7Y, _("Shadows"), 0);
if (getDrawShadows())
{
addTextButton(FRONTEND_SHADOWS_R, FRONTEND_POS6M - 55, FRONTEND_POS6Y, _("On"), 0);
addTextButton(FRONTEND_SHADOWS_R, FRONTEND_POS7M - 55, FRONTEND_POS7Y, _("On"), 0);
}
else
{ // not flipped
addTextButton(FRONTEND_SHADOWS_R, FRONTEND_POS6M - 55, FRONTEND_POS6Y, _("Off"), 0);
addTextButton(FRONTEND_SHADOWS_R, FRONTEND_POS7M - 55, FRONTEND_POS7Y, _("Off"), 0);
}

// Add some text down the side of the form
Expand Down Expand Up @@ -651,6 +668,26 @@ BOOL runGraphicsOptionsMenu(void)
}
break;

case FRONTEND_SCANLINES:
case FRONTEND_SCANLINES_R:
switch (mode = war_getScanlineMode())
{
case SCANLINES_OFF:
war_setScanlineMode(SCANLINES_50);
widgSetString(psWScreen, FRONTEND_SCANLINES_R, _("50%"));
break;

case SCANLINES_50:
war_setScanlineMode(SCANLINES_BLACK);
widgSetString(psWScreen, FRONTEND_SCANLINES_R, _("Black"));
break;

case SCANLINES_BLACK:
war_setScanlineMode(SCANLINES_OFF);
widgSetString(psWScreen, FRONTEND_SCANLINES_R, _("Off"));
break;
}

default:
break;
}
Expand Down
2 changes: 2 additions & 0 deletions src/frontend.h
Expand Up @@ -200,6 +200,8 @@ enum
FRONTEND_SSHAKE_R,
FRONTEND_FMVMODE,
FRONTEND_FMVMODE_R,
FRONTEND_SCANLINES,
FRONTEND_SCANLINES_R,
FRONTEND_SUBTITLES,
FRONTEND_SUBTITLES_R,
FRONTEND_SHADOWS,
Expand Down
13 changes: 13 additions & 0 deletions src/warzoneconfig.c
Expand Up @@ -44,6 +44,7 @@
typedef struct _warzoneGlobals
{
FMV_MODE FMVmode;
SCANLINE_MODE scanlines;
BOOL bFog;
SWORD effectsLevel;
BOOL Fullscreen;
Expand Down Expand Up @@ -182,6 +183,18 @@ FMV_MODE war_GetFMVmode(void)
return warGlobs.FMVmode;
}

void war_setScanlineMode(SCANLINE_MODE mode)
{
debug(LOG_VIDEO, "%d", mode);
warGlobs.scanlines = mode;
}

SCANLINE_MODE war_getScanlineMode(void)
{
debug(LOG_VIDEO, "%d", warGlobs.scanlines);
return warGlobs.scanlines;
}

void war_SetPauseOnFocusLoss(bool enabled)
{
warGlobs.pauseOnFocusLoss = enabled;
Expand Down
3 changes: 3 additions & 0 deletions src/warzoneconfig.h
Expand Up @@ -25,6 +25,7 @@
#define __INCLUDED_SRC_WARZONECONFIG_H__

#include "lib/framework/frame.h"
#include "lib/sequence/sequence.h"

/***************************************************************************/
/*
Expand Down Expand Up @@ -68,6 +69,8 @@ extern bool war_GetColouredCursor(void);
extern void war_SetColouredCursor(bool enabled);
extern bool war_GetMusicEnabled(void);
extern void war_SetMusicEnabled(bool enabled);
void war_setScanlineMode(SCANLINE_MODE mode);
SCANLINE_MODE war_getScanlineMode(void);

/**
* Enable or disable sound initialization
Expand Down

0 comments on commit 9698470

Please sign in to comment.