a few tinydisplay optimizations

This commit is contained in:
David Rose 2008-05-10 21:51:22 +00:00
parent faa94cf0b9
commit 979896da75
16 changed files with 518 additions and 297 deletions

View File

@ -51,6 +51,7 @@
modifierButtons.I modifierButtons.h mouseButton.h \
mouseData.I mouseData.h nameUniquifier.I nameUniquifier.h \
nodeCachedReferenceCount.h nodeCachedReferenceCount.I \
pbitops.I pbitops.h \
portalMask.h \
pta_double.h \
pta_float.h pta_int.h \
@ -98,6 +99,7 @@
modifierButtons.cxx mouseButton.cxx mouseData.cxx \
nameUniquifier.cxx \
nodeCachedReferenceCount.cxx \
pbitops.cxx \
pta_double.cxx pta_float.cxx \
pta_int.cxx pta_ushort.cxx \
simpleHashMap.cxx \
@ -156,6 +158,7 @@
nameUniquifier.I nameUniquifier.h \
nodeCachedReferenceCount.h nodeCachedReferenceCount.I \
portalMask.h \
pbitops.I pbitops.h \
pta_double.h \
pta_float.h pta_int.h pta_ushort.h \
simpleHashMap.I simpleHashMap.h \

View File

@ -462,12 +462,7 @@ get_lowest_off_bit() const {
template<class WType, int nbits>
INLINE int BitMask<WType, nbits>::
get_highest_on_bit() const {
if (_word == 0) {
return -1;
}
WordType w = ::flood_bits_down(_word);
return count_bits_in_word(w) - 1;
return ::get_highest_on_bit(_word);
}
////////////////////////////////////////////////////////////////////
@ -871,88 +866,6 @@ init_type() {
register_type(_type_handle, str.str());
}
////////////////////////////////////////////////////////////////////
// Function: count_bits_in_word
// Description: Returns the number of 1 bits in the indicated word.
////////////////////////////////////////////////////////////////////
INLINE int
count_bits_in_word(PN_uint32 x) {
return (int)num_bits_on[x & 0xffff] + (int)num_bits_on[(x >> 16) & 0xffff];
}
////////////////////////////////////////////////////////////////////
// Function: count_bits_in_word
// Description: Returns the number of 1 bits in the indicated word.
////////////////////////////////////////////////////////////////////
INLINE int
count_bits_in_word(PN_uint64 x) {
return count_bits_in_word((PN_uint32)x) + count_bits_in_word((PN_uint32)(x >> 32));
}
////////////////////////////////////////////////////////////////////
// Function: flood_bits_down
// Description: Returns a value such that every bit at or below the
// highest bit in x is 1.
////////////////////////////////////////////////////////////////////
INLINE PN_uint32
flood_bits_down(PN_uint32 x) {
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return x;
}
////////////////////////////////////////////////////////////////////
// Function: flood_bits_down
// Description: Returns a value such that every bit at or below the
// highest bit in x is 1.
////////////////////////////////////////////////////////////////////
INLINE PN_uint64
flood_bits_down(PN_uint64 x) {
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
x |= (x >> 32);
return x;
}
////////////////////////////////////////////////////////////////////
// Function: flood_bits_up
// Description: Returns a value such that every bit at or above the
// highest bit in x is 1.
////////////////////////////////////////////////////////////////////
INLINE PN_uint32
flood_bits_up(PN_uint32 x) {
x |= (x << 1);
x |= (x << 2);
x |= (x << 4);
x |= (x << 8);
x |= (x << 16);
return x;
}
////////////////////////////////////////////////////////////////////
// Function: flood_bits_up
// Description: Returns a value such that every bit at or above the
// highest bit in x is 1.
////////////////////////////////////////////////////////////////////
INLINE PN_uint64
flood_bits_up(PN_uint64 x) {
x |= (x << 1);
x |= (x << 2);
x |= (x << 4);
x |= (x << 8);
x |= (x << 16);
x |= (x << 32);
return x;
}
////////////////////////////////////////////////////////////////////
// Function: BitMask::flood_up_in_place
// Access: Published

View File

@ -22,5 +22,3 @@
#ifdef __GNUC__
#pragma implementation
#endif
unsigned char num_bits_on[65536];

View File

@ -20,7 +20,7 @@
#define BITMASK_H
#include "pandabase.h"
#include "pbitops.h"
#include "numeric_types.h"
#include "typedObject.h"
#include "indent.h"
@ -151,16 +151,6 @@ private:
static TypeHandle _type_handle;
};
INLINE int count_bits_in_word(PN_uint32 x);
INLINE int count_bits_in_word(PN_uint64 x);
INLINE PN_uint32 flood_bits_down(PN_uint32 x);
INLINE PN_uint64 flood_bits_down(PN_uint64 x);
INLINE PN_uint32 flood_bits_up(PN_uint32 x);
INLINE PN_uint64 flood_bits_up(PN_uint64 x);
// This table precomputes the number of on bits in each 16-bit word.
extern EXPCL_PANDA_PUTIL unsigned char num_bits_on[65536];
#include "bitMask.I"
template<class WType, int nbits>

146
panda/src/putil/pbitops.I Normal file
View File

@ -0,0 +1,146 @@
// Filename: pbitops.I
// Created by: drose (10May08)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: count_bits_in_word
// Description: Returns the number of 1 bits in the indicated word.
////////////////////////////////////////////////////////////////////
INLINE int
count_bits_in_word(PN_uint32 x) {
return (int)num_bits_on[x & 0xffff] + (int)num_bits_on[(x >> 16) & 0xffff];
}
////////////////////////////////////////////////////////////////////
// Function: count_bits_in_word
// Description: Returns the number of 1 bits in the indicated word.
////////////////////////////////////////////////////////////////////
INLINE int
count_bits_in_word(PN_uint64 x) {
return count_bits_in_word((PN_uint32)x) + count_bits_in_word((PN_uint32)(x >> 32));
}
////////////////////////////////////////////////////////////////////
// Function: flood_bits_down
// Description: Returns a value such that every bit at or below the
// highest bit in x is 1.
////////////////////////////////////////////////////////////////////
INLINE PN_uint32
flood_bits_down(PN_uint32 x) {
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return x;
}
////////////////////////////////////////////////////////////////////
// Function: flood_bits_down
// Description: Returns a value such that every bit at or below the
// highest bit in x is 1.
////////////////////////////////////////////////////////////////////
INLINE PN_uint64
flood_bits_down(PN_uint64 x) {
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
x |= (x >> 32);
return x;
}
////////////////////////////////////////////////////////////////////
// Function: flood_bits_up
// Description: Returns a value such that every bit at or above the
// highest bit in x is 1.
////////////////////////////////////////////////////////////////////
INLINE PN_uint32
flood_bits_up(PN_uint32 x) {
x |= (x << 1);
x |= (x << 2);
x |= (x << 4);
x |= (x << 8);
x |= (x << 16);
return x;
}
////////////////////////////////////////////////////////////////////
// Function: flood_bits_up
// Description: Returns a value such that every bit at or above the
// highest bit in x is 1.
////////////////////////////////////////////////////////////////////
INLINE PN_uint64
flood_bits_up(PN_uint64 x) {
x |= (x << 1);
x |= (x << 2);
x |= (x << 4);
x |= (x << 8);
x |= (x << 16);
x |= (x << 32);
return x;
}
////////////////////////////////////////////////////////////////////
// Function: get_highest_on_bit
// Description: Returns the index of the highest 1 bit in the word.
// Returns -1 if there are no 1 bits.
////////////////////////////////////////////////////////////////////
INLINE int
get_highest_on_bit(PN_uint32 x) {
PN_uint32 w = flood_bits_down(x);
return count_bits_in_word(w) - 1;
}
////////////////////////////////////////////////////////////////////
// Function: get_highest_on_bit
// Description: Returns the index of the highest 1 bit in the word.
// Returns -1 if there are no 1 bits.
////////////////////////////////////////////////////////////////////
INLINE int
get_highest_on_bit(PN_uint64 x) {
PN_uint64 w = flood_bits_down(x);
return count_bits_in_word(w) - 1;
}
////////////////////////////////////////////////////////////////////
// Function: get_next_higher_bit
// Description: Returns the smallest power of 2 greater than x.
//
// Returns the smallest number n such that (1 << n) is
// larger than x.
////////////////////////////////////////////////////////////////////
INLINE int
get_next_higher_bit(PN_uint32 x) {
PN_uint32 w = flood_bits_down(x);
return count_bits_in_word(w);
}
////////////////////////////////////////////////////////////////////
// Function: get_next_higher_bit
// Description: Returns the smallest power of 2 greater than x.
//
// Returns the smallest number n such that (1 << n) is
// larger than x.
////////////////////////////////////////////////////////////////////
INLINE int
get_next_higher_bit(PN_uint64 x) {
PN_uint64 w = flood_bits_down(x);
return count_bits_in_word(w);
}

View File

@ -0,0 +1,21 @@
// Filename: pbitops.cxx
// Created by: drose (10May08)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "pbitops.h"
unsigned char num_bits_on[65536];

49
panda/src/putil/pbitops.h Normal file
View File

@ -0,0 +1,49 @@
// Filename: pbitops.h
// Created by: drose (10May08)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef PBITOPS_H
#define PBITOPS_H
#include "pandabase.h"
#include "numeric_types.h"
////////////////////////////////////////////////////////////////////
// This file defines a few low-level bit-operation routines, optimized
// all to heck.
////////////////////////////////////////////////////////////////////
INLINE int count_bits_in_word(PN_uint32 x);
INLINE int count_bits_in_word(PN_uint64 x);
INLINE PN_uint32 flood_bits_down(PN_uint32 x);
INLINE PN_uint64 flood_bits_down(PN_uint64 x);
INLINE PN_uint32 flood_bits_up(PN_uint32 x);
INLINE PN_uint64 flood_bits_up(PN_uint64 x);
INLINE int get_highest_on_bit(PN_uint32 x);
INLINE int get_highest_on_bit(PN_uint64 x);
INLINE int get_next_higher_bit(PN_uint32 x);
INLINE int get_next_higher_bit(PN_uint64 x);
// This table precomputes the number of on bits in each 16-bit word.
extern EXPCL_PANDA_PUTIL unsigned char num_bits_on[65536];
#include "pbitops.I"
#endif

View File

@ -8,6 +8,7 @@
#include "mouseData.cxx"
#include "nameUniquifier.cxx"
#include "nodeCachedReferenceCount.cxx"
#include "pbitops.cxx"
#include "pta_double.cxx"
#include "pta_float.cxx"
#include "pta_int.cxx"

View File

@ -70,6 +70,17 @@ ConfigVariableInt td_texture_ram
"frame, even if this means this limit remains exceeded.) "
"Set it to -1 for no limit."));
ConfigVariableBool td_ignore_mipmaps
("td-ignore-mipmaps", false,
PRC_DESC("Configure this true to disable use of mipmaps on the "
"tinydisplay software renderer."));
ConfigVariableBool td_perspective_textures
("td-perspective-textures", true,
PRC_DESC("Configure this false to disable use of perspective-correct "
"textures on the tinydisplay software renderer, for a small "
"performance gain."));
////////////////////////////////////////////////////////////////////
// Function: init_libtinydisplay
// Description: Initializes the library. This must be called at

View File

@ -35,5 +35,7 @@ extern ConfigVariableInt x_wheel_up_button;
extern ConfigVariableInt x_wheel_down_button;
extern ConfigVariableInt td_texture_ram;
extern ConfigVariableBool td_ignore_mipmaps;
extern ConfigVariableBool td_perspective_textures;
#endif

View File

@ -598,6 +598,15 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
}
}
if (_c->texture_2d_enabled && _texture_replace) {
// We don't need the vertex color or lighting calculation after
// all, since the current texture will just hide all of that.
needs_color = false;
needs_normal = false;
}
bool lighting_enabled = (needs_normal && _c->lighting_enabled);
for (i = 0; i < num_used_vertices; ++i) {
GLVertex *v = &_vertices[i];
const LVecBase4f &d = rvertex.get_data4f();
@ -642,18 +651,18 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
v->color = _c->current_color;
if (needs_normal) {
if (lighting_enabled) {
const LVecBase3f &d = rnormal.get_data3f();
_c->current_normal.X = d[0];
_c->current_normal.Y = d[1];
_c->current_normal.Z = d[2];
_c->current_normal.W = 0.0f;
}
gl_vertex_transform(_c, v);
if (_c->lighting_enabled) {
gl_vertex_transform(_c, v);
gl_shade_vertex(_c, v);
} else {
gl_vertex_transform(_c, v);
}
if (v->clip_code == 0) {
@ -666,16 +675,16 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
// Set up the appropriate function callback for filling triangles,
// according to the current state.
int depth_write_state = 0;
int depth_write_state = 0; // zon
if (_target._depth_write->get_mode() != DepthWriteAttrib::M_on) {
depth_write_state = 1;
depth_write_state = 1; // zoff
}
int color_write_state = 0;
int color_write_state = 0; // noblend
switch (_target._transparency->get_mode()) {
case TransparencyAttrib::M_alpha:
case TransparencyAttrib::M_dual:
color_write_state = 1;
color_write_state = 1; // blend
break;
default:
@ -685,36 +694,36 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
unsigned int color_channels =
_target._color_write->get_channels() & _color_write_mask;
if (color_channels == ColorWriteAttrib::C_off) {
color_write_state = 2;
color_write_state = 2; // nocolor
}
int alpha_test_state = 0;
int alpha_test_state = 0; // anone
switch (_target._alpha_test->get_mode()) {
case AlphaTestAttrib::M_none:
case AlphaTestAttrib::M_never:
case AlphaTestAttrib::M_always:
case AlphaTestAttrib::M_equal:
case AlphaTestAttrib::M_not_equal:
alpha_test_state = 0;
alpha_test_state = 0; // anone
break;
case AlphaTestAttrib::M_less:
case AlphaTestAttrib::M_less_equal:
alpha_test_state = 1;
alpha_test_state = 1; // aless
_c->zb->reference_alpha = (unsigned int)_target._alpha_test->get_reference_alpha() * 0xff00;
break;
case AlphaTestAttrib::M_greater:
case AlphaTestAttrib::M_greater_equal:
alpha_test_state = 2;
alpha_test_state = 2; // amore
_c->zb->reference_alpha = (unsigned int)_target._alpha_test->get_reference_alpha() * 0xff00;
break;
}
int depth_test_state = 1;
int depth_test_state = 1; // zless
_c->depth_test = 1; // set this for ZB_line
if (_target._depth_test->get_mode() == DepthTestAttrib::M_none) {
depth_test_state = 0;
depth_test_state = 0; // zless
_c->depth_test = 0;
}
@ -724,17 +733,17 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
// as well use the flat shading model.
shade_model = ShadeModelAttrib::M_flat;
}
int shading_state = 2; // smooth
int shade_model_state = 2; // smooth
_c->smooth_shade_model = true;
if (shade_model == ShadeModelAttrib::M_flat) {
_c->smooth_shade_model = false;
shading_state = 1; // flat
shade_model_state = 1; // flat
if (_c->current_color.X == 1.0f &&
_c->current_color.Y == 1.0f &&
_c->current_color.Z == 1.0f &&
_c->current_color.W == 1.0f) {
shading_state = 0; // white
shade_model_state = 0; // white
}
}
@ -743,12 +752,18 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
if (_c->texture_2d_enabled) {
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) {
texturing_state = 1; // non-perspective-correct textures
}
if (_texture_replace) {
// If we're completely replacing the underlying color, then it
// doesn't matter what the color is.
shade_model_state = 0;
}
}
_c->zb_fill_tri = fill_tri_funcs[depth_write_state][color_write_state][alpha_test_state][depth_test_state][texfilter_state][shading_state][texturing_state];
_c->zb_fill_tri = fill_tri_funcs[depth_write_state][color_write_state][alpha_test_state][depth_test_state][texfilter_state][shade_model_state][texturing_state];
return true;
}
@ -1592,6 +1607,16 @@ do_issue_texture() {
// Then, turn on the current texture mode.
apply_texture(tc);
// Set a few state cache values.
_texfilter_state = 0; // nearest
if (texture->uses_mipmaps() && !td_ignore_mipmaps) {
_texfilter_state = 1; // mipmap
}
// M_replace means M_replace; anything else is treated the same as
// M_modulate.
_texture_replace = (stage->get_mode() == TextureStage::M_replace);
}
////////////////////////////////////////////////////////////////////
@ -1609,11 +1634,6 @@ apply_texture(TextureContext *tc) {
_c->current_texture = gtc->_gltex;
_c->texture_2d_enabled = true;
_texfilter_state = 0;
if (gtc->get_texture()->uses_mipmaps()) {
_texfilter_state = 1;
}
GLTexture *gltex = gtc->_gltex;
if (gtc->was_image_modified() || gltex->num_levels == 0) {
@ -1808,13 +1828,15 @@ setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels) {
////////////////////////////////////////////////////////////////////
int TinyGraphicsStateGuardian::
get_tex_shift(int orig_size) {
unsigned int filled = flood_bits_down((unsigned int)(orig_size - 1));
int size = filled + 1;
if (size != orig_size || size > _max_texture_dimension) {
if ((orig_size & (orig_size - 1)) != 0) {
// Not a power of 2.
return -1;
}
if (orig_size > _max_texture_dimension) {
return -1;
}
return count_bits_in_word((unsigned int)size - 1);
return count_bits_in_word((unsigned int)orig_size - 1);
}
////////////////////////////////////////////////////////////////////

View File

@ -136,6 +136,7 @@ private:
};
int _color_material_flags;
int _texfilter_state;
bool _texture_replace;
SimpleLru _textures_lru;

View File

@ -6,7 +6,7 @@
*/
#include "zfeatures.h"
#include "bitMask.h"
#include "pbitops.h"
typedef unsigned short ZPOINT;
#define ZB_Z_BITS 16
@ -23,7 +23,7 @@ typedef unsigned short ZPOINT;
/* This is the theoretical max number of bits we have available to
shift down to achieve each next mipmap level, based on the size of
a 32-bit int. We need to preallocate mipmap arrays of this size. */
#define MAX_MIPMAP_LEVELS (32 - ZB_POINT_ST_FRAC_BITS)
#define MAX_MIPMAP_LEVELS (32 - ZB_POINT_ST_FRAC_BITS + 1)
/* Returns the index within a texture level for the given (s, t) texel. */
#define ZB_TEXEL(level, s, t) \
@ -36,8 +36,15 @@ typedef unsigned short ZPOINT;
#define ZB_LOOKUP_TEXTURE_NEAREST_MIPMAP(texture_levels, s, t, level) \
ZB_LOOKUP_TEXTURE_NEAREST((texture_levels) + (level), (s) >> (level), (t) >> (level))
/* A special abs() function which doesn't require any branching
instructions. Might not work on some exotic hardware. */
/* Also doesn't appear to be any faster in practice. Guess gcc is
already doing the right thing. Is msvc? */
//#define FAST_ABS(v) (((v) ^ ((v) >> (sizeof(v) * 8 - 1))) - ((v) >> (sizeof(v) * 8 - 1)))
#define DO_CALC_MIPMAP_LEVEL \
mipmap_level = count_bits_in_word(flood_bits_down((unsigned int)max(abs(dsdx), abs(dtdx)) >> ZB_POINT_ST_FRAC_BITS))
mipmap_level = get_next_higher_bit(((unsigned int)abs(dsdx) + (unsigned int)abs(dtdx)) >> ZB_POINT_ST_FRAC_BITS)
#if 0
/* Experiment with bilinear filtering. Looks great, but seems to run

View File

@ -69,6 +69,8 @@
return;
fz = 1.0f / fz;
EARLY_OUT_FZ();
fdx1 *= fz;
fdy1 *= fz;
fdx2 *= fz;
@ -378,6 +380,7 @@
#undef INTERP_STZ
#undef EARLY_OUT
#undef EARLY_OUT_FZ
#undef DRAW_INIT
#undef DRAW_LINE
#undef PUT_PIXEL

View File

@ -30,7 +30,7 @@ Options = [
# The various combinations of these options are explicit within
# ztriangle_two.h.
ExtraOptions = [
# shading
# shade model
[ 'white', 'flat', 'smooth' ],
# texturing

View File

@ -7,18 +7,22 @@ static void FNAME(white_untextured) (ZBuffer *zb,
{ \
}
#define EARLY_OUT_FZ() \
{ \
}
#define DRAW_INIT() \
{ \
}
#define PUT_PIXEL(_a) \
{ \
zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \
STORE_PIX(pp[_a], 0xffffffffUL, 0xffffUL, 0xffffUL, 0xffffUL, 0xffffUL); \
STORE_Z(pz[_a], zz); \
} \
z+=dzdx; \
#define PUT_PIXEL(_a) \
{ \
zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \
STORE_PIX(pp[_a], 0xffffffffUL, 0xffffUL, 0xffffUL, 0xffffUL, 0xffffUL); \
STORE_Z(pz[_a], zz); \
} \
z+=dzdx; \
}
#include "ztriangle.h"
@ -36,6 +40,10 @@ static void FNAME(flat_untextured) (ZBuffer *zb,
{ \
}
#define EARLY_OUT_FZ() \
{ \
}
#define DRAW_INIT() \
{ \
if (!ACMP(zb, p2->a)) { \
@ -80,10 +88,14 @@ static void FNAME(smooth_untextured) (ZBuffer *zb,
c2 = RGBA_TO_PIXEL(p2->r, p2->g, p2->b, p2->a); \
if (c0 == c1 && c0 == c2) { \
/* It's really a flat-shaded triangle. */ \
FNAME(flat_untextured)(zb, p0, p1, p2); \
FNAME(flat_untextured)(zb, p0, p1, p2); \
return; \
} \
}
#define EARLY_OUT_FZ() \
{ \
}
#define DRAW_INIT() \
{ \
@ -120,16 +132,20 @@ static void FNAME(white_textured) (ZBuffer *zb,
{ \
}
#define EARLY_OUT_FZ() \
{ \
}
#define DRAW_INIT() \
{ \
texture_levels = zb->current_texture; \
texture_levels = zb->current_texture; \
}
#define PUT_PIXEL(_a) \
{ \
zz=z >> ZB_POINT_Z_FRAC_BITS; \
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); \
if (ACMP(zb, 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); \
@ -156,37 +172,41 @@ static void FNAME(flat_textured) (ZBuffer *zb,
{ \
}
#define EARLY_OUT_FZ() \
{ \
}
#define DRAW_INIT() \
{ \
texture_levels = zb->current_texture; \
texture_levels = zb->current_texture; \
or0 = p2->r; \
og0 = p2->g; \
ob0 = p2->b; \
oa0 = p2->a; \
}
#define PUT_PIXEL(_a) \
{ \
zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \
int a = oa0 * PIXEL_A(tmp) >> 16; \
if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \
RGBA_TO_PIXEL(or0 * PIXEL_R(tmp) >> 16, \
og0 * PIXEL_G(tmp) >> 16, \
ob0 * PIXEL_B(tmp) >> 16, \
a), \
or0 * PIXEL_R(tmp) >> 16, \
og0 * PIXEL_G(tmp) >> 16, \
ob0 * PIXEL_B(tmp) >> 16, \
a); \
STORE_Z(pz[_a], zz); \
} \
} \
z+=dzdx; \
s+=dsdx; \
t+=dtdx; \
#define PUT_PIXEL(_a) \
{ \
zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \
int a = oa0 * PIXEL_A(tmp) >> 16; \
if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \
RGBA_TO_PIXEL(or0 * PIXEL_R(tmp) >> 16, \
og0 * PIXEL_G(tmp) >> 16, \
ob0 * PIXEL_B(tmp) >> 16, \
a), \
or0 * PIXEL_R(tmp) >> 16, \
og0 * PIXEL_G(tmp) >> 16, \
ob0 * PIXEL_B(tmp) >> 16, \
a); \
STORE_Z(pz[_a], zz); \
} \
} \
z+=dzdx; \
s+=dsdx; \
t+=dtdx; \
}
#include "ztriangle.h"
@ -201,55 +221,59 @@ static void FNAME(smooth_textured) (ZBuffer *zb,
#define INTERP_ST
#define INTERP_RGB
#define EARLY_OUT() \
{ \
int c0, c1, c2; \
c0 = RGBA_TO_PIXEL(p0->r, p0->g, p0->b, p0->a); \
c1 = RGBA_TO_PIXEL(p1->r, p1->g, p1->b, p1->a); \
c2 = RGBA_TO_PIXEL(p2->r, p2->g, p2->b, p2->a); \
if (c0 == c1 && c0 == c2) { \
/* It's really a flat-shaded triangle. */ \
if (c0 == 0xffffffff) { \
/* Actually, it's a white triangle. */ \
#define EARLY_OUT() \
{ \
int c0, c1, c2; \
c0 = RGBA_TO_PIXEL(p0->r, p0->g, p0->b, p0->a); \
c1 = RGBA_TO_PIXEL(p1->r, p1->g, p1->b, p1->a); \
c2 = RGBA_TO_PIXEL(p2->r, p2->g, p2->b, p2->a); \
if (c0 == c1 && c0 == c2) { \
/* It's really a flat-shaded triangle. */ \
if (c0 == 0xffffffff) { \
/* Actually, it's a white triangle. */ \
FNAME(white_textured)(zb, p0, p1, p2); \
return; \
} \
FNAME(flat_textured)(zb, p0, p1, p2); \
return; \
} \
return; \
} \
FNAME(flat_textured)(zb, p0, p1, p2); \
return; \
} \
}
#define EARLY_OUT_FZ() \
{ \
}
#define DRAW_INIT() \
{ \
texture_levels = zb->current_texture; \
texture_levels = zb->current_texture; \
}
#define PUT_PIXEL(_a) \
{ \
zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \
int a = oa1 * PIXEL_A(tmp) >> 16; \
if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \
RGBA_TO_PIXEL(or1 * PIXEL_R(tmp) >> 16, \
og1 * PIXEL_G(tmp) >> 16, \
ob1 * PIXEL_B(tmp) >> 16, \
a), \
or1 * PIXEL_R(tmp) >> 16, \
og1 * PIXEL_G(tmp) >> 16, \
ob1 * PIXEL_B(tmp) >> 16, \
a); \
STORE_Z(pz[_a], zz); \
} \
} \
z+=dzdx; \
og1+=dgdx; \
or1+=drdx; \
ob1+=dbdx; \
oa1+=dadx; \
s+=dsdx; \
t+=dtdx; \
#define PUT_PIXEL(_a) \
{ \
zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \
int a = oa1 * PIXEL_A(tmp) >> 16; \
if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \
RGBA_TO_PIXEL(or1 * PIXEL_R(tmp) >> 16, \
og1 * PIXEL_G(tmp) >> 16, \
ob1 * PIXEL_B(tmp) >> 16, \
a), \
or1 * PIXEL_R(tmp) >> 16, \
og1 * PIXEL_G(tmp) >> 16, \
ob1 * PIXEL_B(tmp) >> 16, \
a); \
STORE_Z(pz[_a], zz); \
} \
} \
z+=dzdx; \
og1+=dgdx; \
or1+=drdx; \
ob1+=dbdx; \
oa1+=dadx; \
s+=dsdx; \
t+=dtdx; \
}
#include "ztriangle.h"
@ -275,9 +299,19 @@ static void FNAME(white_perspective) (ZBuffer *zb,
{ \
}
#define EARLY_OUT_FZ() \
{ \
if (fz > 0.001 || fz < -.001) { \
/* This triangle is small enough not to worry about perspective \
correction. */ \
FNAME(white_textured)(zb, p0, p1, p2); \
return; \
} \
}
#define DRAW_INIT() \
{ \
texture_levels = zb->current_texture; \
texture_levels = zb->current_texture; \
fdzdx=(float)dzdx; \
fndzdx=NB_INTERP * fdzdx; \
ndszdx=NB_INTERP * dszdx; \
@ -289,7 +323,7 @@ static void FNAME(white_perspective) (ZBuffer *zb,
{ \
zz=z >> ZB_POINT_Z_FRAC_BITS; \
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); \
if (ACMP(zb, 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); \
@ -302,7 +336,7 @@ static void FNAME(white_perspective) (ZBuffer *zb,
#define DRAW_LINE() \
{ \
register ZPOINT *pz; \
register ZPOINT *pz; \
register PIXEL *pp; \
register unsigned int s,t,z,zz; \
register int n,dsdx,dtdx; \
@ -320,11 +354,11 @@ static void FNAME(white_perspective) (ZBuffer *zb,
float ss,tt; \
ss=(sz * zinv); \
tt=(tz * zinv); \
s=(unsigned int) ss; \
t=(unsigned int) tt; \
s=(unsigned int) ss; \
t=(unsigned int) tt; \
dsdx= (int)( (dszdx - ss*fdzdx)*zinv ); \
dtdx= (int)( (dtzdx - tt*fdzdx)*zinv ); \
CALC_MIPMAP_LEVEL; \
CALC_MIPMAP_LEVEL; \
fz+=fndzdx; \
zinv=1.0f / fz; \
} \
@ -346,11 +380,11 @@ static void FNAME(white_perspective) (ZBuffer *zb,
float ss,tt; \
ss=(sz * zinv); \
tt=(tz * zinv); \
s=(unsigned int) ss; \
t=(unsigned int) tt; \
s=(unsigned int) ss; \
t=(unsigned int) tt; \
dsdx= (int)( (dszdx - ss*fdzdx)*zinv ); \
dtdx= (int)( (dtzdx - tt*fdzdx)*zinv ); \
CALC_MIPMAP_LEVEL; \
CALC_MIPMAP_LEVEL; \
} \
while (n>=0) { \
PUT_PIXEL(0); \
@ -383,9 +417,19 @@ static void FNAME(flat_perspective) (ZBuffer *zb,
{ \
}
#define EARLY_OUT_FZ() \
{ \
if (fz > 0.001 || fz < -.001) { \
/* This triangle is small enough not to worry about perspective \
correction. */ \
FNAME(flat_textured)(zb, p0, p1, p2); \
return; \
} \
}
#define DRAW_INIT() \
{ \
texture_levels = zb->current_texture; \
texture_levels = zb->current_texture; \
fdzdx=(float)dzdx; \
fndzdx=NB_INTERP * fdzdx; \
ndszdx=NB_INTERP * dszdx; \
@ -396,33 +440,33 @@ static void FNAME(flat_perspective) (ZBuffer *zb,
oa0 = p2->a; \
}
#define PUT_PIXEL(_a) \
{ \
zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \
int a = oa0 * PIXEL_A(tmp) >> 16; \
if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \
RGBA_TO_PIXEL(or0 * PIXEL_R(tmp) >> 16, \
og0 * PIXEL_G(tmp) >> 16, \
ob0 * PIXEL_B(tmp) >> 16, \
a), \
or0 * PIXEL_R(tmp) >> 16, \
og0 * PIXEL_G(tmp) >> 16, \
ob0 * PIXEL_B(tmp) >> 16, \
a); \
STORE_Z(pz[_a], zz); \
} \
} \
z+=dzdx; \
s+=dsdx; \
t+=dtdx; \
#define PUT_PIXEL(_a) \
{ \
zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \
int a = oa0 * PIXEL_A(tmp) >> 16; \
if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \
RGBA_TO_PIXEL(or0 * PIXEL_R(tmp) >> 16, \
og0 * PIXEL_G(tmp) >> 16, \
ob0 * PIXEL_B(tmp) >> 16, \
a), \
or0 * PIXEL_R(tmp) >> 16, \
og0 * PIXEL_G(tmp) >> 16, \
ob0 * PIXEL_B(tmp) >> 16, \
a); \
STORE_Z(pz[_a], zz); \
} \
} \
z+=dzdx; \
s+=dsdx; \
t+=dtdx; \
}
#define DRAW_LINE() \
{ \
register ZPOINT *pz; \
register ZPOINT *pz; \
register PIXEL *pp; \
register unsigned int s,t,z,zz; \
register int n,dsdx,dtdx; \
@ -445,11 +489,11 @@ static void FNAME(flat_perspective) (ZBuffer *zb,
float ss,tt; \
ss=(sz * zinv); \
tt=(tz * zinv); \
s=(unsigned int) ss; \
t=(unsigned int) tt; \
s=(unsigned int) ss; \
t=(unsigned int) tt; \
dsdx= (int)( (dszdx - ss*fdzdx)*zinv ); \
dtdx= (int)( (dtzdx - tt*fdzdx)*zinv ); \
CALC_MIPMAP_LEVEL; \
CALC_MIPMAP_LEVEL; \
fz+=fndzdx; \
zinv=1.0f / fz; \
} \
@ -471,11 +515,11 @@ static void FNAME(flat_perspective) (ZBuffer *zb,
float ss,tt; \
ss=(sz * zinv); \
tt=(tz * zinv); \
s=(unsigned int) ss; \
t=(unsigned int) tt; \
s=(unsigned int) ss; \
t=(unsigned int) tt; \
dsdx= (int)( (dszdx - ss*fdzdx)*zinv ); \
dtdx= (int)( (dtzdx - tt*fdzdx)*zinv ); \
CALC_MIPMAP_LEVEL; \
CALC_MIPMAP_LEVEL; \
} \
while (n>=0) { \
PUT_PIXEL(0); \
@ -502,64 +546,74 @@ static void FNAME(smooth_perspective) (ZBuffer *zb,
#define INTERP_STZ
#define INTERP_RGB
#define EARLY_OUT() \
{ \
int c0, c1, c2; \
c0 = RGBA_TO_PIXEL(p0->r, p0->g, p0->b, p0->a); \
c1 = RGBA_TO_PIXEL(p1->r, p1->g, p1->b, p1->a); \
c2 = RGBA_TO_PIXEL(p2->r, p2->g, p2->b, p2->a); \
if (c0 == c1 && c0 == c2) { \
/* It's really a flat-shaded triangle. */ \
if (c0 == 0xffffffff) { \
/* Actually, it's a white triangle. */ \
#define EARLY_OUT() \
{ \
int c0, c1, c2; \
c0 = RGBA_TO_PIXEL(p0->r, p0->g, p0->b, p0->a); \
c1 = RGBA_TO_PIXEL(p1->r, p1->g, p1->b, p1->a); \
c2 = RGBA_TO_PIXEL(p2->r, p2->g, p2->b, p2->a); \
if (c0 == c1 && c0 == c2) { \
/* It's really a flat-shaded triangle. */ \
if (c0 == 0xffffffff) { \
/* Actually, it's a white triangle. */ \
FNAME(white_perspective)(zb, p0, p1, p2); \
return; \
} \
FNAME(flat_perspective)(zb, p0, p1, p2); \
return; \
} \
FNAME(flat_perspective)(zb, p0, p1, p2); \
return; \
} \
}
#define EARLY_OUT_FZ() \
{ \
if (fz > 0.001 || fz < -.001) { \
/* This triangle is small enough not to worry about perspective \
correction. */ \
FNAME(smooth_textured)(zb, p0, p1, p2); \
return; \
} \
}
#define DRAW_INIT() \
{ \
texture_levels = zb->current_texture; \
texture_levels = zb->current_texture; \
fdzdx=(float)dzdx; \
fndzdx=NB_INTERP * fdzdx; \
ndszdx=NB_INTERP * dszdx; \
ndtzdx=NB_INTERP * dtzdx; \
}
#define PUT_PIXEL(_a) \
{ \
zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \
int a = oa1 * PIXEL_A(tmp) >> 16; \
if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \
RGBA_TO_PIXEL(or1 * PIXEL_R(tmp) >> 16, \
og1 * PIXEL_G(tmp) >> 16, \
ob1 * PIXEL_B(tmp) >> 16, \
a), \
or1 * PIXEL_R(tmp) >> 16, \
og1 * PIXEL_G(tmp) >> 16, \
ob1 * PIXEL_B(tmp) >> 16, \
a); \
STORE_Z(pz[_a], zz); \
} \
} \
z+=dzdx; \
og1+=dgdx; \
or1+=drdx; \
ob1+=dbdx; \
oa1+=dadx; \
s+=dsdx; \
t+=dtdx; \
#define PUT_PIXEL(_a) \
{ \
zz=z >> ZB_POINT_Z_FRAC_BITS; \
if (ZCMP(pz[_a], zz)) { \
tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level); \
int a = oa1 * PIXEL_A(tmp) >> 16; \
if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \
RGBA_TO_PIXEL(or1 * PIXEL_R(tmp) >> 16, \
og1 * PIXEL_G(tmp) >> 16, \
ob1 * PIXEL_B(tmp) >> 16, \
a), \
or1 * PIXEL_R(tmp) >> 16, \
og1 * PIXEL_G(tmp) >> 16, \
ob1 * PIXEL_B(tmp) >> 16, \
a); \
STORE_Z(pz[_a], zz); \
} \
} \
z+=dzdx; \
og1+=dgdx; \
or1+=drdx; \
ob1+=dbdx; \
oa1+=dadx; \
s+=dsdx; \
t+=dtdx; \
}
#define DRAW_LINE() \
{ \
register ZPOINT *pz; \
register ZPOINT *pz; \
register PIXEL *pp; \
register unsigned int s,t,z,zz; \
register int n,dsdx,dtdx; \
@ -582,11 +636,11 @@ static void FNAME(smooth_perspective) (ZBuffer *zb,
float ss,tt; \
ss=(sz * zinv); \
tt=(tz * zinv); \
s=(unsigned int) ss; \
t=(unsigned int) tt; \
s=(unsigned int) ss; \
t=(unsigned int) tt; \
dsdx= (int)( (dszdx - ss*fdzdx)*zinv ); \
dtdx= (int)( (dtzdx - tt*fdzdx)*zinv ); \
CALC_MIPMAP_LEVEL; \
CALC_MIPMAP_LEVEL; \
fz+=fndzdx; \
zinv=1.0f / fz; \
} \
@ -608,11 +662,11 @@ static void FNAME(smooth_perspective) (ZBuffer *zb,
float ss,tt; \
ss=(sz * zinv); \
tt=(tz * zinv); \
s=(unsigned int) ss; \
t=(unsigned int) tt; \
s=(unsigned int) ss; \
t=(unsigned int) tt; \
dsdx= (int)( (dszdx - ss*fdzdx)*zinv ); \
dtdx= (int)( (dtzdx - tt*fdzdx)*zinv ); \
CALC_MIPMAP_LEVEL; \
CALC_MIPMAP_LEVEL; \
} \
while (n>=0) { \
PUT_PIXEL(0); \