242 lines
7.1 KiB
C
242 lines
7.1 KiB
C
#define GL_GLEXT_LEGACY
|
|
#ifdef APPLEOPENGL
|
|
#include <OpenGL/gl.h>
|
|
#include <OpenGL/glu.h>
|
|
#include <OpenGL/glext.h>
|
|
#else
|
|
#include <GL/gl.h>
|
|
#include <GL/glu.h>
|
|
#include <GL/glext.h>
|
|
#endif
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "sdl.h"
|
|
#include "sdl-opengl.h"
|
|
#include "../common/vidblit.h"
|
|
|
|
#ifndef APIENTRY
|
|
#define APIENTRY
|
|
#endif
|
|
|
|
static GLuint textures[2]={0,0}; // Normal image, scanline overlay.
|
|
|
|
static int left,right,top,bottom; // right and bottom are not inclusive.
|
|
static int scanlines;
|
|
static void *HiBuffer;
|
|
|
|
void APIENTRY (*p_glBindTexture)(GLenum target,GLuint texture);
|
|
void APIENTRY (*p_glColorTableEXT)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
|
|
void APIENTRY (*p_glTexImage2D)( GLenum target, GLint level,
|
|
GLint internalFormat,
|
|
GLsizei width, GLsizei height, GLint border,
|
|
GLenum format, GLenum type,
|
|
const GLvoid *pixels );
|
|
void APIENTRY (*p_glBegin)(GLenum mode);
|
|
void APIENTRY (*p_glVertex2f)(GLfloat x, GLfloat y);
|
|
void APIENTRY (*p_glTexCoord2f)(GLfloat s, GLfloat t);
|
|
void APIENTRY (*p_glEnd)(void);
|
|
void APIENTRY (*p_glEnable)(GLenum cap);
|
|
void APIENTRY (*p_glBlendFunc)(GLenum sfactor, GLenum dfactor);
|
|
const GLubyte* APIENTRY (*p_glGetString)(GLenum name);
|
|
void APIENTRY (*p_glViewport)(GLint x, GLint y,GLsizei width, GLsizei height);
|
|
void APIENTRY (*p_glGenTextures)(GLsizei n, GLuint *textures);
|
|
void APIENTRY (*p_glDeleteTextures)(GLsizei n,const GLuint *textures);
|
|
void APIENTRY (*p_glTexParameteri)(GLenum target, GLenum pname, GLint param);
|
|
void APIENTRY (*p_glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
|
void APIENTRY (*p_glLoadIdentity)(void);
|
|
void APIENTRY (*p_glClear)(GLbitfield mask);
|
|
void APIENTRY (*p_glMatrixMode)(GLenum mode);
|
|
void APIENTRY (*p_glDisable)(GLenum cap);
|
|
|
|
void SetOpenGLPalette(uint8 *data)
|
|
{
|
|
if(!HiBuffer)
|
|
{
|
|
p_glBindTexture(GL_TEXTURE_2D, textures[0]);
|
|
p_glColorTableEXT(GL_TEXTURE_2D,GL_RGB,256,GL_RGBA,GL_UNSIGNED_BYTE,data);
|
|
}
|
|
else
|
|
SetPaletteBlitToHigh((uint8*)data);
|
|
}
|
|
|
|
void BlitOpenGL(uint8 *buf)
|
|
{
|
|
p_glBindTexture(GL_TEXTURE_2D, textures[0]);
|
|
if(HiBuffer)
|
|
{
|
|
static int xo=0;
|
|
xo=(xo+1)&3;
|
|
Blit8ToHigh(buf,(uint8*)HiBuffer,256,240,256*4,1,1);
|
|
if(!xo)
|
|
p_glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,256,256, 0, GL_RGBA,GL_UNSIGNED_BYTE,
|
|
HiBuffer);
|
|
}
|
|
else
|
|
{
|
|
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 256);
|
|
p_glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, 256, 256, 0,
|
|
GL_COLOR_INDEX,GL_UNSIGNED_BYTE,buf);
|
|
}
|
|
|
|
p_glBegin(GL_QUADS);
|
|
p_glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of our picture.
|
|
p_glVertex2f(-1.0f, -1.0f); // Bottom left of target.
|
|
|
|
p_glTexCoord2f(1.0f*right/256, 1.0f*bottom/256); // Bottom right of our picture.
|
|
p_glVertex2f( 1.0f, -1.0f); // Bottom right of target.
|
|
|
|
p_glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture.
|
|
p_glVertex2f( 1.0f, 1.0f); // Top right of target.
|
|
|
|
p_glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture.
|
|
p_glVertex2f(-1.0f, 1.0f); // Top left of target.
|
|
p_glEnd();
|
|
|
|
//glDisable(GL_BLEND);
|
|
if(scanlines)
|
|
{
|
|
p_glEnable(GL_BLEND);
|
|
|
|
p_glBindTexture(GL_TEXTURE_2D, textures[1]);
|
|
p_glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
|
|
|
|
p_glBegin(GL_QUADS);
|
|
|
|
p_glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of our picture.
|
|
p_glVertex2f(-1.0f, -1.0f); // Bottom left of target.
|
|
|
|
p_glTexCoord2f(1.0f*right/256, 1.0f*bottom/256); // Bottom right of our picture.
|
|
p_glVertex2f( 1.0f, -1.0f); // Bottom right of target.
|
|
|
|
p_glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture.
|
|
p_glVertex2f( 1.0f, 1.0f); // Top right of target.
|
|
|
|
p_glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture.
|
|
p_glVertex2f(-1.0f, 1.0f); // Top left of target.
|
|
|
|
p_glEnd();
|
|
p_glDisable(GL_BLEND);
|
|
}
|
|
SDL_GL_SwapBuffers();
|
|
}
|
|
|
|
void KillOpenGL(void)
|
|
{
|
|
if(textures[0])
|
|
p_glDeleteTextures(2, &textures[0]);
|
|
textures[0]=0;
|
|
if(HiBuffer)
|
|
{
|
|
free(HiBuffer);
|
|
HiBuffer=0;
|
|
}
|
|
}
|
|
/* Rectangle, left, right(not inclusive), top, bottom(not inclusive). */
|
|
|
|
int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx, int ipolate,
|
|
int stretchx, int stretchy, SDL_Surface *screen)
|
|
{
|
|
const char *extensions;
|
|
|
|
#define LFG(x) if(!(p_##x = SDL_GL_GetProcAddress(#x))) return(0);
|
|
|
|
#define LFGN(x) p_##x = SDL_GL_GetProcAddress(#x)
|
|
|
|
LFG(glBindTexture);
|
|
LFGN(glColorTableEXT);
|
|
LFG(glTexImage2D);
|
|
LFG(glBegin);
|
|
LFG(glVertex2f);
|
|
LFG(glTexCoord2f);
|
|
LFG(glEnd);
|
|
LFG(glEnable);
|
|
LFG(glBlendFunc);
|
|
LFG(glGetString);
|
|
LFG(glViewport);
|
|
LFG(glGenTextures);
|
|
LFG(glDeleteTextures);
|
|
LFG(glTexParameteri);
|
|
LFG(glClearColor);
|
|
LFG(glLoadIdentity);
|
|
LFG(glClear);
|
|
LFG(glMatrixMode);
|
|
LFG(glDisable);
|
|
|
|
left=l;
|
|
right=r;
|
|
top=t;
|
|
bottom=b;
|
|
|
|
HiBuffer=0;
|
|
|
|
extensions=(const char*)p_glGetString(GL_EXTENSIONS);
|
|
|
|
if((efx&2) || !extensions || !p_glColorTableEXT || !strstr(extensions,"GL_EXT_paletted_texture"))
|
|
{
|
|
if(!(efx&2)) // Don't want to print out a warning message in this case...
|
|
FCEU_printf("Paletted texture extension not found. Using slower texture format...");
|
|
HiBuffer=malloc(4*256*256);
|
|
memset(HiBuffer,0x00,4*256*256);
|
|
#ifndef LSB_FIRST
|
|
InitBlitToHigh(4,0xFF000000,0xFF0000,0xFF00,efx&2,0);
|
|
#else
|
|
InitBlitToHigh(4,0xFF,0xFF00,0xFF0000,efx&2,0);
|
|
#endif
|
|
}
|
|
|
|
{
|
|
int rw=(r-l)*xscale;
|
|
int rh=(b-t)*yscale;
|
|
int sx=(screen->w-rw)/2; // Start x
|
|
int sy=(screen->h-rh)/2; // Start y
|
|
|
|
if(stretchx) { sx=0; rw=screen->w; }
|
|
if(stretchy) { sy=0; rh=screen->h; }
|
|
p_glViewport(sx, sy, rw, rh);
|
|
}
|
|
p_glGenTextures(2, &textures[0]);
|
|
scanlines=0;
|
|
|
|
if(efx&1)
|
|
{
|
|
uint8 *buf;
|
|
int x,y;
|
|
|
|
scanlines=1;
|
|
|
|
p_glBindTexture(GL_TEXTURE_2D, textures[1]);
|
|
p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
|
|
p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
|
|
|
|
buf=(uint8*)malloc(256*(256*2)*4);
|
|
|
|
for(y=0;y<(256*2);y++)
|
|
for(x=0;x<256;x++)
|
|
{
|
|
buf[y*256*4+x*4]=0;
|
|
buf[y*256*4+x*4+1]=0;
|
|
buf[y*256*4+x*4+2]=0;
|
|
buf[y*256*4+x*4+3]=(y&1)?0x00:0xFF; //?0xa0:0xFF; // <-- Pretty
|
|
//buf[y*256+x]=(y&1)?0x00:0xFF;
|
|
}
|
|
p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, (scanlines==2)?256*4:512, 0,
|
|
GL_RGBA,GL_UNSIGNED_BYTE,buf);
|
|
free(buf);
|
|
}
|
|
p_glBindTexture(GL_TEXTURE_2D, textures[0]);
|
|
|
|
p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
|
|
p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
|
|
p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
|
|
p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
|
|
p_glEnable(GL_TEXTURE_2D);
|
|
p_glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black.
|
|
p_glMatrixMode(GL_MODELVIEW);
|
|
|
|
p_glClear(GL_COLOR_BUFFER_BIT);
|
|
p_glLoadIdentity();
|
|
|
|
return(1);
|
|
}
|