Win32: add support for cg meta shaders (currently opengl only)

This commit is contained in:
OV2 2011-07-02 04:25:13 +02:00
parent 3e84a2eaf4
commit 4d2fbc241a
11 changed files with 940 additions and 114 deletions

119
win32/CCGShader.cpp Normal file
View File

@ -0,0 +1,119 @@
#include "CCGShader.h"
#include "../conffile.h"
CCGShader::CCGShader(void)
{
}
CCGShader::~CCGShader(void)
{
}
cgScaleType CCGShader::scaleStringToEnum(const char *scale)
{
if(!strcasecmp(scale,"source")) {
return CG_SCALE_SOURCE;
} else if(!strcasecmp(scale,"viewport")) {
return CG_SCALE_VIEWPORT;
} else if(!strcasecmp(scale,"absolute")) {
return CG_SCALE_ABSOLUTE;
} else {
return CG_SCALE_NONE;
}
}
bool CCGShader::LoadShader(const char *path)
{
ConfigFile conf;
int shaderCount;
char keyName[100];
shaderPasses.clear();
lookupTextures.clear();
if(strlen(path)<4 || strcasecmp(&path[strlen(path)-4],".cgp")) {
shaderPass pass;
pass.scaleParams.scaleTypeX = CG_SCALE_NONE;
pass.scaleParams.scaleTypeY = CG_SCALE_NONE;
pass.linearFilter = false;
pass.filterSet = false;
strcpy(pass.cgShaderFile,path);
shaderPasses.push_back(pass);
return true;
} else {
conf.LoadFile(path);
}
shaderCount = conf.GetInt("::shaders",0);
if(shaderCount<1)
return false;
for(int i=0;i<shaderCount;i++) {
shaderPass pass;
sprintf(keyName,"::filter_linear%u",i);
pass.linearFilter = conf.GetBool(keyName);
pass.filterSet = conf.Exists(keyName);
sprintf(keyName,"::scale_type%u",i);
const char *scaleType = conf.GetString(keyName,"");
if(!strcasecmp(scaleType,"")) {
sprintf(keyName,"::scale_type_x%u",i);
const char *scaleTypeX = conf.GetString(keyName,"");
if(*scaleTypeX=='\0' && (i!=(shaderCount-1)))
scaleTypeX = "source";
pass.scaleParams.scaleTypeX = scaleStringToEnum(scaleTypeX);
sprintf(keyName,"::scale_type_y%u",i);
const char *scaleTypeY = conf.GetString(keyName,"");
if(*scaleTypeY=='\0' && (i!=(shaderCount-1)))
scaleTypeY = "source";
pass.scaleParams.scaleTypeY = scaleStringToEnum(scaleTypeY);
} else {
cgScaleType sType = scaleStringToEnum(scaleType);
pass.scaleParams.scaleTypeX = sType;
pass.scaleParams.scaleTypeY = sType;
}
sprintf(keyName,"::scale%u",i);
const char *scaleFloat = conf.GetString(keyName,"");
int scaleInt = conf.GetInt(keyName,0);
if(!strcasecmp(scaleFloat,"")) {
sprintf(keyName,"::scalex%u",i);
const char *scaleFloatX = conf.GetString(keyName,"1.0");
pass.scaleParams.scaleX = atof(scaleFloatX);
pass.scaleParams.absX = conf.GetInt(keyName,1);
sprintf(keyName,"::scaley%u",i);
const char *scaleFloatY = conf.GetString(keyName,"1.0");
pass.scaleParams.scaleY = atof(scaleFloatY);
pass.scaleParams.absY = conf.GetInt(keyName,1);
} else {
float floatval = atof(scaleFloat);
pass.scaleParams.scaleX = floatval;
pass.scaleParams.absX = scaleInt;
pass.scaleParams.scaleY = floatval;
pass.scaleParams.absY = scaleInt;
}
sprintf(keyName,"::shader%u",i);
strcpy(pass.cgShaderFile,conf.GetString(keyName,""));
shaderPasses.push_back(pass);
}
char *shaderIds = conf.GetStringDup("::textures","");
char *id = strtok(shaderIds,";");
while(id!=NULL) {
lookupTexture tex;
sprintf(keyName,"::%s",id);
strcpy(tex.id,id);
strcpy(tex.texturePath,conf.GetString(keyName,""));
sprintf(keyName,"::%s_linear",id);
tex.linearfilter = conf.GetBool(keyName,true);
lookupTextures.push_back(tex);
id = strtok(NULL,";");
}
return true;
}

43
win32/CCGShader.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef CCGSHADER_H
#define CCGSHADER_H
#include "port.h"
#include "cgFunctions.h"
#include <vector>
enum cgScaleType { CG_SCALE_NONE, CG_SCALE_SOURCE, CG_SCALE_VIEWPORT, CG_SCALE_ABSOLUTE };
typedef struct _cgScaleParams {
cgScaleType scaleTypeX;
cgScaleType scaleTypeY;
float scaleX;
float scaleY;
unsigned absX;
unsigned absY;
} cgScaleParams;
class CCGShader
{
private:
cgScaleType scaleStringToEnum(const char* scale);
public:
typedef struct _shaderPass {
cgScaleParams scaleParams;
bool linearFilter;
bool filterSet;
char cgShaderFile[PATH_MAX];
} shaderPass;
typedef struct _lookupTexture {
char id[PATH_MAX];
char texturePath[PATH_MAX];
bool linearfilter;
} lookupTexture;
CCGShader(void);
~CCGShader(void);
bool LoadShader(const char *path);
std::vector<shaderPass> shaderPasses;
std::vector<lookupTexture> lookupTextures;
};
#endif

594
win32/CGLCG.cpp Normal file
View File

@ -0,0 +1,594 @@
#include "CGLCG.h"
#include "wsnes9x.h"
#include "win32_display.h"
#include <png.h>
#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif
float npot(float desired)
{
float out=512.0;
while(out<desired)
out*=2;
return out;
}
const GLfloat CGLCG::lut_coords[8] = {0, 0, 1, 0, 1, 1, 0, 1};
CGLCG::CGLCG(CGcontext cgContext)
{
this->cgContext = cgContext;
fboFunctionsLoaded = FALSE;
ClearPasses();
LoadFBOFunctions();
frameCnt=0;
}
CGLCG::~CGLCG(void)
{
}
void CGLCG::ClearPasses()
{
if(shaderPasses.size()>1) {
for(std::vector<shaderPass>::iterator it=(shaderPasses.begin()+1);it!=shaderPasses.end();it++) {
if(it->cgFragmentProgram)
cgDestroyProgram(it->cgFragmentProgram);
if(it->cgVertexProgram)
cgDestroyProgram(it->cgVertexProgram);
if(it->fbo)
glDeleteFramebuffers(1,&it->fbo);
if(it->tex)
glDeleteTextures(1,&it->tex);
}
}
for(std::vector<lookupTexture>::iterator it=lookupTextures.begin();it!=lookupTextures.end();it++) {
if(it->tex)
glDeleteTextures(1,&it->tex);
}
shaderPasses.clear();
lookupTextures.clear();
shaderLoaded = false;
}
bool CGLCG::LoadFBOFunctions()
{
if(fboFunctionsLoaded)
return true;
const char *extensions = (const char *) glGetString(GL_EXTENSIONS);
if(extensions && strstr(extensions, "framebuffer_object")) {
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffers");
glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffers");
glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer");
glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2D");
glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatus");
glClientActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glClientActiveTexture");
if(glGenFramebuffers && glDeleteFramebuffers && glBindFramebuffer && glFramebufferTexture2D && glClientActiveTexture) {
fboFunctionsLoaded = true;
}
}
return fboFunctionsLoaded;
}
void CGLCG::checkForCgError(const char *situation)
{
char buffer[4096];
CGerror error = cgGetError();
const char *string = cgGetErrorString(error);
if (error != CG_NO_ERROR) {
sprintf(buffer,
"Situation: %s\n"
"Error: %s\n\n"
"Cg compiler output...\n", situation, string);
MessageBoxA(0, buffer,
"Cg error", MB_OK|MB_ICONEXCLAMATION);
if (error == CG_COMPILER_ERROR) {
MessageBoxA(0, cgGetLastListing(cgContext),
"Cg compilation error", MB_OK|MB_ICONEXCLAMATION);
}
}
}
#define IS_SLASH(x) ((x) == TEXT('\\') || (x) == TEXT('/'))
bool CGLCG::LoadShader(const TCHAR *shaderFile)
{
CCGShader cgShader;
TCHAR shaderPath[MAX_PATH];
TCHAR tempPath[MAX_PATH];
CGprofile vertexProfile, fragmentProfile;
GLenum error;
if(!fboFunctionsLoaded) {
MessageBox(NULL, TEXT("Your OpenGL graphics driver does not support framebuffer objects.\nYou will not be able to use CG shaders in OpenGL mode."), TEXT("CG Error"),
MB_OK|MB_ICONEXCLAMATION);
return false;
}
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLDisableProfile(vertexProfile);
cgGLDisableProfile(fragmentProfile);
ClearPasses();
if (shaderFile == NULL || *shaderFile==TEXT('\0'))
return true;
lstrcpy(shaderPath,shaderFile);
for(int i=lstrlen(shaderPath); i>=0; i--){
if(IS_SLASH(shaderPath[i])){
shaderPath[i]=TEXT('\0');
break;
}
}
SetCurrentDirectory(shaderPath);
if(!cgShader.LoadShader(_tToChar(shaderFile)))
return false;
cgGLSetOptimalOptions(vertexProfile);
cgGLSetOptimalOptions(fragmentProfile);
shaderPasses.push_back(shaderPass());
for(std::vector<CCGShader::shaderPass>::iterator it=cgShader.shaderPasses.begin();it!=cgShader.shaderPasses.end();it++) {
shaderPasses.push_back(shaderPass());
shaderPass &pass = shaderPasses.back();
pass.scaleParams = it->scaleParams;
pass.linearFilter = (pass.scaleParams.scaleTypeX==CG_SCALE_NONE && !it->filterSet)?GUI.BilinearFilter:it->linearFilter;
_tfullpath(tempPath,_tFromChar(it->cgShaderFile),MAX_PATH);
char *fileContents = ReadShaderFileContents(tempPath);
if(!fileContents)
return false;
pass.cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents,
vertexProfile, "main_vertex", NULL);
checkForCgError("Compiling vertex program");
pass.cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents,
fragmentProfile, "main_fragment", NULL);
checkForCgError("Compiling fragment program");
delete [] fileContents;
if(!pass.cgVertexProgram || !pass.cgFragmentProgram) {
return false;
}
cgGLLoadProgram(pass.cgVertexProgram);
cgGLLoadProgram(pass.cgFragmentProgram);
glGenFramebuffers(1,&pass.fbo);
glGenTextures(1,&pass.tex);
glBindTexture(GL_TEXTURE_2D,pass.tex);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
for(std::vector<CCGShader::lookupTexture>::iterator it=cgShader.lookupTextures.begin();it!=cgShader.lookupTextures.end();it++) {
lookupTextures.push_back(lookupTexture());
lookupTexture &tex = lookupTextures.back();
strcpy(tex.id,it->id);
glGenTextures(1,&tex.tex);
glBindTexture(GL_TEXTURE_2D,tex.tex);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, it->linearfilter?GL_LINEAR:GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, it->linearfilter?GL_LINEAR:GL_NEAREST);
_tfullpath(tempPath,_tFromChar(it->texturePath),MAX_PATH);
int strLen = strlen(it->texturePath);
if(strLen>4) {
if(!strcasecmp(&it->texturePath[strLen-4],".png")) {
int width, height;
bool hasAlpha;
GLubyte *texData;
if(loadPngImage(tempPath,width,height,hasAlpha,&texData)) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
glTexImage2D(GL_TEXTURE_2D, 0, hasAlpha ? 4 : 3, width,
height, 0, hasAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, texData);
free(texData);
}
} else if(!strcasecmp(&it->texturePath[strLen-4],".tga")) {
STGA stga;
if(loadTGA(tempPath,stga)) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, stga.width);
glTexImage2D(GL_TEXTURE_2D, 0, 4, stga.width,
stga.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, stga.data);
}
}
}
}
glClientActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2,GL_FLOAT,0,lut_coords);
glClientActiveTexture(GL_TEXTURE0);
shaderLoaded = true;
return true;
}
void CGLCG::setTexCoords(int pass,xySize inputSize,xySize textureSize,bool topdown)
{
float tX = inputSize.x / textureSize.x;
float tY = inputSize.y / textureSize.y;
if(topdown) {
shaderPasses[pass].texcoords[0] = 0.0f;
shaderPasses[pass].texcoords[1] = tY;
shaderPasses[pass].texcoords[2] = tX;
shaderPasses[pass].texcoords[3] = tY;
shaderPasses[pass].texcoords[4] = tX;
shaderPasses[pass].texcoords[5] = 0.0f;
shaderPasses[pass].texcoords[6] = 0.0f;
shaderPasses[pass].texcoords[7] = 0.0f;
} else {
shaderPasses[pass].texcoords[0] = 0.0f;
shaderPasses[pass].texcoords[1] = 0.0f;
shaderPasses[pass].texcoords[2] = tX;
shaderPasses[pass].texcoords[3] = 0.0f;
shaderPasses[pass].texcoords[4] = tX;
shaderPasses[pass].texcoords[5] = tY;
shaderPasses[pass].texcoords[6] = 0.0f;
shaderPasses[pass].texcoords[7] = tY;
}
glTexCoordPointer(2, GL_FLOAT, 0, shaderPasses[pass].texcoords);
}
void CGLCG::Render(GLuint origTex, xySize textureSize, xySize inputSize, xySize viewportSize, xySize windowSize)
{
GLenum error;
frameCnt++;
CGprofile vertexProfile, fragmentProfile;
if(!shaderLoaded)
return;
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLEnableProfile(vertexProfile);
cgGLEnableProfile(fragmentProfile);
shaderPasses[0].tex = origTex;
shaderPasses[0].outputSize = inputSize;
shaderPasses[0].textureSize = textureSize;
for(int i=1;i<shaderPasses.size();i++) {
switch(shaderPasses[i].scaleParams.scaleTypeX) {
case CG_SCALE_ABSOLUTE:
shaderPasses[i].outputSize.x = (double)shaderPasses[i].scaleParams.absX;
break;
case CG_SCALE_SOURCE:
shaderPasses[i].outputSize.x = shaderPasses[i-1].outputSize.x * shaderPasses[i].scaleParams.scaleX;
break;
case CG_SCALE_VIEWPORT:
shaderPasses[i].outputSize.x = viewportSize.x * shaderPasses[i].scaleParams.scaleX;
break;
default:
shaderPasses[i].outputSize.x = viewportSize.x;
}
switch(shaderPasses[i].scaleParams.scaleTypeY) {
case CG_SCALE_ABSOLUTE:
shaderPasses[i].outputSize.y = (double)shaderPasses[i].scaleParams.absX;
break;
case CG_SCALE_SOURCE:
shaderPasses[i].outputSize.y = shaderPasses[i-1].outputSize.y * shaderPasses[i].scaleParams.scaleY;
break;
case CG_SCALE_VIEWPORT:
shaderPasses[i].outputSize.y = viewportSize.y * shaderPasses[i].scaleParams.scaleY;
break;
default:
shaderPasses[i].outputSize.y = viewportSize.y;
}
float texSize = npot(max(shaderPasses[i].outputSize.x,shaderPasses[i].outputSize.y));
shaderPasses[i].textureSize.x = shaderPasses[i].textureSize.y = texSize;
setShaderVars(i);
setTexCoords(i,shaderPasses[i-1].outputSize,shaderPasses[i-1].textureSize);
cgGLBindProgram(shaderPasses[i].cgVertexProgram);
cgGLBindProgram(shaderPasses[i].cgFragmentProgram);
glBindTexture(GL_TEXTURE_2D,shaderPasses[i].tex);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,(unsigned int)shaderPasses[i].textureSize.x,(unsigned int)shaderPasses[i].textureSize.y,0,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,NULL);
glViewport(0,0,shaderPasses[i].outputSize.x,shaderPasses[i].outputSize.y);
glBindFramebuffer(GL_FRAMEBUFFER,shaderPasses[i].fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shaderPasses[i].tex, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindTexture(GL_TEXTURE_2D,shaderPasses[i-1].tex);
glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)shaderPasses[i-1].textureSize.x);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shaderPasses[i].linearFilter?GL_LINEAR:GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, shaderPasses[i].linearFilter?GL_LINEAR:GL_NEAREST);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays (GL_QUADS, 0, 4);
}
glBindFramebuffer(GL_FRAMEBUFFER,0);
glBindTexture(GL_TEXTURE_2D,shaderPasses.back().tex);
glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)shaderPasses.back().textureSize.x);
RECT displayRect=CalculateDisplayRect(shaderPasses.back().outputSize.x,shaderPasses.back().outputSize.y,windowSize.x,windowSize.y);
glViewport(displayRect.left,windowSize.y-displayRect.bottom,displayRect.right-displayRect.left,displayRect.bottom-displayRect.top);
setTexCoords(shaderPasses.size()-1,shaderPasses.back().outputSize,shaderPasses.back().textureSize,true);
cgGLDisableProfile(vertexProfile);
cgGLDisableProfile(fragmentProfile);
}
void CGLCG::setShaderVars(int pass)
{
float inputSize[2] = {shaderPasses[pass-1].outputSize.x,shaderPasses[pass-1].outputSize.y};
float textureSize[2] = {shaderPasses[pass-1].textureSize.x,shaderPasses[pass-1].textureSize.y};
float outputSize[2] = {shaderPasses[pass].outputSize.x,shaderPasses[pass].outputSize.y};
CGparameter cgpModelViewProj = cgGetNamedParameter(shaderPasses[pass].cgVertexProgram, "modelViewProj");
cgGLSetStateMatrixParameter(cgpModelViewProj, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
#define setProgram2fv(pass,varname,floats)\
{\
CGparameter cgpf = cgGetNamedParameter(shaderPasses[pass].cgFragmentProgram, varname);\
CGparameter cgpv = cgGetNamedParameter(shaderPasses[pass].cgVertexProgram, varname);\
if(cgpf)\
cgGLSetParameter2fv(cgpf,floats);\
if(cgpv)\
cgGLSetParameter2fv(cgpv,floats);\
}\
#define setProgram1f(pass,varname,val)\
{\
CGparameter cgpf = cgGetNamedParameter(shaderPasses[pass].cgFragmentProgram, varname);\
CGparameter cgpv = cgGetNamedParameter(shaderPasses[pass].cgVertexProgram, varname);\
if(cgpf)\
cgGLSetParameter1f(cgpf,val);\
if(cgpv)\
cgGLSetParameter1f(cgpv,val);\
}\
#define setTextureParameter(pass,varname,val)\
{\
CGparameter cgpf = cgGetNamedParameter(shaderPasses[pass].cgFragmentProgram, varname);\
if(cgpf) {\
cgGLSetTextureParameter(cgpf,val);\
cgGLEnableTextureParameter(cgpf);\
}\
}\
#define setTexCoordsParameter(pass,varname,val)\
{\
CGparameter cgpv = cgGetNamedParameter(shaderPasses[pass].cgVertexProgram, varname);\
if(cgpv) {\
cgGLSetParameterPointer(cgpv, 2, GL_FLOAT, 0, val);\
cgGLEnableClientState(cgpv);\
}\
}\
setProgram2fv(pass,"IN.video_size",inputSize);
setProgram2fv(pass,"IN.texture_size",textureSize);
setProgram2fv(pass,"IN.output_size",outputSize);
setProgram1f(pass,"IN.frame_count",(float)frameCnt);
float video_Size[2] = {shaderPasses[0].outputSize.x,shaderPasses[0].outputSize.y};
float texture_Size[2] = {shaderPasses[0].textureSize.x,shaderPasses[0].outputSize.y};
setProgram2fv(pass,"ORIG.video_size",video_Size);
setProgram2fv(pass,"ORIG.texture_size",texture_Size);
setTextureParameter(pass,"ORIG.texture",shaderPasses[0].tex);
setTexCoordsParameter(pass,"ORIG.tex_coord",shaderPasses[0].texcoords);
for(int i=0;i<lookupTextures.size();i++) {
setTextureParameter(pass,lookupTextures[i].id,lookupTextures[i].tex);
}
if(pass>1) {
for(int i=1;i<pass-1;i++) {
char varname[100];
float video_Size[2] = {shaderPasses[i].outputSize.x,shaderPasses[i].outputSize.y};
float texture_Size[2] = {shaderPasses[i].textureSize.x,shaderPasses[i].outputSize.y};
sprintf(varname,"PASS%d.video_size",i);
setProgram2fv(i,varname,video_Size);
sprintf(varname,"PASS%d.texture_size",i);
setProgram2fv(i,varname,texture_Size);
sprintf(varname,"PASS%d.texture",i);
setTextureParameter(i,varname,shaderPasses[i].tex);
sprintf(varname,"PASS%d.tex_coord",i);
setTexCoordsParameter(i,varname,shaderPasses[i].texcoords);
}
}
}
bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) {
png_structp png_ptr;
png_infop info_ptr;
unsigned int sig_read = 0;
int color_type, interlace_type;
FILE *fp;
if ((fp = _tfopen(name, TEXT("rb"))) == NULL)
return false;
/* Create and initialize the png_struct
* with the desired error handler
* functions. If you want to use the
* default stderr and longjump method,
* you can supply NULL for the last
* three parameters. We also supply the
* the compiler header file version, so
* that we know if the application
* was compiled with a compatible version
* of the library. REQUIRED
*/
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL);
if (png_ptr == NULL) {
fclose(fp);
return false;
}
/* Allocate/initialize the memory
* for image information. REQUIRED. */
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
fclose(fp);
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
return false;
}
/* Set error handling if you are
* using the setjmp/longjmp method
* (this is the normal method of
* doing things with libpng).
* REQUIRED unless you set up
* your own error handlers in
* the png_create_read_struct()
* earlier.
*/
if (setjmp(png_jmpbuf(png_ptr))) {
/* Free all of the memory associated
* with the png_ptr and info_ptr */
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
fclose(fp);
/* If we get here, we had a
* problem reading the file */
return false;
}
/* Set up the output control if
* you are using standard C streams */
png_init_io(png_ptr, fp);
/* If we have already
* read some of the signature */
png_set_sig_bytes(png_ptr, sig_read);
/*
* If you have enough memory to read
* in the entire image at once, and
* you need to specify only
* transforms that can be controlled
* with one of the PNG_TRANSFORM_*
* bits (this presently excludes
* dithering, filling, setting
* background, and doing gamma
* adjustment), then you can read the
* entire image (including pixels)
* into the info structure with this
* call
*
* PNG_TRANSFORM_STRIP_16 |
* PNG_TRANSFORM_PACKING forces 8 bit
* PNG_TRANSFORM_EXPAND forces to
* expand a palette into RGB
*/
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, png_voidp_NULL);
outWidth = info_ptr->width;
outHeight = info_ptr->height;
switch (info_ptr->color_type) {
case PNG_COLOR_TYPE_RGBA:
outHasAlpha = true;
break;
case PNG_COLOR_TYPE_RGB:
outHasAlpha = false;
break;
default:
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(fp);
return false;
}
unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
*outData = (unsigned char*) malloc(row_bytes * outHeight);
png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);
for (int i = 0; i < outHeight; i++) {
memcpy(*outData+(row_bytes * i), row_pointers[i], row_bytes);
}
/* Clean up after the read,
* and free any memory allocated */
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
/* Close the file */
fclose(fp);
/* That's it */
return true;
}
bool CGLCG::loadTGA(const TCHAR *filename, STGA& tgaFile)
{
FILE *file;
unsigned char type[4];
unsigned char info[6];
file = _tfopen(filename, TEXT("rb"));
if (!file)
return false;
fread (&type, sizeof (char), 3, file);
fseek (file, 12, SEEK_SET);
fread (&info, sizeof (char), 6, file);
//image type either 2 (color) or 3 (greyscale)
if (type[1] != 0 || (type[2] != 2 && type[2] != 3))
{
fclose(file);
return false;
}
tgaFile.width = info[0] + info[1] * 256;
tgaFile.height = info[2] + info[3] * 256;
tgaFile.byteCount = info[4] / 8;
if (tgaFile.byteCount != 3 && tgaFile.byteCount != 4) {
fclose(file);
return false;
}
long imageSize = tgaFile.width * tgaFile.height * tgaFile.byteCount;
//allocate memory for image data
unsigned char *tempBuf = new unsigned char[imageSize];
tgaFile.data = new unsigned char[tgaFile.width * tgaFile.height * 4];
//read in image data
fread(tempBuf, sizeof(unsigned char), imageSize, file);
//swap line order and convert to RBGA
for(int i=0;i<tgaFile.height;i++) {
unsigned char* source = tempBuf + tgaFile.width * (tgaFile.height - 1 - i) * tgaFile.byteCount;
unsigned char* destination = tgaFile.data + tgaFile.width * i * 4;
for(int j=0;j<tgaFile.width;j++) {
destination[0]=source[2];
destination[1]=source[1];
destination[2]=source[0];
destination[3]=tgaFile.byteCount==4?source[3]:0xff;
source+=tgaFile.byteCount;
destination+=4;
}
}
delete [] tempBuf;
tgaFile.byteCount = 4;
//close file
fclose(file);
return true;
}

87
win32/CGLCG.h Normal file
View File

@ -0,0 +1,87 @@
#ifndef CGGLCG_H
#define CGGLCG_H
#include <windows.h>
#include <gl/gl.h>
#include "glext.h"
#include "cgFunctions.h"
#include "CCGShader.h"
#include <vector>
typedef struct _xySize {
double x;
double y;
} xySize;
class CGLCG
{
private:
typedef struct _STGA {
_STGA() {data = (unsigned char*)0;
width = 0;
height = 0;
byteCount = 0;}
~_STGA() { delete[] data; data = 0; }
void destroy() { delete[] data; data = 0; }
int width;
int height;
unsigned char byteCount;
unsigned char* data;
} STGA;
typedef struct _shaderPass {
cgScaleParams scaleParams;
bool linearFilter;
CGprogram cgVertexProgram, cgFragmentProgram;
GLuint tex;
GLuint fbo;
xySize outputSize;
xySize textureSize;
GLfloat texcoords[8];
_shaderPass() {cgVertexProgram=NULL;
cgFragmentProgram=NULL;
fbo=NULL;
tex=NULL;}
} shaderPass;
typedef struct _lookupTexture {
char id[PATH_MAX];
GLuint tex;
_lookupTexture() {tex=NULL;}
} lookupTexture;
std::vector<shaderPass> shaderPasses;
std::vector<lookupTexture> lookupTextures;
bool fboFunctionsLoaded;
bool shaderLoaded;
bool LoadFBOFunctions();
void checkForCgError(const char *situation);
void setTexCoords(int pass,xySize inputSize,xySize textureSize,bool topdown=false);
void setShaderVars(int pass);
bool loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData);
bool loadTGA(const TCHAR *filename, STGA& tgaFile);
CGcontext cgContext;
int frameCnt;
static const GLfloat lut_coords[8];
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
PFNGLACTIVETEXTUREPROC glClientActiveTexture;
public:
CGLCG(CGcontext cgContext);
~CGLCG(void);
bool LoadShader(const TCHAR *shaderFile);
void Render(GLuint origTex, xySize textureSize, xySize inputSize, xySize viewportSize, xySize windowSize);
void ClearPasses();
};
#endif

View File

@ -211,6 +211,7 @@ COpenGL::COpenGL(void)
cgVertexProgram = cgFragmentProgram = NULL; cgVertexProgram = cgFragmentProgram = NULL;
cgAvailable = false; cgAvailable = false;
frameCount = 0; frameCount = 0;
cgShader = NULL;
} }
COpenGL::~COpenGL(void) COpenGL::~COpenGL(void)
@ -285,6 +286,7 @@ bool COpenGL::Initialize(HWND hWnd)
cgAvailable = loadCgFunctions(); cgAvailable = loadCgFunctions();
if(cgAvailable) { if(cgAvailable) {
cgContext = cgCreateContext(); cgContext = cgCreateContext();
cgShader = new CGLCG(cgContext);
} }
GetClientRect(hWnd,&windowRect); GetClientRect(hWnd,&windowRect);
@ -323,6 +325,10 @@ void COpenGL::DeInitialize()
if(cgAvailable) if(cgAvailable)
unloadCgLibrary(); unloadCgLibrary();
cgAvailable = false; cgAvailable = false;
if(cgShader) {
delete cgShader;
cgShader = NULL;
}
} }
void COpenGL::CreateDrawSurface() void COpenGL::CreateDrawSurface()
@ -402,6 +408,7 @@ void COpenGL::SetupVertices()
texcoords[5] = 0.0f; texcoords[5] = 0.0f;
texcoords[6] = 0.0f; texcoords[6] = 0.0f;
texcoords[7] = 0.0f; texcoords[7] = 0.0f;
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
} }
void COpenGL::Render(SSurface Src) void COpenGL::Render(SSurface Src)
@ -421,6 +428,7 @@ void COpenGL::Render(SSurface Src)
} }
if(pboFunctionsLoaded) { if(pboFunctionsLoaded) {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, drawBuffer);
Dst.Surface = (unsigned char *)glMapBuffer(GL_PIXEL_UNPACK_BUFFER,GL_WRITE_ONLY); Dst.Surface = (unsigned char *)glMapBuffer(GL_PIXEL_UNPACK_BUFFER,GL_WRITE_ONLY);
} else { } else {
Dst.Surface = noPboBuffer; Dst.Surface = noPboBuffer;
@ -444,7 +452,16 @@ void COpenGL::Render(SSurface Src)
ApplyDisplayChanges(); ApplyDisplayChanges();
} }
glBindTexture(GL_TEXTURE_2D,drawTexture);
glPixelStorei(GL_UNPACK_ROW_LENGTH, quadTextureSize);
glTexSubImage2D (GL_TEXTURE_2D,0,0,0,dstRect.right-dstRect.left,dstRect.bottom-dstRect.top,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,pboFunctionsLoaded?0:noPboBuffer);
if(pboFunctionsLoaded)
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
if (shader_type != OGL_SHADER_NONE) { if (shader_type != OGL_SHADER_NONE) {
if(shader_type == OGL_SHADER_GLSL) {
GLint location; GLint location;
float inputSize[2] = { (float)afterRenderWidth, (float)afterRenderHeight }; float inputSize[2] = { (float)afterRenderWidth, (float)afterRenderHeight };
@ -454,8 +471,6 @@ void COpenGL::Render(SSurface Src)
(float)(GUI.Stretch?windowSize.bottom:afterRenderHeight) }; (float)(GUI.Stretch?windowSize.bottom:afterRenderHeight) };
float textureSize[2] = { (float)quadTextureSize, (float)quadTextureSize }; float textureSize[2] = { (float)quadTextureSize, (float)quadTextureSize };
float frameCnt = (float)++frameCount; float frameCnt = (float)++frameCount;
if(shader_type == OGL_SHADER_GLSL) {
location = glGetUniformLocation (shaderProgram, "rubyInputSize"); location = glGetUniformLocation (shaderProgram, "rubyInputSize");
glUniform2fv (location, 1, inputSize); glUniform2fv (location, 1, inputSize);
@ -465,37 +480,26 @@ void COpenGL::Render(SSurface Src)
location = glGetUniformLocation (shaderProgram, "rubyTextureSize"); location = glGetUniformLocation (shaderProgram, "rubyTextureSize");
glUniform2fv (location, 1, textureSize); glUniform2fv (location, 1, textureSize);
} else if(shader_type == OGL_SHADER_CG) { } else if(shader_type == OGL_SHADER_CG) {
CGparameter cgpModelViewProj = cgGetNamedParameter(cgVertexProgram, "modelViewProj"); xySize inputSize = { (float)afterRenderWidth, (float)afterRenderHeight };
RECT windowSize, displayRect;
cgGLSetStateMatrixParameter(cgpModelViewProj, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); GetClientRect(hWnd,&windowSize);
xySize xywindowSize = { (double)windowSize.right, (double)windowSize.bottom };
#define setProgram2fv(program,varname,floats)\ //Get maximum rect respecting AR setting
{\ displayRect=CalculateDisplayRect(windowSize.right,windowSize.bottom,windowSize.right,windowSize.bottom);
CGparameter cgp = cgGetNamedParameter(program, varname);\ xySize viewportSize = { (double)(displayRect.right - displayRect.left),
if(cgp)\ (double)(displayRect.bottom - displayRect.top) };
cgGLSetParameter2fv(cgp,floats);\ xySize textureSize = { (double)quadTextureSize, (double)quadTextureSize };
}\ cgShader->Render(drawTexture, textureSize, inputSize, viewportSize, xywindowSize);
#define setProgram1f(program,varname,val)\
{\
CGparameter cgp = cgGetNamedParameter(program, varname);\
if(cgp)\
cgGLSetParameter1f(cgp,val);\
}\
setProgram2fv(cgFragmentProgram,"IN.video_size",inputSize);
setProgram2fv(cgFragmentProgram,"IN.texture_size",textureSize);
setProgram2fv(cgFragmentProgram,"IN.output_size",outputSize);
setProgram1f(cgFragmentProgram,"IN.frame_count",frameCnt);
setProgram2fv(cgVertexProgram,"IN.video_size",inputSize);
setProgram2fv(cgVertexProgram,"IN.texture_size",textureSize);
setProgram2fv(cgVertexProgram,"IN.output_size",outputSize);
setProgram1f(cgVertexProgram,"IN.frame_count",frameCnt);
} }
} }
glPixelStorei(GL_UNPACK_ROW_LENGTH, quadTextureSize); if(GUI.BilinearFilter) {
glTexSubImage2D (GL_TEXTURE_2D,0,0,0,dstRect.right-dstRect.left,dstRect.bottom-dstRect.top,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,pboFunctionsLoaded?0:noPboBuffer); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
@ -515,13 +519,6 @@ bool COpenGL::ChangeRenderSize(unsigned int newWidth, unsigned int newHeight)
bool COpenGL::ApplyDisplayChanges(void) bool COpenGL::ApplyDisplayChanges(void)
{ {
if(GUI.BilinearFilter) {
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
if(wglSwapIntervalEXT) { if(wglSwapIntervalEXT) {
wglSwapIntervalEXT(GUI.Vsync?1:0); wglSwapIntervalEXT(GUI.Vsync?1:0);
} }
@ -683,7 +680,9 @@ bool COpenGL::SetShaders(const TCHAR *file)
SetShadersCG(NULL); SetShadersCG(NULL);
SetShadersGLSL(NULL); SetShadersGLSL(NULL);
shader_type = OGL_SHADER_NONE; shader_type = OGL_SHADER_NONE;
if(file!=NULL && lstrlen(file)>3 && _tcsncicmp(&file[lstrlen(file)-3],TEXT(".cg"),3)==0) { if(file!=NULL && (
(lstrlen(file)>3 && _tcsncicmp(&file[lstrlen(file)-3],TEXT(".cg"),3)==0) ||
(lstrlen(file)>4 && _tcsncicmp(&file[lstrlen(file)-4],TEXT(".cgp"),4)==0))) {
return SetShadersCG(file); return SetShadersCG(file);
} else { } else {
return SetShadersGLSL(file); return SetShadersGLSL(file);
@ -712,70 +711,15 @@ void COpenGL::checkForCgError(const char *situation)
bool COpenGL::SetShadersCG(const TCHAR *file) bool COpenGL::SetShadersCG(const TCHAR *file)
{ {
TCHAR errorMsg[MAX_PATH + 50];
HRESULT hr;
CGprofile vertexProfile, fragmentProfile;
if(cgFragmentProgram) {
cgDestroyProgram(cgFragmentProgram);
cgFragmentProgram = NULL;
}
if(cgVertexProgram) {
cgDestroyProgram(cgVertexProgram);
cgVertexProgram = NULL;
}
if(cgAvailable) {
vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLDisableProfile(vertexProfile);
cgGLDisableProfile(fragmentProfile);
}
if (file == NULL || *file==TEXT('\0'))
return true;
if(!cgAvailable) { if(!cgAvailable) {
MessageBox(NULL, TEXT("The CG runtime is unavailable, CG shaders will not run.\nConsult the snes9x readme for information on how to obtain the runtime."), TEXT("CG Error"), MessageBox(NULL, TEXT("The CG runtime is unavailable, CG shaders will not run.\nConsult the snes9x readme for information on how to obtain the runtime."), TEXT("CG Error"),
MB_OK|MB_ICONEXCLAMATION); MB_OK|MB_ICONEXCLAMATION);
return false; return false;
} }
cgGLSetOptimalOptions(vertexProfile); if(!cgShader->LoadShader(file))
cgGLSetOptimalOptions(fragmentProfile);
char *fileContents = ReadShaderFileContents(file);
if(!fileContents)
return false; return false;
cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents,
vertexProfile, "main_vertex", NULL);
checkForCgError("Compiling vertex program");
cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents,
fragmentProfile, "main_fragment", NULL);
checkForCgError("Compiling fragment program");
delete [] fileContents;
if(!cgVertexProgram || !cgFragmentProgram) {
return false;
}
if(cgVertexProgram) {
cgGLEnableProfile(vertexProfile);
cgGLLoadProgram(cgVertexProgram);
cgGLBindProgram(cgVertexProgram);
}
if(cgFragmentProgram) {
cgGLEnableProfile(fragmentProfile);
cgGLLoadProgram(cgFragmentProgram);
cgGLBindProgram(cgFragmentProgram);
}
shader_type = OGL_SHADER_CG; shader_type = OGL_SHADER_CG;
return true; return true;

View File

@ -183,6 +183,7 @@
#include <windows.h> #include <windows.h>
#include <gl\gl.h> #include <gl\gl.h>
#include "cgFunctions.h" #include "cgFunctions.h"
#include "CGLCG.h"
#include "glext.h" #include "glext.h"
#include "wglext.h" #include "wglext.h"
@ -219,6 +220,8 @@ private:
current_ogl_shader_type shader_type; current_ogl_shader_type shader_type;
bool cgAvailable; bool cgAvailable;
CGLCG *cgShader;
GLuint shaderProgram; GLuint shaderProgram;
GLuint vertexShader; GLuint vertexShader;
GLuint fragmentShader; GLuint fragmentShader;

View File

@ -211,6 +211,10 @@ CGGLDP cgGLDisableProfile = NULL;
CGGLSOO cgGLSetOptimalOptions = NULL; CGGLSOO cgGLSetOptimalOptions = NULL;
CGGLLP cgGLLoadProgram = NULL; CGGLLP cgGLLoadProgram = NULL;
CGGLBP cgGLBindProgram = NULL; CGGLBP cgGLBindProgram = NULL;
CGGLSTP cgGLSetTextureParameter = NULL;
CGGLETP cgGLEnableTextureParameter = NULL;
CGGLSPP cgGLSetParameterPointer = NULL;
CGGLECS cgGLEnableClientState = NULL;
bool loadCgFunctions() bool loadCgFunctions()
{ {
@ -256,6 +260,10 @@ bool loadCgFunctions()
cgGLSetOptimalOptions = (CGGLSOO)GetProcAddress(hCgGLDll,"cgGLSetOptimalOptions"); cgGLSetOptimalOptions = (CGGLSOO)GetProcAddress(hCgGLDll,"cgGLSetOptimalOptions");
cgGLLoadProgram = (CGGLLP)GetProcAddress(hCgGLDll,"cgGLLoadProgram"); cgGLLoadProgram = (CGGLLP)GetProcAddress(hCgGLDll,"cgGLLoadProgram");
cgGLBindProgram = (CGGLBP)GetProcAddress(hCgGLDll,"cgGLBindProgram"); cgGLBindProgram = (CGGLBP)GetProcAddress(hCgGLDll,"cgGLBindProgram");
cgGLSetTextureParameter = (CGGLSTP)GetProcAddress(hCgGLDll,"cgGLSetTextureParameter");
cgGLEnableTextureParameter = (CGGLETP)GetProcAddress(hCgGLDll,"cgGLEnableTextureParameter");
cgGLSetParameterPointer = (CGGLSPP)GetProcAddress(hCgGLDll,"cgGLSetParameterPointer");
cgGLEnableClientState = (CGGLECS)GetProcAddress(hCgGLDll,"cgGLEnableClientState");
if( if(
//cg.dll //cg.dll
@ -285,7 +293,11 @@ bool loadCgFunctions()
!cgGLDisableProfile || !cgGLDisableProfile ||
!cgGLSetOptimalOptions || !cgGLSetOptimalOptions ||
!cgGLLoadProgram || !cgGLLoadProgram ||
!cgGLBindProgram) { !cgGLBindProgram ||
!cgGLSetTextureParameter ||
!cgGLEnableTextureParameter ||
!cgGLSetParameterPointer ||
!cgGLEnableClientState) {
unloadCgLibrary(); unloadCgLibrary();
return false; return false;
} }

View File

@ -243,7 +243,14 @@ typedef CGGL_API void (CGGLENTRY *CGGLLP)(CGprogram program);
extern CGGLLP cgGLLoadProgram; extern CGGLLP cgGLLoadProgram;
typedef CGGL_API void (CGGLENTRY *CGGLBP)(CGprogram program); typedef CGGL_API void (CGGLENTRY *CGGLBP)(CGprogram program);
extern CGGLBP cgGLBindProgram; extern CGGLBP cgGLBindProgram;
typedef CGGL_API void (CGGLENTRY *CGGLSTP)(CGparameter param, GLuint texobj);
extern CGGLSTP cgGLSetTextureParameter;
typedef CGGL_API void (CGGLENTRY *CGGLETP)(CGparameter param);
extern CGGLETP cgGLEnableTextureParameter;
typedef CGGL_API void (CGGLENTRY *CGGLSPP)(CGparameter param, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer);
extern CGGLSPP cgGLSetParameterPointer;
typedef CGGL_API void (CGGLENTRY *CGGLECS)(CGparameter param);
extern CGGLECS cgGLEnableClientState;
//cgfunctions.cpp //cgfunctions.cpp

View File

@ -3129,6 +3129,14 @@
<Filter <Filter
Name="VideoDriver" Name="VideoDriver"
> >
<File
RelativePath=".\CCGShader.cpp"
>
</File>
<File
RelativePath=".\CCGShader.h"
>
</File>
<File <File
RelativePath=".\CDirect3D.cpp" RelativePath=".\CDirect3D.cpp"
> >
@ -3209,6 +3217,14 @@
RelativePath=".\cgFunctions.h" RelativePath=".\cgFunctions.h"
> >
</File> </File>
<File
RelativePath=".\CGLCG.cpp"
>
</File>
<File
RelativePath=".\CGLCG.h"
>
</File>
<File <File
RelativePath=".\COpenGL.cpp" RelativePath=".\COpenGL.cpp"
> >

View File

@ -272,27 +272,27 @@ void WinDisplayApplyChanges()
RECT CalculateDisplayRect(unsigned int sourceWidth,unsigned int sourceHeight, RECT CalculateDisplayRect(unsigned int sourceWidth,unsigned int sourceHeight,
unsigned int displayWidth,unsigned int displayHeight) unsigned int displayWidth,unsigned int displayHeight)
{ {
float xFactor; double xFactor;
float yFactor; double yFactor;
float minFactor; double minFactor;
float renderWidthCalc,renderHeightCalc; double renderWidthCalc,renderHeightCalc;
int hExtend = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT; int hExtend = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT;
float snesAspect = (float)GUI.AspectWidth/hExtend; double snesAspect = (double)GUI.AspectWidth/hExtend;
RECT drawRect; RECT drawRect;
if(GUI.Stretch) { if(GUI.Stretch) {
if(GUI.AspectRatio) { if(GUI.AspectRatio) {
//fix for hi-res images with FILTER_NONE //fix for hi-res images with FILTER_NONE
//where we need to correct the aspect ratio //where we need to correct the aspect ratio
renderWidthCalc = (float)sourceWidth; renderWidthCalc = (double)sourceWidth;
renderHeightCalc = (float)sourceHeight; renderHeightCalc = (double)sourceHeight;
if(renderWidthCalc/renderHeightCalc>snesAspect) if(renderWidthCalc/renderHeightCalc>snesAspect)
renderWidthCalc = renderHeightCalc * snesAspect; renderWidthCalc = renderHeightCalc * snesAspect;
else if(renderWidthCalc/renderHeightCalc<snesAspect) else if(renderWidthCalc/renderHeightCalc<snesAspect)
renderHeightCalc = renderWidthCalc / snesAspect; renderHeightCalc = renderWidthCalc / snesAspect;
xFactor = (float)displayWidth / renderWidthCalc; xFactor = (double)displayWidth / renderWidthCalc;
yFactor = (float)displayHeight / renderHeightCalc; yFactor = (double)displayHeight / renderHeightCalc;
minFactor = xFactor < yFactor ? xFactor : yFactor; minFactor = xFactor < yFactor ? xFactor : yFactor;
drawRect.right = (LONG)(renderWidthCalc * minFactor); drawRect.right = (LONG)(renderWidthCalc * minFactor);

View File

@ -200,6 +200,7 @@
#include "wsnes9x.h" #include "wsnes9x.h"
#include "win32_sound.h" #include "win32_sound.h"
#include "win32_display.h" #include "win32_display.h"
#include "CCGShader.h"
#include "../snes9x.h" #include "../snes9x.h"
#include "../memmap.h" #include "../memmap.h"
#include "../cpuexec.h" #include "../cpuexec.h"
@ -7264,7 +7265,7 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
ofn.lStructSize = sizeof(OPENFILENAME); ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hDlg; ofn.hwndOwner = hDlg;
ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg\0All Files\0*.*\0\0"); ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg;*.cgp\0All Files\0*.*\0\0");
ofn.lpstrFile = openFileName; ofn.lpstrFile = openFileName;
ofn.lpstrTitle = TEXT("Select Shader"); ofn.lpstrTitle = TEXT("Select Shader");
ofn.lpstrDefExt = TEXT("shader"); ofn.lpstrDefExt = TEXT("shader");
@ -7283,7 +7284,7 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
ofn.lStructSize = sizeof(OPENFILENAME); ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hDlg; ofn.hwndOwner = hDlg;
ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg\0All Files\0*.*\0\0"); ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg;*.cgp\0All Files\0*.*\0\0");
ofn.lpstrFile = openFileName; ofn.lpstrFile = openFileName;
ofn.lpstrTitle = TEXT("Select Shader"); ofn.lpstrTitle = TEXT("Select Shader");
ofn.lpstrDefExt = TEXT("shader"); ofn.lpstrDefExt = TEXT("shader");