Fixed bug wrt 'fullres' argument; it wasn't actually being used.

Removed references to 'original' palette from VideoDialog, since it's no
longer present in the codebase.

Added dummy files for Direct3D framebuffer.  It looks like Windows Vista
has finally screwed up OpenGL enough that I have to write Windows-specific
code.  Damn, have I ever mentioned how much I hate Microsoft?  They've
been trying to kill OpenGL for years, and now they might actually
succeed.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1337 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2007-08-05 15:34:26 +00:00
parent 42757f85ca
commit d42ad61ddb
5 changed files with 867 additions and 26 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: VideoModeList.hxx,v 1.2 2007-07-11 15:08:04 stephena Exp $
// $Id: VideoModeList.hxx,v 1.3 2007-08-05 15:34:26 stephena Exp $
//============================================================================
#ifndef VIDMODE_LIST_HXX
@ -33,7 +33,7 @@ struct VideoMode {
This class implements an iterator around an array of VideoMode objects.
@author Stephen Anthony
@version $Id: VideoModeList.hxx,v 1.2 2007-07-11 15:08:04 stephena Exp $
@version $Id: VideoModeList.hxx,v 1.3 2007-08-05 15:34:26 stephena Exp $
*/
class VideoModeList
{
@ -69,8 +69,8 @@ class VideoModeList
void setByResolution(uInt32 width, uInt32 height)
{
// Find the largest resolution able to hold the given bounds
myIdx = 0;
for(unsigned int i = myModeList.size() - 1; i; --i)
myIdx = myModeList.size() - 1;
for(unsigned int i = 0; i < myModeList.size(); ++i)
{
if(width <= myModeList[i].screen_w && height <= myModeList[i].screen_h)
{
@ -94,18 +94,6 @@ class VideoModeList
}
}
static bool modesAreEqual(const VideoMode& m1, const VideoMode& m2)
{
return (m1.image_x == m2.image_x) &&
(m1.image_y == m2.image_y) &&
(m1.image_w == m2.image_w) &&
(m1.image_h == m2.image_h) &&
(m1.screen_w == m2.screen_w) &&
(m1.screen_h == m2.screen_h) &&
(m1.zoom == m2.zoom) &&
(m1.name == m2.name);
}
private:
Common::Array<VideoMode> myModeList;
int myIdx;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: VideoDialog.cxx,v 1.44 2007-06-21 12:27:00 stephena Exp $
// $Id: VideoDialog.cxx,v 1.45 2007-08-05 15:34:26 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -80,9 +80,8 @@ VideoDialog::VideoDialog(OSystem* osystem, DialogContainer* parent,
myPalettePopup = new PopUpWidget(this, font, xpos, ypos, pwidth,
lineHeight, "Palette: ", lwidth);
myPalettePopup->appendEntry("Standard", 1);
myPalettePopup->appendEntry("Original", 2);
myPalettePopup->appendEntry("Z26", 3);
myPalettePopup->appendEntry("User", 4);
myPalettePopup->appendEntry("Z26", 2);
myPalettePopup->appendEntry("User", 3);
wid.push_back(myPalettePopup);
ypos += lineHeight + 4;
@ -233,9 +232,8 @@ void VideoDialog::loadConfig()
// Palette
s = instance()->settings().getString("palette");
if(s == "standard") myPalettePopup->setSelectedTag(1);
else if(s == "original") myPalettePopup->setSelectedTag(2);
else if(s == "z26") myPalettePopup->setSelectedTag(3);
else if(s == "user") myPalettePopup->setSelectedTag(4);
else if(s == "z26") myPalettePopup->setSelectedTag(2);
else if(s == "user") myPalettePopup->setSelectedTag(3);
// Fullscreen resolution
s = instance()->settings().getString("fullres");
@ -310,9 +308,8 @@ void VideoDialog::saveConfig()
// Palette
i = myPalettePopup->getSelectedTag();
if(i == 1) s = "standard";
else if(i == 2) s = "original";
else if(i == 3) s = "z26";
else if(i == 4) s = "user";
else if(i == 2) s = "z26";
else if(i == 3) s = "user";
instance()->settings().setString("palette", s);
// Fullscreen resolution

View File

@ -0,0 +1,577 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferD3D.cxx,v 1.1 2007-08-05 15:34:26 stephena Exp $
//============================================================================
#ifdef DISPLAY_D3D
#include <SDL.h>
#include <SDL_syswm.h>
#include <sstream>
#include "Console.hxx"
#include "FrameBuffer.hxx"
#include "FrameBufferD3D.hxx"
#include "MediaSrc.hxx"
#include "Settings.hxx"
#include "OSystem.hxx"
#include "Font.hxx"
#include "GuiUtils.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBufferD3D::FrameBufferD3D(OSystem* osystem)
: FrameBuffer(osystem),
myTexture(NULL),
myHaveTexRectEXT(false),
myFilterParamName("GL_NEAREST"),
myScaleFactor(1.0),
myDirtyFlag(true)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBufferD3D::~FrameBufferD3D()
{
if(myTexture)
SDL_FreeSurface(myTexture);
p_glDeleteTextures(1, &myBuffer.texture);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferD3D::loadFuncs(const string& library)
{
return myFuncsLoaded = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferD3D::initSubsystem(VideoMode mode)
{
mySDLFlags |= SDL_OPENGL;
// Set up the OpenGL attributes
myDepth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
switch(myDepth)
{
case 15:
case 16:
myRGB[0] = 5; myRGB[1] = 5; myRGB[2] = 5; myRGB[3] = 0;
break;
case 24:
case 32:
myRGB[0] = 8; myRGB[1] = 8; myRGB[2] = 8; myRGB[3] = 0;
break;
default: // This should never happen
return false;
break;
}
// Create the screen
if(!setVidMode(mode))
return false;
// Now check to see what color components were actually created
SDL_GL_GetAttribute( SDL_GL_RED_SIZE, (int*)&myRGB[0] );
SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, (int*)&myRGB[1] );
SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, (int*)&myRGB[2] );
SDL_GL_GetAttribute( SDL_GL_ALPHA_SIZE, (int*)&myRGB[3] );
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string FrameBufferD3D::about()
{
string extensions;
if(myHaveTexRectEXT) extensions += "GL_TEXTURE_RECTANGLE_ARB ";
if(extensions == "") extensions = "None";
ostringstream out;
out << "Video rendering: OpenGL mode" << endl
<< " Vendor: " << p_glGetString(GL_VENDOR) << endl
<< " Renderer: " << p_glGetString(GL_RENDERER) << endl
<< " Version: " << p_glGetString(GL_VERSION) << endl
<< " Color: " << myDepth << " bit, " << myRGB[0] << "-"
<< myRGB[1] << "-" << myRGB[2] << "-" << myRGB[3] << endl
<< " Filter: " << myFilterParamName << endl
<< " Extensions: " << extensions << endl;
return out.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferD3D::setVidMode(VideoMode mode)
{
myScreenDim.x = myScreenDim.y = 0;
myScreenDim.w = mode.screen_w;
myScreenDim.h = mode.screen_h;
myImageDim.x = mode.image_x;
myImageDim.y = mode.image_y;
myImageDim.w = mode.image_w;
myImageDim.h = mode.image_h;
// Activate stretching if its been requested and it makes sense to do so
myScaleFactor = 1.0;
if(fullScreen() && (mode.image_w < mode.screen_w) &&
(mode.image_h < mode.screen_h))
{
const string& gl_fsmax = myOSystem->settings().getString("gl_fsmax");
bool inUIMode =
myOSystem->eventHandler().state() == EventHandler::S_LAUNCHER ||
myOSystem->eventHandler().state() == EventHandler::S_DEBUGGER;
// Only stretch in certain modes
if((gl_fsmax == "always") ||
(inUIMode && gl_fsmax == "ui") ||
(!inUIMode && gl_fsmax == "tia"))
{
float scaleX = float(myImageDim.w) / myScreenDim.w;
float scaleY = float(myImageDim.h) / myScreenDim.h;
if(scaleX > scaleY)
myScaleFactor = float(myScreenDim.w) / myImageDim.w;
else
myScaleFactor = float(myScreenDim.h) / myImageDim.h;
myImageDim.w = (Uint16) (myScaleFactor * myImageDim.w);
myImageDim.h = (Uint16) (myScaleFactor * myImageDim.h);
myImageDim.x = (myScreenDim.w - myImageDim.w) / 2;
myImageDim.y = (myScreenDim.h - myImageDim.h) / 2;
}
}
// Combine the zoom level and scaler into one quantity
myScaleFactor *= (float) mode.zoom;
GLdouble orthoWidth = (GLdouble)
(myImageDim.w / myScaleFactor);
GLdouble orthoHeight = (GLdouble)
(myImageDim.h / myScaleFactor);
// Create screen containing GL context
if(myScreen)
{
p_glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapBuffers();
p_glClear(GL_COLOR_BUFFER_BIT);
}
myScreen = SDL_SetVideoMode(myScreenDim.w, myScreenDim.h, 0, mySDLFlags);
if(myScreen == NULL)
{
cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl;
return false;
}
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, myRGB[0] );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, myRGB[1] );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, myRGB[2] );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, myRGB[3] );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 );
// There's no guarantee this is supported on all hardware
// We leave it to the user to test and decide
int vsync = myOSystem->settings().getBool("gl_vsync") ? 1 : 0;
SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, vsync );
loadFuncs("");
// Check for some extensions that can potentially speed up operation
cerr << "address = " << (int) p_glGetString << endl;
const char* extensions = (const char *) p_glGetString(GL_EXTENSIONS);
myHaveTexRectEXT = strstr(extensions, "ARB_texture_rectangle") != NULL;
// Initialize GL display
p_glViewport(myImageDim.x, myImageDim.y, myImageDim.w, myImageDim.h);
p_glShadeModel(GL_FLAT);
p_glDisable(GL_CULL_FACE);
p_glDisable(GL_DEPTH_TEST);
p_glDisable(GL_ALPHA_TEST);
p_glDisable(GL_LIGHTING);
p_glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
p_glMatrixMode(GL_PROJECTION);
p_glLoadIdentity();
p_glOrtho(0.0, orthoWidth, orthoHeight, 0, -1.0, 1.0);
p_glMatrixMode(GL_MODELVIEW);
p_glLoadIdentity();
// Allocate GL textures
createTextures();
p_glEnable(myBuffer.target);
// Make sure any old parts of the screen are erased
p_glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapBuffers();
p_glClear(GL_COLOR_BUFFER_BIT);
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::drawMediaSource()
{
MediaSource& mediasrc = myOSystem->console().mediaSource();
// Copy the mediasource framebuffer to the RGB texture
uInt8* currentFrame = mediasrc.currentFrameBuffer();
uInt8* previousFrame = mediasrc.previousFrameBuffer();
uInt32 width = mediasrc.width();
uInt32 height = mediasrc.height();
uInt16* buffer = (uInt16*) myTexture->pixels;
// TODO - is this fast enough?
if(!myUsePhosphor)
{
uInt32 bufofsY = 0;
uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y )
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x )
{
const uInt32 bufofs = bufofsY + x;
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
if(v != w || theRedrawTIAIndicator)
{
// If we ever get to this point, we know the current and previous
// buffers differ. In that case, make sure the changes are
// are drawn in postFrameUpdate()
myDirtyFlag = true;
buffer[pos] = buffer[pos+1] = (uInt16) myDefPalette[v];
}
pos += 2;
}
bufofsY += width;
screenofsY += myBuffer.pitch;
}
}
else
{
// Phosphor mode always implies a dirty update,
// so we don't care about theRedrawTIAIndicator
myDirtyFlag = true;
uInt32 bufofsY = 0;
uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y )
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x )
{
const uInt32 bufofs = bufofsY + x;
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
buffer[pos++] = (uInt16) myAvgPalette[v][w];
buffer[pos++] = (uInt16) myAvgPalette[v][w];
}
bufofsY += width;
screenofsY += myBuffer.pitch;
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::preFrameUpdate()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::postFrameUpdate()
{
if(myDirtyFlag)
{
// Texturemap complete texture to surface so we have free scaling
// and antialiasing
uInt32 w = myBuffer.width, h = myBuffer.height;
p_glTexSubImage2D(myBuffer.target, 0, 0, 0,
myBuffer.texture_width, myBuffer.texture_height,
myBuffer.format, myBuffer.type, myBuffer.pixels);
p_glBegin(GL_QUADS);
p_glTexCoord2f(myBuffer.tex_coord[0], myBuffer.tex_coord[1]); p_glVertex2i(0, 0);
p_glTexCoord2f(myBuffer.tex_coord[2], myBuffer.tex_coord[1]); p_glVertex2i(w, 0);
p_glTexCoord2f(myBuffer.tex_coord[2], myBuffer.tex_coord[3]); p_glVertex2i(w, h);
p_glTexCoord2f(myBuffer.tex_coord[0], myBuffer.tex_coord[3]); p_glVertex2i(0, h);
p_glEnd();
// Now show all changes made to the texture
SDL_GL_SwapBuffers();
myDirtyFlag = false;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::scanline(uInt32 row, uInt8* data)
{
// Invert the row, since OpenGL rows start at the bottom
// of the framebuffer
row = myImageDim.h + myImageDim.y - row - 1;
p_glPixelStorei(GL_PACK_ALIGNMENT, 1);
p_glReadPixels(myImageDim.x, row, myImageDim.w, 1, GL_RGB, GL_UNSIGNED_BYTE, data);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::toggleFilter()
{
if(myBuffer.filter == GL_NEAREST)
{
myBuffer.filter = GL_LINEAR;
myOSystem->settings().setString("gl_filter", "linear");
showMessage("Filtering: GL_LINEAR");
}
else
{
myBuffer.filter = GL_NEAREST;
myOSystem->settings().setString("gl_filter", "nearest");
showMessage("Filtering: GL_NEAREST");
}
p_glBindTexture(myBuffer.target, myBuffer.texture);
p_glTexParameteri(myBuffer.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
p_glTexParameteri(myBuffer.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
p_glTexParameteri(myBuffer.target, GL_TEXTURE_MAG_FILTER, myBuffer.filter);
p_glTexParameteri(myBuffer.target, GL_TEXTURE_MIN_FILTER, myBuffer.filter);
// The filtering has changed, so redraw the entire screen
theRedrawTIAIndicator = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::hLine(uInt32 x, uInt32 y, uInt32 x2, int color)
{
// Horizontal line
SDL_Rect tmp;
tmp.x = x;
tmp.y = y;
tmp.w = x2 - x + 1;
tmp.h = 1;
SDL_FillRect(myTexture, &tmp, myDefPalette[color]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::vLine(uInt32 x, uInt32 y, uInt32 y2, int color)
{
// Vertical line
SDL_Rect tmp;
tmp.x = x;
tmp.y = y;
tmp.w = 1;
tmp.h = y2 - y + 1;
SDL_FillRect(myTexture, &tmp, myDefPalette[color]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
int color)
{
// Fill the rectangle
SDL_Rect tmp;
tmp.x = x;
tmp.y = y;
tmp.w = w;
tmp.h = h;
SDL_FillRect(myTexture, &tmp, myDefPalette[color]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::drawChar(const GUI::Font* font, uInt8 chr,
uInt32 tx, uInt32 ty, int color)
{
// If this character is not included in the font, use the default char.
if(chr < font->desc().firstchar ||
chr >= font->desc().firstchar + font->desc().size)
{
if (chr == ' ')
return;
chr = font->desc().defaultchar;
}
const Int32 w = font->getCharWidth(chr);
const Int32 h = font->getFontHeight();
chr -= font->desc().firstchar;
const uInt16* tmp = font->desc().bits + (font->desc().offset ?
font->desc().offset[chr] : (chr * h));
uInt16* buffer = (uInt16*) myTexture->pixels + ty * myBuffer.pitch + tx;
for(int y = 0; y < h; ++y)
{
const uInt16 ptr = *tmp++;
uInt16 mask = 0x8000;
for(int x = 0; x < w; ++x, mask >>= 1)
if(ptr & mask)
buffer[x] = (uInt16) myDefPalette[color];
buffer += myBuffer.pitch;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::drawBitmap(uInt32* bitmap, Int32 tx, Int32 ty,
int color, Int32 h)
{
uInt16* buffer = (uInt16*) myTexture->pixels + ty * myBuffer.pitch + tx;
for(int y = 0; y < h; ++y)
{
uInt32 mask = 0xF0000000;
for(int x = 0; x < 8; ++x, mask >>= 4)
if(bitmap[y] & mask)
buffer[x] = (uInt16) myDefPalette[color];
buffer += myBuffer.pitch;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::translateCoords(Int32& x, Int32& y)
{
// Wow, what a mess :)
x = (Int32) ((x - myImageDim.x) / myScaleFactor);
y = (Int32) ((y - myImageDim.y) / myScaleFactor);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
{
myDirtyFlag = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferD3D::enablePhosphor(bool enable, int blend)
{
myUsePhosphor = enable;
myPhosphorBlend = blend;
theRedrawTIAIndicator = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferD3D::createTextures()
{
if(myTexture) SDL_FreeSurface(myTexture);
if(myBuffer.texture) p_glDeleteTextures(1, &myBuffer.texture);
memset(&myBuffer, 0, sizeof(glBufferType));
myBuffer.filter = GL_NEAREST;
// Fill buffer struct with valid data
// This changes depending on the texturing used
myBuffer.width = myBaseDim.w;
myBuffer.height = myBaseDim.h;
myBuffer.tex_coord[0] = 0.0f;
myBuffer.tex_coord[1] = 0.0f;
if(myHaveTexRectEXT)
{
myBuffer.texture_width = myBuffer.width;
myBuffer.texture_height = myBuffer.height;
myBuffer.target = GL_TEXTURE_RECTANGLE_ARB;
myBuffer.tex_coord[2] = (GLfloat) myBuffer.texture_width;
myBuffer.tex_coord[3] = (GLfloat) myBuffer.texture_height;
}
else
{
myBuffer.texture_width = power_of_two(myBuffer.width);
myBuffer.texture_height = power_of_two(myBuffer.height);
myBuffer.target = GL_TEXTURE_2D;
myBuffer.tex_coord[2] = (GLfloat) myBuffer.width / myBuffer.texture_width;
myBuffer.tex_coord[3] = (GLfloat) myBuffer.height / myBuffer.texture_height;
}
// Create a texture that best suits the current display depth and system
// This code needs to be Apple-specific, otherwise performance is
// terrible on a Mac Mini
#if defined(MAC_OSX)
myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE,
myBuffer.texture_width, myBuffer.texture_height, 16,
0x00007c00, 0x000003e0, 0x0000001f, 0x00000000);
#else
myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE,
myBuffer.texture_width, myBuffer.texture_height, 16,
0x0000f800, 0x000007e0, 0x0000001f, 0x00000000);
#endif
if(myTexture == NULL)
return false;
myBuffer.pixels = myTexture->pixels;
switch(myTexture->format->BytesPerPixel)
{
case 2: // 16-bit
myBuffer.pitch = myTexture->pitch/2;
break;
case 3: // 24-bit
myBuffer.pitch = myTexture->pitch;
break;
case 4: // 32-bit
myBuffer.pitch = myTexture->pitch/4;
break;
default:
break;
}
// Create an OpenGL texture from the SDL texture
const string& filter = myOSystem->settings().getString("gl_filter");
if(filter == "linear")
{
myBuffer.filter = GL_LINEAR;
myFilterParamName = "GL_LINEAR";
}
else if(filter == "nearest")
{
myBuffer.filter = GL_NEAREST;
myFilterParamName = "GL_NEAREST";
}
p_glGenTextures(1, &myBuffer.texture);
p_glBindTexture(myBuffer.target, myBuffer.texture);
p_glTexParameteri(myBuffer.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
p_glTexParameteri(myBuffer.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
p_glTexParameteri(myBuffer.target, GL_TEXTURE_MIN_FILTER, myBuffer.filter);
p_glTexParameteri(myBuffer.target, GL_TEXTURE_MAG_FILTER, myBuffer.filter);
// Finally, create the texture in the most optimal format
GLenum tex_intformat;
#if defined (MAC_OSX)
tex_intformat = GL_RGB5;
myBuffer.format = GL_BGRA;
myBuffer.type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
#else
tex_intformat = GL_RGB;
myBuffer.format = GL_RGB;
myBuffer.type = GL_UNSIGNED_SHORT_5_6_5;
#endif
p_glTexImage2D(myBuffer.target, 0, tex_intformat,
myBuffer.texture_width, myBuffer.texture_height, 0,
myBuffer.format, myBuffer.type, myBuffer.pixels);
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferD3D::myFuncsLoaded = false;
#endif // DISPLAY_D3D

View File

@ -0,0 +1,271 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferD3D.hxx,v 1.1 2007-08-05 15:34:26 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_D3D_HXX
#define FRAMEBUFFER_D3D_HXX
#ifdef DISPLAY_D3D
#include <SDL.h>
#include <SDL_opengl.h>
#include <SDL_syswm.h>
#include <d3d9.h>
#include <d3dx9.h>
#include "bspf.hxx"
#include "GuiUtils.hxx"
#include "FrameBuffer.hxx"
class OSystem;
class GUI::Font;
/**
This class implements an SDL Direct3D framebuffer.
@author Stephen Anthony
@version $Id: FrameBufferD3D.hxx,v 1.1 2007-08-05 15:34:26 stephena Exp $
*/
class FrameBufferD3D : public FrameBuffer
{
public:
/**
Creates a new Direct3D framebuffer
*/
FrameBufferD3D(OSystem* osystem);
/**
Destructor
*/
virtual ~FrameBufferD3D();
/**
Check if OpenGL is available on this system and dynamically load
all required GL functions. If any errors occur, we shouldn't attempt
to instantiate a FrameBufferGL object.
@param library The filename of the OpenGL library
*/
static bool loadFuncs(const string& library);
//////////////////////////////////////////////////////////////////////
// The following methods are derived from FrameBuffer.hxx
//////////////////////////////////////////////////////////////////////
/**
This method is called to initialize OpenGL video mode.
Return false if any operation fails, otherwise return true.
*/
virtual bool initSubsystem(VideoMode mode);
/**
This method is called to query the type of the FrameBuffer.
*/
virtual BufferType type() { return kGLBuffer; }
/**
This method is called to provide information about the FrameBuffer.
*/
virtual string about();
/**
This method is called to change to the given video mode.
@param mode The mode to use for rendering the mediasource
*/
virtual bool setVidMode(VideoMode mode);
/**
Switches between the two filtering options in OpenGL.
Currently, these are GL_NEAREST and GL_LINEAR.
*/
virtual void toggleFilter();
/**
This method should be called anytime the MediaSource needs to be redrawn
to the screen.
*/
virtual void drawMediaSource();
/**
This method is called before any drawing is done (per-frame).
*/
virtual void preFrameUpdate();
/**
This method is called after any drawing is done (per-frame).
*/
virtual void postFrameUpdate();
/**
This method is called to get the specified scanline data.
@param row The row we are looking for
@param data The actual pixel data (in bytes)
*/
virtual void scanline(uInt32 row, uInt8* data);
/**
This method is called to map a given r,g,b triple to the screen palette.
@param r The red component of the color.
@param g The green component of the color.
@param b The blue component of the color.
*/
virtual Uint32 mapRGB(Uint8 r, Uint8 g, Uint8 b)
{ return SDL_MapRGB(myTexture->format, r, g, b); }
/**
This method is called to draw a horizontal line.
@param x The first x coordinate
@param y The y coordinate
@param x2 The second x coordinate
@param color The color of the line
*/
virtual void hLine(uInt32 x, uInt32 y, uInt32 x2, int color);
/**
This method is called to draw a vertical line.
@param x The x coordinate
@param y The first y coordinate
@param y2 The second y coordinate
@param color The color of the line
*/
virtual void vLine(uInt32 x, uInt32 y, uInt32 y2, int color);
/**
This method is called to draw a filled rectangle.
@param x The x coordinate
@param y The y coordinate
@param w The width of the area
@param h The height of the area
@param color The color of the area
*/
virtual void fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
int color);
/**
This method is called to draw the specified character.
@param font The font to use to draw the character
@param c The character to draw
@param x The x coordinate
@param y The y coordinate
@param color The color of the character
*/
virtual void drawChar(const GUI::Font* font, uInt8 c, uInt32 x, uInt32 y,
int color);
/**
This method is called to draw the bitmap image.
@param bitmap The data to draw
@param x The x coordinate
@param y The y coordinate
@param color The color of the character
@param h The height of the data image
*/
virtual void drawBitmap(uInt32* bitmap, Int32 x, Int32 y, int color,
Int32 h = 8);
/**
This method translates the given coordinates to their
unzoomed/unscaled equivalents.
@param x X coordinate to translate
@param y Y coordinate to translate
*/
inline virtual void translateCoords(Int32& x, Int32& y);
/**
This method adds a dirty rectangle
(ie, an area of the screen that has changed)
@param x The x coordinate
@param y The y coordinate
@param w The width of the area
@param h The height of the area
*/
virtual void addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h);
/**
Enable/disable phosphor effect.
*/
virtual void enablePhosphor(bool enable, int blend);
private:
bool createTextures();
inline uInt32 power_of_two(uInt32 input)
{
uInt32 value = 1;
while( value < input )
value <<= 1;
return value;
}
private:
// Points to the current texture data
SDL_Surface* myTexture;
// Holds all items specifically needed by GL commands
struct glBufferType
{
GLuint texture;
GLsizei texture_width;
GLsizei texture_height;
GLfloat tex_coord[4];
GLenum target;
GLenum format;
GLenum type;
GLint filter;
void* pixels;
int width, height;
int pitch;
};
glBufferType myBuffer;
// Optional GL extensions that may increase performance
bool myHaveTexRectEXT;
// The depth of the texture buffer
uInt32 myDepth;
// The size of color components for OpenGL
uInt32 myRGB[4];
// The name of the texture filtering to use
string myFilterParamName;
// The amount by which to scale the imagein fullscreen mode
float myScaleFactor;
// TODO - will be removed when textured dirty rect support is added
bool myDirtyFlag;
// Indicates if the OpenGL functions have been properly loaded
static bool myFuncsLoaded;
};
#endif // DISPLAY_D3D
#endif

View File

@ -183,6 +183,10 @@
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\FrameBufferD3D.cxx"
>
</File>
<File
RelativePath="..\common\FrameBufferGL.cxx"
>
@ -725,6 +729,10 @@
RelativePath="..\common\Array.hxx"
>
</File>
<File
RelativePath=".\FrameBufferD3D.hxx"
>
</File>
<File
RelativePath="..\common\FrameBufferGL.hxx"
>