mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
avoid async texload race condition
This commit is contained in:
parent
f57d2b07da
commit
d71d7a0fdb
@ -2240,6 +2240,7 @@ async_reload_texture(TextureContext *tc) {
|
||||
nassertv(_loader != (Loader *)NULL);
|
||||
|
||||
PT(AsyncTask) request =
|
||||
new TextureReloadRequest(tc, _supports_compressed_texture);
|
||||
new TextureReloadRequest(_prepared_objects, tc->get_texture(),
|
||||
_supports_compressed_texture);
|
||||
_loader->load_async(request);
|
||||
}
|
||||
|
@ -59,6 +59,7 @@
|
||||
texturePeeker.I texturePeeker.h \
|
||||
texturePool.I texturePool.h \
|
||||
texturePoolFilter.I texturePoolFilter.h \
|
||||
textureReloadRequest.I textureReloadRequest.h \
|
||||
textureStage.I textureStage.h \
|
||||
transformBlend.I transformBlend.h \
|
||||
transformBlendTable.I transformBlendTable.h \
|
||||
@ -123,6 +124,7 @@
|
||||
texturePeeker.cxx \
|
||||
texturePool.cxx \
|
||||
texturePoolFilter.cxx \
|
||||
textureReloadRequest.cxx \
|
||||
textureStage.cxx \
|
||||
transformBlend.cxx \
|
||||
transformBlendTable.cxx \
|
||||
@ -190,6 +192,7 @@
|
||||
texturePeeker.I texturePeeker.h \
|
||||
texturePool.I texturePool.h \
|
||||
texturePoolFilter.I texturePoolFilter.h \
|
||||
textureReloadRequest.I textureReloadRequest.h \
|
||||
textureStage.I textureStage.h \
|
||||
transformBlend.I transformBlend.h \
|
||||
transformBlendTable.I transformBlendTable.h \
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "sliderTable.h"
|
||||
#include "texture.h"
|
||||
#include "texturePoolFilter.h"
|
||||
#include "textureReloadRequest.h"
|
||||
#include "textureStage.h"
|
||||
#include "textureContext.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 "
|
||||
"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) {
|
||||
BufferContext::init_type();
|
||||
@ -435,6 +446,7 @@ ConfigureFn(config_gobj) {
|
||||
Texture::init_type();
|
||||
TextureContext::init_type();
|
||||
TexturePoolFilter::init_type();
|
||||
TextureReloadRequest::init_type();
|
||||
TextureStage::init_type();
|
||||
TransformBlend::init_type();
|
||||
TransformBlendTable::init_type();
|
||||
|
@ -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 ConfigVariableDouble adaptive_lru_weight;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableInt adaptive_lru_max_updates_per_frame;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableDouble async_load_delay;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "texturePeeker.cxx"
|
||||
#include "texturePool.cxx"
|
||||
#include "texturePoolFilter.cxx"
|
||||
#include "textureReloadRequest.cxx"
|
||||
#include "textureStage.cxx"
|
||||
#include "transformBlend.cxx"
|
||||
#include "transformBlendTable.cxx"
|
||||
|
@ -71,6 +71,7 @@ PreparedGraphicsObjects::
|
||||
TextureContext *tc = (*tci);
|
||||
tc->set_owning_chain(NULL);
|
||||
}
|
||||
// Is this a leak? Should we delete these TextureContexts?
|
||||
_released_textures.clear();
|
||||
|
||||
release_all_geoms();
|
||||
@ -213,7 +214,7 @@ void PreparedGraphicsObjects::
|
||||
release_texture(TextureContext *tc) {
|
||||
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
|
||||
// the Texture itself might destruct at any time after it has been
|
||||
@ -256,7 +257,7 @@ release_all_textures() {
|
||||
tci != _prepared_textures.end();
|
||||
++tci) {
|
||||
TextureContext *tc = (*tci);
|
||||
tc->get_texture()->clear_prepared(this);
|
||||
tc->_texture->clear_prepared(this);
|
||||
tc->_texture = (Texture *)NULL;
|
||||
|
||||
_released_textures.insert(tc);
|
||||
|
@ -2010,6 +2010,26 @@ is_prepared(PreparedGraphicsObjects *prepared_objects) const {
|
||||
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
|
||||
// Access: Published
|
||||
|
@ -346,6 +346,7 @@ PUBLISHED:
|
||||
|
||||
void prepare(PreparedGraphicsObjects *prepared_objects);
|
||||
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const;
|
||||
bool was_image_modified(PreparedGraphicsObjects *prepared_objects) const;
|
||||
bool release(PreparedGraphicsObjects *prepared_objects);
|
||||
int release_all();
|
||||
|
||||
|
@ -20,24 +20,37 @@
|
||||
// via load_async(), to begin an asynchronous load.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TextureReloadRequest::
|
||||
TextureReloadRequest(TextureContext *tc, bool allow_compressed) :
|
||||
_texture_context(tc),
|
||||
TextureReloadRequest(PreparedGraphicsObjects *pgo, Texture *texture,
|
||||
bool allow_compressed) :
|
||||
_pgo(pgo),
|
||||
_texture(texture),
|
||||
_allow_compressed(allow_compressed),
|
||||
_is_ready(false)
|
||||
{
|
||||
nassertv(_texture_context != (TextureContext *)NULL);
|
||||
_texture = _texture_context->get_texture();
|
||||
nassertv(_pgo != (PreparedGraphicsObjects *)NULL);
|
||||
nassertv(_texture != (Texture *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureReloadRequest::get_texture_context
|
||||
// Function: TextureReloadRequest::get_prepared_graphics_objects
|
||||
// Access: Published
|
||||
// Description: Returns the TextureContext object associated with
|
||||
// Description: Returns the PreparedGraphicsObjects object associated with
|
||||
// this asynchronous TextureReloadRequest.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TextureContext *TextureReloadRequest::
|
||||
get_texture_context() const {
|
||||
return _texture_context;
|
||||
INLINE PreparedGraphicsObjects *TextureReloadRequest::
|
||||
get_prepared_graphics_objects() const {
|
||||
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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
@ -13,7 +13,7 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "textureReloadRequest.h"
|
||||
#include "loader.h"
|
||||
#include "textureContext.h"
|
||||
|
||||
TypeHandle TextureReloadRequest::_type_handle;
|
||||
|
||||
@ -25,18 +25,20 @@ TypeHandle TextureReloadRequest::_type_handle;
|
||||
bool TextureReloadRequest::
|
||||
do_task() {
|
||||
// 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;
|
||||
if (delay != 0.0) {
|
||||
Thread::sleep(delay);
|
||||
}
|
||||
|
||||
if (_texture->was_image_modified(_pgo)) {
|
||||
if (_allow_compressed) {
|
||||
_texture->get_ram_image();
|
||||
} else {
|
||||
_texture->get_uncompressed_ram_image();
|
||||
}
|
||||
}
|
||||
}
|
||||
_is_ready = true;
|
||||
|
||||
// Don't continue the task; we're done.
|
@ -19,8 +19,9 @@
|
||||
|
||||
#include "asyncTask.h"
|
||||
#include "texture.h"
|
||||
#include "textureContext.h"
|
||||
#include "preparedGraphicsObjects.h"
|
||||
#include "pointerTo.h"
|
||||
#include "pmutex.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : TextureReloadRequest
|
||||
@ -30,14 +31,16 @@
|
||||
// used by GraphicsStateGuardian::async_reload_texture(),
|
||||
// when get_incomplete_render() is true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_PGRAPH TextureReloadRequest : public AsyncTask {
|
||||
class EXPCL_PANDA_GOBJ TextureReloadRequest : public AsyncTask {
|
||||
public:
|
||||
ALLOC_DELETED_CHAIN(TextureReloadRequest);
|
||||
|
||||
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 is_ready() const;
|
||||
|
||||
@ -45,9 +48,9 @@ protected:
|
||||
virtual bool do_task();
|
||||
|
||||
private:
|
||||
TextureContext *_texture_context;
|
||||
bool _allow_compressed;
|
||||
PT(PreparedGraphicsObjects) _pgo;
|
||||
PT(Texture) _texture;
|
||||
bool _allow_compressed;
|
||||
bool _is_ready;
|
||||
|
||||
public:
|
@ -118,7 +118,6 @@
|
||||
textureAttrib.I textureAttrib.h \
|
||||
texGenAttrib.I texGenAttrib.h \
|
||||
textureCollection.I textureCollection.h \
|
||||
textureReloadRequest.I textureReloadRequest.h \
|
||||
textureStageCollection.I textureStageCollection.h \
|
||||
transformState.I transformState.h \
|
||||
transparencyAttrib.I transparencyAttrib.h \
|
||||
@ -231,7 +230,6 @@
|
||||
textureAttrib.cxx \
|
||||
texGenAttrib.cxx \
|
||||
textureCollection.cxx \
|
||||
textureReloadRequest.cxx \
|
||||
textureStageCollection.cxx \
|
||||
transformState.cxx \
|
||||
transparencyAttrib.cxx \
|
||||
@ -342,7 +340,6 @@
|
||||
textureAttrib.I textureAttrib.h \
|
||||
texGenAttrib.I texGenAttrib.h \
|
||||
textureCollection.I textureCollection.h \
|
||||
textureReloadRequest.I textureReloadRequest.h \
|
||||
textureStageCollection.I textureStageCollection.h \
|
||||
transformState.I transformState.h \
|
||||
transparencyAttrib.I transparencyAttrib.h \
|
||||
|
@ -94,7 +94,6 @@
|
||||
#include "texMatrixAttrib.h"
|
||||
#include "texProjectorEffect.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "textureReloadRequest.h"
|
||||
#include "texGenAttrib.h"
|
||||
#include "transformState.h"
|
||||
#include "transparencyAttrib.h"
|
||||
@ -274,16 +273,6 @@ ConfigVariableBool flatten_geoms
|
||||
"only the NodePath interfaces; you may still make the lower-level "
|
||||
"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
|
||||
("polylight-info", false,
|
||||
PRC_DESC("Set this true to view some info statements regarding the polylight. "
|
||||
@ -460,7 +449,6 @@ init_libpgraph() {
|
||||
TexMatrixAttrib::init_type();
|
||||
TexProjectorEffect::init_type();
|
||||
TextureAttrib::init_type();
|
||||
TextureReloadRequest::init_type();
|
||||
TexGenAttrib::init_type();
|
||||
TransformState::init_type();
|
||||
TransparencyAttrib::init_type();
|
||||
|
@ -53,7 +53,6 @@ extern ConfigVariableInt max_collect_indices;
|
||||
extern ConfigVariableBool premunge_data;
|
||||
extern ConfigVariableBool preserve_geom_nodes;
|
||||
extern ConfigVariableBool flatten_geoms;
|
||||
extern ConfigVariableDouble async_load_delay;
|
||||
|
||||
extern ConfigVariableBool polylight_info;
|
||||
extern ConfigVariableDouble lod_fade_time;
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "textureAttrib.cxx"
|
||||
#include "texGenAttrib.cxx"
|
||||
#include "textureCollection.cxx"
|
||||
#include "textureReloadRequest.cxx"
|
||||
#include "textureStageCollection.cxx"
|
||||
#include "transformState.cxx"
|
||||
#include "transparencyAttrib.cxx"
|
||||
|
@ -765,13 +765,13 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
|
||||
case AlphaTestAttrib::M_less:
|
||||
case AlphaTestAttrib::M_less_equal:
|
||||
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;
|
||||
|
||||
case AlphaTestAttrib::M_greater:
|
||||
case AlphaTestAttrib::M_greater_equal:
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -78,15 +78,23 @@ typedef unsigned int PIXEL;
|
||||
#define PSZB 4
|
||||
#define PSZSH 5
|
||||
|
||||
#define PIXEL_MULT(p1, p2) \
|
||||
RGB_TO_PIXEL((PIXEL_R(p1) * PIXEL_R(p2)) >> 16, \
|
||||
(PIXEL_G(p1) * PIXEL_G(p2)) >> 16, \
|
||||
(PIXEL_B(p1) * PIXEL_B(p2)) >> 16)
|
||||
// Returns an unsigned product of c1 * c2
|
||||
#define PCOMPONENT_MULT(c1, c2) \
|
||||
((((unsigned int)(c1) * (unsigned int)(c2))) >> 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) \
|
||||
RGBA_TO_PIXEL(((r1) * (0xffff - (a2)) + (r2) * (a2)) >> 16, \
|
||||
((g1) * (0xffff - (a2)) + (g2) * (a2)) >> 16, \
|
||||
((b1) * (0xffff - (a2)) + (b2) * (a2)) >> 16, \
|
||||
RGBA_TO_PIXEL(PCOMPONENT_BLEND(r1, r2, a2), \
|
||||
PCOMPONENT_BLEND(g1, g2, a2), \
|
||||
PCOMPONENT_BLEND(b1, b2, a2), \
|
||||
a2)
|
||||
#define PIXEL_BLEND_RGB(rgb, r, g, b, a) \
|
||||
PIXEL_BLEND(PIXEL_R(rgb), PIXEL_G(rgb), PIXEL_B(rgb), r, g, b, a)
|
||||
|
@ -182,16 +182,16 @@ static void FNAME(flat_textured) (ZBuffer *zb,
|
||||
zz=z >> ZB_POINT_Z_FRAC_BITS; \
|
||||
if (ZCMP(pz[_a], zz)) { \
|
||||
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)) { \
|
||||
STORE_PIX(pp[_a], \
|
||||
RGBA_TO_PIXEL(or0 * PIXEL_R(tmp) >> 16, \
|
||||
og0 * PIXEL_G(tmp) >> 16, \
|
||||
ob0 * PIXEL_B(tmp) >> 16, \
|
||||
RGBA_TO_PIXEL(PCOMPONENT_MULT(or0, PIXEL_R(tmp)), \
|
||||
PCOMPONENT_MULT(og0, PIXEL_G(tmp)), \
|
||||
PCOMPONENT_MULT(ob0, PIXEL_B(tmp)), \
|
||||
a), \
|
||||
or0 * PIXEL_R(tmp) >> 16, \
|
||||
og0 * PIXEL_G(tmp) >> 16, \
|
||||
ob0 * PIXEL_B(tmp) >> 16, \
|
||||
PCOMPONENT_MULT(or0, PIXEL_R(tmp)), \
|
||||
PCOMPONENT_MULT(og0, PIXEL_G(tmp)), \
|
||||
PCOMPONENT_MULT(ob0, PIXEL_B(tmp)), \
|
||||
a); \
|
||||
STORE_Z(pz[_a], zz); \
|
||||
} \
|
||||
@ -243,16 +243,16 @@ static void FNAME(smooth_textured) (ZBuffer *zb,
|
||||
zz=z >> ZB_POINT_Z_FRAC_BITS; \
|
||||
if (ZCMP(pz[_a], zz)) { \
|
||||
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)) { \
|
||||
STORE_PIX(pp[_a], \
|
||||
RGBA_TO_PIXEL(or1 * PIXEL_R(tmp) >> 16, \
|
||||
og1 * PIXEL_G(tmp) >> 16, \
|
||||
ob1 * PIXEL_B(tmp) >> 16, \
|
||||
RGBA_TO_PIXEL(PCOMPONENT_MULT(or1, PIXEL_R(tmp)), \
|
||||
PCOMPONENT_MULT(og1, PIXEL_G(tmp)), \
|
||||
PCOMPONENT_MULT(ob1, PIXEL_B(tmp)), \
|
||||
a), \
|
||||
or1 * PIXEL_R(tmp) >> 16, \
|
||||
og1 * PIXEL_G(tmp) >> 16, \
|
||||
ob1 * PIXEL_B(tmp) >> 16, \
|
||||
PCOMPONENT_MULT(or1, PIXEL_R(tmp)), \
|
||||
PCOMPONENT_MULT(og1, PIXEL_G(tmp)), \
|
||||
PCOMPONENT_MULT(ob1, PIXEL_B(tmp)), \
|
||||
a); \
|
||||
STORE_Z(pz[_a], zz); \
|
||||
} \
|
||||
@ -422,16 +422,16 @@ static void FNAME(flat_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, mipmap_dx); \
|
||||
int a = oa0 * PIXEL_A(tmp) >> 16; \
|
||||
int a = PALPHA_MULT(oa0, PIXEL_A(tmp)); \
|
||||
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, \
|
||||
RGBA_TO_PIXEL(PCOMPONENT_MULT(or0, PIXEL_R(tmp)), \
|
||||
PCOMPONENT_MULT(og0, PIXEL_G(tmp)), \
|
||||
PCOMPONENT_MULT(ob0, PIXEL_B(tmp)), \
|
||||
a), \
|
||||
or0 * PIXEL_R(tmp) >> 16, \
|
||||
og0 * PIXEL_G(tmp) >> 16, \
|
||||
ob0 * PIXEL_B(tmp) >> 16, \
|
||||
PCOMPONENT_MULT(or0, PIXEL_R(tmp)), \
|
||||
PCOMPONENT_MULT(og0, PIXEL_G(tmp)), \
|
||||
PCOMPONENT_MULT(ob0, PIXEL_B(tmp)), \
|
||||
a); \
|
||||
STORE_Z(pz[_a], zz); \
|
||||
} \
|
||||
@ -557,16 +557,16 @@ static void FNAME(smooth_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, mipmap_dx); \
|
||||
int a = oa1 * PIXEL_A(tmp) >> 16; \
|
||||
int a = PALPHA_MULT(oa1, PIXEL_A(tmp)); \
|
||||
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, \
|
||||
RGBA_TO_PIXEL(PCOMPONENT_MULT(or1, PIXEL_R(tmp)), \
|
||||
PCOMPONENT_MULT(og1, PIXEL_G(tmp)), \
|
||||
PCOMPONENT_MULT(ob1, PIXEL_B(tmp)), \
|
||||
a), \
|
||||
or1 * PIXEL_R(tmp) >> 16, \
|
||||
og1 * PIXEL_G(tmp) >> 16, \
|
||||
ob1 * PIXEL_B(tmp) >> 16, \
|
||||
PCOMPONENT_MULT(or1, PIXEL_R(tmp)), \
|
||||
PCOMPONENT_MULT(og1, PIXEL_G(tmp)), \
|
||||
PCOMPONENT_MULT(ob1, PIXEL_B(tmp)), \
|
||||
a); \
|
||||
STORE_Z(pz[_a], zz); \
|
||||
} \
|
||||
|
Loading…
x
Reference in New Issue
Block a user