Support sampler states in tinyGL renderer

This commit is contained in:
rdb 2014-12-12 20:32:36 +01:00
parent 89031b4e48
commit 8a5452b0b6
2 changed files with 65 additions and 46 deletions

View File

@ -34,6 +34,7 @@
#include "lightAttrib.h"
#include "scissorAttrib.h"
#include "bitMask.h"
#include "samplerState.h"
#include "zgl.h"
#include "zmath.h"
#include "ztriangle_table.h"
@ -1717,10 +1718,11 @@ update_texture(TextureContext *tc, bool force) {
if (gtc->was_image_modified() || gltex->num_levels == 0) {
// If the texture image was modified, reload the texture.
bool okflag = upload_texture(gtc, force);
Texture *tex = gtc->get_texture();
bool okflag = upload_texture(gtc, force, tex->uses_mipmaps());
if (!okflag) {
tinydisplay_cat.error()
<< "Could not load " << *gtc->get_texture() << "\n";
<< "Could not load " << *tex << "\n";
return false;
}
}
@ -1746,7 +1748,7 @@ update_texture(TextureContext *tc, bool force) {
// true).
////////////////////////////////////////////////////////////////////
bool TinyGraphicsStateGuardian::
update_texture(TextureContext *tc, bool force, int stage_index) {
update_texture(TextureContext *tc, bool force, int stage_index, bool uses_mipmaps) {
if (!update_texture(tc, force)) {
return false;
}
@ -1754,6 +1756,17 @@ update_texture(TextureContext *tc, bool force, int stage_index) {
TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
GLTexture *gltex = &gtc->_gltex;
if (uses_mipmaps && gltex->num_levels <= 1) {
// We don't have mipmaps, yet we are sampling with mipmaps.
Texture *tex = gtc->get_texture();
bool okflag = upload_texture(gtc, force, true);
if (!okflag) {
tinydisplay_cat.error()
<< "Could not load " << *tex << "\n";
return false;
}
}
_c->current_textures[stage_index] = gltex;
ZTextureDef *texture_def = &_c->zb->current_textures[stage_index];
@ -2275,8 +2288,11 @@ do_issue_texture() {
return;
}
// Get the sampler state that we are supposed to use.
const SamplerState &sampler = _target_texture->get_on_sampler(stage);
// Then, turn on the current texture mode.
if (!update_texture(tc, false, si)) {
if (!update_texture(tc, false, si, sampler.uses_mipmaps())) {
return;
}
@ -2300,10 +2316,10 @@ do_issue_texture() {
// Fill in the filter func pointers. These may not actually get
// called, if we decide below we can inline the filters.
SamplerState::FilterType minfilter = texture->get_minfilter();
SamplerState::FilterType magfilter = texture->get_magfilter();
SamplerState::FilterType minfilter = sampler.get_minfilter();
SamplerState::FilterType magfilter = sampler.get_magfilter();
if (td_ignore_mipmaps && Texture::is_mipmap(minfilter)) {
if (td_ignore_mipmaps && SamplerState::is_mipmap(minfilter)) {
// Downgrade mipmaps.
if (minfilter == SamplerState::FT_nearest_mipmap_nearest) {
minfilter = SamplerState::FT_nearest;
@ -2319,7 +2335,7 @@ do_issue_texture() {
magfilter = SamplerState::FT_nearest;
} else if (quality_level == Texture::QL_normal) {
if (Texture::is_mipmap(minfilter)) {
if (SamplerState::is_mipmap(minfilter)) {
minfilter = SamplerState::FT_nearest_mipmap_nearest;
} else {
minfilter = SamplerState::FT_nearest;
@ -2327,15 +2343,15 @@ do_issue_texture() {
magfilter = SamplerState::FT_nearest;
} else if (quality_level == Texture::QL_best) {
minfilter = texture->get_effective_minfilter();
magfilter = texture->get_effective_magfilter();
minfilter = sampler.get_effective_minfilter();
magfilter = sampler.get_effective_magfilter();
}
texture_def->tex_minfilter_func = get_tex_filter_func(minfilter);
texture_def->tex_magfilter_func = get_tex_filter_func(magfilter);
SamplerState::WrapMode wrap_u = texture->get_wrap_u();
SamplerState::WrapMode wrap_v = texture->get_wrap_v();
SamplerState::WrapMode wrap_u = sampler.get_wrap_u();
SamplerState::WrapMode wrap_v = sampler.get_wrap_v();
if (td_ignore_clamp) {
wrap_u = SamplerState::WM_repeat;
wrap_v = SamplerState::WM_repeat;
@ -2382,7 +2398,7 @@ do_issue_texture() {
all_mipmap_nearest = false;
}
if (Texture::is_mipmap(minfilter)) {
if (SamplerState::is_mipmap(minfilter)) {
any_mipmap = true;
}
}
@ -2500,7 +2516,7 @@ apply_texture(TextureContext *tc) {
// the texture has no image.
////////////////////////////////////////////////////////////////////
bool TinyGraphicsStateGuardian::
upload_texture(TinyTextureContext *gtc, bool force) {
upload_texture(TinyTextureContext *gtc, bool force, bool uses_mipmaps) {
Texture *tex = gtc->get_texture();
if (_effective_incomplete_render && !force) {
@ -2525,21 +2541,24 @@ upload_texture(TinyTextureContext *gtc, bool force) {
return false;
}
if (tinydisplay_cat.is_debug()) {
tinydisplay_cat.debug()
<< "loading texture " << tex->get_name() << "\n";
}
#ifdef DO_PSTATS
_data_transferred_pcollector.add_level(tex->get_ram_image_size());
#endif
GLTexture *gltex = &gtc->_gltex;
int num_levels = 1;
if (tex->uses_mipmaps()) {
if (!tex->has_all_ram_mipmap_images()) {
if (uses_mipmaps) {
num_levels = tex->get_expected_num_mipmap_levels();
if (tex->get_num_ram_mipmap_images() < num_levels) {
tex->generate_ram_mipmap_images();
}
num_levels = tex->get_num_ram_mipmap_images();
}
if (tinydisplay_cat.is_debug()) {
tinydisplay_cat.debug()
<< "loading texture " << tex->get_name() << ", "
<< tex->get_x_size() << " x " << tex->get_y_size() << ", mipmaps = "
<< num_levels << ", uses_mipmaps = " << uses_mipmaps << "\n";
}
if (!setup_gltex(gltex, tex->get_x_size(), tex->get_y_size(), num_levels)) {

View File

@ -91,7 +91,7 @@ public:
virtual TextureContext *prepare_texture(Texture *tex, int view);
virtual bool update_texture(TextureContext *tc, bool force);
bool update_texture(TextureContext *tc, bool force, int stage_index);
bool update_texture(TextureContext *tc, bool force, int stage_index, bool uses_mipmaps);
virtual void release_texture(TextureContext *tc);
virtual void do_issue_light();
@ -115,7 +115,7 @@ private:
void set_scissor(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top);
bool apply_texture(TextureContext *tc);
bool upload_texture(TinyTextureContext *gtc, bool force);
bool upload_texture(TinyTextureContext *gtc, bool force, bool uses_mipmaps);
bool upload_simple_texture(TinyTextureContext *gtc);
bool setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels);
int get_tex_shift(int orig_size);