Cache texture parameters. Fixed exclusion volume modifiers.
This commit is contained in:
parent
e73d11d0ab
commit
80c193b3de
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
#include <map>
|
||||
#include "gles.h"
|
||||
|
||||
#define TEXTURE_ID_CACHE_SIZE 32
|
||||
|
@ -43,10 +44,9 @@ public:
|
|||
|
||||
void DeleteTextures(GLsizei n, const GLuint *textures) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (textures[i] == _texture) {
|
||||
_texture_params.erase(textures[i]);
|
||||
if (textures[i] == _texture)
|
||||
_texture = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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() {
|
||||
if (_texture_cache_size == 0) {
|
||||
_texture_cache_size = TEXTURE_ID_CACHE_SIZE;
|
||||
|
@ -141,6 +171,16 @@ public:
|
|||
}
|
||||
|
||||
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) {
|
||||
bool *pCap = NULL;
|
||||
switch (cap) {
|
||||
|
@ -196,6 +236,7 @@ private:
|
|||
GLuint _stencil_mask;
|
||||
GLuint _texture_ids[TEXTURE_ID_CACHE_SIZE];
|
||||
GLuint _texture_cache_size;
|
||||
std::map<GLuint, TextureParameters> _texture_params;
|
||||
};
|
||||
|
||||
extern GLCache glcache;
|
||||
|
|
|
@ -74,18 +74,6 @@ extern int screen_height;
|
|||
PipelineShader* CurrentShader;
|
||||
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)
|
||||
{
|
||||
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>
|
||||
__forceinline
|
||||
void SetGPState(const PolyParam* gp,u32 cflip=0)
|
||||
|
@ -174,17 +170,24 @@ __forceinline
|
|||
|
||||
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
|
||||
if (gp->texid != cache.texture)
|
||||
SetTextureRepeatMode(GL_TEXTURE_WRAP_S, gp->tsp.ClampU, gp->tsp.FlipU);
|
||||
SetTextureRepeatMode(GL_TEXTURE_WRAP_T, gp->tsp.ClampV, gp->tsp.FlipV);
|
||||
|
||||
//set texture filter mode
|
||||
if (gp->tsp.FilterMode == 0)
|
||||
{
|
||||
cache.texture=gp->texid;
|
||||
if (gp->texid != -1) {
|
||||
//verify(glIsTexture(gp->texid));
|
||||
glcache.BindTexture(GL_TEXTURE_2D, gp->texid);
|
||||
texture_changed = true;
|
||||
}
|
||||
//disable filtering, mipmaps
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glcache.TexParameteri(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
|
||||
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)
|
||||
|
@ -195,29 +198,6 @@ __forceinline
|
|||
else
|
||||
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 !
|
||||
//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
|
||||
|
@ -819,48 +799,39 @@ void SetMVS_Mode(u32 mv_mode,ISP_Modvol ispc)
|
|||
|
||||
//no depth test
|
||||
glcache.Disable(GL_DEPTH_TEST);
|
||||
//write bits 1:0
|
||||
glcache.StencilMask(3);
|
||||
|
||||
if (mv_mode==1)
|
||||
{
|
||||
// Inclusion volume
|
||||
//res : old : final
|
||||
//0 : 0 : 00
|
||||
//0 : 1 : 01
|
||||
//1 : 0 : 01
|
||||
//1 : 1 : 01
|
||||
|
||||
//write bits 1:0
|
||||
glcache.StencilMask(3);
|
||||
//if (1<=st) st=1; else st=0;
|
||||
glcache.StencilFunc(GL_LEQUAL,1,3);
|
||||
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
|
||||
{
|
||||
// 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)
|
||||
(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
|
||||
//0 : 0 : 00
|
||||
//0 : 1 : 00
|
||||
//0 : 1 : 01
|
||||
//1 : 0 : 00
|
||||
//1 : 1 : 01
|
||||
//1 : 1 : 00
|
||||
|
||||
// Write to bit 0
|
||||
glcache.StencilMask(1); // FIXME bit 1 is not reset. Need other pass
|
||||
//if (3==st) st=1; else st=0; //can't be done with a single pass
|
||||
glcache.StencilFunc(GL_EQUAL, 3, 3);
|
||||
glcache.StencilOp(GL_ZERO,GL_KEEP,GL_REPLACE);
|
||||
// if (1 == st) st = 1; else st = 0;
|
||||
glcache.StencilFunc(GL_EQUAL, 1, 3);
|
||||
glcache.StencilOp(GL_ZERO, GL_ZERO, GL_REPLACE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -921,7 +892,7 @@ void DrawModVols(int first, int count)
|
|||
glcache.DepthMask(GL_FALSE);
|
||||
glcache.DepthFunc(GL_GREATER);
|
||||
|
||||
if(0 /*|| GetAsyncKeyState(VK_F5)*/ )
|
||||
if(0)
|
||||
{
|
||||
//simply draw the volumes -- for debugging
|
||||
SetCull(0);
|
||||
|
@ -948,7 +919,7 @@ void DrawModVols(int first, int count)
|
|||
|
||||
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
|
||||
|
||||
if ( 0 /* || GetAsyncKeyState(VK_F6)*/ )
|
||||
if (0)
|
||||
{
|
||||
//simple single level stencil
|
||||
glcache.Enable(GL_STENCIL_TEST);
|
||||
|
|
|
@ -2039,7 +2039,7 @@ GLuint loadPNG(const string& fname, int &width, int &height)
|
|||
glcache.BindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
|
||||
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
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
|
|
|
@ -163,14 +163,6 @@ struct TextureCacheData
|
|||
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
|
||||
void Create(bool isGL)
|
||||
{
|
||||
|
@ -199,30 +191,6 @@ struct TextureCacheData
|
|||
w=8<<tsp.TexU; //tex width
|
||||
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
|
||||
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);
|
||||
|
||||
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
|
||||
glGenFramebuffers(1, &rv.fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rv.fbo);
|
||||
|
|
Loading…
Reference in New Issue