Texture::set_quality_level()

This commit is contained in:
David Rose 2008-05-13 23:31:19 +00:00
parent 11aaf2ffce
commit acb0faae46
28 changed files with 2922 additions and 1119 deletions

View File

@ -447,6 +447,23 @@ appear before they are referenced.
the polygon itself. See the description for draw_order under the polygon itself. See the description for draw_order under
polygon attributes. polygon attributes.
<Scalar> quality-level { quality }
Sets a hint to the renderer about the desired performance /
quality tradeoff for this particular texture. This is most useful
for the tinydisplay software renderer; for normal,
hardware-accelerated renderers, this may have little or no effect.
This may be one of:
DEFAULT
FASTEST
NORMAL
BEST
"Default" means to use whatever quality level is specified by the
global texture-quality-level config variable.
<Transform> { transform-definition } <Transform> { transform-definition }
This specifies a 2-d or 3-d transformation that is applied to the This specifies a 2-d or 3-d transformation that is applied to the

View File

@ -441,6 +441,26 @@ get_tex_gen() const {
return _tex_gen; return _tex_gen;
} }
////////////////////////////////////////////////////////////////////
// Function: EggTexture::set_quality_level
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE void EggTexture::
set_quality_level(QualityLevel quality_level) {
_quality_level = quality_level;
}
////////////////////////////////////////////////////////////////////
// Function: EggTexture::get_quality_level
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE EggTexture::QualityLevel EggTexture::
get_quality_level() const {
return _quality_level;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: EggTexture::set_stage_name // Function: EggTexture::set_stage_name
// Access: Published // Access: Published

View File

@ -48,6 +48,7 @@ EggTexture(const string &tref_name, const string &filename)
_env_type = ET_unspecified; _env_type = ET_unspecified;
_saved_result = false; _saved_result = false;
_tex_gen = TG_unspecified; _tex_gen = TG_unspecified;
_quality_level = QL_unspecified;
_priority = 0; _priority = 0;
_color.set(0.0f, 0.0f, 0.0f, 1.0f); _color.set(0.0f, 0.0f, 0.0f, 1.0f);
_border_color.set(0.0f, 0.0f, 0.0f, 1.0f); _border_color.set(0.0f, 0.0f, 0.0f, 1.0f);
@ -93,6 +94,7 @@ operator = (const EggTexture &copy) {
_env_type = copy._env_type; _env_type = copy._env_type;
_saved_result = copy._saved_result; _saved_result = copy._saved_result;
_tex_gen = copy._tex_gen; _tex_gen = copy._tex_gen;
_quality_level = copy._quality_level;
_stage_name = copy._stage_name; _stage_name = copy._stage_name;
_priority = copy._priority; _priority = copy._priority;
_color = copy._color; _color = copy._color;
@ -237,6 +239,11 @@ write(ostream &out, int indent_level) const {
<< "<Scalar> tex-gen { " << get_tex_gen() << " }\n"; << "<Scalar> tex-gen { " << get_tex_gen() << " }\n";
} }
if (get_quality_level() != QL_unspecified) {
indent(out, indent_level + 2)
<< "<Scalar> quality-level { " << get_quality_level() << " }\n";
}
if (has_stage_name()) { if (has_stage_name()) {
indent(out, indent_level + 2) indent(out, indent_level + 2)
<< "<Scalar> stage-name { " << get_stage_name() << " }\n"; << "<Scalar> stage-name { " << get_stage_name() << " }\n";
@ -1050,6 +1057,35 @@ string_tex_gen(const string &string) {
} }
} }
////////////////////////////////////////////////////////////////////
// Function: EggTexture::string_quality_level
// Access: Published, Static
// Description: Returns the TexGen value associated with the given
// string representation, or ET_unspecified if the string
// does not match any known TexGen value.
////////////////////////////////////////////////////////////////////
EggTexture::QualityLevel EggTexture::
string_quality_level(const string &string) {
if (cmp_nocase_uh(string, "unspecified") == 0) {
return QL_unspecified;
} else if (cmp_nocase_uh(string, "default") == 0) {
return QL_default;
} else if (cmp_nocase_uh(string, "fastest") == 0) {
return QL_fastest;
} else if (cmp_nocase_uh(string, "normal") == 0) {
return QL_normal;
} else if (cmp_nocase_uh(string, "best") == 0) {
return QL_best;
} else {
return QL_unspecified;
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: EggTexture::as_transform // Function: EggTexture::as_transform
// Access: Public, Virtual // Access: Public, Virtual
@ -1469,3 +1505,21 @@ operator << (ostream &out, EggTexture::TexGen tex_gen) {
return out << "**invalid TexGen(" << (int)tex_gen << ")**"; return out << "**invalid TexGen(" << (int)tex_gen << ")**";
} }
ostream &
operator << (ostream &out, EggTexture::QualityLevel quality_level) {
switch (quality_level) {
case EggTexture::QL_unspecified:
return out << "unspecified";
case EggTexture::QL_default:
return out << "default";
case EggTexture::QL_fastest:
return out << "fastest";
case EggTexture::QL_normal:
return out << "normal";
case EggTexture::QL_best:
return out << "best";
}
return out << "**invalid QualityLevel(" << (int)quality_level << ")**";
}

View File

@ -162,6 +162,13 @@ PUBLISHED:
TG_point_sprite, TG_point_sprite,
}; };
enum QualityLevel {
QL_unspecified,
QL_default,
QL_fastest,
QL_normal,
QL_best,
};
INLINE void set_texture_type(TextureType texture_type); INLINE void set_texture_type(TextureType texture_type);
INLINE TextureType get_texture_type() const; INLINE TextureType get_texture_type() const;
@ -215,6 +222,9 @@ PUBLISHED:
INLINE void set_tex_gen(TexGen tex_gen); INLINE void set_tex_gen(TexGen tex_gen);
INLINE TexGen get_tex_gen() const; INLINE TexGen get_tex_gen() const;
INLINE void set_quality_level(QualityLevel quality_level);
INLINE QualityLevel get_quality_level() const;
INLINE void set_stage_name(const string &stage_name); INLINE void set_stage_name(const string &stage_name);
INLINE void clear_stage_name(); INLINE void clear_stage_name();
INLINE bool has_stage_name() const; INLINE bool has_stage_name() const;
@ -281,6 +291,7 @@ PUBLISHED:
static CombineSource string_combine_source(const string &string); static CombineSource string_combine_source(const string &string);
static CombineOperand string_combine_operand(const string &string); static CombineOperand string_combine_operand(const string &string);
static TexGen string_tex_gen(const string &string); static TexGen string_tex_gen(const string &string);
static QualityLevel string_quality_level(const string &string);
public: public:
virtual EggTransform *as_transform(); virtual EggTransform *as_transform();
@ -314,6 +325,7 @@ private:
EnvType _env_type; EnvType _env_type;
bool _saved_result; bool _saved_result;
TexGen _tex_gen; TexGen _tex_gen;
QualityLevel _quality_level;
string _stage_name; string _stage_name;
int _priority; int _priority;
Colorf _color; Colorf _color;
@ -399,6 +411,7 @@ EXPCL_PANDAEGG ostream &operator << (ostream &out, EggTexture::CombineChannel cc
EXPCL_PANDAEGG ostream &operator << (ostream &out, EggTexture::CombineSource cs); EXPCL_PANDAEGG ostream &operator << (ostream &out, EggTexture::CombineSource cs);
EXPCL_PANDAEGG ostream &operator << (ostream &out, EggTexture::CombineOperand co); EXPCL_PANDAEGG ostream &operator << (ostream &out, EggTexture::CombineOperand co);
EXPCL_PANDAEGG ostream &operator << (ostream &out, EggTexture::TexGen tex_gen); EXPCL_PANDAEGG ostream &operator << (ostream &out, EggTexture::TexGen tex_gen);
EXPCL_PANDAEGG ostream &operator << (ostream &out, EggTexture::QualityLevel quality_level);
#include "eggTexture.I" #include "eggTexture.I"

View File

@ -537,11 +537,19 @@ texture_body:
} else if (cmp_nocase_uh(name, "tex_gen") == 0) { } else if (cmp_nocase_uh(name, "tex_gen") == 0) {
EggTexture::TexGen tex_gen = EggTexture::string_tex_gen(strval); EggTexture::TexGen tex_gen = EggTexture::string_tex_gen(strval);
if (tex_gen == EggTexture::TG_unspecified) { if (tex_gen == EggTexture::TG_unspecified) {
eggyywarning("Unknown texture env type " + strval); eggyywarning("Unknown tex-gen " + strval);
} else { } else {
texture->set_tex_gen(tex_gen); texture->set_tex_gen(tex_gen);
} }
} else if (cmp_nocase_uh(name, "quality_level") == 0) {
EggTexture::QualityLevel quality_level = EggTexture::string_quality_level(strval);
if (quality_level == EggTexture::QL_unspecified) {
eggyywarning("Unknown quality-level " + strval);
} else {
texture->set_quality_level(quality_level);
}
} else if (cmp_nocase_uh(name, "stage_name") == 0) { } else if (cmp_nocase_uh(name, "stage_name") == 0) {
texture->set_stage_name(strval); texture->set_stage_name(strval);

View File

@ -1261,6 +1261,25 @@ apply_texture_attributes(Texture *tex, const EggTexture *egg_tex) {
<< " for 4-component texture " << egg_tex->get_name() << "\n"; << " for 4-component texture " << egg_tex->get_name() << "\n";
} }
} }
switch (egg_tex->get_quality_level()) {
case EggTexture::QL_unspecified:
case EggTexture::QL_default:
tex->set_quality_level(Texture::QL_default);
break;
case EggTexture::QL_fastest:
tex->set_quality_level(Texture::QL_fastest);
break;
case EggTexture::QL_normal:
tex->set_quality_level(Texture::QL_normal);
break;
case EggTexture::QL_best:
tex->set_quality_level(Texture::QL_best);
break;
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -743,6 +743,17 @@ uses_mipmaps() const {
return is_mipmap(get_minfilter()); return is_mipmap(get_minfilter());
} }
////////////////////////////////////////////////////////////////////
// Function: Texture::get_quality_level
// Access: Public
// Description: Returns the current quality_level hint. See
// set_quality_level().
////////////////////////////////////////////////////////////////////
INLINE Texture::QualityLevel Texture::
get_quality_level() const {
return _quality_level;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: Texture::might_have_ram_image // Function: Texture::might_have_ram_image
// Access: Published // Access: Published

View File

@ -42,6 +42,16 @@
#include <stddef.h> #include <stddef.h>
ConfigVariableEnum<Texture::QualityLevel> texture_quality_level
("texture-quality-level", Texture::QL_normal,
PRC_DESC("This specifies a global quality level for all textures. You "
"may specify either fastest, normal, or best. This actually "
"affects the meaning of Texture::set_quality_level(TQL_default), "
"so it may be overridden on a per-texture basis. This generally "
"only has an effect when using the tinydisplay software renderer; "
"it has little or no effect on normal, hardware-accelerated "
"renderers. See Texture::set_quality_level()."));
PStatCollector Texture::_texture_read_pcollector("*:Texture:Read"); PStatCollector Texture::_texture_read_pcollector("*:Texture:Read");
TypeHandle Texture::_type_handle; TypeHandle Texture::_type_handle;
AutoTextureScale Texture::_textures_power_2 = ATS_UNSPECIFIED; AutoTextureScale Texture::_textures_power_2 = ATS_UNSPECIFIED;
@ -72,6 +82,7 @@ Texture(const string &name) :
_ram_image_compression = CM_off; _ram_image_compression = CM_off;
_render_to_texture = false; _render_to_texture = false;
_match_framebuffer_format = false; _match_framebuffer_format = false;
_quality_level = QL_default;
_texture_type = TT_2d_texture; _texture_type = TT_2d_texture;
_x_size = 0; _x_size = 0;
@ -129,6 +140,7 @@ Texture(const Texture &copy) :
_border_color(copy._border_color), _border_color(copy._border_color),
_compression(copy._compression), _compression(copy._compression),
_match_framebuffer_format(copy._match_framebuffer_format), _match_framebuffer_format(copy._match_framebuffer_format),
_quality_level(copy._quality_level),
_pad_x_size(copy._pad_x_size), _pad_x_size(copy._pad_x_size),
_pad_y_size(copy._pad_y_size), _pad_y_size(copy._pad_y_size),
_pad_z_size(copy._pad_z_size), _pad_z_size(copy._pad_z_size),
@ -179,6 +191,7 @@ operator = (const Texture &copy) {
_border_color = copy._border_color; _border_color = copy._border_color;
_compression = copy._compression; _compression = copy._compression;
_match_framebuffer_format = copy._match_framebuffer_format; _match_framebuffer_format = copy._match_framebuffer_format;
_quality_level = copy._quality_level;
_ram_image_compression = copy._ram_image_compression; _ram_image_compression = copy._ram_image_compression;
_ram_images = copy._ram_images; _ram_images = copy._ram_images;
++_properties_modified; ++_properties_modified;
@ -838,6 +851,23 @@ set_render_to_texture(bool render_to_texture) {
_render_to_texture = render_to_texture; _render_to_texture = render_to_texture;
} }
////////////////////////////////////////////////////////////////////
// Function: Texture::set_quality_level
// Access: Public
// Description: Sets a hint to the renderer about the desired
// performance / quality tradeoff for this particular
// texture. This is most useful for the tinydisplay
// software renderer; for normal, hardware-accelerated
// renderers, this may have little or no effect.
////////////////////////////////////////////////////////////////////
void Texture::
set_quality_level(Texture::QualityLevel quality_level) {
if (_quality_level != quality_level) {
++_properties_modified;
_quality_level = quality_level;
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: Texture::get_expected_num_mipmap_levels // Function: Texture::get_expected_num_mipmap_levels
// Access: Published // Access: Published
@ -3539,6 +3569,9 @@ fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata) {
if (manager->get_file_minor_ver() >= 1) { if (manager->get_file_minor_ver() >= 1) {
set_compression((CompressionMode)scan.get_uint8()); set_compression((CompressionMode)scan.get_uint8());
} }
if (manager->get_file_minor_ver() >= 16) {
set_quality_level((QualityLevel)scan.get_uint8());
}
Format format = (Format)scan.get_uint8(); Format format = (Format)scan.get_uint8();
int num_components = scan.get_uint8(); int num_components = scan.get_uint8();
@ -3696,6 +3729,7 @@ write_datagram(BamWriter *manager, Datagram &me) {
me.add_int16(_anisotropic_degree); me.add_int16(_anisotropic_degree);
_border_color.write_datagram(me); _border_color.write_datagram(me);
me.add_uint8(_compression); me.add_uint8(_compression);
me.add_uint8(_quality_level);
me.add_uint8(_format); me.add_uint8(_format);
me.add_uint8(_num_components); me.add_uint8(_num_components);
@ -3927,3 +3961,51 @@ operator << (ostream &out, Texture::CompressionMode cm) {
return out << "(**invalid Texture::CompressionMode(" << (int)cm << ")**)"; return out << "(**invalid Texture::CompressionMode(" << (int)cm << ")**)";
} }
////////////////////////////////////////////////////////////////////
// Function: Texture::QualityLevel output operator
// Description:
////////////////////////////////////////////////////////////////////
ostream &
operator << (ostream &out, Texture::QualityLevel tql) {
switch (tql) {
case Texture::QL_default:
return out << "default";
case Texture::QL_fastest:
return out << "fastest";
case Texture::QL_normal:
return out << "normal";
case Texture::QL_best:
return out << "best";
}
return out << "**invalid Texture::QualityLevel (" << (int)tql << ")**";
}
////////////////////////////////////////////////////////////////////
// Function: Texture::QualityLevel input operator
// Description:
////////////////////////////////////////////////////////////////////
istream &
operator >> (istream &in, Texture::QualityLevel &tql) {
string word;
in >> word;
if (cmp_nocase(word, "default") == 0) {
tql = Texture::QL_default;
} else if (cmp_nocase(word, "fastest") == 0) {
tql = Texture::QL_fastest;
} else if (cmp_nocase(word, "normal") == 0) {
tql = Texture::QL_normal;
} else if (cmp_nocase(word, "best") == 0) {
tql = Texture::QL_best;
} else {
gobj_cat->error() << "Invalid Texture::QualityLevel value: " << word << "\n";
tql = Texture::QL_default;
}
return in;
}

View File

@ -175,6 +175,13 @@ PUBLISHED:
CM_dxt5, CM_dxt5,
}; };
enum QualityLevel {
QL_default, // according to texture-quality-level
QL_fastest,
QL_normal,
QL_best,
};
PUBLISHED: PUBLISHED:
Texture(const string &name = string()); Texture(const string &name = string());
protected: protected:
@ -271,6 +278,9 @@ PUBLISHED:
INLINE bool get_render_to_texture() const; INLINE bool get_render_to_texture() const;
INLINE bool uses_mipmaps() const; INLINE bool uses_mipmaps() const;
void set_quality_level(QualityLevel quality_level);
INLINE QualityLevel get_quality_level() const;
int get_expected_num_mipmap_levels() const; int get_expected_num_mipmap_levels() const;
int get_expected_mipmap_x_size(int n) const; int get_expected_mipmap_x_size(int n) const;
int get_expected_mipmap_y_size(int n) const; int get_expected_mipmap_y_size(int n) const;
@ -515,6 +525,7 @@ protected:
CompressionMode _compression; CompressionMode _compression;
bool _render_to_texture; bool _render_to_texture;
bool _match_framebuffer_format; bool _match_framebuffer_format;
QualityLevel _quality_level;
int _pad_x_size; int _pad_x_size;
int _pad_y_size; int _pad_y_size;
@ -587,6 +598,8 @@ private:
friend class TexturePool; friend class TexturePool;
}; };
extern EXPCL_PANDA_GOBJ ConfigVariableEnum<Texture::QualityLevel> texture_quality_level;
EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, Texture::TextureType tt); EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, Texture::TextureType tt);
EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, Texture::ComponentType ct); EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, Texture::ComponentType ct);
EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, Texture::Format f); EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, Texture::Format f);
@ -598,6 +611,8 @@ EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, Texture::WrapMode wm);
EXPCL_PANDA_GOBJ istream &operator >> (istream &in, Texture::WrapMode &wm); EXPCL_PANDA_GOBJ istream &operator >> (istream &in, Texture::WrapMode &wm);
EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, Texture::CompressionMode cm); EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, Texture::CompressionMode cm);
EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, Texture::QualityLevel tql);
EXPCL_PANDA_GOBJ istream &operator >> (istream &in, Texture::QualityLevel &tql);
#include "texture.I" #include "texture.I"

View File

@ -36,7 +36,7 @@ static const unsigned short _bam_major_ver = 6;
// Bumped to major version 5 on 5/6/05 for new Geom implementation. // Bumped to major version 5 on 5/6/05 for new Geom implementation.
// Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData. // Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
static const unsigned short _bam_minor_ver = 15; static const unsigned short _bam_minor_ver = 16;
// Bumped to minor version 1 on 3/12/06 to add Texture::_compression. // Bumped to minor version 1 on 3/12/06 to add Texture::_compression.
// Bumped to minor version 2 on 3/17/06 to add PandaNode::_draw_control_mask. // Bumped to minor version 2 on 3/17/06 to add PandaNode::_draw_control_mask.
// Bumped to minor version 3 on 3/21/06 to add Texture::_ram_images. // Bumped to minor version 3 on 3/21/06 to add Texture::_ram_images.
@ -52,6 +52,7 @@ static const unsigned short _bam_minor_ver = 15;
// Bumped to minor version 13 on 8/15/07 to reverse CollisionPolygon vertices. // Bumped to minor version 13 on 8/15/07 to reverse CollisionPolygon vertices.
// Bumped to minor version 14 on 12/19/07 to change default ColorAttrib. // Bumped to minor version 14 on 12/19/07 to change default ColorAttrib.
// Bumped to minor version 15 on 4/9/08 to add TextureAttrib::_implicit_sort. // Bumped to minor version 15 on 4/9/08 to add TextureAttrib::_implicit_sort.
// Bumped to minor version 16 on 5/13/08 to add Texture::_quality_level.
#endif #endif

View File

@ -37,6 +37,10 @@ DynamicTextPage(DynamicTextFont *font, int page_number) :
// it by default. // it by default.
_compression = CM_off; _compression = CM_off;
// It's usually pretty important for text to look its best, and it
// doesn't usually have a high fill factor.
set_quality_level(Texture::QL_best);
_x_size = _font->get_page_x_size(); _x_size = _font->get_page_x_size();
_y_size = _font->get_page_y_size(); _y_size = _font->get_page_y_size();

View File

@ -33,7 +33,6 @@ void gl_transform_to_viewport(GLContext *c,GLVertex *v)
+ ZB_POINT_ALPHA_MIN); + ZB_POINT_ALPHA_MIN);
/* texture */ /* texture */
if (c->texture_2d_enabled) { if (c->texture_2d_enabled) {
v->zp.s = (int)(v->tex_coord.X * c->current_texture->s_max); v->zp.s = (int)(v->tex_coord.X * c->current_texture->s_max);
v->zp.t = (int)(v->tex_coord.Y * c->current_texture->t_max); v->zp.t = (int)(v->tex_coord.Y * c->current_texture->t_max);

View File

@ -599,7 +599,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
} }
} }
if (_c->texture_2d_enabled && _texture_replace) { if (_texturing_state != 0 && _texture_replace) {
// We don't need the vertex color or lighting calculation after // We don't need the vertex color or lighting calculation after
// all, since the current texture will just hide all of that. // all, since the current texture will just hide all of that.
needs_color = false; needs_color = false;
@ -763,13 +763,14 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
} }
} }
int texturing_state = 0; // untextured int texturing_state = _texturing_state;
int texfilter_state = 0; // nearest int texfilter_state = 0; // tnearest
if (_c->texture_2d_enabled) { if (texturing_state > 0) {
texfilter_state = _texfilter_state; texfilter_state = _texfilter_state;
texturing_state = 2; // perspective-correct textures if (_c->matrix_model_projection_no_w_transform) {
if (_c->matrix_model_projection_no_w_transform || !td_perspective_textures) { // Don't bother with the perspective-correct algorithm if we're
texturing_state = 1; // non-perspective-correct textures // under an orthonormal lens, e.g. render2d.
texturing_state = 1; // textured (not perspective correct)
} }
if (_texture_replace) { if (_texture_replace) {
@ -1241,10 +1242,7 @@ release_texture(TextureContext *tc) {
GLTexture *gltex = gtc->_gltex; GLTexture *gltex = gtc->_gltex;
gtc->_gltex = NULL; gtc->_gltex = NULL;
if (_c->current_texture == gltex) { _texturing_state = 0; // just in case
_c->current_texture = NULL;
_c->texture_2d_enabled = false;
}
for (int i = 0; i < gltex->num_levels; ++i) { for (int i = 0; i < gltex->num_levels; ++i) {
gl_free(gltex->levels[i].pixmap); gl_free(gltex->levels[i].pixmap);
@ -1602,6 +1600,7 @@ do_issue_material() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void TinyGraphicsStateGuardian:: void TinyGraphicsStateGuardian::
do_issue_texture() { do_issue_texture() {
_texturing_state = 0; // untextured
_c->texture_2d_enabled = false; _c->texture_2d_enabled = false;
int num_stages = _effective_texture->get_num_on_ff_stages(); int num_stages = _effective_texture->get_num_on_ff_stages();
@ -1622,12 +1621,53 @@ do_issue_texture() {
} }
// Then, turn on the current texture mode. // Then, turn on the current texture mode.
apply_texture(tc); if (!apply_texture(tc)) {
return;
}
// Set a few state cache values. // Set a few state cache values.
_texfilter_state = 0; // nearest _c->texture_2d_enabled = true;
if (texture->uses_mipmaps() && !td_ignore_mipmaps) {
_texfilter_state = 1; // mipmap _texturing_state = 2; // perspective (perspective-correct texturing)
if (!td_perspective_textures) {
_texturing_state = 1; // textured (not perspective correct)
}
Texture::QualityLevel quality_level = texture->get_quality_level();
if (quality_level == Texture::QL_default) {
quality_level = texture_quality_level;
}
if (quality_level == Texture::QL_best) {
// This is the most generic texture filter. Slow, but pretty.
_texfilter_state = 2; // tgeneral
_c->zb->tex_minfilter_func = get_tex_filter_func(texture->get_minfilter());
_c->zb->tex_magfilter_func = get_tex_filter_func(texture->get_magfilter());
if (texture->get_minfilter() == Texture::FT_nearest &&
texture->get_magfilter() == Texture::FT_nearest) {
// This case is inlined.
_texfilter_state = 0; // tnearest
} else if (texture->get_minfilter() == Texture::FT_nearest_mipmap_nearest &&
texture->get_magfilter() == Texture::FT_nearest) {
// So is this case.
_texfilter_state = 1; // tmipmap
}
} else if (quality_level == Texture::QL_fastest) {
// This is the cheapest texture filter. We disallow mipmaps and
// perspective correctness.
_texfilter_state = 0; // tnearest
_texturing_state = 1; // textured (not perspective correct)
} else {
// This is the default texture filter. We use nearest sampling if
// there are no mipmaps, and mipmap_nearest if there are any
// mipmaps--these are the two inlined filters.
_texfilter_state = 0; // tnearest
if (texture->uses_mipmaps() && !td_ignore_mipmaps) {
_texfilter_state = 1; // tmipmap
}
} }
// M_replace means M_replace; anything else is treated the same as // M_replace means M_replace; anything else is treated the same as
@ -1642,29 +1682,32 @@ do_issue_texture() {
// texture, and makes it the current texture available // texture, and makes it the current texture available
// for rendering. // for rendering.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void TinyGraphicsStateGuardian:: bool TinyGraphicsStateGuardian::
apply_texture(TextureContext *tc) { apply_texture(TextureContext *tc) {
TinyTextureContext *gtc = DCAST(TinyTextureContext, tc); TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
gtc->set_active(true); gtc->set_active(true);
_c->current_texture = gtc->_gltex;
_c->texture_2d_enabled = true;
GLTexture *gltex = gtc->_gltex; GLTexture *gltex = gtc->_gltex;
if (gtc->was_image_modified() || gltex->num_levels == 0) { if (gtc->was_image_modified() || gltex->num_levels == 0) {
// If the texture image was modified, reload the texture. // If the texture image was modified, reload the texture.
if (!upload_texture(gtc)) { bool okflag = upload_texture(gtc);
if (!okflag) {
tinydisplay_cat.error() tinydisplay_cat.error()
<< "Could not load " << *gtc->get_texture() << "Could not load " << *gtc->get_texture()
<< ": inappropriate size.\n"; << ": inappropriate size.\n";
_c->texture_2d_enabled = false;
} }
gtc->mark_loaded(); gtc->mark_loaded();
if (!okflag) {
return false;
}
} }
gtc->enqueue_lru(&_textures_lru); gtc->enqueue_lru(&_textures_lru);
_c->current_texture = gltex;
_c->zb->current_texture = gltex->levels; _c->zb->current_texture = gltex->levels;
return true;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -2211,3 +2254,48 @@ get_color_blend_op(ColorBlendAttrib::Operand operand) {
} }
return 0; return 0;
} }
////////////////////////////////////////////////////////////////////
// Function: TinyGraphicsStateGuardian::get_tex_filter_func
// Access: Private, Static
// Description: Returns the pointer to the appropriate filter
// function according to the texture's filter type.
////////////////////////////////////////////////////////////////////
ZB_lookupTextureFunc TinyGraphicsStateGuardian::
get_tex_filter_func(Texture::FilterType filter) {
switch (filter) {
case Texture::FT_nearest:
return &lookup_texture_nearest;
case Texture::FT_linear:
return &lookup_texture_bilinear;
case Texture::FT_nearest_mipmap_nearest:
if (td_ignore_mipmaps) {
return &lookup_texture_nearest;
}
return &lookup_texture_mipmap_nearest;
case Texture::FT_nearest_mipmap_linear:
if (td_ignore_mipmaps) {
return &lookup_texture_nearest;
}
return &lookup_texture_mipmap_linear;
case Texture::FT_linear_mipmap_nearest:
if (td_ignore_mipmaps) {
return &lookup_texture_bilinear;
}
return &lookup_texture_mipmap_bilinear;
case Texture::FT_linear_mipmap_linear:
if (td_ignore_mipmaps) {
return &lookup_texture_bilinear;
}
return &lookup_texture_mipmap_trilinear;
default:
return &lookup_texture_nearest;
}
}

View File

@ -104,7 +104,7 @@ private:
void do_issue_material(); void do_issue_material();
void do_issue_texture(); void do_issue_texture();
void apply_texture(TextureContext *tc); bool apply_texture(TextureContext *tc);
bool upload_texture(TinyTextureContext *gtc); bool upload_texture(TinyTextureContext *gtc);
bool setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels); bool setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels);
int get_tex_shift(int orig_size); int get_tex_shift(int orig_size);
@ -119,6 +119,7 @@ private:
void setup_material(GLMaterial *gl_material, const Material *material); void setup_material(GLMaterial *gl_material, const Material *material);
static void load_matrix(M4 *matrix, const TransformState *transform); static void load_matrix(M4 *matrix, const TransformState *transform);
static int get_color_blend_op(ColorBlendAttrib::Operand operand); static int get_color_blend_op(ColorBlendAttrib::Operand operand);
static ZB_lookupTextureFunc get_tex_filter_func(Texture::FilterType filter);
public: public:
// Filled in by the Tiny*GraphicsWindow at begin_frame(). // Filled in by the Tiny*GraphicsWindow at begin_frame().
@ -136,6 +137,7 @@ private:
CMF_diffuse = 0x002, CMF_diffuse = 0x002,
}; };
int _color_material_flags; int _color_material_flags;
int _texturing_state;
int _texfilter_state; int _texfilter_state;
bool _texture_replace; bool _texture_replace;

View File

@ -509,6 +509,9 @@ TinyOsxGraphicsWindow::TinyOsxGraphicsWindow(GraphicsPipe *pipe,
_cursor_hidden = false; _cursor_hidden = false;
_display_hide_cursor = false; _display_hide_cursor = false;
_wheel_delta = 0; _wheel_delta = 0;
_frame_buffer = NULL;
update_pixel_factor();
if (tinydisplay_cat.is_debug()) if (tinydisplay_cat.is_debug())
tinydisplay_cat.debug() << "TinyOsxGraphicsWindow::TinyOsxGraphicsWindow() -" <<_ID << "\n"; tinydisplay_cat.debug() << "TinyOsxGraphicsWindow::TinyOsxGraphicsWindow() -" <<_ID << "\n";

View File

@ -8,6 +8,7 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include "zbuffer.h" #include "zbuffer.h"
#include "pnotify.h"
ZBuffer *ZB_open(int xsize, int ysize, int mode, ZBuffer *ZB_open(int xsize, int ysize, int mode,
int nb_colors, int nb_colors,
@ -343,8 +344,26 @@ void ZB_clear_viewport(ZBuffer * zb, int clear_z, ZPOINT z,
#define ZB_ST_FRAC_HIGH (1 << ZB_POINT_ST_FRAC_BITS) #define ZB_ST_FRAC_HIGH (1 << ZB_POINT_ST_FRAC_BITS)
#define ZB_ST_FRAC_MASK (ZB_ST_FRAC_HIGH - 1) #define ZB_ST_FRAC_MASK (ZB_ST_FRAC_HIGH - 1)
PIXEL lookup_texture_bilinear(ZTextureLevel *base_level, int s, int t) #define LINEAR_FILTER_BITSIZE(c1, c2, f, bitsize) \
((((c2) * (f)) >> bitsize) + (((c1) * ((1 << bitsize) - (f))) >> bitsize))
#define LINEAR_FILTER(c1, c2, f) \
LINEAR_FILTER_BITSIZE(c1, c2, f, ZB_POINT_ST_FRAC_BITS)
#define BILINEAR_FILTER(c1, c2, c3, c4, sf, tf) \
(LINEAR_FILTER(LINEAR_FILTER(c1, c2, sf), LINEAR_FILTER(c3, c4, sf), tf))
// Grab the nearest texel from the base level. This is also
// implemented inline as ZB_LOOKUP_TEXTURE_NEAREST.
PIXEL lookup_texture_nearest(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx)
{ {
return ZB_LOOKUP_TEXTURE_NEAREST(texture_levels, s, t);
}
// Bilinear filter four texels in the base level.
PIXEL lookup_texture_bilinear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx)
{
ZTextureLevel *base_level = texture_levels;
PIXEL p1, p2, p3, p4; PIXEL p1, p2, p3, p4;
int sf, tf; int sf, tf;
int r, g, b, a; int r, g, b, a;
@ -356,18 +375,127 @@ PIXEL lookup_texture_bilinear(ZTextureLevel *base_level, int s, int t)
p3 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s, t + ZB_ST_FRAC_HIGH); p3 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s, t + ZB_ST_FRAC_HIGH);
p4 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s + ZB_ST_FRAC_HIGH, t + ZB_ST_FRAC_HIGH); p4 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s + ZB_ST_FRAC_HIGH, t + ZB_ST_FRAC_HIGH);
tf = t & ZB_ST_FRAC_MASK; tf = t & ZB_ST_FRAC_MASK;
r = (((PIXEL_R(p4) * sf + PIXEL_R(p3) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * tf +
((PIXEL_R(p2) * sf + PIXEL_R(p1) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * (ZB_ST_FRAC_HIGH - tf)) >> ZB_POINT_ST_FRAC_BITS;
g = (((PIXEL_G(p4) * sf + PIXEL_G(p3) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * tf + r = BILINEAR_FILTER(PIXEL_R(p1), PIXEL_R(p2), PIXEL_R(p3), PIXEL_R(p4), sf, tf);
((PIXEL_G(p2) * sf + PIXEL_G(p1) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * (ZB_ST_FRAC_HIGH - tf)) >> ZB_POINT_ST_FRAC_BITS; g = BILINEAR_FILTER(PIXEL_G(p1), PIXEL_G(p2), PIXEL_G(p3), PIXEL_G(p4), sf, tf);
b = BILINEAR_FILTER(PIXEL_B(p1), PIXEL_B(p2), PIXEL_B(p3), PIXEL_B(p4), sf, tf);
b = (((PIXEL_B(p4) * sf + PIXEL_B(p3) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * tf + a = BILINEAR_FILTER(PIXEL_A(p1), PIXEL_A(p2), PIXEL_A(p3), PIXEL_A(p4), sf, tf);
((PIXEL_B(p2) * sf + PIXEL_B(p1) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * (ZB_ST_FRAC_HIGH - tf)) >> ZB_POINT_ST_FRAC_BITS;
return RGBA_TO_PIXEL(r, g, b, a);
a = (((PIXEL_A(p4) * sf + PIXEL_A(p3) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * tf + }
((PIXEL_A(p2) * sf + PIXEL_A(p1) * (ZB_ST_FRAC_HIGH - sf)) >> ZB_POINT_ST_FRAC_BITS) * (ZB_ST_FRAC_HIGH - tf)) >> ZB_POINT_ST_FRAC_BITS;
// Grab the nearest texel from the nearest mipmap level. This is also
// implemented inline as ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST.
PIXEL lookup_texture_mipmap_nearest(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx)
{
return ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_levels, s, t, level);
}
// Linear filter the two texels from the two nearest mipmap levels.
PIXEL lookup_texture_mipmap_linear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx)
{
PIXEL p1, p2;
int r, g, b, a;
p1 = ZB_LOOKUP_TEXTURE_NEAREST(texture_levels + level - 1, s >> (level - 1), t >> (level - 1));
p2 = ZB_LOOKUP_TEXTURE_NEAREST(texture_levels + level, s >> level, t >> level);
unsigned int bitsize = (level - 1) + ZB_POINT_ST_FRAC_BITS;
r = LINEAR_FILTER_BITSIZE(PIXEL_R(p1), PIXEL_R(p2), level_dx, bitsize);
g = LINEAR_FILTER_BITSIZE(PIXEL_G(p1), PIXEL_G(p2), level_dx, bitsize);
b = LINEAR_FILTER_BITSIZE(PIXEL_B(p1), PIXEL_B(p2), level_dx, bitsize);
a = LINEAR_FILTER_BITSIZE(PIXEL_A(p1), PIXEL_A(p2), level_dx, bitsize);
return RGBA_TO_PIXEL(r, g, b, a);
}
// Bilinear filter four texels in the nearest mipmap level.
PIXEL lookup_texture_mipmap_bilinear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx)
{
ZTextureLevel *base_level = texture_levels + level;
s >>= level;
t >>= level;
PIXEL p1, p2, p3, p4;
int sf, tf;
int r, g, b, a;
p1 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s, t);
p2 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s + ZB_ST_FRAC_HIGH, t);
sf = s & ZB_ST_FRAC_MASK;
p3 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s, t + ZB_ST_FRAC_HIGH);
p4 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, s + ZB_ST_FRAC_HIGH, t + ZB_ST_FRAC_HIGH);
tf = t & ZB_ST_FRAC_MASK;
r = BILINEAR_FILTER(PIXEL_R(p1), PIXEL_R(p2), PIXEL_R(p3), PIXEL_R(p4), sf, tf);
g = BILINEAR_FILTER(PIXEL_G(p1), PIXEL_G(p2), PIXEL_G(p3), PIXEL_G(p4), sf, tf);
b = BILINEAR_FILTER(PIXEL_B(p1), PIXEL_B(p2), PIXEL_B(p3), PIXEL_B(p4), sf, tf);
a = BILINEAR_FILTER(PIXEL_A(p1), PIXEL_A(p2), PIXEL_A(p3), PIXEL_A(p4), sf, tf);
return RGBA_TO_PIXEL(r, g, b, a);
}
// Bilinear filter four texels in each of the nearest two mipmap
// levels, then linear filter them together.
PIXEL lookup_texture_mipmap_trilinear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx)
{
PIXEL p1a, p2a;
{
ZTextureLevel *base_level = texture_levels + level - 1;
int sl = s >> (level - 1);
int tl = t >> (level - 1);
PIXEL p1, p2, p3, p4;
int sf, tf;
int r, g, b, a;
p1 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl, tl);
p2 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl + ZB_ST_FRAC_HIGH, tl);
sf = sl & ZB_ST_FRAC_MASK;
p3 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl, tl + ZB_ST_FRAC_HIGH);
p4 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl + ZB_ST_FRAC_HIGH, tl + ZB_ST_FRAC_HIGH);
tf = tl & ZB_ST_FRAC_MASK;
r = BILINEAR_FILTER(PIXEL_R(p1), PIXEL_R(p2), PIXEL_R(p3), PIXEL_R(p4), sf, tf);
g = BILINEAR_FILTER(PIXEL_G(p1), PIXEL_G(p2), PIXEL_G(p3), PIXEL_G(p4), sf, tf);
b = BILINEAR_FILTER(PIXEL_B(p1), PIXEL_B(p2), PIXEL_B(p3), PIXEL_B(p4), sf, tf);
a = BILINEAR_FILTER(PIXEL_A(p1), PIXEL_A(p2), PIXEL_A(p3), PIXEL_A(p4), sf, tf);
p1a = RGBA_TO_PIXEL(r, g, b, a);
}
{
ZTextureLevel *base_level = texture_levels + level;
int sl = s >> level;
int tl = t >> level;
PIXEL p1, p2, p3, p4;
int sf, tf;
int r, g, b, a;
p1 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl, tl);
p2 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl + ZB_ST_FRAC_HIGH, tl);
sf = sl & ZB_ST_FRAC_MASK;
p3 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl, tl + ZB_ST_FRAC_HIGH);
p4 = ZB_LOOKUP_TEXTURE_NEAREST(base_level, sl + ZB_ST_FRAC_HIGH, tl + ZB_ST_FRAC_HIGH);
tf = tl & ZB_ST_FRAC_MASK;
r = BILINEAR_FILTER(PIXEL_R(p1), PIXEL_R(p2), PIXEL_R(p3), PIXEL_R(p4), sf, tf);
g = BILINEAR_FILTER(PIXEL_G(p1), PIXEL_G(p2), PIXEL_G(p3), PIXEL_G(p4), sf, tf);
b = BILINEAR_FILTER(PIXEL_B(p1), PIXEL_B(p2), PIXEL_B(p3), PIXEL_B(p4), sf, tf);
a = BILINEAR_FILTER(PIXEL_A(p1), PIXEL_A(p2), PIXEL_A(p3), PIXEL_A(p4), sf, tf);
p2a = RGBA_TO_PIXEL(r, g, b, a);
}
int r, g, b, a;
unsigned int bitsize = (level - 1) + ZB_POINT_ST_FRAC_BITS;
r = LINEAR_FILTER_BITSIZE(PIXEL_R(p1a), PIXEL_R(p2a), level_dx, bitsize);
g = LINEAR_FILTER_BITSIZE(PIXEL_G(p1a), PIXEL_G(p2a), level_dx, bitsize);
b = LINEAR_FILTER_BITSIZE(PIXEL_B(p1a), PIXEL_B(p2a), level_dx, bitsize);
a = LINEAR_FILTER_BITSIZE(PIXEL_A(p1a), PIXEL_A(p2a), level_dx, bitsize);
return RGBA_TO_PIXEL(r, g, b, a); return RGBA_TO_PIXEL(r, g, b, a);
} }

View File

@ -33,7 +33,7 @@ typedef unsigned short ZPOINT;
#define ZB_LOOKUP_TEXTURE_NEAREST(texture_levels, s, t) \ #define ZB_LOOKUP_TEXTURE_NEAREST(texture_levels, s, t) \
(texture_levels)->pixmap[ZB_TEXEL(texture_levels, s, t)] (texture_levels)->pixmap[ZB_TEXEL(texture_levels, s, t)]
#define ZB_LOOKUP_TEXTURE_NEAREST_MIPMAP(texture_levels, s, t, level) \ #define ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_levels, s, t, level) \
ZB_LOOKUP_TEXTURE_NEAREST((texture_levels) + (level), (s) >> (level), (t) >> (level)) ZB_LOOKUP_TEXTURE_NEAREST((texture_levels) + (level), (s) >> (level), (t) >> (level))
/* A special abs() function which doesn't require any branching /* A special abs() function which doesn't require any branching
@ -44,15 +44,11 @@ typedef unsigned short ZPOINT;
//#define FAST_ABS(v) (((v) ^ ((v) >> (sizeof(v) * 8 - 1))) - ((v) >> (sizeof(v) * 8 - 1))) //#define FAST_ABS(v) (((v) ^ ((v) >> (sizeof(v) * 8 - 1))) - ((v) >> (sizeof(v) * 8 - 1)))
#define DO_CALC_MIPMAP_LEVEL \ #define DO_CALC_MIPMAP_LEVEL \
mipmap_level = get_next_higher_bit(((unsigned int)abs(dsdx) + (unsigned int)abs(dtdx)) >> ZB_POINT_ST_FRAC_BITS) { \
mipmap_dx = ((unsigned int)abs(dsdx) + (unsigned int)abs(dtdx)); \
#if 0 mipmap_level = get_next_higher_bit(mipmap_dx >> ZB_POINT_ST_FRAC_BITS); \
/* Experiment with bilinear filtering. Looks great, but seems to run mipmap_dx &= ((1 << ((mipmap_level - 1) + ZB_POINT_ST_FRAC_BITS)) - 1); \
about 25% slower. */ }
#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level) \
lookup_texture_bilinear((texture_levels), (s), (t))
#endif
#define ZB_POINT_RED_MIN 0x0000 #define ZB_POINT_RED_MIN 0x0000
#define ZB_POINT_RED_MAX 0xffff #define ZB_POINT_RED_MAX 0xffff
@ -106,7 +102,9 @@ typedef struct ZBufferPoint ZBufferPoint;
typedef void (*ZB_fillTriangleFunc)(ZBuffer *, typedef void (*ZB_fillTriangleFunc)(ZBuffer *,
ZBufferPoint *,ZBufferPoint *,ZBufferPoint *); ZBufferPoint *,ZBufferPoint *,ZBufferPoint *);
typedef void (*ZB_storePixelFunc) (ZBuffer *zb, PIXEL &result, int r, int g, int b, int a); typedef void (*ZB_storePixelFunc)(ZBuffer *zb, PIXEL &result, int r, int g, int b, int a);
typedef PIXEL (*ZB_lookupTextureFunc)(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
struct ZBuffer { struct ZBuffer {
int xsize,ysize; int xsize,ysize;
@ -124,6 +122,8 @@ struct ZBuffer {
int reference_alpha; int reference_alpha;
int blend_r, blend_g, blend_b, blend_a; int blend_r, blend_g, blend_b, blend_a;
ZB_storePixelFunc store_pix_func; ZB_storePixelFunc store_pix_func;
ZB_lookupTextureFunc tex_minfilter_func;
ZB_lookupTextureFunc tex_magfilter_func;
}; };
struct ZBufferPoint { struct ZBufferPoint {
@ -152,7 +152,12 @@ void ZB_clear_viewport(ZBuffer * zb, int clear_z, ZPOINT z,
int clear_color, unsigned int r, unsigned int g, unsigned int b, unsigned int a, int clear_color, unsigned int r, unsigned int g, unsigned int b, unsigned int a,
int xmin, int ymin, int xsize, int ysize); int xmin, int ymin, int xsize, int ysize);
PIXEL lookup_texture_bilinear(ZTextureLevel *base_level, int s, int t); PIXEL lookup_texture_nearest(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
PIXEL lookup_texture_bilinear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
PIXEL lookup_texture_mipmap_nearest(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
PIXEL lookup_texture_mipmap_linear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
PIXEL lookup_texture_mipmap_bilinear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
PIXEL lookup_texture_mipmap_trilinear(ZTextureLevel *texture_levels, int s, int t, unsigned int level, unsigned int level_dx);
/* linesize is in BYTES */ /* linesize is in BYTES */
void ZB_copyFrameBuffer(ZBuffer *zb,void *buf,int linesize); void ZB_copyFrameBuffer(ZBuffer *zb,void *buf,int linesize);

View File

@ -146,7 +146,7 @@ typedef struct GLContext {
/* textures */ /* textures */
GLTexture *current_texture; GLTexture *current_texture;
int texture_2d_enabled; int texture_2d_enabled;
/* matrix */ /* matrix */
M4 matrix_projection; M4 matrix_projection;
M4 matrix_model_view; M4 matrix_model_view;

View File

@ -34,7 +34,7 @@
float tz1,dtzdx,dtzdy,dtzdl_min,dtzdl_max; float tz1,dtzdx,dtzdy,dtzdl_min,dtzdl_max;
#endif #endif
#if defined(INTERP_MIPMAP) && (defined(INTERP_ST) || defined(INTERP_STZ)) #if defined(INTERP_MIPMAP) && (defined(INTERP_ST) || defined(INTERP_STZ))
int mipmap_level; unsigned int mipmap_dx, mipmap_level;
#endif #endif
EARLY_OUT(); EARLY_OUT();

View File

@ -24,7 +24,7 @@ Options = [
[ 'znone', 'zless' ], [ 'znone', 'zless' ],
# texture filters # texture filters
[ 'nearest', 'mipmap' ], [ 'tnearest', 'tmipmap', 'tgeneral' ],
] ]
# The various combinations of these options are explicit within # The various combinations of these options are explicit within
@ -60,8 +60,9 @@ CodeTable = {
'zless' : '#define ZCMP(zpix, z) ((ZPOINT)(zpix) < (ZPOINT)(z))', 'zless' : '#define ZCMP(zpix, z) ((ZPOINT)(zpix) < (ZPOINT)(z))',
# texture filters # texture filters
'nearest' : '#define CALC_MIPMAP_LEVEL\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level) ZB_LOOKUP_TEXTURE_NEAREST(texture_levels, s, t)', 'tnearest' : '#define CALC_MIPMAP_LEVEL\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level, level_dx) ZB_LOOKUP_TEXTURE_NEAREST(texture_levels, s, t)',
'mipmap' : '#define CALC_MIPMAP_LEVEL DO_CALC_MIPMAP_LEVEL\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level) ZB_LOOKUP_TEXTURE_NEAREST_MIPMAP(texture_levels, s, t, level)', 'tmipmap' : '#define CALC_MIPMAP_LEVEL DO_CALC_MIPMAP_LEVEL\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level, level_dx) ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_levels, s, t, level)',
'tgeneral' : '#define CALC_MIPMAP_LEVEL DO_CALC_MIPMAP_LEVEL\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_levels, s, t, level, level_dx) ((level == 0) ? zb->tex_magfilter_func(texture_levels, s, t, level, level_dx) : zb->tex_minfilter_func(texture_levels, s, t, level, level_dx))',
} }
ops = [0] * len(Options) ops = [0] * len(Options)

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,3 @@
/* This file is generated code--do not edit. See ztriangle.py. */ /* This file is generated code--do not edit. See ztriangle.py. */
extern const ZB_fillTriangleFunc fill_tri_funcs[2][4][3][2][2][3][3]; extern const ZB_fillTriangleFunc fill_tri_funcs[2][4][3][2][3][3][3];

View File

@ -129,7 +129,7 @@ static void FNAME(white_textured) (ZBuffer *zb,
{ \ { \
zz=z >> ZB_POINT_Z_FRAC_BITS; \ zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \ if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \ tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx); \
if (ACMP(zb, PIXEL_A(tmp))) { \ if (ACMP(zb, PIXEL_A(tmp))) { \
STORE_PIX(pp[_a], tmp, PIXEL_R(tmp), PIXEL_G(tmp), PIXEL_B(tmp), PIXEL_A(tmp)); \ STORE_PIX(pp[_a], tmp, PIXEL_R(tmp), PIXEL_G(tmp), PIXEL_B(tmp), PIXEL_A(tmp)); \
STORE_Z(pz[_a], zz); \ STORE_Z(pz[_a], zz); \
@ -173,7 +173,7 @@ static void FNAME(flat_textured) (ZBuffer *zb,
{ \ { \
zz=z >> ZB_POINT_Z_FRAC_BITS; \ zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \ if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \ tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx); \
int a = oa0 * PIXEL_A(tmp) >> 16; \ int a = oa0 * PIXEL_A(tmp) >> 16; \
if (ACMP(zb, a)) { \ if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \ STORE_PIX(pp[_a], \
@ -232,7 +232,7 @@ static void FNAME(smooth_textured) (ZBuffer *zb,
{ \ { \
zz=z >> ZB_POINT_Z_FRAC_BITS; \ zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \ if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \ tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx); \
int a = oa1 * PIXEL_A(tmp) >> 16; \ int a = oa1 * PIXEL_A(tmp) >> 16; \
if (ACMP(zb, a)) { \ if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \ STORE_PIX(pp[_a], \
@ -293,7 +293,7 @@ static void FNAME(white_perspective) (ZBuffer *zb,
{ \ { \
zz=z >> ZB_POINT_Z_FRAC_BITS; \ zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \ if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \ tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx); \
if (ACMP(zb, PIXEL_A(tmp))) { \ if (ACMP(zb, PIXEL_A(tmp))) { \
STORE_PIX(pp[_a], tmp, PIXEL_R(tmp), PIXEL_G(tmp), PIXEL_B(tmp), PIXEL_A(tmp)); \ STORE_PIX(pp[_a], tmp, PIXEL_R(tmp), PIXEL_G(tmp), PIXEL_B(tmp), PIXEL_A(tmp)); \
STORE_Z(pz[_a], zz); \ STORE_Z(pz[_a], zz); \
@ -408,7 +408,7 @@ static void FNAME(flat_perspective) (ZBuffer *zb,
{ \ { \
zz=z >> ZB_POINT_Z_FRAC_BITS; \ zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \ if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \ tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx); \
int a = oa0 * PIXEL_A(tmp) >> 16; \ int a = oa0 * PIXEL_A(tmp) >> 16; \
if (ACMP(zb, a)) { \ if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \ STORE_PIX(pp[_a], \
@ -541,7 +541,7 @@ static void FNAME(smooth_perspective) (ZBuffer *zb,
{ \ { \
zz=z >> ZB_POINT_Z_FRAC_BITS; \ zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \ if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \ tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx); \
int a = oa1 * PIXEL_A(tmp) >> 16; \ int a = oa1 * PIXEL_A(tmp) >> 16; \
if (ACMP(zb, a)) { \ if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \ STORE_PIX(pp[_a], \

View File

@ -406,6 +406,7 @@ run() {
PT(EggData) egg_data = new EggData; PT(EggData) egg_data = new EggData;
_group = new EggGroup(); _group = new EggGroup();
egg_data->add_child(_group); egg_data->add_child(_group);
append_command_comment(egg_data);
_vpool = new EggVertexPool("vpool"); _vpool = new EggVertexPool("vpool");
_group->add_child(_vpool); _group->add_child(_vpool);
@ -446,7 +447,7 @@ run() {
texture->write(texture->read_source_image()); texture->write(texture->read_source_image());
} }
write_egg_file(); egg_data->write_egg(get_output());
} else { } else {
// Pass the generated egg structure through egg-palettize, without // Pass the generated egg structure through egg-palettize, without
@ -641,6 +642,7 @@ make_tref(PNMTextGlyph *glyph, int character) {
tref->set_wrap_mode(EggTexture::WM_clamp); tref->set_wrap_mode(EggTexture::WM_clamp);
tref->set_minfilter(EggTexture::FT_linear_mipmap_linear); tref->set_minfilter(EggTexture::FT_linear_mipmap_linear);
tref->set_magfilter(EggTexture::FT_linear); tref->set_magfilter(EggTexture::FT_linear);
tref->set_quality_level(EggTexture::QL_best);
return tref; return tref;
} }

View File

@ -41,7 +41,7 @@ Palettizer *pal = (Palettizer *)NULL;
// allows us to easily update egg-palettize to write out additional // allows us to easily update egg-palettize to write out additional
// information to its pi file, without having it increment the bam // information to its pi file, without having it increment the bam
// version number for all bam and boo files anywhere in the world. // version number for all bam and boo files anywhere in the world.
int Palettizer::_pi_version = 17; int Palettizer::_pi_version = 18;
// Updated to version 8 on 3/20/03 to remove extensions from texture key names. // Updated to version 8 on 3/20/03 to remove extensions from texture key names.
// Updated to version 9 on 4/13/03 to add a few properties in various places. // Updated to version 9 on 4/13/03 to add a few properties in various places.
// Updated to version 10 on 4/15/03 to add _alpha_file_channel. // Updated to version 10 on 4/15/03 to add _alpha_file_channel.
@ -52,6 +52,7 @@ int Palettizer::_pi_version = 17;
// Updated to version 15 on 8/01/05 to make TextureImages be case-insensitive. // Updated to version 15 on 8/01/05 to make TextureImages be case-insensitive.
// Updated to version 16 on 4/03/06 to add Palettizer::_cutout_mode et al. // Updated to version 16 on 4/03/06 to add Palettizer::_cutout_mode et al.
// Updated to version 17 on 3/02/07 to add TextureImage::_txa_wrap_u etc. // Updated to version 17 on 3/02/07 to add TextureImage::_txa_wrap_u etc.
// Updated to version 18 on 5/13/08 to add TextureProperties::_quality_level.
int Palettizer::_min_pi_version = 8; int Palettizer::_min_pi_version = 8;
// Dropped support for versions 7 and below on 7/14/03. // Dropped support for versions 7 and below on 7/14/03.

View File

@ -43,6 +43,7 @@ TextureProperties() {
_keep_format = false; _keep_format = false;
_minfilter = EggTexture::FT_unspecified; _minfilter = EggTexture::FT_unspecified;
_magfilter = EggTexture::FT_unspecified; _magfilter = EggTexture::FT_unspecified;
_quality_level = EggTexture::QL_unspecified;
_anisotropic_degree = 0; _anisotropic_degree = 0;
_color_type = (PNMFileType *)NULL; _color_type = (PNMFileType *)NULL;
_alpha_type = (PNMFileType *)NULL; _alpha_type = (PNMFileType *)NULL;
@ -61,6 +62,7 @@ TextureProperties(const TextureProperties &copy) :
_keep_format(copy._keep_format), _keep_format(copy._keep_format),
_minfilter(copy._minfilter), _minfilter(copy._minfilter),
_magfilter(copy._magfilter), _magfilter(copy._magfilter),
_quality_level(copy._quality_level),
_anisotropic_degree(copy._anisotropic_degree), _anisotropic_degree(copy._anisotropic_degree),
_color_type(copy._color_type), _color_type(copy._color_type),
_alpha_type(copy._alpha_type), _alpha_type(copy._alpha_type),
@ -82,6 +84,7 @@ operator = (const TextureProperties &copy) {
_keep_format = copy._keep_format; _keep_format = copy._keep_format;
_minfilter = copy._minfilter; _minfilter = copy._minfilter;
_magfilter = copy._magfilter; _magfilter = copy._magfilter;
_quality_level = copy._quality_level;
_anisotropic_degree = copy._anisotropic_degree; _anisotropic_degree = copy._anisotropic_degree;
_color_type = copy._color_type; _color_type = copy._color_type;
_alpha_type = copy._alpha_type; _alpha_type = copy._alpha_type;
@ -105,6 +108,7 @@ clear_basic() {
_minfilter = EggTexture::FT_unspecified; _minfilter = EggTexture::FT_unspecified;
_magfilter = EggTexture::FT_unspecified; _magfilter = EggTexture::FT_unspecified;
_quality_level = EggTexture::QL_unspecified;
_anisotropic_degree = 0; _anisotropic_degree = 0;
} }
@ -249,6 +253,7 @@ update_properties(const TextureProperties &other) {
_minfilter = union_filter(_minfilter, other._minfilter); _minfilter = union_filter(_minfilter, other._minfilter);
_magfilter = union_filter(_magfilter, other._magfilter); _magfilter = union_filter(_magfilter, other._magfilter);
_quality_level = union_quality_level(_quality_level, other._quality_level);
_anisotropic_degree = other._anisotropic_degree; _anisotropic_degree = other._anisotropic_degree;
@ -494,6 +499,7 @@ update_egg_tex(EggTexture *egg_tex) const {
egg_tex->set_format(_format); egg_tex->set_format(_format);
egg_tex->set_minfilter(_minfilter); egg_tex->set_minfilter(_minfilter);
egg_tex->set_magfilter(_minfilter); egg_tex->set_magfilter(_minfilter);
egg_tex->set_quality_level(_quality_level);
egg_tex->set_anisotropic_degree(_anisotropic_degree); egg_tex->set_anisotropic_degree(_anisotropic_degree);
} }
@ -510,6 +516,7 @@ egg_properties_match(const TextureProperties &other) const {
return (_format == other._format && return (_format == other._format &&
_minfilter == other._minfilter && _minfilter == other._minfilter &&
_magfilter == other._magfilter && _magfilter == other._magfilter &&
_quality_level == other._quality_level &&
_anisotropic_degree == other._anisotropic_degree); _anisotropic_degree == other._anisotropic_degree);
} }
@ -529,6 +536,9 @@ operator < (const TextureProperties &other) const {
if (_magfilter != other._magfilter) { if (_magfilter != other._magfilter) {
return (int)_magfilter < (int)other._magfilter; return (int)_magfilter < (int)other._magfilter;
} }
if (_quality_level != other._quality_level) {
return (int)_quality_level < (int)other._quality_level;
}
if (_anisotropic_degree != other._anisotropic_degree) { if (_anisotropic_degree != other._anisotropic_degree) {
return _anisotropic_degree < other._anisotropic_degree; return _anisotropic_degree < other._anisotropic_degree;
} }
@ -553,6 +563,7 @@ operator == (const TextureProperties &other) const {
return (_format == other._format && return (_format == other._format &&
_minfilter == other._minfilter && _minfilter == other._minfilter &&
_magfilter == other._magfilter && _magfilter == other._magfilter &&
_quality_level == other._quality_level &&
_anisotropic_degree == other._anisotropic_degree && _anisotropic_degree == other._anisotropic_degree &&
_color_type == other._color_type && _color_type == other._color_type &&
(_color_type == (PNMFileType *)NULL || (_color_type == (PNMFileType *)NULL ||
@ -759,6 +770,21 @@ union_filter(EggTexture::FilterType a, EggTexture::FilterType b) {
} }
} }
////////////////////////////////////////////////////////////////////
// Function: TextureProperties::union_quality_level
// Access: Private, Static
// Description: Returns the EggTexture quality level which is the
// more specific of the two.
////////////////////////////////////////////////////////////////////
EggTexture::QualityLevel TextureProperties::
union_quality_level(EggTexture::QualityLevel a, EggTexture::QualityLevel b) {
if ((int)a < (int)b) {
return b;
} else {
return a;
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: TextureProperties::register_with_read_factory // Function: TextureProperties::register_with_read_factory
// Access: Public, Static // Access: Public, Static
@ -790,6 +816,7 @@ write_datagram(BamWriter *writer, Datagram &datagram) {
datagram.add_bool(_keep_format); datagram.add_bool(_keep_format);
datagram.add_int32((int)_minfilter); datagram.add_int32((int)_minfilter);
datagram.add_int32((int)_magfilter); datagram.add_int32((int)_magfilter);
datagram.add_int32((int)_quality_level);
datagram.add_int32(_anisotropic_degree); datagram.add_int32(_anisotropic_degree);
writer->write_pointer(datagram, _color_type); writer->write_pointer(datagram, _color_type);
writer->write_pointer(datagram, _alpha_type); writer->write_pointer(datagram, _alpha_type);
@ -868,6 +895,9 @@ fillin(DatagramIterator &scan, BamReader *manager) {
} }
_minfilter = (EggTexture::FilterType)scan.get_int32(); _minfilter = (EggTexture::FilterType)scan.get_int32();
_magfilter = (EggTexture::FilterType)scan.get_int32(); _magfilter = (EggTexture::FilterType)scan.get_int32();
if (Palettizer::_read_pi_version >= 18) {
_quality_level = (EggTexture::QualityLevel)scan.get_int32();
}
_anisotropic_degree = scan.get_int32(); _anisotropic_degree = scan.get_int32();
manager->read_pointer(scan); // _color_type manager->read_pointer(scan); // _color_type

View File

@ -66,6 +66,7 @@ public:
bool _generic_format; // true if 'generic' keyword, meaning rgba8 -> rgba. bool _generic_format; // true if 'generic' keyword, meaning rgba8 -> rgba.
bool _keep_format; // true if 'keep-format' keyword. bool _keep_format; // true if 'keep-format' keyword.
EggTexture::FilterType _minfilter, _magfilter; EggTexture::FilterType _minfilter, _magfilter;
EggTexture::QualityLevel _quality_level;
int _anisotropic_degree; int _anisotropic_degree;
PNMFileType *_color_type; PNMFileType *_color_type;
PNMFileType *_alpha_type; PNMFileType *_alpha_type;
@ -82,6 +83,8 @@ private:
static EggTexture::FilterType union_filter(EggTexture::FilterType a, static EggTexture::FilterType union_filter(EggTexture::FilterType a,
EggTexture::FilterType b); EggTexture::FilterType b);
static EggTexture::QualityLevel union_quality_level(EggTexture::QualityLevel a,
EggTexture::QualityLevel b);
bool _got_num_channels; bool _got_num_channels;
int _num_channels; int _num_channels;

View File

@ -106,6 +106,7 @@ from_egg(EggFile *egg_file, EggData *data, EggTexture *egg_tex) {
_properties._format = _egg_tex->get_format(); _properties._format = _egg_tex->get_format();
_properties._minfilter = _egg_tex->get_minfilter(); _properties._minfilter = _egg_tex->get_minfilter();
_properties._magfilter = _egg_tex->get_magfilter(); _properties._magfilter = _egg_tex->get_magfilter();
_properties._quality_level = _egg_tex->get_quality_level();
_properties._anisotropic_degree = _egg_tex->get_anisotropic_degree(); _properties._anisotropic_degree = _egg_tex->get_anisotropic_degree();
string name = filename.get_basename_wo_extension(); string name = filename.get_basename_wo_extension();