~ubuntu-branches/debian/squeeze/stella/squeeze

« back to all changes in this revision

Viewing changes to src/common/FrameBufferGL.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna, Franczen Attila, Luca Falavigna
  • Date: 2008-11-08 12:04:12 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20081108120412-w6xq87vzgokstfey
Tags: 2.6.1-0ubuntu1
[ Franczen Attila ]
* New upstream release (LP: #183571).
* Updated policy to 3.8.0.

[ Luca Falavigna ]
* debian/patches/gcc-4.3: fix FTBFS with gcc-4.3 compiler.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
//  SS  SS   tt   ee      ll   ll  aa  aa
9
9
//   SSSS     ttt  eeeee llll llll  aaaaa
10
10
//
11
 
// Copyright (c) 1995-2005 by Bradford W. Mott and the Stella team
 
11
// Copyright (c) 1995-2008 by Bradford W. Mott and the Stella team
12
12
//
13
13
// See the file "license" for information on usage and redistribution of
14
14
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
15
15
//
16
 
// $Id: FrameBufferGL.cxx,v 1.60 2006/03/25 00:34:17 stephena Exp $
 
16
// $Id: FrameBufferGL.cxx,v 1.102 2008/04/28 15:53:05 stephena Exp $
17
17
//============================================================================
18
18
 
19
19
#ifdef DISPLAY_OPENGL
22
22
#include <SDL_syswm.h>
23
23
#include <sstream>
24
24
 
 
25
#include "bspf.hxx"
 
26
 
25
27
#include "Console.hxx"
26
 
#include "FrameBuffer.hxx"
27
 
#include "FrameBufferGL.hxx"
 
28
#include "Font.hxx"
28
29
#include "MediaSrc.hxx"
 
30
#include "OSystem.hxx"
29
31
#include "Settings.hxx"
30
 
#include "OSystem.hxx"
31
 
#include "Font.hxx"
32
 
#include "GuiUtils.hxx"
 
32
#include "Surface.hxx"
 
33
 
 
34
#include "FrameBufferGL.hxx"
33
35
 
34
36
// Maybe this code could be cleaner ...
35
37
static void (APIENTRY* p_glClear)( GLbitfield );
38
40
static void (APIENTRY* p_glPushAttrib)( GLbitfield );
39
41
static const GLubyte* (APIENTRY* p_glGetString)( GLenum );
40
42
static void (APIENTRY* p_glHint)( GLenum, GLenum );
 
43
static void (APIENTRY* p_glShadeModel)( GLenum );
41
44
 
42
45
// Matrix
43
46
static void (APIENTRY* p_glMatrixMode)( GLenum );
70
73
FrameBufferGL::FrameBufferGL(OSystem* osystem)
71
74
  : FrameBuffer(osystem),
72
75
    myTexture(NULL),
73
 
    myScreenmode(0),
74
 
    myScreenmodeCount(0),
75
 
    myTextureID(0),
76
 
    myFilterParam(GL_NEAREST),
 
76
    myHaveTexRectEXT(false),
77
77
    myFilterParamName("GL_NEAREST"),
78
 
    myFSScaleFactor(1.0),
 
78
    myWidthScaleFactor(1.0),
 
79
    myHeightScaleFactor(1.0),
79
80
    myDirtyFlag(true)
80
81
{
81
82
}
86
87
  if(myTexture)
87
88
    SDL_FreeSurface(myTexture);
88
89
 
89
 
  p_glDeleteTextures(1, &myTextureID);
 
90
  p_glDeleteTextures(1, &myBuffer.texture);
90
91
}
91
92
 
92
93
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
93
 
bool FrameBufferGL::loadFuncs(const string& library)
 
94
bool FrameBufferGL::loadLibrary(const string& library)
94
95
{
95
 
  if(myFuncsLoaded)
 
96
  if(myLibraryLoaded)
96
97
    return true;
97
98
 
98
99
  if(SDL_WasInit(SDL_INIT_VIDEO) == 0)
99
100
    SDL_Init(SDL_INIT_VIDEO);
100
101
 
101
 
  if(SDL_GL_LoadLibrary(library.c_str()) < 0)
 
102
  // Try both the specified library and auto-detection
 
103
  bool libLoaded = (library != "" && SDL_GL_LoadLibrary(library.c_str()) >= 0);
 
104
  bool autoLoaded = false;
 
105
  if(!libLoaded) autoLoaded = (SDL_GL_LoadLibrary(0) >= 0);
 
106
  if(!libLoaded && !autoLoaded)
102
107
    return false;
103
108
 
104
 
  // Otherwise, fill the function pointers for GL functions
105
 
  // If anything fails, we'll know it immediately, and return false
106
 
  // Yes, this syntax is ugly, but I can type it out faster than the time
107
 
  // it takes to figure our macro magic to do it neatly
108
 
  p_glClear = (void(APIENTRY*)(GLbitfield))
 
109
  return myLibraryLoaded = true;
 
110
}
 
111
 
 
112
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
113
bool FrameBufferGL::loadFuncs()
 
114
{
 
115
  if(myLibraryLoaded)
 
116
  {
 
117
    // Fill the function pointers for GL functions
 
118
    // If anything fails, we'll know it immediately, and return false
 
119
    // Yes, this syntax is ugly, but I can type it out faster than the time
 
120
    // it takes to figure our macro magic to do it neatly
 
121
    p_glClear = (void(APIENTRY*)(GLbitfield))
109
122
      SDL_GL_GetProcAddress("glClear"); if(!p_glClear) return false;
110
 
  p_glEnable = (void(APIENTRY*)(GLenum))
 
123
    p_glEnable = (void(APIENTRY*)(GLenum))
111
124
      SDL_GL_GetProcAddress("glEnable"); if(!p_glEnable) return false;
112
 
  p_glDisable = (void(APIENTRY*)(GLenum))
 
125
    p_glDisable = (void(APIENTRY*)(GLenum))
113
126
      SDL_GL_GetProcAddress("glDisable"); if(!p_glDisable) return false;
114
 
  p_glPushAttrib = (void(APIENTRY*)(GLbitfield))
 
127
    p_glPushAttrib = (void(APIENTRY*)(GLbitfield))
115
128
      SDL_GL_GetProcAddress("glPushAttrib"); if(!p_glPushAttrib) return false;
116
 
  p_glGetString = (const GLubyte*(APIENTRY*)(GLenum))
 
129
    p_glGetString = (const GLubyte*(APIENTRY*)(GLenum))
117
130
      SDL_GL_GetProcAddress("glGetString"); if(!p_glGetString) return false;
118
 
  p_glHint = (void(APIENTRY*)(GLenum, GLenum))
 
131
    p_glHint = (void(APIENTRY*)(GLenum, GLenum))
119
132
      SDL_GL_GetProcAddress("glHint"); if(!p_glHint) return false;
 
133
    p_glShadeModel = (void(APIENTRY*)(GLenum))
 
134
      SDL_GL_GetProcAddress("glShadeModel"); if(!p_glShadeModel) return false;
120
135
 
121
 
  p_glMatrixMode = (void(APIENTRY*)(GLenum))
 
136
    p_glMatrixMode = (void(APIENTRY*)(GLenum))
122
137
      SDL_GL_GetProcAddress("glMatrixMode"); if(!p_glMatrixMode) return false;
123
 
  p_glOrtho = (void(APIENTRY*)(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
 
138
    p_glOrtho = (void(APIENTRY*)(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
124
139
      SDL_GL_GetProcAddress("glOrtho"); if(!p_glOrtho) return false;
125
 
  p_glViewport = (void(APIENTRY*)(GLint, GLint, GLsizei, GLsizei))
 
140
    p_glViewport = (void(APIENTRY*)(GLint, GLint, GLsizei, GLsizei))
126
141
      SDL_GL_GetProcAddress("glViewport"); if(!p_glViewport) return false;
127
 
  p_glPushMatrix = (void(APIENTRY*)(void))
 
142
    p_glPushMatrix = (void(APIENTRY*)(void))
128
143
      SDL_GL_GetProcAddress("glPushMatrix"); if(!p_glPushMatrix) return false;
129
 
  p_glLoadIdentity = (void(APIENTRY*)(void))
 
144
    p_glLoadIdentity = (void(APIENTRY*)(void))
130
145
      SDL_GL_GetProcAddress("glLoadIdentity"); if(!p_glLoadIdentity) return false;
131
146
 
132
 
  p_glBegin = (void(APIENTRY*)(GLenum))
 
147
    p_glBegin = (void(APIENTRY*)(GLenum))
133
148
      SDL_GL_GetProcAddress("glBegin"); if(!p_glBegin) return false;
134
 
  p_glEnd = (void(APIENTRY*)(void))
 
149
    p_glEnd = (void(APIENTRY*)(void))
135
150
      SDL_GL_GetProcAddress("glEnd"); if(!p_glEnd) return false;
136
 
  p_glVertex2i = (void(APIENTRY*)(GLint, GLint))
 
151
    p_glVertex2i = (void(APIENTRY*)(GLint, GLint))
137
152
      SDL_GL_GetProcAddress("glVertex2i"); if(!p_glVertex2i) return false;
138
 
  p_glTexCoord2f = (void(APIENTRY*)(GLfloat, GLfloat))
 
153
    p_glTexCoord2f = (void(APIENTRY*)(GLfloat, GLfloat))
139
154
      SDL_GL_GetProcAddress("glTexCoord2f"); if(!p_glTexCoord2f) return false;
140
155
 
141
 
  p_glReadPixels = (void(APIENTRY*)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*))
 
156
    p_glReadPixels = (void(APIENTRY*)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*))
142
157
      SDL_GL_GetProcAddress("glReadPixels"); if(!p_glReadPixels) return false;
143
 
  p_glPixelStorei = (void(APIENTRY*)(GLenum, GLint))
 
158
    p_glPixelStorei = (void(APIENTRY*)(GLenum, GLint))
144
159
      SDL_GL_GetProcAddress("glPixelStorei"); if(!p_glPixelStorei) return false;
145
160
 
146
 
  p_glTexEnvf = (void(APIENTRY*)(GLenum, GLenum, GLfloat))
 
161
    p_glTexEnvf = (void(APIENTRY*)(GLenum, GLenum, GLfloat))
147
162
      SDL_GL_GetProcAddress("glTexEnvf"); if(!p_glTexEnvf) return false;
148
 
  p_glGenTextures = (void(APIENTRY*)(GLsizei, GLuint*))
 
163
    p_glGenTextures = (void(APIENTRY*)(GLsizei, GLuint*))
149
164
      SDL_GL_GetProcAddress("glGenTextures"); if(!p_glGenTextures) return false;
150
 
  p_glDeleteTextures = (void(APIENTRY*)(GLsizei, const GLuint*))
 
165
    p_glDeleteTextures = (void(APIENTRY*)(GLsizei, const GLuint*))
151
166
      SDL_GL_GetProcAddress("glDeleteTextures"); if(!p_glDeleteTextures) return false;
152
 
  p_glBindTexture = (void(APIENTRY*)(GLenum, GLuint))
 
167
    p_glBindTexture = (void(APIENTRY*)(GLenum, GLuint))
153
168
      SDL_GL_GetProcAddress("glBindTexture"); if(!p_glBindTexture) return false;
154
 
  p_glTexImage2D = (void(APIENTRY*)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*))
 
169
    p_glTexImage2D = (void(APIENTRY*)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*))
155
170
      SDL_GL_GetProcAddress("glTexImage2D"); if(!p_glTexImage2D) return false;
156
 
  p_glTexSubImage2D = (void(APIENTRY*)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*))
 
171
    p_glTexSubImage2D = (void(APIENTRY*)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*))
157
172
      SDL_GL_GetProcAddress("glTexSubImage2D"); if(!p_glTexSubImage2D) return false;
158
 
  p_glTexParameteri = (void(APIENTRY*)(GLenum, GLenum, GLint))
 
173
    p_glTexParameteri = (void(APIENTRY*)(GLenum, GLenum, GLint))
159
174
      SDL_GL_GetProcAddress("glTexParameteri"); if(!p_glTexParameteri) return false;
 
175
  }
 
176
  else
 
177
    return false;
160
178
 
161
 
  return myFuncsLoaded = true;
 
179
  return true;
162
180
}
163
181
 
164
182
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
165
 
bool FrameBufferGL::initSubsystem()
 
183
bool FrameBufferGL::initSubsystem(VideoMode mode)
166
184
{
167
185
  mySDLFlags |= SDL_OPENGL;
168
186
 
170
188
  myDepth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
171
189
  switch(myDepth)
172
190
  {
173
 
    case 8:
174
 
      myRGB[0] = 3;
175
 
      myRGB[1] = 3;
176
 
      myRGB[2] = 2;
177
 
      myRGB[3] = 0;
178
 
      break;
179
 
 
180
191
    case 15:
181
 
      myRGB[0] = 5;
182
 
      myRGB[1] = 5;
183
 
      myRGB[2] = 5;
184
 
      myRGB[3] = 0;
185
 
      break;
186
 
 
187
192
    case 16:
188
 
      myRGB[0] = 5;
189
 
      myRGB[1] = 6;
190
 
      myRGB[2] = 5;
191
 
      myRGB[3] = 0;
 
193
      myRGB[0] = 5; myRGB[1] = 5; myRGB[2] = 5; myRGB[3] = 0;
192
194
      break;
193
 
 
194
195
    case 24:
195
 
      myRGB[0] = 8;
196
 
      myRGB[1] = 8;
197
 
      myRGB[2] = 8;
198
 
      myRGB[3] = 0;
199
 
      break;
200
 
 
201
196
    case 32:
202
 
      myRGB[0] = 8;
203
 
      myRGB[1] = 8;
204
 
      myRGB[2] = 8;
205
 
      myRGB[3] = 8;
 
197
      myRGB[0] = 8; myRGB[1] = 8; myRGB[2] = 8; myRGB[3] = 0;
206
198
      break;
207
 
 
208
199
    default:  // This should never happen
 
200
      return false;
209
201
      break;
210
202
  }
211
203
 
212
 
  // Get the valid OpenGL screenmodes
213
 
  myScreenmodeCount = 0;
214
 
  myScreenmode = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_OPENGL);
215
 
  if((myScreenmode != (SDL_Rect**) -1) && (myScreenmode != (SDL_Rect**) 0))
216
 
    for(uInt32 i = 0; myScreenmode[i]; ++i)
217
 
      myScreenmodeCount++;
218
 
 
219
204
  // Create the screen
220
 
  if(!createScreen())
 
205
  if(!setVidMode(mode))
221
206
    return false;
222
207
 
223
208
  // Now check to see what color components were actually created
226
211
  SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, (int*)&myRGB[2] );
227
212
  SDL_GL_GetAttribute( SDL_GL_ALPHA_SIZE, (int*)&myRGB[3] );
228
213
 
229
 
#ifndef TEXTURES_ARE_LOST
230
 
  // Create the texture surface
231
 
  createTextures();
232
 
#endif
233
 
 
234
 
  // Show some OpenGL info
235
 
  if(myOSystem->settings().getBool("showinfo"))
236
 
  {
237
 
    cout << "Video rendering: OpenGL mode" << endl;
238
 
 
239
 
    ostringstream colormode;
240
 
    colormode << "  Color   : " << myDepth << " bit, " << myRGB[0] << "-"
241
 
              << myRGB[1] << "-" << myRGB[2] << "-" << myRGB[3];
242
 
 
243
 
    cout << "  Vendor  : " << p_glGetString(GL_VENDOR) << endl
244
 
         << "  Renderer: " << p_glGetString(GL_RENDERER) << endl
245
 
         << "  Version : " << p_glGetString(GL_VERSION) << endl
246
 
         << colormode.str() << endl
247
 
         << "  Filter  : " << myFilterParamName << endl
248
 
         << endl;
249
 
  }
250
 
 
251
214
  return true;
252
215
}
253
216
 
254
217
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
255
 
void FrameBufferGL::setAspectRatio()
 
218
string FrameBufferGL::about() const
256
219
{
257
 
  theAspectRatio = myOSystem->settings().getFloat("gl_aspect") / 2;
258
 
  if(theAspectRatio <= 0.0)
259
 
    theAspectRatio = 1.0;
 
220
  const string& extensions =
 
221
    myHaveTexRectEXT ? "GL_TEXTURE_RECTANGLE_ARB" : "None";
 
222
 
 
223
  ostringstream out;
 
224
  out << "Video rendering: OpenGL mode" << endl
 
225
      << "  Vendor:     " << p_glGetString(GL_VENDOR) << endl
 
226
      << "  Renderer:   " << p_glGetString(GL_RENDERER) << endl
 
227
      << "  Version:    " << p_glGetString(GL_VERSION) << endl
 
228
      << "  Color:      " << myDepth << " bit, " << myRGB[0] << "-"
 
229
      << myRGB[1] << "-"  << myRGB[2] << "-" << myRGB[3] << endl
 
230
      << "  Filter:     " << myFilterParamName << endl
 
231
      << "  Extensions: " << extensions << endl;
 
232
 
 
233
  return out.str();
260
234
}
261
235
 
262
236
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
263
 
bool FrameBufferGL::createScreen()
 
237
bool FrameBufferGL::setVidMode(VideoMode mode)
264
238
{
 
239
  bool inUIMode =
 
240
    myOSystem->eventHandler().state() == EventHandler::S_LAUNCHER ||
 
241
    myOSystem->eventHandler().state() == EventHandler::S_DEBUGGER;
 
242
 
 
243
  myScreenDim.x = myScreenDim.y = 0;
 
244
  myScreenDim.w = mode.screen_w;
 
245
  myScreenDim.h = mode.screen_h;
 
246
 
 
247
  myImageDim.x = mode.image_x;
 
248
  myImageDim.y = mode.image_y;
 
249
  myImageDim.w = mode.image_w;
 
250
  myImageDim.h = mode.image_h;
 
251
 
 
252
  // Normally, we just scale to the given zoom level
 
253
  myWidthScaleFactor  = (float) mode.zoom;
 
254
  myHeightScaleFactor = (float) mode.zoom;
 
255
 
 
256
  // Activate aspect ratio correction in TIA mode
 
257
  int iaspect = myOSystem->settings().getInt("gl_aspect");
 
258
  if(!inUIMode && iaspect < 100)
 
259
  {
 
260
    float aspectFactor = float(iaspect) / 100.0;
 
261
    myWidthScaleFactor *= aspectFactor;
 
262
    myImageDim.w = (uInt16)(float(myImageDim.w) * aspectFactor);
 
263
  }
 
264
 
 
265
  // Activate stretching if its been requested in fullscreen mode
 
266
  float stretchFactor = 1.0;
 
267
  if(fullScreen() && (myImageDim.w < myScreenDim.w) &&
 
268
     (myImageDim.h < myScreenDim.h))
 
269
  {
 
270
    const string& gl_fsmax = myOSystem->settings().getString("gl_fsmax");
 
271
 
 
272
    // Only stretch in certain modes
 
273
    if((gl_fsmax == "always") || 
 
274
       (inUIMode && gl_fsmax == "ui") ||
 
275
       (!inUIMode && gl_fsmax == "tia"))
 
276
    {
 
277
      float scaleX = float(myImageDim.w) / myScreenDim.w;
 
278
      float scaleY = float(myImageDim.h) / myScreenDim.h;
 
279
 
 
280
      if(scaleX > scaleY)
 
281
        stretchFactor = float(myScreenDim.w) / myImageDim.w;
 
282
      else
 
283
        stretchFactor = float(myScreenDim.h) / myImageDim.h;
 
284
    }
 
285
  }
 
286
  myWidthScaleFactor  *= stretchFactor;
 
287
  myHeightScaleFactor *= stretchFactor;
 
288
 
 
289
  // Now re-calculate the dimensions
 
290
  myImageDim.w = (Uint16) (stretchFactor * myImageDim.w);
 
291
  myImageDim.h = (Uint16) (stretchFactor * myImageDim.h);
 
292
  if(!fullScreen()) myScreenDim.w = myImageDim.w;
 
293
  myImageDim.x = (myScreenDim.w - myImageDim.w) / 2;
 
294
  myImageDim.y = (myScreenDim.h - myImageDim.h) / 2;
 
295
 
265
296
  SDL_GL_SetAttribute( SDL_GL_RED_SIZE,   myRGB[0] );
266
297
  SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, myRGB[1] );
267
298
  SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE,  myRGB[2] );
268
299
  SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, myRGB[3] );
269
300
  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
270
 
 
271
 
  // Set the screen coordinates
272
 
  GLdouble orthoWidth  = 0.0;
273
 
  GLdouble orthoHeight = 0.0;
274
 
  setDimensions(&orthoWidth, &orthoHeight);
275
 
 
 
301
  SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 );
 
302
 
 
303
  // There's no guarantee this is supported on all hardware
 
304
  // We leave it to the user to test and decide
 
305
  int vsync = myOSystem->settings().getBool("gl_vsync") ? 1 : 0;
 
306
  SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, vsync );
 
307
 
 
308
  // Create screen containing GL context
276
309
  myScreen = SDL_SetVideoMode(myScreenDim.w, myScreenDim.h, 0, mySDLFlags);
277
310
  if(myScreen == NULL)
278
311
  {
280
313
    return false;
281
314
  }
282
315
 
283
 
  p_glPushAttrib(GL_ENABLE_BIT);
284
 
 
285
 
  // Center the image horizontally and vertically
 
316
  // Reload OpenGL function pointers.  This only seems to be needed for Windows
 
317
  // Vista, but it shouldn't hurt on other systems.
 
318
  if(!loadFuncs())
 
319
    return false;
 
320
 
 
321
  // Check for some extensions that can potentially speed up operation
 
322
  // Don't use it if we've been instructed not to
 
323
  if(myOSystem->settings().getBool("gl_texrect"))
 
324
  {
 
325
    const char* extensions = (const char *) p_glGetString(GL_EXTENSIONS);
 
326
    myHaveTexRectEXT = strstr(extensions, "ARB_texture_rectangle") != NULL;
 
327
  }
 
328
  else
 
329
    myHaveTexRectEXT = false;
 
330
 
 
331
  // Initialize GL display
286
332
  p_glViewport(myImageDim.x, myImageDim.y, myImageDim.w, myImageDim.h);
 
333
  p_glShadeModel(GL_FLAT);
 
334
  p_glDisable(GL_CULL_FACE);
 
335
  p_glDisable(GL_DEPTH_TEST);
 
336
  p_glDisable(GL_ALPHA_TEST);
 
337
  p_glDisable(GL_LIGHTING);
 
338
  p_glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
287
339
 
288
340
  p_glMatrixMode(GL_PROJECTION);
289
 
  p_glPushMatrix();
290
341
  p_glLoadIdentity();
291
 
 
292
 
  p_glOrtho(0.0, orthoWidth, orthoHeight, 0.0, 0.0, 1.0);
293
 
 
 
342
  p_glOrtho(0.0, myImageDim.w, myImageDim.h, 0.0, 0.0, 1.0);
294
343
  p_glMatrixMode(GL_MODELVIEW);
295
 
  p_glPushMatrix();
296
344
  p_glLoadIdentity();
297
345
 
298
 
#ifdef TEXTURES_ARE_LOST
 
346
  // Allocate GL textures
299
347
  createTextures();
300
 
#endif
 
348
 
 
349
  p_glEnable(myBuffer.target);
301
350
 
302
351
  // Make sure any old parts of the screen are erased
303
 
  // Do it for both buffers!
304
352
  p_glClear(GL_COLOR_BUFFER_BIT);
305
353
  SDL_GL_SwapBuffers();
306
354
  p_glClear(GL_COLOR_BUFFER_BIT);
321
369
  uInt16* buffer       = (uInt16*) myTexture->pixels;
322
370
 
323
371
  // TODO - is this fast enough?
324
 
  switch((int)myUsePhosphor) // use switch/case, since we'll eventually have filters
 
372
  if(!myUsePhosphor)
325
373
  {
326
 
    case 0:
 
374
    uInt32 bufofsY    = 0;
 
375
    uInt32 screenofsY = 0;
 
376
    for(uInt32 y = 0; y < height; ++y )
327
377
    {
328
 
      uInt32 bufofsY    = 0;
329
 
      uInt32 screenofsY = 0;
330
 
      for(uInt32 y = 0; y < height; ++y )
 
378
      uInt32 pos = screenofsY;
 
379
      for(uInt32 x = 0; x < width; ++x )
331
380
      {
332
 
        uInt32 pos = screenofsY;
333
 
        for(uInt32 x = 0; x < width; ++x )
 
381
        const uInt32 bufofs = bufofsY + x;
 
382
        uInt8 v = currentFrame[bufofs];
 
383
        uInt8 w = previousFrame[bufofs];
 
384
 
 
385
        if(v != w || theRedrawTIAIndicator)
334
386
        {
335
 
          const uInt32 bufofs = bufofsY + x;
336
 
          uInt8 v = currentFrame[bufofs];
337
 
          uInt8 w = previousFrame[bufofs];
338
 
 
339
 
          if(v != w || theRedrawTIAIndicator)
340
 
          {
341
 
            // If we ever get to this point, we know the current and previous
342
 
            // buffers differ.  In that case, make sure the changes are
343
 
            // are drawn in postFrameUpdate()
344
 
            myDirtyFlag = true;
345
 
 
346
 
            buffer[pos] = buffer[pos+1] = (uInt16) myDefPalette[v];
347
 
          }
348
 
          pos += 2;
 
387
          // If we ever get to this point, we know the current and previous
 
388
          // buffers differ.  In that case, make sure the changes are
 
389
          // are drawn in postFrameUpdate()
 
390
          myDirtyFlag = true;
 
391
 
 
392
          buffer[pos] = buffer[pos+1] = (uInt16) myDefPalette[v];
349
393
        }
350
 
        bufofsY    += width;
351
 
        screenofsY += myTexture->w;
 
394
        pos += 2;
352
395
      }
353
 
      break;
 
396
      bufofsY    += width;
 
397
      screenofsY += myBuffer.pitch;
354
398
    }
 
399
  }
 
400
  else
 
401
  {
 
402
    // Phosphor mode always implies a dirty update,
 
403
    // so we don't care about theRedrawTIAIndicator
 
404
    myDirtyFlag = true;
355
405
 
356
 
    case 1:
 
406
    uInt32 bufofsY    = 0;
 
407
    uInt32 screenofsY = 0;
 
408
    for(uInt32 y = 0; y < height; ++y )
357
409
    {
358
 
      // Phosphor mode always implies a dirty update,
359
 
      // so we don't care about theRedrawTIAIndicator
360
 
      myDirtyFlag = true;
361
 
 
362
 
      uInt32 bufofsY    = 0;
363
 
      uInt32 screenofsY = 0;
364
 
      for(uInt32 y = 0; y < height; ++y )
 
410
      uInt32 pos = screenofsY;
 
411
      for(uInt32 x = 0; x < width; ++x )
365
412
      {
366
 
        uInt32 pos = screenofsY;
367
 
        for(uInt32 x = 0; x < width; ++x )
368
 
        {
369
 
          const uInt32 bufofs = bufofsY + x;
370
 
          uInt8 v = currentFrame[bufofs];
371
 
          uInt8 w = previousFrame[bufofs];
 
413
        const uInt32 bufofs = bufofsY + x;
 
414
        uInt8 v = currentFrame[bufofs];
 
415
        uInt8 w = previousFrame[bufofs];
372
416
 
373
 
          buffer[pos++] = (uInt16) myAvgPalette[v][w];
374
 
          buffer[pos++] = (uInt16) myAvgPalette[v][w];
375
 
        }
376
 
        bufofsY    += width;
377
 
        screenofsY += myTexture->w;
 
417
        buffer[pos++] = (uInt16) myAvgPalette[v][w];
 
418
        buffer[pos++] = (uInt16) myAvgPalette[v][w];
378
419
      }
379
 
      break;
 
420
      bufofsY    += width;
 
421
      screenofsY += myBuffer.pitch;
380
422
    }
381
423
  }
382
424
}
393
435
  {
394
436
    // Texturemap complete texture to surface so we have free scaling 
395
437
    // and antialiasing 
396
 
    uInt32 w = myBaseDim.w, h = myBaseDim.h;
 
438
    uInt32 w = myImageDim.w, h = myImageDim.h;
397
439
 
398
 
    p_glBindTexture(GL_TEXTURE_2D, myTextureID);
399
 
    p_glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myTexture->w, myTexture->h,
400
 
                      GL_RGB, GL_UNSIGNED_SHORT_5_6_5, myTexture->pixels);
 
440
    p_glTexSubImage2D(myBuffer.target, 0, 0, 0,
 
441
                      myBuffer.texture_width, myBuffer.texture_height,
 
442
                      myBuffer.format, myBuffer.type, myBuffer.pixels);
401
443
    p_glBegin(GL_QUADS);
402
 
      p_glTexCoord2f(myTexCoord[0], myTexCoord[1]); p_glVertex2i(0, 0);
403
 
      p_glTexCoord2f(myTexCoord[2], myTexCoord[1]); p_glVertex2i(w, 0);
404
 
      p_glTexCoord2f(myTexCoord[2], myTexCoord[3]); p_glVertex2i(w, h);
405
 
      p_glTexCoord2f(myTexCoord[0], myTexCoord[3]); p_glVertex2i(0, h);
 
444
      p_glTexCoord2f(myBuffer.tex_coord[0], myBuffer.tex_coord[1]); p_glVertex2i(0, 0);
 
445
      p_glTexCoord2f(myBuffer.tex_coord[2], myBuffer.tex_coord[1]); p_glVertex2i(w, 0);
 
446
      p_glTexCoord2f(myBuffer.tex_coord[2], myBuffer.tex_coord[3]); p_glVertex2i(w, h);
 
447
      p_glTexCoord2f(myBuffer.tex_coord[0], myBuffer.tex_coord[3]); p_glVertex2i(0, h);
406
448
    p_glEnd();
407
449
 
 
450
    // Overlay UI dialog boxes
 
451
 
 
452
 
408
453
    // Now show all changes made to the texture
409
454
    SDL_GL_SwapBuffers();
410
455
 
413
458
}
414
459
 
415
460
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
416
 
void FrameBufferGL::scanline(uInt32 row, uInt8* data)
 
461
void FrameBufferGL::scanline(uInt32 row, uInt8* data) const
417
462
{
418
463
  // Invert the row, since OpenGL rows start at the bottom
419
464
  // of the framebuffer
426
471
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
427
472
void FrameBufferGL::toggleFilter()
428
473
{
429
 
  if(myFilterParam == GL_NEAREST)
 
474
  if(myBuffer.filter == GL_NEAREST)
430
475
  {
431
 
    myFilterParam = GL_LINEAR;
 
476
    myBuffer.filter = GL_LINEAR;
432
477
    myOSystem->settings().setString("gl_filter", "linear");
433
478
    showMessage("Filtering: GL_LINEAR");
434
479
  }
435
480
  else
436
481
  {
437
 
    myFilterParam = GL_NEAREST;
 
482
    myBuffer.filter = GL_NEAREST;
438
483
    myOSystem->settings().setString("gl_filter", "nearest");
439
484
    showMessage("Filtering: GL_NEAREST");
440
485
  }
441
486
 
442
 
  p_glBindTexture(GL_TEXTURE_2D, myTextureID);
443
 
  p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
444
 
  p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
445
 
  p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myFilterParam);
446
 
  p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myFilterParam);
 
487
  p_glBindTexture(myBuffer.target, myBuffer.texture);
 
488
  p_glTexParameteri(myBuffer.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 
489
  p_glTexParameteri(myBuffer.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
490
  p_glTexParameteri(myBuffer.target, GL_TEXTURE_MAG_FILTER, myBuffer.filter);
 
491
  p_glTexParameteri(myBuffer.target, GL_TEXTURE_MIN_FILTER, myBuffer.filter);
447
492
 
448
493
  // The filtering has changed, so redraw the entire screen
449
494
  theRedrawTIAIndicator = true;
452
497
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
453
498
void FrameBufferGL::hLine(uInt32 x, uInt32 y, uInt32 x2, int color)
454
499
{
455
 
  uInt16* buffer = (uInt16*) myTexture->pixels + y * myTexture->w + x;
 
500
  uInt16* buffer = (uInt16*) myTexture->pixels + y * myBuffer.pitch + x;
456
501
  while(x++ <= x2)
457
502
    *buffer++ = (uInt16) myDefPalette[color];
458
503
}
460
505
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
461
506
void FrameBufferGL::vLine(uInt32 x, uInt32 y, uInt32 y2, int color)
462
507
{
463
 
  uInt16* buffer = (uInt16*) myTexture->pixels + y * myTexture->w + x;
 
508
  uInt16* buffer = (uInt16*) myTexture->pixels + y * myBuffer.pitch + x;
464
509
  while(y++ <= y2)
465
510
  {
466
511
    *buffer = (uInt16) myDefPalette[color];
467
 
    buffer += myTexture->w;
 
512
    buffer += myBuffer.pitch;
468
513
  }
469
514
}
470
515
 
471
516
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
472
 
void FrameBufferGL::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
473
 
                             int color)
 
517
void FrameBufferGL::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, int color)
474
518
{
 
519
  // Fill the rectangle
475
520
  SDL_Rect tmp;
476
 
 
477
 
  // Fill the rectangle
478
521
  tmp.x = x;
479
522
  tmp.y = y;
480
523
  tmp.w = w;
483
526
}
484
527
 
485
528
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
486
 
void FrameBufferGL::drawChar(const GUI::Font* FONT, uInt8 chr,
 
529
void FrameBufferGL::drawChar(const GUI::Font* font, uInt8 chr,
487
530
                             uInt32 tx, uInt32 ty, int color)
488
531
{
489
 
  GUI::Font* font = (GUI::Font*) FONT;
 
532
  const FontDesc& desc = font->desc();
490
533
 
491
534
  // If this character is not included in the font, use the default char.
492
 
  if(chr < font->desc().firstchar ||
493
 
     chr >= font->desc().firstchar + font->desc().size)
 
535
  if(chr < desc.firstchar || chr >= desc.firstchar + desc.size)
494
536
  {
495
 
    if (chr == ' ')
496
 
      return;
497
 
    chr = font->desc().defaultchar;
 
537
    if (chr == ' ') return;
 
538
    chr = desc.defaultchar;
498
539
  }
499
540
 
500
541
  const Int32 w = font->getCharWidth(chr);
501
542
  const Int32 h = font->getFontHeight();
502
 
  chr -= font->desc().firstchar;
503
 
  const uInt16* tmp = font->desc().bits + (font->desc().offset ?
504
 
                      font->desc().offset[chr] : (chr * h));
 
543
  chr -= desc.firstchar;
 
544
  const uInt32* tmp = desc.bits + (desc.offset ? desc.offset[chr] : (chr * h));
505
545
 
506
 
  uInt16* buffer = (uInt16*) myTexture->pixels + ty * myTexture->w + tx;
 
546
  uInt16* buffer = (uInt16*) myTexture->pixels + ty * myBuffer.pitch + tx;
507
547
  for(int y = 0; y < h; ++y)
508
548
  {
509
 
    const uInt16 ptr = *tmp++;
510
 
    uInt16 mask = 0x8000;
511
 
 
512
 
    for(int x = 0; x < w; ++x, mask >>= 1)
 
549
    const uInt32 ptr = *tmp++;
 
550
    if(ptr)
513
551
    {
514
 
      if(ptr & mask)
515
 
        buffer[x] = (uInt16) myDefPalette[color];
 
552
      uInt32 mask = 0x80000000;
 
553
      for(int x = 0; x < w; ++x, mask >>= 1)
 
554
        if(ptr & mask)
 
555
          buffer[x] = (uInt16) myDefPalette[color];
516
556
    }
517
 
    buffer += myTexture->w;
 
557
    buffer += myBuffer.pitch;
518
558
  }
519
559
}
520
560
 
522
562
void FrameBufferGL::drawBitmap(uInt32* bitmap, Int32 tx, Int32 ty,
523
563
                               int color, Int32 h)
524
564
{
525
 
  uInt16* buffer = (uInt16*) myTexture->pixels + ty * myTexture->w + tx;
 
565
  uInt16* buffer = (uInt16*) myTexture->pixels + ty * myBuffer.pitch + tx;
526
566
 
527
567
  for(int y = 0; y < h; ++y)
528
568
  {
529
569
    uInt32 mask = 0xF0000000;
530
570
    for(int x = 0; x < 8; ++x, mask >>= 4)
531
 
    {
532
571
      if(bitmap[y] & mask)
533
572
        buffer[x] = (uInt16) myDefPalette[color];
534
 
    }
535
 
    buffer += myTexture->w;
 
573
 
 
574
    buffer += myBuffer.pitch;
536
575
  }
537
576
}
538
577
 
539
578
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
540
 
void FrameBufferGL::translateCoords(Int32* x, Int32* y)
 
579
void FrameBufferGL::drawSurface(const GUI::Surface* surface, Int32 x, Int32 y)
 
580
{
 
581
  SDL_Rect dstrect;
 
582
  dstrect.x = x;
 
583
  dstrect.y = y;
 
584
  SDL_Rect srcrect;
 
585
  srcrect.x = 0;
 
586
  srcrect.y = 0;
 
587
  srcrect.w = surface->myClipWidth;
 
588
  srcrect.h = surface->myClipHeight;
 
589
 
 
590
  SDL_BlitSurface(surface->myData, &srcrect, myTexture, &dstrect);
 
591
}
 
592
 
 
593
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
594
void FrameBufferGL::bytesToSurface(GUI::Surface* surface, int row,
 
595
                                   uInt8* data, int rowbytes) const
 
596
{
 
597
  SDL_Surface* s = surface->myData;
 
598
  uInt16* pixels = (uInt16*) s->pixels;
 
599
  pixels += (row * s->pitch/2);
 
600
 
 
601
  for(int c = 0; c < rowbytes; c += 3)
 
602
    *pixels++ = SDL_MapRGB(s->format, data[c], data[c+1], data[c+2]);
 
603
}
 
604
 
 
605
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
606
void FrameBufferGL::translateCoords(Int32& x, Int32& y) const
541
607
{
542
608
  // Wow, what a mess :)
543
 
  *x = (Int32) (((*x - myImageDim.x) / (theZoomLevel * myFSScaleFactor * theAspectRatio)));
544
 
  *y = (Int32) (((*y - myImageDim.y) / (theZoomLevel * myFSScaleFactor)));
 
609
  x = (Int32) ((x - myImageDim.x) / myWidthScaleFactor);
 
610
  y = (Int32) ((y - myImageDim.y) / myHeightScaleFactor);
545
611
}
546
612
 
547
613
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
548
614
void FrameBufferGL::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
549
615
{
550
 
  // TODO
551
 
  //    Add logic to create one large dirty-rect that encompasses all
552
 
  //    smaller dirty rects.  Then in postFrameUpdate(), change the
553
 
  //    coordinates to only update that portion of the texture.
554
616
  myDirtyFlag = true;
555
617
}
556
618
 
557
619
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
558
 
void FrameBufferGL::enablePhosphor(bool enable)
 
620
void FrameBufferGL::enablePhosphor(bool enable, int blend)
559
621
{
560
622
  myUsePhosphor   = enable;
561
 
  myPhosphorBlend = myOSystem->settings().getInt("ppblend");
562
 
}
 
623
  myPhosphorBlend = blend;
563
624
 
564
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
565
 
void FrameBufferGL::cls()
566
 
{
567
 
/* FIXME - commented out until I figure out why it crashes in OSX
568
 
  if(myFuncsLoaded)
569
 
  {
570
 
    p_glClear(GL_COLOR_BUFFER_BIT);
571
 
    SDL_GL_SwapBuffers();
572
 
    p_glClear(GL_COLOR_BUFFER_BIT);
573
 
  }
574
 
*/
 
625
  theRedrawTIAIndicator = true;
575
626
}
576
627
 
577
628
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
579
630
{
580
631
  if(myTexture)
581
632
  {
 
633
    p_glClear(GL_COLOR_BUFFER_BIT);
 
634
    SDL_GL_SwapBuffers();
 
635
    p_glClear(GL_COLOR_BUFFER_BIT);
582
636
    SDL_FreeSurface(myTexture);
583
 
    myTexture = NULL;
584
 
  }
585
 
 
586
 
  p_glDeleteTextures(1, &myTextureID);
587
 
 
588
 
  uInt32 w = power_of_two(myBaseDim.w);
589
 
  uInt32 h = power_of_two(myBaseDim.h);
590
 
 
591
 
  myTexCoord[0] = 0.0f;
592
 
  myTexCoord[1] = 0.0f;
593
 
  myTexCoord[2] = (GLfloat) myBaseDim.w / w;
594
 
  myTexCoord[3] = (GLfloat) myBaseDim.h / h;
595
 
 
596
 
  myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 16,
597
 
    0x0000F800, 0x000007E0, 0x0000001F, 0x00000000);
598
 
 
 
637
  }
 
638
  if(myBuffer.texture)  p_glDeleteTextures(1, &myBuffer.texture);
 
639
  memset(&myBuffer, 0, sizeof(glBufferType));
 
640
  myBuffer.filter = GL_NEAREST;
 
641
 
 
642
  // Fill buffer struct with valid data
 
643
  // This changes depending on the texturing used
 
644
  myBuffer.width  = myBaseDim.w;
 
645
  myBuffer.height = myBaseDim.h;
 
646
  myBuffer.tex_coord[0] = 0.0f;
 
647
  myBuffer.tex_coord[1] = 0.0f;
 
648
  if(myHaveTexRectEXT)
 
649
  {
 
650
    myBuffer.texture_width  = myBuffer.width;
 
651
    myBuffer.texture_height = myBuffer.height;
 
652
    myBuffer.target         = GL_TEXTURE_RECTANGLE_ARB;
 
653
    myBuffer.tex_coord[2]   = (GLfloat) myBuffer.texture_width;
 
654
    myBuffer.tex_coord[3]   = (GLfloat) myBuffer.texture_height;
 
655
  }
 
656
  else
 
657
  {
 
658
    myBuffer.texture_width  = power_of_two(myBuffer.width);
 
659
    myBuffer.texture_height = power_of_two(myBuffer.height);
 
660
    myBuffer.target         = GL_TEXTURE_2D;
 
661
    myBuffer.tex_coord[2]   = (GLfloat) myBuffer.width / myBuffer.texture_width;
 
662
    myBuffer.tex_coord[3]   = (GLfloat) myBuffer.height / myBuffer.texture_height;
 
663
  }
 
664
 
 
665
  // Create a texture that best suits the current display depth and system
 
666
  // This code needs to be Apple-specific, otherwise performance is
 
667
  // terrible on a Mac Mini
 
668
#if defined(MAC_OSX)
 
669
  myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE,
 
670
                myBuffer.texture_width, myBuffer.texture_height, 16,
 
671
                0x00007c00, 0x000003e0, 0x0000001f, 0x00000000);
 
672
#else
 
673
  myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE,
 
674
                myBuffer.texture_width, myBuffer.texture_height, 16,
 
675
                0x0000f800, 0x000007e0, 0x0000001f, 0x00000000);
 
676
#endif
599
677
  if(myTexture == NULL)
600
678
    return false;
601
679
 
 
680
  myBuffer.pixels = myTexture->pixels;
 
681
  switch(myTexture->format->BytesPerPixel)
 
682
  {
 
683
    case 2:  // 16-bit
 
684
      myBuffer.pitch = myTexture->pitch/2;
 
685
      break;
 
686
    case 3:  // 24-bit
 
687
      myBuffer.pitch = myTexture->pitch;
 
688
      break;
 
689
    case 4:  // 32-bit
 
690
      myBuffer.pitch = myTexture->pitch/4;
 
691
      break;
 
692
    default:
 
693
      break;
 
694
  }
 
695
 
602
696
  // Create an OpenGL texture from the SDL texture
603
 
  string filter = myOSystem->settings().getString("gl_filter");
 
697
  const string& filter = myOSystem->settings().getString("gl_filter");
604
698
  if(filter == "linear")
605
699
  {
606
 
    myFilterParam     = GL_LINEAR;
 
700
    myBuffer.filter   = GL_LINEAR;
607
701
    myFilterParamName = "GL_LINEAR";
608
702
  }
609
703
  else if(filter == "nearest")
610
704
  {
611
 
    myFilterParam     = GL_NEAREST;
 
705
    myBuffer.filter   = GL_NEAREST;
612
706
    myFilterParamName = "GL_NEAREST";
613
707
  }
614
708
 
615
 
  p_glGenTextures(1, &myTextureID);
616
 
  p_glBindTexture(GL_TEXTURE_2D, myTextureID);
617
 
  p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
618
 
  p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
619
 
  p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myFilterParam);
620
 
  p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myFilterParam);
621
 
  p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
622
 
               myTexture->pixels);
623
 
 
624
 
  p_glDisable(GL_DEPTH_TEST);
625
 
  p_glDisable(GL_CULL_FACE);
626
 
  p_glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
627
 
  p_glEnable(GL_TEXTURE_2D);
628
 
 
629
 
  p_glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
 
709
  p_glGenTextures(1, &myBuffer.texture);
 
710
  p_glBindTexture(myBuffer.target, myBuffer.texture);
 
711
  p_glTexParameteri(myBuffer.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 
712
  p_glTexParameteri(myBuffer.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
713
  p_glTexParameteri(myBuffer.target, GL_TEXTURE_MIN_FILTER, myBuffer.filter);
 
714
  p_glTexParameteri(myBuffer.target, GL_TEXTURE_MAG_FILTER, myBuffer.filter);
 
715
 
 
716
  // Finally, create the texture in the most optimal format
 
717
  GLenum tex_intformat;
 
718
#if defined (MAC_OSX)
 
719
  tex_intformat   = GL_RGB5;
 
720
  myBuffer.format = GL_BGRA;
 
721
  myBuffer.type   = GL_UNSIGNED_SHORT_1_5_5_5_REV;
 
722
#else
 
723
  tex_intformat   = GL_RGB;
 
724
  myBuffer.format = GL_RGB;
 
725
  myBuffer.type   = GL_UNSIGNED_SHORT_5_6_5;
 
726
#endif
 
727
  p_glTexImage2D(myBuffer.target, 0, tex_intformat,
 
728
                 myBuffer.texture_width, myBuffer.texture_height, 0,
 
729
                 myBuffer.format, myBuffer.type, myBuffer.pixels);
630
730
 
631
731
  return true;
632
732
}
633
733
 
634
734
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
635
 
void FrameBufferGL::setDimensions(GLdouble* orthoWidth, GLdouble* orthoHeight)
 
735
GUI::Surface* FrameBufferGL::createSurface(int width, int height) const
636
736
{
637
 
  // We always know the initial image width and height
638
 
  // We have to determine final image dimensions as well as screen dimensions
639
 
  myImageDim.x = 0;
640
 
  myImageDim.y = 0;
641
 
  myImageDim.w = (Uint16) (myBaseDim.w * theZoomLevel * theAspectRatio);
642
 
  myImageDim.h = (Uint16) (myBaseDim.h * theZoomLevel);
643
 
  myScreenDim  = myImageDim;
644
 
 
645
 
  myFSScaleFactor = 1.0f;
646
 
 
647
 
  // Determine if we're in fullscreen or windowed mode
648
 
  // In fullscreen mode, we clip the SDL screen to known resolutions
649
 
  // In windowed mode, we use the actual image resolution for the SDL screen
650
 
  if(mySDLFlags & SDL_FULLSCREEN)
651
 
  {
652
 
    float scaleX = 0.0f;
653
 
    float scaleY = 0.0f;
654
 
 
655
 
    if(myOSystem->settings().getBool("gl_fsmax") &&
656
 
       myDesktopDim.w != 0 && myDesktopDim.h != 0)
657
 
    {
658
 
      // Use the largest available screen size
659
 
      myScreenDim.w = myDesktopDim.w;
660
 
      myScreenDim.h = myDesktopDim.h;
661
 
 
662
 
      scaleX = float(myImageDim.w) / myScreenDim.w;
663
 
      scaleY = float(myImageDim.h) / myScreenDim.h;
664
 
 
665
 
      if(scaleX > scaleY)
666
 
        myFSScaleFactor = float(myScreenDim.w) / myImageDim.w;
667
 
      else
668
 
        myFSScaleFactor = float(myScreenDim.h) / myImageDim.h;
669
 
 
670
 
      myImageDim.w = (Uint16) (myFSScaleFactor * myImageDim.w);
671
 
      myImageDim.h = (Uint16) (myFSScaleFactor * myImageDim.h);
672
 
    }
673
 
    else if(myOSystem->settings().getBool("gl_fsmax") &&
674
 
            myScreenmode != (SDL_Rect**) -1)
675
 
    {
676
 
      // Use the largest available screen size
677
 
      myScreenDim.w = myScreenmode[0]->w;
678
 
      myScreenDim.h = myScreenmode[0]->h;
679
 
 
680
 
      scaleX = float(myImageDim.w) / myScreenDim.w;
681
 
      scaleY = float(myImageDim.h) / myScreenDim.h;
682
 
 
683
 
      if(scaleX > scaleY)
684
 
        myFSScaleFactor = float(myScreenDim.w) / myImageDim.w;
685
 
      else
686
 
        myFSScaleFactor = float(myScreenDim.h) / myImageDim.h;
687
 
 
688
 
      myImageDim.w = (Uint16) (myFSScaleFactor * myImageDim.w);
689
 
      myImageDim.h = (Uint16) (myFSScaleFactor * myImageDim.h);
690
 
    }
691
 
    else if(myScreenmode == (SDL_Rect**) -1)
692
 
    {
693
 
      // All modes are available, so use the exact image resolution
694
 
      myScreenDim.w = myImageDim.w;
695
 
      myScreenDim.h = myImageDim.h;
696
 
    }
697
 
    else  // otherwise, search for a valid screenmode
698
 
    {
699
 
      for(uInt32 i = myScreenmodeCount-1; i >= 0; i--)
700
 
      {
701
 
        if(myImageDim.w <= myScreenmode[i]->w && myImageDim.h <= myScreenmode[i]->h)
702
 
        {
703
 
          myScreenDim.w = myScreenmode[i]->w;
704
 
          myScreenDim.h = myScreenmode[i]->h;
705
 
          break;
706
 
        }
707
 
      }
708
 
    }
709
 
 
710
 
    // Now calculate the OpenGL coordinates
711
 
    myImageDim.x = (myScreenDim.w - myImageDim.w) / 2;
712
 
    myImageDim.y = (myScreenDim.h - myImageDim.h) / 2;
713
 
 
714
 
    *orthoWidth  = (GLdouble) (myImageDim.w / (theZoomLevel * theAspectRatio * myFSScaleFactor));
715
 
    *orthoHeight = (GLdouble) (myImageDim.h / (theZoomLevel * myFSScaleFactor));
716
 
  }
717
 
  else
718
 
  {
719
 
    *orthoWidth  = (GLdouble) (myImageDim.w / (theZoomLevel * theAspectRatio));
720
 
    *orthoHeight = (GLdouble) (myImageDim.h / theZoomLevel);
721
 
  }
722
 
/*
723
 
  cerr << "myImageDim.x = " << myImageDim.x << ", myImageDim.y = " << myImageDim.y << endl;
724
 
  cerr << "myImageDim.w = " << myImageDim.w << ", myImageDim.h = " << myImageDim.h << endl;
725
 
  cerr << "myScreenDim.w = " << myScreenDim.w << ", myScreenDim.h = " << myScreenDim.h << endl;
726
 
  cerr << endl;
727
 
*/
 
737
  SDL_PixelFormat* fmt = myTexture->format;
 
738
  SDL_Surface* data =
 
739
    SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16,
 
740
                         fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask);
 
741
 
 
742
  return data ? new GUI::Surface(width, height, data) : NULL;
728
743
}
729
744
 
730
745
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
731
 
bool FrameBufferGL::myFuncsLoaded = false;
 
746
bool FrameBufferGL::myLibraryLoaded = false;
732
747
 
733
748
#endif  // DISPLAY_OPENGL