Cache texture parameters. Fixed exclusion volume modifiers.
This commit is contained in:
parent
e73d11d0ab
commit
80c193b3de
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <map>
|
||||||
#include "gles.h"
|
#include "gles.h"
|
||||||
|
|
||||||
#define TEXTURE_ID_CACHE_SIZE 32
|
#define TEXTURE_ID_CACHE_SIZE 32
|
||||||
|
@ -43,10 +44,9 @@ public:
|
||||||
|
|
||||||
void DeleteTextures(GLsizei n, const GLuint *textures) {
|
void DeleteTextures(GLsizei n, const GLuint *textures) {
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
if (textures[i] == _texture) {
|
_texture_params.erase(textures[i]);
|
||||||
|
if (textures[i] == _texture)
|
||||||
_texture = 0;
|
_texture = 0;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
glDeleteTextures(n, textures);
|
glDeleteTextures(n, textures);
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,36 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TexParameteri(GLenum target, GLenum pname, GLint param) {
|
||||||
|
if (target == GL_TEXTURE_2D)
|
||||||
|
{
|
||||||
|
TextureParameters &cur_params = _texture_params[_texture];
|
||||||
|
switch (pname) {
|
||||||
|
case GL_TEXTURE_MIN_FILTER:
|
||||||
|
if (cur_params._min_filter == param)
|
||||||
|
return;
|
||||||
|
cur_params._min_filter = param;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_MAG_FILTER:
|
||||||
|
if (cur_params._mag_filter == param)
|
||||||
|
return;
|
||||||
|
cur_params._mag_filter = param;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_WRAP_S:
|
||||||
|
if (cur_params._wrap_s == param)
|
||||||
|
return;
|
||||||
|
cur_params._wrap_s = param;
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_WRAP_T:
|
||||||
|
if (cur_params._wrap_t == param)
|
||||||
|
return;
|
||||||
|
cur_params._wrap_t = param;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glTexParameteri(target, pname, param);
|
||||||
|
}
|
||||||
|
|
||||||
GLuint GenTexture() {
|
GLuint GenTexture() {
|
||||||
if (_texture_cache_size == 0) {
|
if (_texture_cache_size == 0) {
|
||||||
_texture_cache_size = TEXTURE_ID_CACHE_SIZE;
|
_texture_cache_size = TEXTURE_ID_CACHE_SIZE;
|
||||||
|
@ -141,6 +171,16 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class TextureParameters {
|
||||||
|
public:
|
||||||
|
TextureParameters() : _min_filter(GL_NEAREST_MIPMAP_LINEAR), _mag_filter(GL_LINEAR), _wrap_s(GL_REPEAT), _wrap_t(GL_REPEAT) {}
|
||||||
|
|
||||||
|
GLenum _min_filter;
|
||||||
|
GLenum _mag_filter;
|
||||||
|
GLenum _wrap_s;
|
||||||
|
GLenum _wrap_t;
|
||||||
|
};
|
||||||
|
|
||||||
void setCapability(GLenum cap, bool value) {
|
void setCapability(GLenum cap, bool value) {
|
||||||
bool *pCap = NULL;
|
bool *pCap = NULL;
|
||||||
switch (cap) {
|
switch (cap) {
|
||||||
|
@ -196,6 +236,7 @@ private:
|
||||||
GLuint _stencil_mask;
|
GLuint _stencil_mask;
|
||||||
GLuint _texture_ids[TEXTURE_ID_CACHE_SIZE];
|
GLuint _texture_ids[TEXTURE_ID_CACHE_SIZE];
|
||||||
GLuint _texture_cache_size;
|
GLuint _texture_cache_size;
|
||||||
|
std::map<GLuint, TextureParameters> _texture_params;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern GLCache glcache;
|
extern GLCache glcache;
|
||||||
|
|
|
@ -74,18 +74,6 @@ extern int screen_height;
|
||||||
PipelineShader* CurrentShader;
|
PipelineShader* CurrentShader;
|
||||||
u32 gcflip;
|
u32 gcflip;
|
||||||
|
|
||||||
static struct
|
|
||||||
{
|
|
||||||
TSP tsp;
|
|
||||||
GLuint texture;
|
|
||||||
|
|
||||||
void Reset(const PolyParam* gp)
|
|
||||||
{
|
|
||||||
texture=~0;
|
|
||||||
tsp.full = ~gp->tsp.full;
|
|
||||||
}
|
|
||||||
} cache;
|
|
||||||
|
|
||||||
s32 SetTileClip(u32 val, bool set)
|
s32 SetTileClip(u32 val, bool set)
|
||||||
{
|
{
|
||||||
u32 clipmode=val>>28;
|
u32 clipmode=val>>28;
|
||||||
|
@ -149,6 +137,14 @@ void SetCull(u32 CulliMode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetTextureRepeatMode(GLuint dir, u32 clamp, u32 mirror)
|
||||||
|
{
|
||||||
|
if (clamp)
|
||||||
|
glcache.TexParameteri(GL_TEXTURE_2D, dir, GL_CLAMP_TO_EDGE);
|
||||||
|
else
|
||||||
|
glcache.TexParameteri(GL_TEXTURE_2D, dir, mirror ? GL_MIRRORED_REPEAT : GL_REPEAT);
|
||||||
|
}
|
||||||
|
|
||||||
template <u32 Type, bool SortingEnabled>
|
template <u32 Type, bool SortingEnabled>
|
||||||
__forceinline
|
__forceinline
|
||||||
void SetGPState(const PolyParam* gp,u32 cflip=0)
|
void SetGPState(const PolyParam* gp,u32 cflip=0)
|
||||||
|
@ -174,17 +170,24 @@ __forceinline
|
||||||
|
|
||||||
glcache.StencilFunc(GL_ALWAYS,stencil,stencil);
|
glcache.StencilFunc(GL_ALWAYS,stencil,stencil);
|
||||||
|
|
||||||
bool texture_changed = false;
|
glcache.BindTexture(GL_TEXTURE_2D, gp->texid == -1 ? 0 : gp->texid);
|
||||||
|
|
||||||
// FIXME the same gl texture id can be used with different parameters (filtering, clamping, etc.) This is not handled here
|
SetTextureRepeatMode(GL_TEXTURE_WRAP_S, gp->tsp.ClampU, gp->tsp.FlipU);
|
||||||
if (gp->texid != cache.texture)
|
SetTextureRepeatMode(GL_TEXTURE_WRAP_T, gp->tsp.ClampV, gp->tsp.FlipV);
|
||||||
|
|
||||||
|
//set texture filter mode
|
||||||
|
if (gp->tsp.FilterMode == 0)
|
||||||
{
|
{
|
||||||
cache.texture=gp->texid;
|
//disable filtering, mipmaps
|
||||||
if (gp->texid != -1) {
|
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
//verify(glIsTexture(gp->texid));
|
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glcache.BindTexture(GL_TEXTURE_2D, gp->texid);
|
}
|
||||||
texture_changed = true;
|
else
|
||||||
}
|
{
|
||||||
|
//bilinear filtering
|
||||||
|
//PowerVR supports also trilinear via two passes, but we ignore that for now
|
||||||
|
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (gp->tcw.MipMapped && settings.rend.UseMipmaps) ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR);
|
||||||
|
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Type==ListType_Translucent)
|
if (Type==ListType_Translucent)
|
||||||
|
@ -195,29 +198,6 @@ __forceinline
|
||||||
else
|
else
|
||||||
glcache.Disable(GL_BLEND);
|
glcache.Disable(GL_BLEND);
|
||||||
|
|
||||||
if (gp->tsp.full != cache.tsp.full || texture_changed)
|
|
||||||
{
|
|
||||||
cache.tsp=gp->tsp;
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (gp->tsp.ClampU ? GL_CLAMP_TO_EDGE : (gp->tsp.FlipU ? GL_MIRRORED_REPEAT : GL_REPEAT))) ;
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (gp->tsp.ClampV ? GL_CLAMP_TO_EDGE : (gp->tsp.FlipV ? GL_MIRRORED_REPEAT : GL_REPEAT))) ;
|
|
||||||
|
|
||||||
//set texture filter mode
|
|
||||||
if (gp->tsp.FilterMode == 0)
|
|
||||||
{
|
|
||||||
//disable filtering, mipmaps
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//bilinear filtering
|
|
||||||
//PowerVR supports also trilinear via two passes, but we ignore that for now
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (gp->tcw.MipMapped && settings.rend.UseMipmaps) ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//set cull mode !
|
//set cull mode !
|
||||||
//cflip is required when exploding triangles for triangle sorting
|
//cflip is required when exploding triangles for triangle sorting
|
||||||
//gcflip is global clip flip, needed for when rendering to texture due to mirrored Y direction
|
//gcflip is global clip flip, needed for when rendering to texture due to mirrored Y direction
|
||||||
|
@ -819,48 +799,39 @@ void SetMVS_Mode(u32 mv_mode,ISP_Modvol ispc)
|
||||||
|
|
||||||
//no depth test
|
//no depth test
|
||||||
glcache.Disable(GL_DEPTH_TEST);
|
glcache.Disable(GL_DEPTH_TEST);
|
||||||
|
//write bits 1:0
|
||||||
|
glcache.StencilMask(3);
|
||||||
|
|
||||||
if (mv_mode==1)
|
if (mv_mode==1)
|
||||||
{
|
{
|
||||||
|
// Inclusion volume
|
||||||
//res : old : final
|
//res : old : final
|
||||||
//0 : 0 : 00
|
//0 : 0 : 00
|
||||||
//0 : 1 : 01
|
//0 : 1 : 01
|
||||||
//1 : 0 : 01
|
//1 : 0 : 01
|
||||||
//1 : 1 : 01
|
//1 : 1 : 01
|
||||||
|
|
||||||
//write bits 1:0
|
|
||||||
glcache.StencilMask(3);
|
|
||||||
//if (1<=st) st=1; else st=0;
|
//if (1<=st) st=1; else st=0;
|
||||||
glcache.StencilFunc(GL_LEQUAL,1,3);
|
glcache.StencilFunc(GL_LEQUAL,1,3);
|
||||||
glcache.StencilOp(GL_ZERO,GL_ZERO,GL_REPLACE);
|
glcache.StencilOp(GL_ZERO,GL_ZERO,GL_REPLACE);
|
||||||
|
|
||||||
/*
|
|
||||||
//if !=0 -> set to 10
|
|
||||||
verifyc(dev->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_LESSEQUAL));
|
|
||||||
verifyc(dev->SetRenderState(D3DRS_STENCILREF,1));
|
|
||||||
verifyc(dev->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_REPLACE));
|
|
||||||
verifyc(dev->SetRenderState(D3DRS_STENCILFAIL,D3DSTENCILOP_ZERO));
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Exclusion volume
|
||||||
/*
|
/*
|
||||||
this is bugged. a lot.
|
|
||||||
I've only seen a single game use it, so i guess it doesn't matter ? (Zombie revenge)
|
I've only seen a single game use it, so i guess it doesn't matter ? (Zombie revenge)
|
||||||
(actually, i think there was also another, racing game)
|
(actually, i think there was also another, racing game)
|
||||||
*/
|
*/
|
||||||
|
// The initial value for exclusion volumes is 1 so we need to invert the result before and'ing.
|
||||||
//res : old : final
|
//res : old : final
|
||||||
//0 : 0 : 00
|
//0 : 0 : 00
|
||||||
//0 : 1 : 00
|
//0 : 1 : 01
|
||||||
//1 : 0 : 00
|
//1 : 0 : 00
|
||||||
//1 : 1 : 01
|
//1 : 1 : 00
|
||||||
|
|
||||||
// Write to bit 0
|
// if (1 == st) st = 1; else st = 0;
|
||||||
glcache.StencilMask(1); // FIXME bit 1 is not reset. Need other pass
|
glcache.StencilFunc(GL_EQUAL, 1, 3);
|
||||||
//if (3==st) st=1; else st=0; //can't be done with a single pass
|
glcache.StencilOp(GL_ZERO, GL_ZERO, GL_REPLACE);
|
||||||
glcache.StencilFunc(GL_EQUAL, 3, 3);
|
|
||||||
glcache.StencilOp(GL_ZERO,GL_KEEP,GL_REPLACE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -921,7 +892,7 @@ void DrawModVols(int first, int count)
|
||||||
glcache.DepthMask(GL_FALSE);
|
glcache.DepthMask(GL_FALSE);
|
||||||
glcache.DepthFunc(GL_GREATER);
|
glcache.DepthFunc(GL_GREATER);
|
||||||
|
|
||||||
if(0 /*|| GetAsyncKeyState(VK_F5)*/ )
|
if(0)
|
||||||
{
|
{
|
||||||
//simply draw the volumes -- for debugging
|
//simply draw the volumes -- for debugging
|
||||||
SetCull(0);
|
SetCull(0);
|
||||||
|
@ -948,7 +919,7 @@ void DrawModVols(int first, int count)
|
||||||
|
|
||||||
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
|
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
|
||||||
|
|
||||||
if ( 0 /* || GetAsyncKeyState(VK_F6)*/ )
|
if (0)
|
||||||
{
|
{
|
||||||
//simple single level stencil
|
//simple single level stencil
|
||||||
glcache.Enable(GL_STENCIL_TEST);
|
glcache.Enable(GL_STENCIL_TEST);
|
||||||
|
|
|
@ -2039,7 +2039,7 @@ GLuint loadPNG(const string& fname, int &width, int &height)
|
||||||
glcache.BindTexture(GL_TEXTURE_2D, texture);
|
glcache.BindTexture(GL_TEXTURE_2D, texture);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
|
||||||
GL_UNSIGNED_BYTE, (GLvoid*) image_data);
|
GL_UNSIGNED_BYTE, (GLvoid*) image_data);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
//clean up memory and close stuff
|
//clean up memory and close stuff
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||||
|
|
|
@ -163,14 +163,6 @@ struct TextureCacheData
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRepeatMode(GLuint dir,u32 clamp,u32 mirror)
|
|
||||||
{
|
|
||||||
if (clamp)
|
|
||||||
glTexParameteri (GL_TEXTURE_2D, dir, GL_CLAMP_TO_EDGE);
|
|
||||||
else
|
|
||||||
glTexParameteri (GL_TEXTURE_2D, dir, mirror?GL_MIRRORED_REPEAT : GL_REPEAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Create GL texture from tsp/tcw
|
//Create GL texture from tsp/tcw
|
||||||
void Create(bool isGL)
|
void Create(bool isGL)
|
||||||
{
|
{
|
||||||
|
@ -199,30 +191,6 @@ struct TextureCacheData
|
||||||
w=8<<tsp.TexU; //tex width
|
w=8<<tsp.TexU; //tex width
|
||||||
h=8<<tsp.TexV; //tex height
|
h=8<<tsp.TexV; //tex height
|
||||||
|
|
||||||
if (texID) {
|
|
||||||
//bind texture to set modes
|
|
||||||
glcache.BindTexture(GL_TEXTURE_2D, texID);
|
|
||||||
|
|
||||||
//set texture repeat mode
|
|
||||||
SetRepeatMode(GL_TEXTURE_WRAP_S, tsp.ClampU, tsp.FlipU); // glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (tsp.ClampU ? GL_CLAMP_TO_EDGE : (tsp.FlipU ? GL_MIRRORED_REPEAT : GL_REPEAT))) ;
|
|
||||||
SetRepeatMode(GL_TEXTURE_WRAP_T, tsp.ClampV, tsp.FlipV); // glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (tsp.ClampV ? GL_CLAMP_TO_EDGE : (tsp.FlipV ? GL_MIRRORED_REPEAT : GL_REPEAT))) ;
|
|
||||||
|
|
||||||
//set texture filter mode
|
|
||||||
if (tsp.FilterMode == 0)
|
|
||||||
{
|
|
||||||
//disable filtering, mipmaps
|
|
||||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//bilinear filtering
|
|
||||||
//PowerVR supports also trilinear via two passes, but we ignore that for now
|
|
||||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, (tcw.MipMapped && settings.rend.UseMipmaps)?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//PAL texture
|
//PAL texture
|
||||||
if (tex->bpp==4)
|
if (tex->bpp==4)
|
||||||
{
|
{
|
||||||
|
@ -467,11 +435,6 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt)
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, channels, fbw2, fbh2, 0, channels, fmt, 0);
|
glTexImage2D(GL_TEXTURE_2D, 0, channels, fbw2, fbh2, 0, channels, fmt, 0);
|
||||||
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
// Create the object that will allow us to render to the aforementioned texture
|
// Create the object that will allow us to render to the aforementioned texture
|
||||||
glGenFramebuffers(1, &rv.fbo);
|
glGenFramebuffers(1, &rv.fbo);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, rv.fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, rv.fbo);
|
||||||
|
|
Loading…
Reference in New Issue