87
88
SDL_FreeSurface(myTexture);
89
p_glDeleteTextures(1, &myTextureID);
90
p_glDeleteTextures(1, &myBuffer.texture);
92
93
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
93
bool FrameBufferGL::loadFuncs(const string& library)
94
bool FrameBufferGL::loadLibrary(const string& library)
98
99
if(SDL_WasInit(SDL_INIT_VIDEO) == 0)
99
100
SDL_Init(SDL_INIT_VIDEO);
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)
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;
112
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
113
bool FrameBufferGL::loadFuncs()
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;
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;
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;
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;
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;
161
return myFuncsLoaded = true;
164
182
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
165
bool FrameBufferGL::initSubsystem()
183
bool FrameBufferGL::initSubsystem(VideoMode mode)
167
185
mySDLFlags |= SDL_OPENGL;
226
211
SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, (int*)&myRGB[2] );
227
212
SDL_GL_GetAttribute( SDL_GL_ALPHA_SIZE, (int*)&myRGB[3] );
229
#ifndef TEXTURES_ARE_LOST
230
// Create the texture surface
234
// Show some OpenGL info
235
if(myOSystem->settings().getBool("showinfo"))
237
cout << "Video rendering: OpenGL mode" << endl;
239
ostringstream colormode;
240
colormode << " Color : " << myDepth << " bit, " << myRGB[0] << "-"
241
<< myRGB[1] << "-" << myRGB[2] << "-" << myRGB[3];
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
254
217
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
255
void FrameBufferGL::setAspectRatio()
218
string FrameBufferGL::about() const
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";
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;
262
236
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
263
bool FrameBufferGL::createScreen()
237
bool FrameBufferGL::setVidMode(VideoMode mode)
240
myOSystem->eventHandler().state() == EventHandler::S_LAUNCHER ||
241
myOSystem->eventHandler().state() == EventHandler::S_DEBUGGER;
243
myScreenDim.x = myScreenDim.y = 0;
244
myScreenDim.w = mode.screen_w;
245
myScreenDim.h = mode.screen_h;
247
myImageDim.x = mode.image_x;
248
myImageDim.y = mode.image_y;
249
myImageDim.w = mode.image_w;
250
myImageDim.h = mode.image_h;
252
// Normally, we just scale to the given zoom level
253
myWidthScaleFactor = (float) mode.zoom;
254
myHeightScaleFactor = (float) mode.zoom;
256
// Activate aspect ratio correction in TIA mode
257
int iaspect = myOSystem->settings().getInt("gl_aspect");
258
if(!inUIMode && iaspect < 100)
260
float aspectFactor = float(iaspect) / 100.0;
261
myWidthScaleFactor *= aspectFactor;
262
myImageDim.w = (uInt16)(float(myImageDim.w) * aspectFactor);
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))
270
const string& gl_fsmax = myOSystem->settings().getString("gl_fsmax");
272
// Only stretch in certain modes
273
if((gl_fsmax == "always") ||
274
(inUIMode && gl_fsmax == "ui") ||
275
(!inUIMode && gl_fsmax == "tia"))
277
float scaleX = float(myImageDim.w) / myScreenDim.w;
278
float scaleY = float(myImageDim.h) / myScreenDim.h;
281
stretchFactor = float(myScreenDim.w) / myImageDim.w;
283
stretchFactor = float(myScreenDim.h) / myImageDim.h;
286
myWidthScaleFactor *= stretchFactor;
287
myHeightScaleFactor *= stretchFactor;
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;
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 );
271
// Set the screen coordinates
272
GLdouble orthoWidth = 0.0;
273
GLdouble orthoHeight = 0.0;
274
setDimensions(&orthoWidth, &orthoHeight);
301
SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 );
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 );
308
// Create screen containing GL context
276
309
myScreen = SDL_SetVideoMode(myScreenDim.w, myScreenDim.h, 0, mySDLFlags);
277
310
if(myScreen == NULL)
321
369
uInt16* buffer = (uInt16*) myTexture->pixels;
323
371
// TODO - is this fast enough?
324
switch((int)myUsePhosphor) // use switch/case, since we'll eventually have filters
375
uInt32 screenofsY = 0;
376
for(uInt32 y = 0; y < height; ++y )
329
uInt32 screenofsY = 0;
330
for(uInt32 y = 0; y < height; ++y )
378
uInt32 pos = screenofsY;
379
for(uInt32 x = 0; x < width; ++x )
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];
385
if(v != w || theRedrawTIAIndicator)
335
const uInt32 bufofs = bufofsY + x;
336
uInt8 v = currentFrame[bufofs];
337
uInt8 w = previousFrame[bufofs];
339
if(v != w || theRedrawTIAIndicator)
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()
346
buffer[pos] = buffer[pos+1] = (uInt16) myDefPalette[v];
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()
392
buffer[pos] = buffer[pos+1] = (uInt16) myDefPalette[v];
351
screenofsY += myTexture->w;
397
screenofsY += myBuffer.pitch;
402
// Phosphor mode always implies a dirty update,
403
// so we don't care about theRedrawTIAIndicator
407
uInt32 screenofsY = 0;
408
for(uInt32 y = 0; y < height; ++y )
358
// Phosphor mode always implies a dirty update,
359
// so we don't care about theRedrawTIAIndicator
363
uInt32 screenofsY = 0;
364
for(uInt32 y = 0; y < height; ++y )
410
uInt32 pos = screenofsY;
411
for(uInt32 x = 0; x < width; ++x )
366
uInt32 pos = screenofsY;
367
for(uInt32 x = 0; x < width; ++x )
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];
373
buffer[pos++] = (uInt16) myAvgPalette[v][w];
374
buffer[pos++] = (uInt16) myAvgPalette[v][w];
377
screenofsY += myTexture->w;
417
buffer[pos++] = (uInt16) myAvgPalette[v][w];
418
buffer[pos++] = (uInt16) myAvgPalette[v][w];
421
screenofsY += myBuffer.pitch;
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;
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);
450
// Overlay UI dialog boxes
408
453
// Now show all changes made to the texture
409
454
SDL_GL_SwapBuffers();
426
471
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
427
472
void FrameBufferGL::toggleFilter()
429
if(myFilterParam == GL_NEAREST)
474
if(myBuffer.filter == GL_NEAREST)
431
myFilterParam = GL_LINEAR;
476
myBuffer.filter = GL_LINEAR;
432
477
myOSystem->settings().setString("gl_filter", "linear");
433
478
showMessage("Filtering: GL_LINEAR");
437
myFilterParam = GL_NEAREST;
482
myBuffer.filter = GL_NEAREST;
438
483
myOSystem->settings().setString("gl_filter", "nearest");
439
484
showMessage("Filtering: GL_NEAREST");
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);
448
493
// The filtering has changed, so redraw the entire screen
449
494
theRedrawTIAIndicator = true;
522
562
void FrameBufferGL::drawBitmap(uInt32* bitmap, Int32 tx, Int32 ty,
523
563
int color, Int32 h)
525
uInt16* buffer = (uInt16*) myTexture->pixels + ty * myTexture->w + tx;
565
uInt16* buffer = (uInt16*) myTexture->pixels + ty * myBuffer.pitch + tx;
527
567
for(int y = 0; y < h; ++y)
529
569
uInt32 mask = 0xF0000000;
530
570
for(int x = 0; x < 8; ++x, mask >>= 4)
532
571
if(bitmap[y] & mask)
533
572
buffer[x] = (uInt16) myDefPalette[color];
535
buffer += myTexture->w;
574
buffer += myBuffer.pitch;
539
578
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
540
void FrameBufferGL::translateCoords(Int32* x, Int32* y)
579
void FrameBufferGL::drawSurface(const GUI::Surface* surface, Int32 x, Int32 y)
587
srcrect.w = surface->myClipWidth;
588
srcrect.h = surface->myClipHeight;
590
SDL_BlitSurface(surface->myData, &srcrect, myTexture, &dstrect);
593
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
594
void FrameBufferGL::bytesToSurface(GUI::Surface* surface, int row,
595
uInt8* data, int rowbytes) const
597
SDL_Surface* s = surface->myData;
598
uInt16* pixels = (uInt16*) s->pixels;
599
pixels += (row * s->pitch/2);
601
for(int c = 0; c < rowbytes; c += 3)
602
*pixels++ = SDL_MapRGB(s->format, data[c], data[c+1], data[c+2]);
605
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
606
void FrameBufferGL::translateCoords(Int32& x, Int32& y) const
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);
547
613
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
548
614
void FrameBufferGL::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
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;
557
619
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
558
void FrameBufferGL::enablePhosphor(bool enable)
620
void FrameBufferGL::enablePhosphor(bool enable, int blend)
560
622
myUsePhosphor = enable;
561
myPhosphorBlend = myOSystem->settings().getInt("ppblend");
623
myPhosphorBlend = blend;
564
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
565
void FrameBufferGL::cls()
567
/* FIXME - commented out until I figure out why it crashes in OSX
570
p_glClear(GL_COLOR_BUFFER_BIT);
571
SDL_GL_SwapBuffers();
572
p_glClear(GL_COLOR_BUFFER_BIT);
625
theRedrawTIAIndicator = true;
577
628
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
633
p_glClear(GL_COLOR_BUFFER_BIT);
634
SDL_GL_SwapBuffers();
635
p_glClear(GL_COLOR_BUFFER_BIT);
582
636
SDL_FreeSurface(myTexture);
586
p_glDeleteTextures(1, &myTextureID);
588
uInt32 w = power_of_two(myBaseDim.w);
589
uInt32 h = power_of_two(myBaseDim.h);
591
myTexCoord[0] = 0.0f;
592
myTexCoord[1] = 0.0f;
593
myTexCoord[2] = (GLfloat) myBaseDim.w / w;
594
myTexCoord[3] = (GLfloat) myBaseDim.h / h;
596
myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 16,
597
0x0000F800, 0x000007E0, 0x0000001F, 0x00000000);
638
if(myBuffer.texture) p_glDeleteTextures(1, &myBuffer.texture);
639
memset(&myBuffer, 0, sizeof(glBufferType));
640
myBuffer.filter = GL_NEAREST;
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;
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;
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;
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
669
myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE,
670
myBuffer.texture_width, myBuffer.texture_height, 16,
671
0x00007c00, 0x000003e0, 0x0000001f, 0x00000000);
673
myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE,
674
myBuffer.texture_width, myBuffer.texture_height, 16,
675
0x0000f800, 0x000007e0, 0x0000001f, 0x00000000);
599
677
if(myTexture == NULL)
680
myBuffer.pixels = myTexture->pixels;
681
switch(myTexture->format->BytesPerPixel)
684
myBuffer.pitch = myTexture->pitch/2;
687
myBuffer.pitch = myTexture->pitch;
690
myBuffer.pitch = myTexture->pitch/4;
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")
606
myFilterParam = GL_LINEAR;
700
myBuffer.filter = GL_LINEAR;
607
701
myFilterParamName = "GL_LINEAR";
609
703
else if(filter == "nearest")
611
myFilterParam = GL_NEAREST;
705
myBuffer.filter = GL_NEAREST;
612
706
myFilterParamName = "GL_NEAREST";
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,
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);
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);
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;
723
tex_intformat = GL_RGB;
724
myBuffer.format = GL_RGB;
725
myBuffer.type = GL_UNSIGNED_SHORT_5_6_5;
727
p_glTexImage2D(myBuffer.target, 0, tex_intformat,
728
myBuffer.texture_width, myBuffer.texture_height, 0,
729
myBuffer.format, myBuffer.type, myBuffer.pixels);
634
734
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
635
void FrameBufferGL::setDimensions(GLdouble* orthoWidth, GLdouble* orthoHeight)
735
GUI::Surface* FrameBufferGL::createSurface(int width, int height) const
637
// We always know the initial image width and height
638
// We have to determine final image dimensions as well as screen dimensions
641
myImageDim.w = (Uint16) (myBaseDim.w * theZoomLevel * theAspectRatio);
642
myImageDim.h = (Uint16) (myBaseDim.h * theZoomLevel);
643
myScreenDim = myImageDim;
645
myFSScaleFactor = 1.0f;
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)
655
if(myOSystem->settings().getBool("gl_fsmax") &&
656
myDesktopDim.w != 0 && myDesktopDim.h != 0)
658
// Use the largest available screen size
659
myScreenDim.w = myDesktopDim.w;
660
myScreenDim.h = myDesktopDim.h;
662
scaleX = float(myImageDim.w) / myScreenDim.w;
663
scaleY = float(myImageDim.h) / myScreenDim.h;
666
myFSScaleFactor = float(myScreenDim.w) / myImageDim.w;
668
myFSScaleFactor = float(myScreenDim.h) / myImageDim.h;
670
myImageDim.w = (Uint16) (myFSScaleFactor * myImageDim.w);
671
myImageDim.h = (Uint16) (myFSScaleFactor * myImageDim.h);
673
else if(myOSystem->settings().getBool("gl_fsmax") &&
674
myScreenmode != (SDL_Rect**) -1)
676
// Use the largest available screen size
677
myScreenDim.w = myScreenmode[0]->w;
678
myScreenDim.h = myScreenmode[0]->h;
680
scaleX = float(myImageDim.w) / myScreenDim.w;
681
scaleY = float(myImageDim.h) / myScreenDim.h;
684
myFSScaleFactor = float(myScreenDim.w) / myImageDim.w;
686
myFSScaleFactor = float(myScreenDim.h) / myImageDim.h;
688
myImageDim.w = (Uint16) (myFSScaleFactor * myImageDim.w);
689
myImageDim.h = (Uint16) (myFSScaleFactor * myImageDim.h);
691
else if(myScreenmode == (SDL_Rect**) -1)
693
// All modes are available, so use the exact image resolution
694
myScreenDim.w = myImageDim.w;
695
myScreenDim.h = myImageDim.h;
697
else // otherwise, search for a valid screenmode
699
for(uInt32 i = myScreenmodeCount-1; i >= 0; i--)
701
if(myImageDim.w <= myScreenmode[i]->w && myImageDim.h <= myScreenmode[i]->h)
703
myScreenDim.w = myScreenmode[i]->w;
704
myScreenDim.h = myScreenmode[i]->h;
710
// Now calculate the OpenGL coordinates
711
myImageDim.x = (myScreenDim.w - myImageDim.w) / 2;
712
myImageDim.y = (myScreenDim.h - myImageDim.h) / 2;
714
*orthoWidth = (GLdouble) (myImageDim.w / (theZoomLevel * theAspectRatio * myFSScaleFactor));
715
*orthoHeight = (GLdouble) (myImageDim.h / (theZoomLevel * myFSScaleFactor));
719
*orthoWidth = (GLdouble) (myImageDim.w / (theZoomLevel * theAspectRatio));
720
*orthoHeight = (GLdouble) (myImageDim.h / theZoomLevel);
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;
737
SDL_PixelFormat* fmt = myTexture->format;
739
SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16,
740
fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask);
742
return data ? new GUI::Surface(width, height, data) : NULL;
730
745
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
731
bool FrameBufferGL::myFuncsLoaded = false;
746
bool FrameBufferGL::myLibraryLoaded = false;
733
748
#endif // DISPLAY_OPENGL