avoid async texload race condition

This commit is contained in:
David Rose 2008-09-11 01:02:11 +00:00
parent f57d2b07da
commit d71d7a0fdb
18 changed files with 129 additions and 80 deletions

View File

@ -2240,6 +2240,7 @@ async_reload_texture(TextureContext *tc) {
nassertv(_loader != (Loader *)NULL); nassertv(_loader != (Loader *)NULL);
PT(AsyncTask) request = PT(AsyncTask) request =
new TextureReloadRequest(tc, _supports_compressed_texture); new TextureReloadRequest(_prepared_objects, tc->get_texture(),
_supports_compressed_texture);
_loader->load_async(request); _loader->load_async(request);
} }

View File

@ -59,6 +59,7 @@
texturePeeker.I texturePeeker.h \ texturePeeker.I texturePeeker.h \
texturePool.I texturePool.h \ texturePool.I texturePool.h \
texturePoolFilter.I texturePoolFilter.h \ texturePoolFilter.I texturePoolFilter.h \
textureReloadRequest.I textureReloadRequest.h \
textureStage.I textureStage.h \ textureStage.I textureStage.h \
transformBlend.I transformBlend.h \ transformBlend.I transformBlend.h \
transformBlendTable.I transformBlendTable.h \ transformBlendTable.I transformBlendTable.h \
@ -123,6 +124,7 @@
texturePeeker.cxx \ texturePeeker.cxx \
texturePool.cxx \ texturePool.cxx \
texturePoolFilter.cxx \ texturePoolFilter.cxx \
textureReloadRequest.cxx \
textureStage.cxx \ textureStage.cxx \
transformBlend.cxx \ transformBlend.cxx \
transformBlendTable.cxx \ transformBlendTable.cxx \
@ -190,6 +192,7 @@
texturePeeker.I texturePeeker.h \ texturePeeker.I texturePeeker.h \
texturePool.I texturePool.h \ texturePool.I texturePool.h \
texturePoolFilter.I texturePoolFilter.h \ texturePoolFilter.I texturePoolFilter.h \
textureReloadRequest.I textureReloadRequest.h \
textureStage.I textureStage.h \ textureStage.I textureStage.h \
transformBlend.I transformBlend.h \ transformBlend.I transformBlend.h \
transformBlendTable.I transformBlendTable.h \ transformBlendTable.I transformBlendTable.h \

View File

@ -38,6 +38,7 @@
#include "sliderTable.h" #include "sliderTable.h"
#include "texture.h" #include "texture.h"
#include "texturePoolFilter.h" #include "texturePoolFilter.h"
#include "textureReloadRequest.h"
#include "textureStage.h" #include "textureStage.h"
#include "textureContext.h" #include "textureContext.h"
#include "shader.h" #include "shader.h"
@ -398,6 +399,16 @@ ConfigVariableInt adaptive_lru_max_updates_per_frame
"frame. Do not set this too high or it will degrade " "frame. Do not set this too high or it will degrade "
"performance.")); "performance."));
ConfigVariableDouble async_load_delay
("async-load-delay", 0.0,
PRC_DESC("If this is nonzero, it represents an artificial delay, "
"in seconds, that is imposed on every asynchronous load attempt "
"(within the thread). Its purpose is to help debug errors that "
"may occur when an asynchronous load is delayed. The "
"delay is per-model, and all aync loads will be queued "
"up behind the delay--it is as if the time it takes to read a "
"file is increased by this amount per read."));
ConfigureFn(config_gobj) { ConfigureFn(config_gobj) {
BufferContext::init_type(); BufferContext::init_type();
@ -435,6 +446,7 @@ ConfigureFn(config_gobj) {
Texture::init_type(); Texture::init_type();
TextureContext::init_type(); TextureContext::init_type();
TexturePoolFilter::init_type(); TexturePoolFilter::init_type();
TextureReloadRequest::init_type();
TextureStage::init_type(); TextureStage::init_type();
TransformBlend::init_type(); TransformBlend::init_type();
TransformBlendTable::init_type(); TransformBlendTable::init_type();

View File

@ -95,6 +95,7 @@ extern EXPCL_PANDA_GOBJ ConfigVariableInt vertex_data_page_threads;
extern EXPCL_PANDA_GOBJ ConfigVariableInt graphics_memory_limit; extern EXPCL_PANDA_GOBJ ConfigVariableInt graphics_memory_limit;
extern EXPCL_PANDA_GOBJ ConfigVariableDouble adaptive_lru_weight; extern EXPCL_PANDA_GOBJ ConfigVariableDouble adaptive_lru_weight;
extern EXPCL_PANDA_GOBJ ConfigVariableInt adaptive_lru_max_updates_per_frame; extern EXPCL_PANDA_GOBJ ConfigVariableInt adaptive_lru_max_updates_per_frame;
extern EXPCL_PANDA_GOBJ ConfigVariableDouble async_load_delay;
#endif #endif

View File

@ -17,6 +17,7 @@
#include "texturePeeker.cxx" #include "texturePeeker.cxx"
#include "texturePool.cxx" #include "texturePool.cxx"
#include "texturePoolFilter.cxx" #include "texturePoolFilter.cxx"
#include "textureReloadRequest.cxx"
#include "textureStage.cxx" #include "textureStage.cxx"
#include "transformBlend.cxx" #include "transformBlend.cxx"
#include "transformBlendTable.cxx" #include "transformBlendTable.cxx"

View File

@ -71,6 +71,7 @@ PreparedGraphicsObjects::
TextureContext *tc = (*tci); TextureContext *tc = (*tci);
tc->set_owning_chain(NULL); tc->set_owning_chain(NULL);
} }
// Is this a leak? Should we delete these TextureContexts?
_released_textures.clear(); _released_textures.clear();
release_all_geoms(); release_all_geoms();
@ -213,7 +214,7 @@ void PreparedGraphicsObjects::
release_texture(TextureContext *tc) { release_texture(TextureContext *tc) {
ReMutexHolder holder(_lock); ReMutexHolder holder(_lock);
tc->get_texture()->clear_prepared(this); tc->_texture->clear_prepared(this);
// We have to set the Texture pointer to NULL at this point, since // We have to set the Texture pointer to NULL at this point, since
// the Texture itself might destruct at any time after it has been // the Texture itself might destruct at any time after it has been
@ -256,7 +257,7 @@ release_all_textures() {
tci != _prepared_textures.end(); tci != _prepared_textures.end();
++tci) { ++tci) {
TextureContext *tc = (*tci); TextureContext *tc = (*tci);
tc->get_texture()->clear_prepared(this); tc->_texture->clear_prepared(this);
tc->_texture = (Texture *)NULL; tc->_texture = (Texture *)NULL;
_released_textures.insert(tc); _released_textures.insert(tc);

View File

@ -2010,6 +2010,26 @@ is_prepared(PreparedGraphicsObjects *prepared_objects) const {
return prepared_objects->is_texture_queued(this); return prepared_objects->is_texture_queued(this);
} }
////////////////////////////////////////////////////////////////////
// Function: Texture::was_image_modified
// Access: Published
// Description: Returns true if the texture needs to be re-loaded
// onto the indicated GSG, either because its image data
// is out-of-date, or because it's not fully prepared
// now.
////////////////////////////////////////////////////////////////////
bool Texture::
was_image_modified(PreparedGraphicsObjects *prepared_objects) const {
ReMutexHolder holder(_lock);
Contexts::const_iterator ci;
ci = _contexts.find(prepared_objects);
if (ci != _contexts.end()) {
TextureContext *tc = (*ci).second;
return tc->was_image_modified();
}
return true;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: Texture::release // Function: Texture::release
// Access: Published // Access: Published

View File

@ -346,6 +346,7 @@ PUBLISHED:
void prepare(PreparedGraphicsObjects *prepared_objects); void prepare(PreparedGraphicsObjects *prepared_objects);
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const; bool is_prepared(PreparedGraphicsObjects *prepared_objects) const;
bool was_image_modified(PreparedGraphicsObjects *prepared_objects) const;
bool release(PreparedGraphicsObjects *prepared_objects); bool release(PreparedGraphicsObjects *prepared_objects);
int release_all(); int release_all();

View File

@ -20,24 +20,37 @@
// via load_async(), to begin an asynchronous load. // via load_async(), to begin an asynchronous load.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE TextureReloadRequest:: INLINE TextureReloadRequest::
TextureReloadRequest(TextureContext *tc, bool allow_compressed) : TextureReloadRequest(PreparedGraphicsObjects *pgo, Texture *texture,
_texture_context(tc), bool allow_compressed) :
_pgo(pgo),
_texture(texture),
_allow_compressed(allow_compressed), _allow_compressed(allow_compressed),
_is_ready(false) _is_ready(false)
{ {
nassertv(_texture_context != (TextureContext *)NULL); nassertv(_pgo != (PreparedGraphicsObjects *)NULL);
_texture = _texture_context->get_texture(); nassertv(_texture != (Texture *)NULL);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: TextureReloadRequest::get_texture_context // Function: TextureReloadRequest::get_prepared_graphics_objects
// Access: Published // Access: Published
// Description: Returns the TextureContext object associated with // Description: Returns the PreparedGraphicsObjects object associated with
// this asynchronous TextureReloadRequest. // this asynchronous TextureReloadRequest.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE TextureContext *TextureReloadRequest:: INLINE PreparedGraphicsObjects *TextureReloadRequest::
get_texture_context() const { get_prepared_graphics_objects() const {
return _texture_context; return _pgo;
}
////////////////////////////////////////////////////////////////////
// Function: TextureReloadRequest::get_texture
// Access: Published
// Description: Returns the Texture object associated with
// this asynchronous TextureReloadRequest.
////////////////////////////////////////////////////////////////////
INLINE Texture *TextureReloadRequest::
get_texture() const {
return _texture;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -13,7 +13,7 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
#include "textureReloadRequest.h" #include "textureReloadRequest.h"
#include "loader.h" #include "textureContext.h"
TypeHandle TextureReloadRequest::_type_handle; TypeHandle TextureReloadRequest::_type_handle;
@ -25,16 +25,18 @@ TypeHandle TextureReloadRequest::_type_handle;
bool TextureReloadRequest:: bool TextureReloadRequest::
do_task() { do_task() {
// Don't reload the texture if it doesn't need it. // Don't reload the texture if it doesn't need it.
if (_texture_context->was_image_modified()) { if (_texture->was_image_modified(_pgo)) {
double delay = async_load_delay; double delay = async_load_delay;
if (delay != 0.0) { if (delay != 0.0) {
Thread::sleep(delay); Thread::sleep(delay);
} }
if (_allow_compressed) { if (_texture->was_image_modified(_pgo)) {
_texture->get_ram_image(); if (_allow_compressed) {
} else { _texture->get_ram_image();
_texture->get_uncompressed_ram_image(); } else {
_texture->get_uncompressed_ram_image();
}
} }
} }
_is_ready = true; _is_ready = true;

View File

@ -19,8 +19,9 @@
#include "asyncTask.h" #include "asyncTask.h"
#include "texture.h" #include "texture.h"
#include "textureContext.h" #include "preparedGraphicsObjects.h"
#include "pointerTo.h" #include "pointerTo.h"
#include "pmutex.h"
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : TextureReloadRequest // Class : TextureReloadRequest
@ -30,14 +31,16 @@
// used by GraphicsStateGuardian::async_reload_texture(), // used by GraphicsStateGuardian::async_reload_texture(),
// when get_incomplete_render() is true. // when get_incomplete_render() is true.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_PGRAPH TextureReloadRequest : public AsyncTask { class EXPCL_PANDA_GOBJ TextureReloadRequest : public AsyncTask {
public: public:
ALLOC_DELETED_CHAIN(TextureReloadRequest); ALLOC_DELETED_CHAIN(TextureReloadRequest);
PUBLISHED: PUBLISHED:
INLINE TextureReloadRequest(TextureContext *tc, bool allow_compressed); INLINE TextureReloadRequest(PreparedGraphicsObjects *pgo, Texture *texture,
bool allow_compressed);
INLINE TextureContext *get_texture_context() const; INLINE PreparedGraphicsObjects *get_prepared_graphics_objects() const;
INLINE Texture *get_texture() const;
INLINE bool get_allow_compressed() const; INLINE bool get_allow_compressed() const;
INLINE bool is_ready() const; INLINE bool is_ready() const;
@ -45,9 +48,9 @@ protected:
virtual bool do_task(); virtual bool do_task();
private: private:
TextureContext *_texture_context; PT(PreparedGraphicsObjects) _pgo;
bool _allow_compressed;
PT(Texture) _texture; PT(Texture) _texture;
bool _allow_compressed;
bool _is_ready; bool _is_ready;
public: public:

View File

@ -118,7 +118,6 @@
textureAttrib.I textureAttrib.h \ textureAttrib.I textureAttrib.h \
texGenAttrib.I texGenAttrib.h \ texGenAttrib.I texGenAttrib.h \
textureCollection.I textureCollection.h \ textureCollection.I textureCollection.h \
textureReloadRequest.I textureReloadRequest.h \
textureStageCollection.I textureStageCollection.h \ textureStageCollection.I textureStageCollection.h \
transformState.I transformState.h \ transformState.I transformState.h \
transparencyAttrib.I transparencyAttrib.h \ transparencyAttrib.I transparencyAttrib.h \
@ -231,7 +230,6 @@
textureAttrib.cxx \ textureAttrib.cxx \
texGenAttrib.cxx \ texGenAttrib.cxx \
textureCollection.cxx \ textureCollection.cxx \
textureReloadRequest.cxx \
textureStageCollection.cxx \ textureStageCollection.cxx \
transformState.cxx \ transformState.cxx \
transparencyAttrib.cxx \ transparencyAttrib.cxx \
@ -342,7 +340,6 @@
textureAttrib.I textureAttrib.h \ textureAttrib.I textureAttrib.h \
texGenAttrib.I texGenAttrib.h \ texGenAttrib.I texGenAttrib.h \
textureCollection.I textureCollection.h \ textureCollection.I textureCollection.h \
textureReloadRequest.I textureReloadRequest.h \
textureStageCollection.I textureStageCollection.h \ textureStageCollection.I textureStageCollection.h \
transformState.I transformState.h \ transformState.I transformState.h \
transparencyAttrib.I transparencyAttrib.h \ transparencyAttrib.I transparencyAttrib.h \

View File

@ -94,7 +94,6 @@
#include "texMatrixAttrib.h" #include "texMatrixAttrib.h"
#include "texProjectorEffect.h" #include "texProjectorEffect.h"
#include "textureAttrib.h" #include "textureAttrib.h"
#include "textureReloadRequest.h"
#include "texGenAttrib.h" #include "texGenAttrib.h"
#include "transformState.h" #include "transformState.h"
#include "transparencyAttrib.h" #include "transparencyAttrib.h"
@ -274,16 +273,6 @@ ConfigVariableBool flatten_geoms
"only the NodePath interfaces; you may still make the lower-level " "only the NodePath interfaces; you may still make the lower-level "
"SceneGraphReducer calls directly.")); "SceneGraphReducer calls directly."));
ConfigVariableDouble async_load_delay
("async-load-delay", 0.0,
PRC_DESC("If this is nonzero, it represents an artificial delay, "
"in seconds, that is imposed on every asynchronous load attempt "
"(within the thread). Its purpose is to help debug errors that "
"may occur when an asynchronous load is delayed. The "
"delay is per-model, and all aync loads will be queued "
"up behind the delay--it is as if the time it takes to read a "
"file is increased by this amount per read."));
ConfigVariableBool polylight_info ConfigVariableBool polylight_info
("polylight-info", false, ("polylight-info", false,
PRC_DESC("Set this true to view some info statements regarding the polylight. " PRC_DESC("Set this true to view some info statements regarding the polylight. "
@ -460,7 +449,6 @@ init_libpgraph() {
TexMatrixAttrib::init_type(); TexMatrixAttrib::init_type();
TexProjectorEffect::init_type(); TexProjectorEffect::init_type();
TextureAttrib::init_type(); TextureAttrib::init_type();
TextureReloadRequest::init_type();
TexGenAttrib::init_type(); TexGenAttrib::init_type();
TransformState::init_type(); TransformState::init_type();
TransparencyAttrib::init_type(); TransparencyAttrib::init_type();

View File

@ -53,7 +53,6 @@ extern ConfigVariableInt max_collect_indices;
extern ConfigVariableBool premunge_data; extern ConfigVariableBool premunge_data;
extern ConfigVariableBool preserve_geom_nodes; extern ConfigVariableBool preserve_geom_nodes;
extern ConfigVariableBool flatten_geoms; extern ConfigVariableBool flatten_geoms;
extern ConfigVariableDouble async_load_delay;
extern ConfigVariableBool polylight_info; extern ConfigVariableBool polylight_info;
extern ConfigVariableDouble lod_fade_time; extern ConfigVariableDouble lod_fade_time;

View File

@ -25,7 +25,6 @@
#include "textureAttrib.cxx" #include "textureAttrib.cxx"
#include "texGenAttrib.cxx" #include "texGenAttrib.cxx"
#include "textureCollection.cxx" #include "textureCollection.cxx"
#include "textureReloadRequest.cxx"
#include "textureStageCollection.cxx" #include "textureStageCollection.cxx"
#include "transformState.cxx" #include "transformState.cxx"
#include "transparencyAttrib.cxx" #include "transparencyAttrib.cxx"

View File

@ -765,13 +765,13 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
case AlphaTestAttrib::M_less: case AlphaTestAttrib::M_less:
case AlphaTestAttrib::M_less_equal: case AlphaTestAttrib::M_less_equal:
alpha_test_state = 1; // aless alpha_test_state = 1; // aless
_c->zb->reference_alpha = (int)_target._alpha_test->get_reference_alpha() * ZB_POINT_ALPHA_MAX; _c->zb->reference_alpha = (int)(_target._alpha_test->get_reference_alpha() * ZB_POINT_ALPHA_MAX);
break; break;
case AlphaTestAttrib::M_greater: case AlphaTestAttrib::M_greater:
case AlphaTestAttrib::M_greater_equal: case AlphaTestAttrib::M_greater_equal:
alpha_test_state = 2; // amore alpha_test_state = 2; // amore
_c->zb->reference_alpha = (int)_target._alpha_test->get_reference_alpha() * ZB_POINT_ALPHA_MAX; _c->zb->reference_alpha = (int)(_target._alpha_test->get_reference_alpha() * ZB_POINT_ALPHA_MAX);
break; break;
} }

View File

@ -78,15 +78,23 @@ typedef unsigned int PIXEL;
#define PSZB 4 #define PSZB 4
#define PSZSH 5 #define PSZSH 5
#define PIXEL_MULT(p1, p2) \ // Returns an unsigned product of c1 * c2
RGB_TO_PIXEL((PIXEL_R(p1) * PIXEL_R(p2)) >> 16, \ #define PCOMPONENT_MULT(c1, c2) \
(PIXEL_G(p1) * PIXEL_G(p2)) >> 16, \ ((((unsigned int)(c1) * (unsigned int)(c2))) >> 16)
(PIXEL_B(p1) * PIXEL_B(p2)) >> 16)
// Returns a signed product of c1 * c2, where c1 is initially signed.
// We leave 2 bits on the top to differentiate between c1 < 0 and c1 >
// 0xffff; the result has the same sign.
#define PALPHA_MULT(c1, c2) \
(((int)(((int)(c1) >> 2) * (unsigned int)(c2))) >> 14)
#define PCOMPONENT_BLEND(c1, c2, a2) \
((((unsigned int)(c1) * ((unsigned int)0xffff - (unsigned int)(a2)) + (unsigned int)(c2) * (unsigned int)(a2))) >> 16)
#define PIXEL_BLEND(r1, g1, b1, r2, g2, b2, a2) \ #define PIXEL_BLEND(r1, g1, b1, r2, g2, b2, a2) \
RGBA_TO_PIXEL(((r1) * (0xffff - (a2)) + (r2) * (a2)) >> 16, \ RGBA_TO_PIXEL(PCOMPONENT_BLEND(r1, r2, a2), \
((g1) * (0xffff - (a2)) + (g2) * (a2)) >> 16, \ PCOMPONENT_BLEND(g1, g2, a2), \
((b1) * (0xffff - (a2)) + (b2) * (a2)) >> 16, \ PCOMPONENT_BLEND(b1, b2, a2), \
a2) a2)
#define PIXEL_BLEND_RGB(rgb, r, g, b, a) \ #define PIXEL_BLEND_RGB(rgb, r, g, b, a) \
PIXEL_BLEND(PIXEL_R(rgb), PIXEL_G(rgb), PIXEL_B(rgb), r, g, b, a) PIXEL_BLEND(PIXEL_R(rgb), PIXEL_G(rgb), PIXEL_B(rgb), r, g, b, a)

View File

@ -182,16 +182,16 @@ 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, mipmap_dx); \ tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx); \
int a = oa0 * PIXEL_A(tmp) >> 16; \ int a = PALPHA_MULT(oa0, PIXEL_A(tmp)); \
if (ACMP(zb, a)) { \ if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \ STORE_PIX(pp[_a], \
RGBA_TO_PIXEL(or0 * PIXEL_R(tmp) >> 16, \ RGBA_TO_PIXEL(PCOMPONENT_MULT(or0, PIXEL_R(tmp)), \
og0 * PIXEL_G(tmp) >> 16, \ PCOMPONENT_MULT(og0, PIXEL_G(tmp)), \
ob0 * PIXEL_B(tmp) >> 16, \ PCOMPONENT_MULT(ob0, PIXEL_B(tmp)), \
a), \ a), \
or0 * PIXEL_R(tmp) >> 16, \ PCOMPONENT_MULT(or0, PIXEL_R(tmp)), \
og0 * PIXEL_G(tmp) >> 16, \ PCOMPONENT_MULT(og0, PIXEL_G(tmp)), \
ob0 * PIXEL_B(tmp) >> 16, \ PCOMPONENT_MULT(ob0, PIXEL_B(tmp)), \
a); \ a); \
STORE_Z(pz[_a], zz); \ STORE_Z(pz[_a], zz); \
} \ } \
@ -243,16 +243,16 @@ 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, mipmap_dx); \ tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx); \
int a = oa1 * PIXEL_A(tmp) >> 16; \ int a = PALPHA_MULT(oa1, PIXEL_A(tmp)); \
if (ACMP(zb, a)) { \ if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \ STORE_PIX(pp[_a], \
RGBA_TO_PIXEL(or1 * PIXEL_R(tmp) >> 16, \ RGBA_TO_PIXEL(PCOMPONENT_MULT(or1, PIXEL_R(tmp)), \
og1 * PIXEL_G(tmp) >> 16, \ PCOMPONENT_MULT(og1, PIXEL_G(tmp)), \
ob1 * PIXEL_B(tmp) >> 16, \ PCOMPONENT_MULT(ob1, PIXEL_B(tmp)), \
a), \ a), \
or1 * PIXEL_R(tmp) >> 16, \ PCOMPONENT_MULT(or1, PIXEL_R(tmp)), \
og1 * PIXEL_G(tmp) >> 16, \ PCOMPONENT_MULT(og1, PIXEL_G(tmp)), \
ob1 * PIXEL_B(tmp) >> 16, \ PCOMPONENT_MULT(ob1, PIXEL_B(tmp)), \
a); \ a); \
STORE_Z(pz[_a], zz); \ STORE_Z(pz[_a], zz); \
} \ } \
@ -422,16 +422,16 @@ 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, mipmap_dx); \ tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx); \
int a = oa0 * PIXEL_A(tmp) >> 16; \ int a = PALPHA_MULT(oa0, PIXEL_A(tmp)); \
if (ACMP(zb, a)) { \ if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \ STORE_PIX(pp[_a], \
RGBA_TO_PIXEL(or0 * PIXEL_R(tmp) >> 16, \ RGBA_TO_PIXEL(PCOMPONENT_MULT(or0, PIXEL_R(tmp)), \
og0 * PIXEL_G(tmp) >> 16, \ PCOMPONENT_MULT(og0, PIXEL_G(tmp)), \
ob0 * PIXEL_B(tmp) >> 16, \ PCOMPONENT_MULT(ob0, PIXEL_B(tmp)), \
a), \ a), \
or0 * PIXEL_R(tmp) >> 16, \ PCOMPONENT_MULT(or0, PIXEL_R(tmp)), \
og0 * PIXEL_G(tmp) >> 16, \ PCOMPONENT_MULT(og0, PIXEL_G(tmp)), \
ob0 * PIXEL_B(tmp) >> 16, \ PCOMPONENT_MULT(ob0, PIXEL_B(tmp)), \
a); \ a); \
STORE_Z(pz[_a], zz); \ STORE_Z(pz[_a], zz); \
} \ } \
@ -556,17 +556,17 @@ 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, mipmap_dx); \ tmp = ZB_LOOKUP_TEXTURE(texture_levels, s, t, mipmap_level, mipmap_dx); \
int a = oa1 * PIXEL_A(tmp) >> 16; \ int a = PALPHA_MULT(oa1, PIXEL_A(tmp)); \
if (ACMP(zb, a)) { \ if (ACMP(zb, a)) { \
STORE_PIX(pp[_a], \ STORE_PIX(pp[_a], \
RGBA_TO_PIXEL(or1 * PIXEL_R(tmp) >> 16, \ RGBA_TO_PIXEL(PCOMPONENT_MULT(or1, PIXEL_R(tmp)), \
og1 * PIXEL_G(tmp) >> 16, \ PCOMPONENT_MULT(og1, PIXEL_G(tmp)), \
ob1 * PIXEL_B(tmp) >> 16, \ PCOMPONENT_MULT(ob1, PIXEL_B(tmp)), \
a), \ a), \
or1 * PIXEL_R(tmp) >> 16, \ PCOMPONENT_MULT(or1, PIXEL_R(tmp)), \
og1 * PIXEL_G(tmp) >> 16, \ PCOMPONENT_MULT(og1, PIXEL_G(tmp)), \
ob1 * PIXEL_B(tmp) >> 16, \ PCOMPONENT_MULT(ob1, PIXEL_B(tmp)), \
a); \ a); \
STORE_Z(pz[_a], zz); \ STORE_Z(pz[_a], zz); \
} \ } \