thin3d: Add sampler state selection.

This commit is contained in:
Unknown W. Brackets committed 2016-02-13 14:03:43 -08:00
1 parent 0d68a172a9
commit 05fee24ccf
7 files changed
+192 -26

No files matched your search

+101 -11
View File
@@ -42,6 +42,23 @@ static const unsigned short blendFactorToGL[] = {
GL_CONSTANT_COLOR,
};
static const unsigned short texWrapToGL[] = {
GL_REPEAT,
GL_CLAMP_TO_EDGE,
};
static const unsigned short texFilterToGL[] = {
GL_NEAREST,
GL_LINEAR,
};
static const unsigned short texMipFilterToGL[2][2] = {
// Min nearest:
{ GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR },
// Min linear:
{ GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR },
};
#ifndef USING_GLES2
static const unsigned short logicOpToGL[] = {
GL_CLEAR,
@@ -114,6 +131,32 @@ public:
}
};
class Thin3DGLSamplerState : public Thin3DSamplerState {
public:
GLint wrapS;
GLint wrapT;
GLint magFilt;
GLint minFilt;
GLint mipMinFilt;
void Apply(bool hasMips, bool canWrap) {
if (canWrap) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilt);
if (hasMips) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mipMinFilt);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilt);
}
}
};
class Thin3DGLDepthStencilState : public Thin3DDepthStencilState {
public:
bool depthTestEnabled;
@@ -307,6 +350,7 @@ public:
Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) override;
Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) override;
Thin3DSamplerState *CreateSamplerState(const T3DSamplerStateDesc &desc) override;
Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override;
Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override;
Thin3DVertexFormat *CreateVertexFormat(const std::vector<Thin3DVertexComponent> &components, int stride, Thin3DShader *vshader) override;
@@ -319,6 +363,28 @@ public:
s->Apply();
}
void SetSamplerStates(int start, int count, Thin3DSamplerState **states) override {
if (samplerStates_.size() < (size_t)(start + count)) {
samplerStates_.resize(start + count);
}
for (int i = 0; i < count; ++i) {
int index = i + start;
Thin3DGLSamplerState *s = static_cast<Thin3DGLSamplerState *>(states[index]);
if (samplerStates_[index]) {
samplerStates_[index]->Release();
}
samplerStates_[index] = s;
samplerStates_[index]->AddRef();
// TODO: Ideally, get these from the texture and apply on the right stage?
if (index == 0) {
s->Apply(false, true);
}
}
}
// Bound state objects
void SetDepthStencilState(Thin3DDepthStencilState *state) override {
Thin3DGLDepthStencilState *s = static_cast<Thin3DGLDepthStencilState *>(state);
@@ -391,6 +457,8 @@ public:
default: return "?";
}
}
std::vector<Thin3DGLSamplerState *> samplerStates_;
};
Thin3DGLContext::Thin3DGLContext() {
@@ -398,6 +466,12 @@ Thin3DGLContext::Thin3DGLContext() {
}
Thin3DGLContext::~Thin3DGLContext() {
for (Thin3DGLSamplerState *s : samplerStates_) {
if (s) {
s->Release();
}
}
samplerStates_.clear();
}
Thin3DVertexFormat *Thin3DGLContext::CreateVertexFormat(const std::vector<Thin3DVertexComponent> &components, int stride, Thin3DShader *vshader) {
@@ -428,6 +502,7 @@ class Thin3DGLTexture : public Thin3DTexture, GfxResourceHolder {
public:
Thin3DGLTexture() : tex_(0), target_(0) {
generatedMips_ = false;
canWrap_ = true;
width_ = 0;
height_ = 0;
depth_ = 0;
@@ -436,6 +511,7 @@ public:
}
Thin3DGLTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) : tex_(0), target_(TypeToTarget(type)), format_(format), mipLevels_(mipLevels) {
generatedMips_ = false;
canWrap_ = true;
width_ = width;
height_ = height;
depth_ = depth;
@@ -449,6 +525,7 @@ public:
bool Create(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) override {
generatedMips_ = false;
canWrap_ = true;
format_ = format;
target_ = TypeToTarget(type);
mipLevels_ = mipLevels;
@@ -468,6 +545,13 @@ public:
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override;
void AutoGenMipmaps() override;
bool HasMips() {
return mipLevels_ > 1 || generatedMips_;
}
bool CanWrap() {
return canWrap_;
}
void Bind() {
glBindTexture(target_, tex_);
}
@@ -494,6 +578,7 @@ private:
T3DImageFormat format_;
int mipLevels_;
bool generatedMips_;
bool canWrap_;
};
Thin3DTexture *Thin3DGLContext::CreateTexture() {
@@ -508,6 +593,7 @@ void Thin3DGLTexture::AutoGenMipmaps() {
if (!generatedMips_) {
Bind();
glGenerateMipmap(target_);
// TODO: Really, this should follow the sampler state.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
generatedMips_ = true;
}
@@ -553,17 +639,7 @@ bool isPowerOf2(int n) {
}
void Thin3DGLTexture::Finalize(int zim_flags) {
GLenum wrap = GL_REPEAT;
if ((zim_flags & ZIM_CLAMP) || !isPowerOf2(width_) || !isPowerOf2(height_))
wrap = GL_CLAMP_TO_EDGE;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
canWrap_ = (zim_flags & ZIM_CLAMP) || !isPowerOf2(width_) || !isPowerOf2(height_);
}
@@ -618,6 +694,16 @@ Thin3DBlendState *Thin3DGLContext::CreateBlendState(const T3DBlendStateDesc &des
return bs;
}
Thin3DSamplerState *Thin3DGLContext::CreateSamplerState(const T3DSamplerStateDesc &desc) {
Thin3DGLSamplerState *samps = new Thin3DGLSamplerState();
samps->wrapS = texWrapToGL[desc.wrapS];
samps->wrapT = texWrapToGL[desc.wrapT];
samps->magFilt = texFilterToGL[desc.magFilt];
samps->minFilt = texFilterToGL[desc.minFilt];
samps->mipMinFilt = texMipFilterToGL[desc.minFilt][desc.mipFilt];
return samps;
}
Thin3DBuffer *Thin3DGLContext::CreateBuffer(size_t size, uint32_t usageFlags) {
return new Thin3DGLBuffer(size, usageFlags);
}
@@ -645,6 +731,10 @@ void Thin3DGLContext::SetTextures(int start, int count, Thin3DTexture **textures
Thin3DGLTexture *glTex = static_cast<Thin3DGLTexture *>(textures[i]);
glActiveTexture(GL_TEXTURE0 + i);
glTex->Bind();
if (samplerStates_.size() > i && samplerStates_[i]) {
samplerStates_[i]->Apply(glTex->HasMips(), glTex->CanWrap());
}
}
glActiveTexture(GL_TEXTURE0);
}