Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
0661574448
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
|
||||
include:
|
||||
- profile: ubuntu-bionic-double-standard-unity-makefile
|
||||
os: ubuntu-22.04
|
||||
os: ubuntu-24.04
|
||||
config: Standard
|
||||
unity: YES
|
||||
generator: Unix Makefiles
|
||||
|
|
@ -32,7 +32,7 @@ jobs:
|
|||
asan: YES
|
||||
|
||||
- profile: ubuntu-bionic-coverage-ninja
|
||||
os: ubuntu-22.04
|
||||
os: ubuntu-24.04
|
||||
config: Coverage
|
||||
unity: NO
|
||||
generator: Ninja
|
||||
|
|
@ -404,12 +404,12 @@ jobs:
|
|||
if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')"
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, windows-2022, macOS-15]
|
||||
os: [ubuntu-24.04, windows-2022, macOS-15]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install dependencies (Ubuntu)
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
if: matrix.os == 'ubuntu-24.04'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential bison flex libfreetype6-dev libgl1-mesa-dev libjpeg-dev libode-dev libopenal-dev libpng-dev libssl-dev libvorbis-dev libx11-dev libxcursor-dev libxrandr-dev nvidia-cg-toolkit zlib1g-dev
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import os
|
||||
import imp
|
||||
import importlib.util
|
||||
|
||||
|
||||
class FileMgr:
|
||||
|
|
@ -32,10 +32,10 @@ class FileMgr:
|
|||
f.write(data)
|
||||
f.write('\n')
|
||||
f.close()
|
||||
self.editor.updateStatusReadout('Sucessfully saved to %s'%fileName)
|
||||
self.editor.updateStatusReadout(f'Sucessfully saved to {fileName}')
|
||||
self.editor.fNeedToSave = False
|
||||
except IOError:
|
||||
print('failed to save %s'%fileName)
|
||||
print(f'failed to save {fileName}')
|
||||
if f:
|
||||
f.close()
|
||||
|
||||
|
|
@ -43,10 +43,11 @@ class FileMgr:
|
|||
dirname, moduleName = os.path.split(fileName)
|
||||
if moduleName.endswith('.py'):
|
||||
moduleName = moduleName[:-3]
|
||||
file, pathname, description = imp.find_module(moduleName, [dirname])
|
||||
spec = importlib.util.spec_from_file_location(moduleName, fileName)
|
||||
try:
|
||||
module = imp.load_module(moduleName, file, pathname, description)
|
||||
self.editor.updateStatusReadout('Sucessfully opened file %s'%fileName)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
self.editor.updateStatusReadout(f'Sucessfully opened file {fileName}')
|
||||
self.editor.fNeedToSave = False
|
||||
except Exception:
|
||||
print('failed to load %s'%fileName)
|
||||
print(f'failed to load {fileName}')
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import imp
|
||||
import importlib.util
|
||||
|
||||
|
||||
class LevelLoaderBase:
|
||||
|
|
@ -30,10 +30,15 @@ class LevelLoaderBase:
|
|||
|
||||
if fileName.endswith('.py'):
|
||||
fileName = fileName[:-3]
|
||||
file, pathname, description = imp.find_module(fileName, [filePath])
|
||||
|
||||
try:
|
||||
module = imp.load_module(fileName, file, pathname, description)
|
||||
spec = importlib.util.spec_from_file_location(fileName, filePath)
|
||||
if spec is None or spec.loader is None:
|
||||
raise ImportError
|
||||
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return True
|
||||
except Exception:
|
||||
print('failed to load %s'%fileName)
|
||||
print(f'failed to load {fileName}')
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Palette for Prototyping
|
||||
"""
|
||||
import os
|
||||
import imp
|
||||
import importlib.util
|
||||
|
||||
|
||||
class ProtoObjs:
|
||||
|
|
@ -15,8 +15,13 @@ class ProtoObjs:
|
|||
def populate(self):
|
||||
moduleName = self.name
|
||||
try:
|
||||
file, pathname, description = imp.find_module(moduleName, [self.dirname])
|
||||
module = imp.load_module(moduleName, file, pathname, description)
|
||||
pathname = self.dirname + self.filename
|
||||
spec = importlib.util.spec_from_file_location(moduleName, pathname)
|
||||
if spec is None or spec.loader is None:
|
||||
raise ImportError
|
||||
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
self.data = module.protoData
|
||||
except Exception:
|
||||
print(f"{self.name} doesn't exist")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
"""
|
||||
Palette for Prototyping
|
||||
"""
|
||||
import imp
|
||||
import importlib.util
|
||||
import os, sys
|
||||
|
||||
from .ObjectPaletteBase import ObjectBase, ObjectPaletteBase
|
||||
|
||||
|
|
@ -23,8 +24,15 @@ class ProtoPaletteBase(ObjectPaletteBase):
|
|||
def populate(self):
|
||||
moduleName = 'protoPaletteData'
|
||||
try:
|
||||
file, pathname, description = imp.find_module(moduleName, [self.dirname])
|
||||
module = imp.load_module(moduleName, file, pathname, description)
|
||||
pathname = os.path.join(self.dirname, moduleName + ".py")
|
||||
spec = importlib.util.spec_from_file_location(moduleName, pathname)
|
||||
if spec is None or spec.loader is None:
|
||||
raise ImportError
|
||||
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[module_name] = module
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
self.data = module.protoData
|
||||
self.dataStruct = module.protoDataStruct
|
||||
except:
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ public:
|
|||
|
||||
virtual ~CocoaGLGraphicsStateGuardian();
|
||||
|
||||
virtual bool make_current();
|
||||
|
||||
INLINE void lock_context();
|
||||
INLINE void unlock_context();
|
||||
|
||||
|
|
|
|||
|
|
@ -297,6 +297,18 @@ choose_pixel_format(const FrameBufferProperties &properties,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the context is current. May return false if the context cannot
|
||||
* be bound without a window.
|
||||
*/
|
||||
bool CocoaGLGraphicsStateGuardian::
|
||||
make_current() {
|
||||
lock_context();
|
||||
[_context makeCurrentContext];
|
||||
unlock_context();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the runtime version of OpenGL in use.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1206,6 +1206,7 @@ dispatch_compute(const LVecBase3i &work_groups, const RenderState *state, Graphi
|
|||
nassertv(gsg != nullptr);
|
||||
|
||||
run_on_draw_thread([=] () {
|
||||
gsg->make_current();
|
||||
gsg->push_group_marker(std::string("Compute ") + shader->get_filename(Shader::ST_compute).get_basename());
|
||||
gsg->set_state_and_transform(state, TransformState::make_identity());
|
||||
gsg->dispatch_compute(work_groups[0], work_groups[1], work_groups[2]);
|
||||
|
|
|
|||
|
|
@ -3084,6 +3084,15 @@ reset() {
|
|||
_is_valid = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the context is current. May return false if the context cannot
|
||||
* be bound without a window.
|
||||
*/
|
||||
bool GraphicsStateGuardian::
|
||||
make_current() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simultaneously resets the render state and the transform state.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -421,6 +421,7 @@ public:
|
|||
INLINE bool reset_if_new();
|
||||
INLINE void mark_new();
|
||||
virtual void reset();
|
||||
virtual bool make_current();
|
||||
|
||||
INLINE CPT(TransformState) get_external_transform() const;
|
||||
INLINE CPT(TransformState) get_internal_transform() const;
|
||||
|
|
|
|||
|
|
@ -280,12 +280,36 @@ void eglGraphicsStateGuardian::
|
|||
reset() {
|
||||
BaseGraphicsStateGuardian::reset();
|
||||
|
||||
#ifdef OPENGLES
|
||||
_supports_surfaceless = has_extension("GL_OES_surfaceless_context") &&
|
||||
#else
|
||||
_supports_surfaceless =
|
||||
#endif
|
||||
has_extension("EGL_KHR_surfaceless_context");
|
||||
|
||||
if (_gl_renderer == "Software Rasterizer") {
|
||||
_fbprops.set_force_software(1);
|
||||
_fbprops.set_force_hardware(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the context is current. May return false if the context cannot
|
||||
* be bound without a window.
|
||||
*/
|
||||
bool eglGraphicsStateGuardian::
|
||||
make_current() {
|
||||
if (eglGetCurrentContext() == _context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_supports_surfaceless) {
|
||||
return eglMakeCurrent(_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, _context) != EGL_FALSE;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the runtime GLX version number is at least the indicated
|
||||
* value, false otherwise.
|
||||
|
|
@ -377,3 +401,12 @@ void *eglGraphicsStateGuardian::
|
|||
do_get_extension_func(const char *name) {
|
||||
return (void *)eglGetProcAddress(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this implementation may support Cg shaders.
|
||||
*/
|
||||
bool eglGraphicsStateGuardian::
|
||||
may_support_cg_shaders() {
|
||||
// Never supported under EGL as CgGL is hard-wired to use GLX functions.
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ public:
|
|||
virtual ~eglGraphicsStateGuardian();
|
||||
|
||||
virtual void reset();
|
||||
virtual bool make_current();
|
||||
|
||||
bool egl_is_at_least_version(int major_version, int minor_version) const;
|
||||
|
||||
|
|
@ -60,6 +61,7 @@ public:
|
|||
#endif
|
||||
EGLConfig _fbconfig;
|
||||
FrameBufferProperties _fbprops;
|
||||
bool _supports_surfaceless = false;
|
||||
|
||||
protected:
|
||||
virtual void gl_flush() const;
|
||||
|
|
@ -68,6 +70,7 @@ protected:
|
|||
virtual void query_gl_version();
|
||||
virtual void get_extra_extensions();
|
||||
virtual void *do_get_extension_func(const char *name);
|
||||
virtual bool may_support_cg_shaders();
|
||||
|
||||
private:
|
||||
int _egl_version_major, _egl_version_minor;
|
||||
|
|
|
|||
|
|
@ -2059,7 +2059,8 @@ reset() {
|
|||
// Check for support for other types of shaders that can be used by Cg.
|
||||
_supports_basic_shaders = false;
|
||||
#if defined(HAVE_CG) && !defined(OPENGLES)
|
||||
if (has_extension("GL_ARB_vertex_program") &&
|
||||
if (may_support_cg_shaders() &&
|
||||
has_extension("GL_ARB_vertex_program") &&
|
||||
has_extension("GL_ARB_fragment_program")) {
|
||||
_supports_basic_shaders = true;
|
||||
_shader_caps._active_vprofile = (int)CG_PROFILE_ARBVP1;
|
||||
|
|
@ -3997,8 +3998,8 @@ reset() {
|
|||
}
|
||||
_auto_detect_shader_model = _shader_model;
|
||||
|
||||
if (GLCAT.is_debug()) {
|
||||
#ifdef HAVE_CG
|
||||
if (GLCAT.is_debug() && may_support_cg_shaders()) {
|
||||
#if CG_VERSION_NUM >= 2200
|
||||
GLCAT.debug() << "Supported Cg profiles:\n";
|
||||
int num_profiles = cgGetNumSupportedProfiles();
|
||||
|
|
@ -4036,8 +4037,10 @@ reset() {
|
|||
GLCAT.debug()
|
||||
<< "Cg active geometry profile = "
|
||||
<< cgGetProfileString((CGprofile)_shader_caps._active_gprofile) << "\n";
|
||||
}
|
||||
#endif // HAVE_CG
|
||||
|
||||
if (GLCAT.is_debug()) {
|
||||
GLCAT.debug() << "shader model = " << _shader_model << "\n";
|
||||
}
|
||||
#endif // !OPENGLES
|
||||
|
|
@ -7027,6 +7030,22 @@ prepare_shader(Shader *se) {
|
|||
void CLP(GraphicsStateGuardian)::
|
||||
release_shader(ShaderContext *sc) {
|
||||
#ifndef OPENGLES_1
|
||||
if (_vertex_array_shader_context == sc) {
|
||||
_vertex_array_shader = nullptr;
|
||||
_vertex_array_shader_context = nullptr;
|
||||
}
|
||||
|
||||
if (_texture_binding_shader_context == sc) {
|
||||
_texture_binding_shader = nullptr;
|
||||
_texture_binding_shader_context = nullptr;
|
||||
}
|
||||
|
||||
if (_current_shader_context == sc) {
|
||||
sc->unbind();
|
||||
_current_shader = nullptr;
|
||||
_current_shader_context = nullptr;
|
||||
}
|
||||
|
||||
if (sc->is_of_type(CLP(ShaderContext)::get_class_type())) {
|
||||
((CLP(ShaderContext) *)sc)->release_resources();
|
||||
}
|
||||
|
|
@ -7035,7 +7054,7 @@ release_shader(ShaderContext *sc) {
|
|||
((CLP(CgShaderContext) *)sc)->release_resources();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif // !OPENGLES_1
|
||||
|
||||
delete sc;
|
||||
}
|
||||
|
|
@ -10236,6 +10255,18 @@ do_get_extension_func(const char *) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this implementation may support Cg shaders.
|
||||
*/
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
may_support_cg_shaders() {
|
||||
#if defined(HAVE_CG) && !defined(OPENGLES)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the glDrawBuffer to render into the buffer indicated by the
|
||||
* RenderBuffer object. This only sets up the color and aux bits; it does not
|
||||
|
|
|
|||
|
|
@ -525,6 +525,7 @@ protected:
|
|||
INLINE bool is_at_least_gles_version(int major_version, int minor_version) const;
|
||||
void *get_extension_func(const char *name);
|
||||
virtual void *do_get_extension_func(const char *name);
|
||||
virtual bool may_support_cg_shaders();
|
||||
|
||||
virtual void reissue_transforms();
|
||||
|
||||
|
|
|
|||
|
|
@ -413,7 +413,8 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
|
|||
_glgsg->report_my_gl_errors();
|
||||
|
||||
// Restore the active shader.
|
||||
if (_glgsg->_current_shader_context == nullptr) {
|
||||
if (_glgsg->_current_shader_context == nullptr ||
|
||||
!_glgsg->_current_shader_context->valid()) {
|
||||
_glgsg->_glUseProgram(0);
|
||||
} else {
|
||||
_glgsg->_current_shader_context->bind(_glgsg);
|
||||
|
|
@ -2185,7 +2186,7 @@ release_resources() {
|
|||
*/
|
||||
bool CLP(ShaderContext)::
|
||||
valid() {
|
||||
if (_shader->get_error_flag()) {
|
||||
if (_shader == nullptr || _shader->get_error_flag()) {
|
||||
return false;
|
||||
}
|
||||
return (_glsl_program != 0);
|
||||
|
|
@ -2197,6 +2198,8 @@ valid() {
|
|||
*/
|
||||
void CLP(ShaderContext)::
|
||||
bind(GraphicsStateGuardian *gsg) {
|
||||
nassertv(_shader != nullptr);
|
||||
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)gsg;
|
||||
_glgsg = glgsg;
|
||||
|
||||
|
|
@ -3314,6 +3317,9 @@ glsl_compile_and_link() {
|
|||
_glsl_shaders.clear();
|
||||
_glsl_program = _glgsg->_glCreateProgram();
|
||||
if (!_glsl_program) {
|
||||
// If this happens, check whether you have a current GL context
|
||||
GLCAT.error()
|
||||
<< "Failed to create GLSL program object\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -434,6 +434,19 @@ choose_pixel_format(const FrameBufferProperties &properties,
|
|||
_context_has_pbuffer = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the context is current. May return false if the context cannot
|
||||
* be bound without a window.
|
||||
*/
|
||||
bool glxGraphicsStateGuardian::
|
||||
make_current() {
|
||||
if (glXGetCurrentContext() == _context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the runtime GLX version number is at least the indicated
|
||||
* value, false otherwise.
|
||||
|
|
@ -572,6 +585,18 @@ do_get_extension_func(const char *name) {
|
|||
return PosixGraphicsStateGuardian::do_get_extension_func(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this implementation may support Cg shaders.
|
||||
*/
|
||||
bool glxGraphicsStateGuardian::
|
||||
may_support_cg_shaders() {
|
||||
#ifdef HAVE_CG
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the GLX extension pointers.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ public:
|
|||
|
||||
virtual ~glxGraphicsStateGuardian();
|
||||
|
||||
virtual bool make_current();
|
||||
|
||||
bool glx_is_at_least_version(int major_version, int minor_version) const;
|
||||
|
||||
GLXContext _share_context;
|
||||
|
|
@ -128,6 +130,7 @@ protected:
|
|||
virtual void query_gl_version();
|
||||
virtual void get_extra_extensions();
|
||||
virtual void *do_get_extension_func(const char *name);
|
||||
virtual bool may_support_cg_shaders();
|
||||
|
||||
private:
|
||||
void query_glx_extensions();
|
||||
|
|
|
|||
|
|
@ -131,6 +131,18 @@ compare_to_impl(const RenderAttrib *other) const {
|
|||
return (int)_b - (int)ta->_b;
|
||||
}
|
||||
|
||||
if (_alpha_mode != ta->_alpha_mode) {
|
||||
return (int)_alpha_mode - (int)ta->_alpha_mode;
|
||||
}
|
||||
|
||||
if (_alpha_a != ta->_alpha_a) {
|
||||
return (int)_alpha_a - (int)ta->_alpha_a;
|
||||
}
|
||||
|
||||
if (_alpha_b != ta->_alpha_b) {
|
||||
return (int)_alpha_b - (int)ta->_alpha_b;
|
||||
}
|
||||
|
||||
return _color.compare_to(ta->_color);
|
||||
}
|
||||
|
||||
|
|
@ -146,6 +158,9 @@ get_hash_impl() const {
|
|||
hash = int_hash::add_hash(hash, (int)_mode);
|
||||
hash = int_hash::add_hash(hash, (int)_a);
|
||||
hash = int_hash::add_hash(hash, (int)_b);
|
||||
hash = int_hash::add_hash(hash, (int)_alpha_mode);
|
||||
hash = int_hash::add_hash(hash, (int)_alpha_a);
|
||||
hash = int_hash::add_hash(hash, (int)_alpha_b);
|
||||
hash = _color.add_hash(hash);
|
||||
|
||||
return hash;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ void gl_transform_to_viewport(GLContext *c,GLVertex *v)
|
|||
+ c->viewport.trans.v[2] );
|
||||
|
||||
// Add the z-bias, if any. Be careful not to overflow the int.
|
||||
int z = v->zp.z + (c->zbias << (ZB_POINT_Z_FRAC_BITS + 4));
|
||||
int z = v->zp.z + c->zbias;
|
||||
if (z < v->zp.z && c->zbias > 0) {
|
||||
v->zp.z = INT_MAX;
|
||||
} else if (z > v->zp.z && c->zbias < 0) {
|
||||
|
|
|
|||
|
|
@ -24,10 +24,50 @@ FNAME(store_pixel) (ZBuffer *zb, PIXEL &result, int r, int g, int b, int a) {
|
|||
unsigned int fb = PIXEL_B(result);
|
||||
unsigned int fa = PIXEL_A(result);
|
||||
|
||||
r = STORE_PIXEL_0(fr, ((unsigned int)r * OP_A(fr, r) >> 16) + ((unsigned int)fr * OP_B(fr, r) >> 16));
|
||||
g = STORE_PIXEL_1(fg, ((unsigned int)g * OP_A(fg, g) >> 16) + ((unsigned int)fg * OP_B(fg, g) >> 16));
|
||||
b = STORE_PIXEL_2(fb, ((unsigned int)b * OP_A(fb, b) >> 16) + ((unsigned int)fb * OP_B(fb, b) >> 16));
|
||||
a = STORE_PIXEL_3(fa, ((unsigned int)a * OP_A(fa, a) >> 16) + ((unsigned int)fa * OP_B(fa, a) >> 16));
|
||||
#if HAVE_R
|
||||
unsigned int r_ops[] = {0, (unsigned int)r, fr, (unsigned int)a, fa};
|
||||
unsigned int r_opa = r_ops[zb->blenda.op_rgb] ^ zb->blenda.xor_r;
|
||||
unsigned int r_opb = r_ops[zb->blendb.op_rgb] ^ zb->blendb.xor_r;
|
||||
(void)r_opa;
|
||||
(void)r_opb;
|
||||
r = MODE_RGB(r, r_opa, fr, r_opb);
|
||||
#else
|
||||
r = fr;
|
||||
#endif
|
||||
|
||||
#if HAVE_G
|
||||
unsigned int g_ops[] = {0, (unsigned int)g, fg, (unsigned int)a, fa};
|
||||
unsigned int g_opa = g_ops[zb->blenda.op_rgb] ^ zb->blenda.xor_g;
|
||||
unsigned int g_opb = g_ops[zb->blendb.op_rgb] ^ zb->blendb.xor_g;
|
||||
(void)g_opa;
|
||||
(void)g_opb;
|
||||
g = MODE_RGB(g, g_opa, fg, g_opb);
|
||||
#else
|
||||
g = fg;
|
||||
#endif
|
||||
|
||||
#if HAVE_B
|
||||
unsigned int b_ops[] = {0, (unsigned int)b, fb, (unsigned int)a, fa};
|
||||
unsigned int b_opa = b_ops[zb->blenda.op_rgb] ^ zb->blenda.xor_b;
|
||||
unsigned int b_opb = b_ops[zb->blendb.op_rgb] ^ zb->blendb.xor_b;
|
||||
(void)b_opa;
|
||||
(void)b_opb;
|
||||
b = MODE_RGB(b, b_opa, fb, b_opb);
|
||||
#else
|
||||
b = fb;
|
||||
#endif
|
||||
|
||||
#if HAVE_A
|
||||
unsigned int a_ops[] = {0, (unsigned int)a, fa, (unsigned int)a, fa};
|
||||
unsigned int a_opa = a_ops[zb->blenda.op_alpha] ^ zb->blenda.xor_a;
|
||||
unsigned int a_opb = a_ops[zb->blendb.op_alpha] ^ zb->blendb.xor_a;
|
||||
(void)a_opa;
|
||||
(void)a_opb;
|
||||
a = MODE_ALPHA(a, a_opa, fa, a_opb);
|
||||
#else
|
||||
a = fa;
|
||||
#endif
|
||||
|
||||
result = RGBA_TO_PIXEL(r, g, b, a);
|
||||
}
|
||||
|
||||
|
|
@ -36,25 +76,67 @@ FNAME(store_pixel) (ZBuffer *zb, PIXEL &result, int r, int g, int b, int a) {
|
|||
|
||||
static void
|
||||
FNAME_S(store_pixel) (ZBuffer *zb, PIXEL &result, int r, int g, int b, int a) {
|
||||
#if HAVE_R || HAVE_G || HAVE_B || HAVE_A
|
||||
unsigned int fr = PIXEL_SR(result);
|
||||
unsigned int fg = PIXEL_SG(result);
|
||||
unsigned int fb = PIXEL_SB(result);
|
||||
unsigned int fa = PIXEL_A(result);
|
||||
|
||||
r = STORE_PIXEL_0(fr, ((unsigned int)r * OP_A(fr, r) >> 16) + ((unsigned int)fr * OP_B(fr, r) >> 16));
|
||||
g = STORE_PIXEL_1(fg, ((unsigned int)g * OP_A(fg, g) >> 16) + ((unsigned int)fg * OP_B(fg, g) >> 16));
|
||||
b = STORE_PIXEL_2(fb, ((unsigned int)b * OP_A(fb, b) >> 16) + ((unsigned int)fb * OP_B(fb, b) >> 16));
|
||||
a = STORE_PIXEL_3(fa, ((unsigned int)a * OP_A(fa, a) >> 16) + ((unsigned int)fa * OP_B(fa, a) >> 16));
|
||||
#if HAVE_R
|
||||
unsigned int r_ops[] = {0, (unsigned int)r, fr, (unsigned int)a, fa};
|
||||
unsigned int r_opa = r_ops[zb->blenda.op_rgb] ^ zb->blenda.xor_r;
|
||||
unsigned int r_opb = r_ops[zb->blendb.op_rgb] ^ zb->blendb.xor_r;
|
||||
(void)r_opa;
|
||||
(void)r_opb;
|
||||
r = MODE_RGB(r, r_opa, fr, r_opb);
|
||||
#else
|
||||
r = fr;
|
||||
#endif
|
||||
|
||||
#if HAVE_G
|
||||
unsigned int g_ops[] = {0, (unsigned int)g, fg, (unsigned int)a, fa};
|
||||
unsigned int g_opa = g_ops[zb->blenda.op_rgb] ^ zb->blenda.xor_g;
|
||||
unsigned int g_opb = g_ops[zb->blendb.op_rgb] ^ zb->blendb.xor_g;
|
||||
(void)g_opa;
|
||||
(void)g_opb;
|
||||
g = MODE_RGB(g, g_opa, fg, g_opb);
|
||||
#else
|
||||
g = fg;
|
||||
#endif
|
||||
|
||||
#if HAVE_B
|
||||
unsigned int b_ops[] = {0, (unsigned int)b, fb, (unsigned int)a, fa};
|
||||
unsigned int b_opa = b_ops[zb->blenda.op_rgb] ^ zb->blenda.xor_b;
|
||||
unsigned int b_opb = b_ops[zb->blendb.op_rgb] ^ zb->blendb.xor_b;
|
||||
(void)b_opa;
|
||||
(void)b_opb;
|
||||
b = MODE_RGB(b, b_opa, fb, b_opb);
|
||||
#else
|
||||
b = fb;
|
||||
#endif
|
||||
|
||||
#if HAVE_A
|
||||
unsigned int a_ops[] = {0, (unsigned int)a, fa, (unsigned int)a, fa};
|
||||
unsigned int a_opa = a_ops[zb->blenda.op_alpha] ^ zb->blenda.xor_a;
|
||||
unsigned int a_opb = a_ops[zb->blendb.op_alpha] ^ zb->blendb.xor_a;
|
||||
(void)a_opa;
|
||||
(void)a_opb;
|
||||
a = MODE_ALPHA(a, a_opa, fa, a_opb);
|
||||
#else
|
||||
a = fa;
|
||||
#endif
|
||||
|
||||
result = SRGBA_TO_PIXEL(r, g, b, a);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef FNAME_S
|
||||
#endif
|
||||
|
||||
#undef FNAME
|
||||
#undef OP_A
|
||||
#undef OP_B
|
||||
#undef STORE_PIXEL_0
|
||||
#undef STORE_PIXEL_1
|
||||
#undef STORE_PIXEL_2
|
||||
#undef STORE_PIXEL_3
|
||||
#undef MODE_RGB
|
||||
#undef MODE_ALPHA
|
||||
#undef HAVE_R
|
||||
#undef HAVE_G
|
||||
#undef HAVE_B
|
||||
#undef HAVE_A
|
||||
|
|
|
|||
|
|
@ -7,109 +7,83 @@ Each different combination of options is compiled to a different
|
|||
inner-loop store function. The code in tinyGraphicsStateGuardian.cxx
|
||||
will select the appropriate function pointer at draw time. """
|
||||
|
||||
Operands = [
|
||||
'zero', 'one',
|
||||
'icolor', 'micolor',
|
||||
'fcolor', 'mfcolor',
|
||||
'ialpha', 'mialpha',
|
||||
'falpha', 'mfalpha',
|
||||
'ccolor', 'mccolor',
|
||||
'calpha', 'mcalpha',
|
||||
Modes = [
|
||||
'add',
|
||||
'min',
|
||||
'max',
|
||||
]
|
||||
|
||||
CodeTable = {
|
||||
'zero' : '0',
|
||||
'one' : '0x10000',
|
||||
'icolor' : 'i',
|
||||
'micolor' : '0xffff - i',
|
||||
'fcolor' : 'f',
|
||||
'mfcolor' : '0xffff - f',
|
||||
'ialpha' : 'a',
|
||||
'mialpha' : '0xffff - a',
|
||||
'falpha' : 'fa',
|
||||
'mfalpha' : '0xffff - fa',
|
||||
'ccolor' : 'zb->blend_ ## i',
|
||||
'mccolor' : '0xffff - zb->blend_ ## i',
|
||||
'calpha' : 'zb->blend_a',
|
||||
'mcalpha' : '0xffff - zb->blend_a',
|
||||
}
|
||||
# We handle alpha write as a special "off" mode, reducing redundancy.
|
||||
AlphaModes = Modes + ['off']
|
||||
|
||||
CodeTable = {
|
||||
'add': 'STORE_PIX_CLAMP(((unsigned int)c * c_opa >> 16) + ((unsigned int)fc * c_opb >> 16))',
|
||||
'min': 'std::min((unsigned int)c, (unsigned int)fc)',
|
||||
'max': 'std::max((unsigned int)c, (unsigned int)fc)',
|
||||
'off': '(unsigned int)fc',
|
||||
}
|
||||
|
||||
bitnames = 'rgba'
|
||||
|
||||
def getFname(op_a, op_b, mask):
|
||||
def get_fname(rgb_mode, alpha_mode, mask):
|
||||
maskname = ''
|
||||
for b in range(4):
|
||||
for b in range(3):
|
||||
if (mask & (1 << b)):
|
||||
maskname += bitnames[b]
|
||||
else:
|
||||
maskname += '0'
|
||||
return 'store_pixel_%s_%s_%s' % (op_a, op_b, maskname)
|
||||
return 'store_pixel_%s_%s_%s' % (rgb_mode, alpha_mode, maskname)
|
||||
|
||||
# We write the code that actually instantiates the various
|
||||
# pixel-storing functions to store_pixel_code.h.
|
||||
code = open('store_pixel_code.h', 'wb')
|
||||
print >> code, '/* This file is generated code--do not edit. See store_pixel.py. */'
|
||||
print >> code, ''
|
||||
code = open('store_pixel_code.h', 'w')
|
||||
print('/* This file is generated code--do not edit. See store_pixel.py. */', file=code)
|
||||
print('', file=code)
|
||||
|
||||
# The external reference for the table containing the above function
|
||||
# pointers gets written here.
|
||||
table = open('store_pixel_table.h', 'wb')
|
||||
print >> table, '/* This file is generated code--do not edit. See store_pixel.py. */'
|
||||
print >> table, ''
|
||||
table = open('store_pixel_table.h', 'w')
|
||||
print('/* This file is generated code--do not edit. See store_pixel.py. */', file=table)
|
||||
print('', file=table)
|
||||
|
||||
for op_a in Operands:
|
||||
for op_b in Operands:
|
||||
for mask in range(0, 16):
|
||||
fname = getFname(op_a, op_b, mask)
|
||||
print >> code, '#define FNAME(name) %s' % (fname)
|
||||
if mask & (1 | 2 | 3):
|
||||
print >> code, '#define FNAME_S(name) %s_s' % (fname)
|
||||
for rgb_mode in Modes:
|
||||
for alpha_mode in AlphaModes:
|
||||
for mask in range(0, 8):
|
||||
fname = get_fname(rgb_mode, alpha_mode, mask)
|
||||
print('#define FNAME(name) %s' % (fname), file=code)
|
||||
if mask != 0:
|
||||
print('#define FNAME_S(name) %s_s' % (fname), file=code)
|
||||
|
||||
print >> code, '#define OP_A(f, i) ((unsigned int)(%s))' % (CodeTable[op_a])
|
||||
print >> code, '#define OP_B(f, i) ((unsigned int)(%s))' % (CodeTable[op_b])
|
||||
for b in range(0, 4):
|
||||
print('#define MODE_RGB(c, c_opa, fc, c_opb) %s' % (CodeTable[rgb_mode]), file=code)
|
||||
print('#define MODE_ALPHA(c, c_opa, fc, c_opb) %s' % (CodeTable[alpha_mode]), file=code)
|
||||
for b in range(0, 3):
|
||||
if (mask & (1 << b)):
|
||||
print >> code, "#define STORE_PIXEL_%s(fr, r) STORE_PIX_CLAMP(r)" % (b)
|
||||
else:
|
||||
print >> code, "#define STORE_PIXEL_%s(fr, r) (fr)" % (b)
|
||||
print >> code, '#include "store_pixel.h"'
|
||||
print >> code, ''
|
||||
print("#define HAVE_%s 1" % (bitnames[b].upper()), file=code)
|
||||
if alpha_mode != 'off':
|
||||
print("#define HAVE_A 1", file=code)
|
||||
print('#include "store_pixel.h"', file=code)
|
||||
print('', file=code)
|
||||
|
||||
|
||||
# Now, generate the table of function pointers.
|
||||
arraySize = '[%s][%s][16]' % (len(Operands), len(Operands))
|
||||
arraySize = '[%s][%s][8][2]' % (len(Modes), len(AlphaModes))
|
||||
|
||||
print >> table, 'extern const ZB_storePixelFunc store_pixel_funcs%s;' % (arraySize)
|
||||
print >> code, 'const ZB_storePixelFunc store_pixel_funcs%s = {' % (arraySize)
|
||||
print('extern const ZB_storePixelFunc store_pixel_funcs%s;' % (arraySize), file=table)
|
||||
print('const ZB_storePixelFunc store_pixel_funcs%s = {' % (arraySize), file=code)
|
||||
|
||||
for op_a in Operands:
|
||||
print >> code, ' {'
|
||||
for op_b in Operands:
|
||||
print >> code, ' {'
|
||||
for mask in range(0, 16):
|
||||
fname = getFname(op_a, op_b, mask)
|
||||
print >> code, ' %s,' % (fname)
|
||||
print >> code, ' },'
|
||||
print >> code, ' },'
|
||||
print >> code, '};'
|
||||
|
||||
print >> code
|
||||
|
||||
# Now do this again, but for the sRGB function pointers.
|
||||
print >> table, 'extern const ZB_storePixelFunc store_pixel_funcs_sRGB%s;' % (arraySize)
|
||||
print >> code, 'const ZB_storePixelFunc store_pixel_funcs_sRGB%s = {' % (arraySize)
|
||||
|
||||
for op_a in Operands:
|
||||
print >> code, ' {'
|
||||
for op_b in Operands:
|
||||
print >> code, ' {'
|
||||
for mask in range(0, 16):
|
||||
fname = getFname(op_a, op_b, mask)
|
||||
if mask & (1 | 2 | 3):
|
||||
print >> code, ' %s_s,' % (fname)
|
||||
for rgb_mode in Modes:
|
||||
print(' {', file=code)
|
||||
for alpha_mode in AlphaModes:
|
||||
print(' {', file=code)
|
||||
for mask in range(0, 8):
|
||||
fname = get_fname(rgb_mode, alpha_mode, mask)
|
||||
if mask != 0:
|
||||
fname_s = fname + '_s'
|
||||
else:
|
||||
print >> code, ' %s,' % (fname)
|
||||
print >> code, ' },'
|
||||
print >> code, ' },'
|
||||
print >> code, '};'
|
||||
fname_s = fname
|
||||
print(' {%s, %s},' % (fname, fname_s), file=code)
|
||||
print(' },', file=code)
|
||||
print(' },', file=code)
|
||||
print('};', file=code)
|
||||
|
||||
print('', file=code)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,4 +1,3 @@
|
|||
/* This file is generated code--do not edit. See store_pixel.py. */
|
||||
|
||||
extern const ZB_storePixelFunc store_pixel_funcs[14][14][16];
|
||||
extern const ZB_storePixelFunc store_pixel_funcs_sRGB[14][14][16];
|
||||
extern const ZB_storePixelFunc store_pixel_funcs[3][4][8][2];
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "directionalLight.h"
|
||||
#include "spotlight.h"
|
||||
#include "depthWriteAttrib.h"
|
||||
#include "depthBiasAttrib.h"
|
||||
#include "depthOffsetAttrib.h"
|
||||
#include "colorWriteAttrib.h"
|
||||
#include "alphaTestAttrib.h"
|
||||
|
|
@ -94,6 +95,7 @@ reset() {
|
|||
_inv_state_mask.clear_bit(ColorAttrib::get_class_slot());
|
||||
_inv_state_mask.clear_bit(ColorScaleAttrib::get_class_slot());
|
||||
_inv_state_mask.clear_bit(CullFaceAttrib::get_class_slot());
|
||||
_inv_state_mask.clear_bit(DepthBiasAttrib::get_class_slot());
|
||||
_inv_state_mask.clear_bit(DepthOffsetAttrib::get_class_slot());
|
||||
_inv_state_mask.clear_bit(RenderModeAttrib::get_class_slot());
|
||||
_inv_state_mask.clear_bit(RescaleNormalAttrib::get_class_slot());
|
||||
|
|
@ -229,10 +231,9 @@ clear(DrawableRegion *clearable) {
|
|||
}
|
||||
|
||||
bool clear_z = false;
|
||||
int z = 0;
|
||||
ZPOINT z = 0;
|
||||
if (clearable->get_clear_depth_active()) {
|
||||
// We ignore the specified depth clear value, since we don't support
|
||||
// alternate depth compare functions anyway.
|
||||
z = (ZPOINT)((1.0f - clearable->get_clear_depth()) * (1 << ZB_Z_BITS));
|
||||
clear_z = true;
|
||||
}
|
||||
|
||||
|
|
@ -280,6 +281,18 @@ prepare_display_region(DisplayRegionPipelineReader *dr) {
|
|||
_c->viewport.ysize = ysize;
|
||||
set_scissor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
|
||||
PN_stdfloat dr_near = 0.0f;
|
||||
PN_stdfloat dr_far = 1.0f;
|
||||
dr->get_depth_range(dr_near, dr_far);
|
||||
|
||||
if (dr_near == 0.0f && dr_far == 1.0f) {
|
||||
_c->has_zrange = false;
|
||||
} else {
|
||||
_c->has_zrange = true;
|
||||
_c->zmin = dr_near;
|
||||
_c->zrange = dr_far - dr_near;
|
||||
}
|
||||
|
||||
nassertv(xmin >= 0 && xmin < _c->zb->xsize &&
|
||||
ymin >= 0 && ymin < _c->zb->ysize &&
|
||||
xmin + xsize >= 0 && xmin + xsize <= _c->zb->xsize &&
|
||||
|
|
@ -757,96 +770,100 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
|
|||
|
||||
int color_write_state = 0; // cstore
|
||||
|
||||
const ColorWriteAttrib *target_color_write = DCAST(ColorWriteAttrib, _target_rs->get_attrib_def(ColorWriteAttrib::get_class_slot()));
|
||||
const ColorWriteAttrib *target_color_write;
|
||||
_target_rs->get_attrib_def(target_color_write);
|
||||
unsigned int color_channels =
|
||||
target_color_write->get_channels() & _color_write_mask;
|
||||
unsigned int rgb_channels = color_channels & ColorWriteAttrib::C_rgb;
|
||||
|
||||
if (color_channels == ColorWriteAttrib::C_all) {
|
||||
if (srgb_blend) {
|
||||
color_write_state = 4; // csstore
|
||||
} else {
|
||||
color_write_state = 0; // cstore
|
||||
}
|
||||
} else {
|
||||
// Implement a color mask.
|
||||
int op_a = get_color_blend_op(ColorBlendAttrib::O_one);
|
||||
int op_b = get_color_blend_op(ColorBlendAttrib::O_zero);
|
||||
|
||||
if (srgb_blend) {
|
||||
_c->zb->store_pix_func = store_pixel_funcs_sRGB[op_a][op_b][color_channels];
|
||||
} else {
|
||||
_c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
|
||||
}
|
||||
color_write_state = 2; // cgeneral
|
||||
}
|
||||
|
||||
const TransparencyAttrib *target_transparency = DCAST(TransparencyAttrib, _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot()));
|
||||
switch (target_transparency->get_mode()) {
|
||||
case TransparencyAttrib::M_alpha:
|
||||
case TransparencyAttrib::M_dual:
|
||||
if (color_channels == ColorWriteAttrib::C_all) {
|
||||
if (srgb_blend) {
|
||||
color_write_state = 5; // csblend
|
||||
} else {
|
||||
color_write_state = 1; // cblend
|
||||
}
|
||||
} else {
|
||||
// Implement a color mask, with alpha blending.
|
||||
int op_a = get_color_blend_op(ColorBlendAttrib::O_incoming_alpha);
|
||||
int op_b = get_color_blend_op(ColorBlendAttrib::O_one_minus_incoming_alpha);
|
||||
|
||||
if (srgb_blend) {
|
||||
_c->zb->store_pix_func = store_pixel_funcs_sRGB[op_a][op_b][color_channels];
|
||||
} else {
|
||||
_c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
|
||||
}
|
||||
color_write_state = 2; // cgeneral
|
||||
}
|
||||
break;
|
||||
|
||||
case TransparencyAttrib::M_premultiplied_alpha:
|
||||
{
|
||||
// Implement a color mask, with pre-multiplied alpha blending.
|
||||
int op_a = get_color_blend_op(ColorBlendAttrib::O_one);
|
||||
int op_b = get_color_blend_op(ColorBlendAttrib::O_one_minus_incoming_alpha);
|
||||
|
||||
if (srgb_blend) {
|
||||
_c->zb->store_pix_func = store_pixel_funcs_sRGB[op_a][op_b][color_channels];
|
||||
} else {
|
||||
_c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
|
||||
}
|
||||
color_write_state = 2; // cgeneral
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const ColorBlendAttrib *target_color_blend = DCAST(ColorBlendAttrib, _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot()));
|
||||
if (target_color_blend->get_mode() == ColorBlendAttrib::M_add) {
|
||||
// If we have a color blend set that we can support, it overrides the
|
||||
// transparency set.
|
||||
LColor c = target_color_blend->get_color();
|
||||
_c->zb->blend_r = (int)(c[0] * ZB_POINT_RED_MAX);
|
||||
_c->zb->blend_g = (int)(c[1] * ZB_POINT_GREEN_MAX);
|
||||
_c->zb->blend_b = (int)(c[2] * ZB_POINT_BLUE_MAX);
|
||||
_c->zb->blend_a = (int)(c[3] * ZB_POINT_ALPHA_MAX);
|
||||
|
||||
int op_a = get_color_blend_op(target_color_blend->get_operand_a());
|
||||
int op_b = get_color_blend_op(target_color_blend->get_operand_b());
|
||||
|
||||
if (srgb_blend) {
|
||||
_c->zb->store_pix_func = store_pixel_funcs_sRGB[op_a][op_b][color_channels];
|
||||
} else {
|
||||
_c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
|
||||
}
|
||||
color_write_state = 2; // cgeneral
|
||||
}
|
||||
const ColorBlendAttrib *target_color_blend;
|
||||
_target_rs->get_attrib_def(target_color_blend);
|
||||
|
||||
if (color_channels == ColorWriteAttrib::C_off) {
|
||||
color_write_state = 3; // coff
|
||||
}
|
||||
else if (target_color_blend->get_mode() != ColorBlendAttrib::M_none) {
|
||||
// If we have a color blend set that we can support, it overrides the
|
||||
// transparency set.
|
||||
|
||||
int rgb_mode = get_color_blend_mode(target_color_blend->get_mode());
|
||||
int alpha_mode;
|
||||
if (color_channels & ColorWriteAttrib::C_alpha) {
|
||||
alpha_mode = get_color_blend_mode(target_color_blend->get_alpha_mode());
|
||||
} else {
|
||||
// Disabled alpha write is encoded as a separate alpha mode, to cut down
|
||||
// on redundancy in the store_pixel table.
|
||||
alpha_mode = 3;
|
||||
}
|
||||
|
||||
LColor c = target_color_blend->get_color();
|
||||
unsigned int cr = (int)(c[0] * ZB_POINT_RED_MAX);
|
||||
unsigned int cg = (int)(c[1] * ZB_POINT_GREEN_MAX);
|
||||
unsigned int cb = (int)(c[2] * ZB_POINT_BLUE_MAX);
|
||||
unsigned int ca = (int)(c[3] * ZB_POINT_ALPHA_MAX);
|
||||
|
||||
setup_color_blend(_c->zb->blenda, target_color_blend->get_operand_a(),
|
||||
target_color_blend->get_alpha_operand_a(),
|
||||
cr, cg, cb, ca);
|
||||
setup_color_blend(_c->zb->blendb, target_color_blend->get_operand_b(),
|
||||
target_color_blend->get_alpha_operand_b(),
|
||||
cr, cg, cb, ca);
|
||||
|
||||
_c->zb->store_pix_func = store_pixel_funcs[rgb_mode][alpha_mode][rgb_channels][srgb_blend];
|
||||
color_write_state = 2; // cgeneral
|
||||
}
|
||||
else {
|
||||
const TransparencyAttrib *target_transparency;
|
||||
_target_rs->get_attrib_def(target_transparency);
|
||||
|
||||
switch (target_transparency->get_mode()) {
|
||||
case TransparencyAttrib::M_alpha:
|
||||
case TransparencyAttrib::M_dual:
|
||||
if (color_channels == ColorWriteAttrib::C_all) {
|
||||
if (srgb_blend) {
|
||||
color_write_state = 5; // csblend
|
||||
} else {
|
||||
color_write_state = 1; // cblend
|
||||
}
|
||||
} else {
|
||||
// Implement a color mask, with alpha blending.
|
||||
setup_color_blend(_c->zb->blenda, ColorBlendAttrib::O_incoming_alpha, ColorBlendAttrib::O_one);
|
||||
setup_color_blend(_c->zb->blendb, ColorBlendAttrib::O_one_minus_incoming_alpha, ColorBlendAttrib::O_one_minus_incoming_alpha);
|
||||
int alpha_mode = (color_channels & ColorWriteAttrib::C_alpha) ? 0 : 3;
|
||||
_c->zb->store_pix_func = store_pixel_funcs[0][alpha_mode][rgb_channels][srgb_blend];
|
||||
color_write_state = 2; // cgeneral
|
||||
}
|
||||
break;
|
||||
|
||||
case TransparencyAttrib::M_premultiplied_alpha:
|
||||
{
|
||||
// Implement a color mask, with pre-multiplied alpha blending.
|
||||
setup_color_blend(_c->zb->blenda, ColorBlendAttrib::O_one, ColorBlendAttrib::O_one);
|
||||
setup_color_blend(_c->zb->blendb, ColorBlendAttrib::O_one_minus_incoming_alpha, ColorBlendAttrib::O_one_minus_incoming_alpha);
|
||||
int alpha_mode = (color_channels & ColorWriteAttrib::C_alpha) ? 0 : 3;
|
||||
_c->zb->store_pix_func = store_pixel_funcs[0][alpha_mode][rgb_channels][srgb_blend];
|
||||
color_write_state = 2; // cgeneral
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (color_channels == ColorWriteAttrib::C_all) {
|
||||
if (srgb_blend) {
|
||||
color_write_state = 4; // csstore
|
||||
} else {
|
||||
color_write_state = 0; // cstore
|
||||
}
|
||||
} else {
|
||||
// Implement a color mask.
|
||||
setup_color_blend(_c->zb->blenda, ColorBlendAttrib::O_one, ColorBlendAttrib::O_one);
|
||||
setup_color_blend(_c->zb->blendb, ColorBlendAttrib::O_zero, ColorBlendAttrib::O_zero);
|
||||
int alpha_mode = (color_channels & ColorWriteAttrib::C_alpha) ? 0 : 3;
|
||||
_c->zb->store_pix_func = store_pixel_funcs[0][alpha_mode][rgb_channels][srgb_blend];
|
||||
color_write_state = 2; // cgeneral
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int alpha_test_state = 0; // anone
|
||||
const AlphaTestAttrib *target_alpha_test = DCAST(AlphaTestAttrib, _target_rs->get_attrib_def(AlphaTestAttrib::get_class_slot()));
|
||||
|
|
@ -875,7 +892,8 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
|
|||
int depth_test_state = 1; // zless
|
||||
_c->depth_test = 1; // set this for ZB_line
|
||||
const DepthTestAttrib *target_depth_test = DCAST(DepthTestAttrib, _target_rs->get_attrib_def(DepthTestAttrib::get_class_slot()));
|
||||
if (target_depth_test->get_mode() == DepthTestAttrib::M_none) {
|
||||
if (target_depth_test->get_mode() == DepthTestAttrib::M_none ||
|
||||
target_depth_test->get_mode() == DepthTestAttrib::M_always) {
|
||||
depth_test_state = 0; // zless
|
||||
_c->depth_test = 0;
|
||||
}
|
||||
|
|
@ -1415,10 +1433,17 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
|
|||
z_size = 1;
|
||||
}
|
||||
|
||||
Texture::ComponentType component_type = Texture::T_unsigned_byte;
|
||||
Texture::Format format = Texture::F_rgba;
|
||||
if (_current_properties->get_srgb_color()) {
|
||||
format = Texture::F_srgb_alpha;
|
||||
Texture::ComponentType component_type;
|
||||
Texture::Format format;
|
||||
if (rb._buffer_type & RenderBuffer::T_depth) {
|
||||
component_type = Texture::T_unsigned_int;
|
||||
format = Texture::F_depth_component;
|
||||
} else {
|
||||
component_type = Texture::T_unsigned_byte;
|
||||
format = Texture::F_rgba;
|
||||
if (_current_properties->get_srgb_color()) {
|
||||
format = Texture::F_srgb_alpha;
|
||||
}
|
||||
}
|
||||
|
||||
if (tex->get_x_size() != w || tex->get_y_size() != h ||
|
||||
|
|
@ -1445,32 +1470,53 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
|
|||
}
|
||||
}
|
||||
|
||||
PIXEL *ip = (PIXEL *)(image_ptr + image_size);
|
||||
PIXEL *fo = _c->zb->pbuf + xo + yo * _c->zb->linesize / PSZB;
|
||||
for (int y = 0; y < h; ++y) {
|
||||
ip -= w;
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
// On a little-endian machine, we can copy the whole row at a time.
|
||||
memcpy(ip, fo, w * PSZB);
|
||||
#else
|
||||
// On a big-endian machine, we have to reverse the color-component order.
|
||||
const char *source = (const char *)fo;
|
||||
const char *stop = (const char *)fo + w * PSZB;
|
||||
char *dest = (char *)ip;
|
||||
while (source < stop) {
|
||||
char b = source[0];
|
||||
char g = source[1];
|
||||
char r = source[2];
|
||||
char a = source[3];
|
||||
dest[0] = a;
|
||||
dest[1] = r;
|
||||
dest[2] = g;
|
||||
dest[3] = b;
|
||||
dest += 4;
|
||||
source += 4;
|
||||
if (rb._buffer_type & RenderBuffer::T_depth) {
|
||||
size_t dst_stride = tex->get_x_size();
|
||||
unsigned int *dst = (unsigned int *)(image_ptr + image_size);
|
||||
size_t src_stride = _c->zb->xsize;
|
||||
ZPOINT *src = _c->zb->zbuf + xo + src_stride * yo;
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
dst -= dst_stride;
|
||||
for (int x = 0; x < w; ++x) {
|
||||
ZPOINT z = src[x];
|
||||
if (z == 0) {
|
||||
z = 0xFFFFFFFF;
|
||||
} else {
|
||||
z = (1 << ZB_Z_BITS) - z;
|
||||
z = z << (32 - ZB_Z_BITS);
|
||||
}
|
||||
dst[x] = z;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PIXEL *ip = (PIXEL *)(image_ptr + image_size);
|
||||
PIXEL *fo = _c->zb->pbuf + xo + yo * _c->zb->linesize / PSZB;
|
||||
for (int y = 0; y < h; ++y) {
|
||||
ip -= w;
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
// On a little-endian machine, we can copy the whole row at a time.
|
||||
memcpy(ip, fo, w * PSZB);
|
||||
#else
|
||||
// On a big-endian machine, we have to reverse the color-component order.
|
||||
const char *source = (const char *)fo;
|
||||
const char *stop = (const char *)fo + w * PSZB;
|
||||
char *dest = (char *)ip;
|
||||
while (source < stop) {
|
||||
char b = source[0];
|
||||
char g = source[1];
|
||||
char r = source[2];
|
||||
char a = source[3];
|
||||
dest[0] = a;
|
||||
dest[1] = r;
|
||||
dest[2] = g;
|
||||
dest[3] = b;
|
||||
dest += 4;
|
||||
source += 4;
|
||||
}
|
||||
#endif
|
||||
fo += _c->zb->linesize / PSZB;
|
||||
fo += _c->zb->linesize / PSZB;
|
||||
}
|
||||
}
|
||||
|
||||
if (request != nullptr) {
|
||||
|
|
@ -1539,11 +1585,15 @@ set_state_and_transform(const RenderState *target,
|
|||
_state_mask.set_bit(cull_face_slot);
|
||||
}
|
||||
|
||||
int depth_bias_slot = DepthBiasAttrib::get_class_slot();
|
||||
int depth_offset_slot = DepthOffsetAttrib::get_class_slot();
|
||||
if (_target_rs->get_attrib(depth_offset_slot) != _state_rs->get_attrib(depth_offset_slot) ||
|
||||
if (_target_rs->get_attrib(depth_bias_slot) != _state_rs->get_attrib(depth_bias_slot) ||
|
||||
_target_rs->get_attrib(depth_offset_slot) != _state_rs->get_attrib(depth_offset_slot) ||
|
||||
!_state_mask.get_bit(depth_bias_slot) ||
|
||||
!_state_mask.get_bit(depth_offset_slot)) {
|
||||
// PStatTimer timer(_draw_set_state_depth_offset_pcollector);
|
||||
do_issue_depth_offset();
|
||||
do_issue_depth_bias();
|
||||
_state_mask.set_bit(depth_bias_slot);
|
||||
_state_mask.set_bit(depth_offset_slot);
|
||||
}
|
||||
|
||||
|
|
@ -2070,13 +2120,30 @@ do_issue_rescale_normal() {
|
|||
*
|
||||
*/
|
||||
void TinyGraphicsStateGuardian::
|
||||
do_issue_depth_offset() {
|
||||
const DepthOffsetAttrib *target_depth_offset = DCAST(DepthOffsetAttrib, _target_rs->get_attrib_def(DepthOffsetAttrib::get_class_slot()));
|
||||
do_issue_depth_bias() {
|
||||
const DepthOffsetAttrib *target_depth_offset;
|
||||
_target_rs->get_attrib_def(target_depth_offset);
|
||||
int offset = target_depth_offset->get_offset();
|
||||
_c->zbias = offset;
|
||||
|
||||
const DepthBiasAttrib *target_depth_bias;
|
||||
if (_target_rs->get_attrib(target_depth_bias)) {
|
||||
PN_stdfloat constant_factor = target_depth_bias->get_constant_factor();
|
||||
|
||||
_c->zbias = (int)(((PN_stdfloat)offset - constant_factor) * (1 << (ZB_POINT_Z_FRAC_BITS + 4)));
|
||||
} else {
|
||||
_c->zbias = offset << (ZB_POINT_Z_FRAC_BITS + 4);
|
||||
}
|
||||
|
||||
PN_stdfloat dr_near = 0.0f;
|
||||
PN_stdfloat dr_far = 1.0f;
|
||||
if (_current_display_region != nullptr) {
|
||||
_current_display_region->get_depth_range(dr_near, dr_far);
|
||||
}
|
||||
|
||||
PN_stdfloat min_value = target_depth_offset->get_min_value();
|
||||
PN_stdfloat max_value = target_depth_offset->get_max_value();
|
||||
min_value = dr_far * min_value + dr_near * (1 - min_value);
|
||||
max_value = dr_far * max_value + dr_near * (1 - max_value);
|
||||
if (min_value == 0.0f && max_value == 1.0f) {
|
||||
_c->has_zrange = false;
|
||||
} else {
|
||||
|
|
@ -3035,66 +3102,141 @@ load_matrix(M4 *matrix, const TransformState *transform) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the integer element of store_pixel_funcs (as defined by
|
||||
* store_pixel.py) that corresponds to the indicated ColorBlendAttrib operand
|
||||
* code.
|
||||
* Returns the integer index into the array of store_pixel functions
|
||||
* corresponding to the given blend mode.
|
||||
*/
|
||||
int TinyGraphicsStateGuardian::
|
||||
get_color_blend_mode(ColorBlendAttrib::Mode mode) {
|
||||
switch (mode) {
|
||||
case ColorBlendAttrib::M_none:
|
||||
case ColorBlendAttrib::M_add:
|
||||
case ColorBlendAttrib::M_subtract:
|
||||
case ColorBlendAttrib::M_inv_subtract:
|
||||
return 0;
|
||||
case ColorBlendAttrib::M_min:
|
||||
return 1;
|
||||
case ColorBlendAttrib::M_max:
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integer index into the array of operands computed by store_pixel
|
||||
* that corresponds to the indicated ColorBlendAttrib operand code.
|
||||
*/
|
||||
int TinyGraphicsStateGuardian::
|
||||
get_color_blend_op(ColorBlendAttrib::Operand operand) {
|
||||
switch (operand) {
|
||||
case ColorBlendAttrib::O_zero:
|
||||
return 0;
|
||||
case ColorBlendAttrib::O_one:
|
||||
return 1;
|
||||
case ColorBlendAttrib::O_incoming_color:
|
||||
return 2;
|
||||
case ColorBlendAttrib::O_one_minus_incoming_color:
|
||||
return 3;
|
||||
case ColorBlendAttrib::O_fbuffer_color:
|
||||
return 4;
|
||||
case ColorBlendAttrib::O_one_minus_fbuffer_color:
|
||||
return 5;
|
||||
case ColorBlendAttrib::O_incoming_alpha:
|
||||
return 6;
|
||||
case ColorBlendAttrib::O_one_minus_incoming_alpha:
|
||||
return 7;
|
||||
case ColorBlendAttrib::O_fbuffer_alpha:
|
||||
return 8;
|
||||
case ColorBlendAttrib::O_one_minus_fbuffer_alpha:
|
||||
return 9;
|
||||
case ColorBlendAttrib::O_constant_color:
|
||||
return 10;
|
||||
case ColorBlendAttrib::O_one_minus_constant_color:
|
||||
return 11;
|
||||
case ColorBlendAttrib::O_constant_alpha:
|
||||
return 12;
|
||||
case ColorBlendAttrib::O_one_minus_constant_alpha:
|
||||
return 13;
|
||||
|
||||
case ColorBlendAttrib::O_incoming_color_saturate:
|
||||
return 1;
|
||||
|
||||
case ColorBlendAttrib::O_incoming1_color:
|
||||
return 1;
|
||||
case ColorBlendAttrib::O_one_minus_incoming1_color:
|
||||
return 0;
|
||||
case ColorBlendAttrib::O_incoming1_alpha:
|
||||
return 1;
|
||||
case ColorBlendAttrib::O_one_minus_incoming1_alpha:
|
||||
return 0;
|
||||
|
||||
case ColorBlendAttrib::O_color_scale:
|
||||
return 10;
|
||||
case ColorBlendAttrib::O_one_minus_color_scale:
|
||||
return 11;
|
||||
case ColorBlendAttrib::O_alpha_scale:
|
||||
return 12;
|
||||
case ColorBlendAttrib::O_one_minus_alpha_scale:
|
||||
return 13;
|
||||
return 0;
|
||||
case ColorBlendAttrib::O_incoming_color:
|
||||
case ColorBlendAttrib::O_one_minus_incoming_color:
|
||||
case ColorBlendAttrib::O_incoming_color_saturate:
|
||||
case ColorBlendAttrib::O_incoming1_color:
|
||||
case ColorBlendAttrib::O_one_minus_incoming1_color:
|
||||
case ColorBlendAttrib::O_incoming1_alpha:
|
||||
case ColorBlendAttrib::O_one_minus_incoming1_alpha:
|
||||
return 1;
|
||||
case ColorBlendAttrib::O_fbuffer_color:
|
||||
case ColorBlendAttrib::O_one_minus_fbuffer_color:
|
||||
return 2;
|
||||
case ColorBlendAttrib::O_incoming_alpha:
|
||||
case ColorBlendAttrib::O_one_minus_incoming_alpha:
|
||||
return 3;
|
||||
case ColorBlendAttrib::O_fbuffer_alpha:
|
||||
case ColorBlendAttrib::O_one_minus_fbuffer_alpha:
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the color blend operand should be inverted.
|
||||
*/
|
||||
bool TinyGraphicsStateGuardian::
|
||||
is_color_blend_op_inverted(ColorBlendAttrib::Operand operand) {
|
||||
switch (operand) {
|
||||
case ColorBlendAttrib::O_zero:
|
||||
case ColorBlendAttrib::O_constant_color:
|
||||
case ColorBlendAttrib::O_constant_alpha:
|
||||
case ColorBlendAttrib::O_color_scale:
|
||||
case ColorBlendAttrib::O_alpha_scale:
|
||||
case ColorBlendAttrib::O_incoming_color:
|
||||
case ColorBlendAttrib::O_incoming_color_saturate:
|
||||
case ColorBlendAttrib::O_incoming1_color:
|
||||
case ColorBlendAttrib::O_incoming1_alpha:
|
||||
case ColorBlendAttrib::O_fbuffer_color:
|
||||
case ColorBlendAttrib::O_incoming_alpha:
|
||||
case ColorBlendAttrib::O_fbuffer_alpha:
|
||||
return false;
|
||||
case ColorBlendAttrib::O_one:
|
||||
case ColorBlendAttrib::O_one_minus_constant_color:
|
||||
case ColorBlendAttrib::O_one_minus_constant_alpha:
|
||||
case ColorBlendAttrib::O_one_minus_color_scale:
|
||||
case ColorBlendAttrib::O_one_minus_alpha_scale:
|
||||
case ColorBlendAttrib::O_one_minus_incoming_color:
|
||||
case ColorBlendAttrib::O_one_minus_incoming1_color:
|
||||
case ColorBlendAttrib::O_one_minus_incoming1_alpha:
|
||||
case ColorBlendAttrib::O_one_minus_fbuffer_color:
|
||||
case ColorBlendAttrib::O_one_minus_incoming_alpha:
|
||||
case ColorBlendAttrib::O_one_minus_fbuffer_alpha:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the color blending state for the given blend operand.
|
||||
*/
|
||||
void TinyGraphicsStateGuardian::
|
||||
setup_color_blend(ZBlend &blend, ColorBlendAttrib::Operand op_rgb,
|
||||
ColorBlendAttrib::Operand op_alpha,
|
||||
int cr, int cg, int cb, int ca) {
|
||||
|
||||
blend.op_rgb = get_color_blend_op(op_rgb);
|
||||
blend.op_alpha = get_color_blend_op(op_alpha);
|
||||
|
||||
// If it's inverted (one minus), we xor the value with 0xffff
|
||||
unsigned int mask_rgb = is_color_blend_op_inverted(op_rgb) ? 0xffff : 0x0;
|
||||
unsigned int mask_alpha = is_color_blend_op_inverted(op_alpha) ? 0xffff : 0x0;
|
||||
|
||||
blend.xor_r = mask_rgb;
|
||||
blend.xor_g = mask_rgb;
|
||||
blend.xor_b = mask_rgb;
|
||||
blend.xor_a = mask_alpha;
|
||||
|
||||
// A constant factor is implemented by doing effectively O_zero ^ constant,
|
||||
// so we can conveniently reuse the xor mask field to store it!
|
||||
if (op_rgb == ColorBlendAttrib::O_constant_color ||
|
||||
op_rgb == ColorBlendAttrib::O_one_minus_constant_color) {
|
||||
blend.xor_r ^= cr;
|
||||
blend.xor_g ^= cg;
|
||||
blend.xor_b ^= cb;
|
||||
}
|
||||
if (op_rgb == ColorBlendAttrib::O_constant_alpha ||
|
||||
op_rgb == ColorBlendAttrib::O_one_minus_constant_alpha) {
|
||||
blend.xor_r ^= ca;
|
||||
blend.xor_g ^= ca;
|
||||
blend.xor_b ^= ca;
|
||||
}
|
||||
if (op_alpha == ColorBlendAttrib::O_constant_color ||
|
||||
op_alpha == ColorBlendAttrib::O_constant_alpha ||
|
||||
op_alpha == ColorBlendAttrib::O_one_minus_constant_color ||
|
||||
op_alpha == ColorBlendAttrib::O_one_minus_constant_alpha) {
|
||||
blend.xor_a ^= ca;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pointer to the appropriate filter function according to the
|
||||
* texture's filter type.
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ private:
|
|||
void do_issue_render_mode();
|
||||
void do_issue_cull_face();
|
||||
void do_issue_rescale_normal();
|
||||
void do_issue_depth_offset();
|
||||
void do_issue_depth_bias();
|
||||
void do_issue_material();
|
||||
void do_issue_texture();
|
||||
void do_issue_scissor();
|
||||
|
|
@ -125,7 +125,13 @@ private:
|
|||
void setup_material(GLMaterial *gl_material, const Material *material);
|
||||
void do_auto_rescale_normal();
|
||||
static void load_matrix(M4 *matrix, const TransformState *transform);
|
||||
static int get_color_blend_mode(ColorBlendAttrib::Mode mode);
|
||||
static int get_color_blend_op(ColorBlendAttrib::Operand operand);
|
||||
static bool is_color_blend_op_inverted(ColorBlendAttrib::Operand operand);
|
||||
static void setup_color_blend(ZBlend &blend,
|
||||
ColorBlendAttrib::Operand op_rgb,
|
||||
ColorBlendAttrib::Operand op_alpha,
|
||||
int cr=0, int cg=0, int cb=0, int ca=0);
|
||||
static ZB_lookupTextureFunc get_tex_filter_func(SamplerState::FilterType filter);
|
||||
static ZB_texWrapFunc get_tex_wrap_func(SamplerState::WrapMode wrap_mode);
|
||||
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ ZB_clear_viewport(ZBuffer * zb, int clear_z, ZPOINT z, int clear_color, PIXEL co
|
|||
if (clear_z) {
|
||||
zz = zb->zbuf + xmin + ymin * zb->xsize;
|
||||
for (y = 0; y < ysize; ++y) {
|
||||
memset(zz, 0, xsize * sizeof(ZPOINT));
|
||||
memset_l(zz, z, xsize);
|
||||
zz += zb->xsize;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,6 +158,15 @@ struct ZTextureDef {
|
|||
PIXEL border_color;
|
||||
};
|
||||
|
||||
struct ZBlend {
|
||||
int op_rgb;
|
||||
int op_alpha;
|
||||
unsigned int xor_r;
|
||||
unsigned int xor_g;
|
||||
unsigned int xor_b;
|
||||
unsigned int xor_a;
|
||||
};
|
||||
|
||||
struct ZBuffer {
|
||||
int xsize,ysize;
|
||||
int linesize; /* line size, in bytes */
|
||||
|
|
@ -172,7 +181,8 @@ struct ZBuffer {
|
|||
int *ctable;
|
||||
ZTextureDef current_textures[MAX_TEXTURE_STAGES];
|
||||
int reference_alpha;
|
||||
int blend_r, blend_g, blend_b, blend_a;
|
||||
ZBlend blenda;
|
||||
ZBlend blendb;
|
||||
ZB_storePixelFunc store_pix_func;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
""" This simple Python script can be run to generate
|
||||
ztriangle_code_*.h, ztriangle_table.*, and ztriangle_*.cxx, which
|
||||
are a poor man's form of generated code to cover the explosion of
|
||||
|
|
@ -34,6 +34,7 @@ Options = [
|
|||
]
|
||||
|
||||
# The total number of different combinations of the various Options, above.
|
||||
from functools import reduce
|
||||
OptionsCount = reduce(lambda a, b: a * b, map(lambda o: len(o), Options))
|
||||
|
||||
# The various combinations of these options are explicit within
|
||||
|
|
@ -99,7 +100,7 @@ ZTriangleStub = """
|
|||
"""
|
||||
ops = [0] * len(Options)
|
||||
|
||||
class DoneException:
|
||||
class DoneException(Exception):
|
||||
pass
|
||||
|
||||
# We write the code that actually instantiates the various
|
||||
|
|
@ -148,11 +149,11 @@ def getFref(ops):
|
|||
def closeCode():
|
||||
""" Close the previously-opened code file. """
|
||||
if code:
|
||||
print >> code, ''
|
||||
print >> code, 'ZB_fillTriangleFunc ztriangle_code_%s[%s] = {' % (codeSeg, len(fnameList))
|
||||
print('', file=code)
|
||||
print('ZB_fillTriangleFunc ztriangle_code_%s[%s] = {' % (codeSeg, len(fnameList)), file=code)
|
||||
for fname in fnameList:
|
||||
print >> code, ' %s,' % (fname)
|
||||
print >> code, '};'
|
||||
print(' %s,' % (fname), file=code)
|
||||
print('};', file=code)
|
||||
code.close()
|
||||
|
||||
|
||||
|
|
@ -173,13 +174,13 @@ def openCode(count):
|
|||
fnameList = []
|
||||
|
||||
# Open a new file.
|
||||
code = open('ztriangle_code_%s.h' % (codeSeg), 'wb')
|
||||
print >> code, '/* This file is generated code--do not edit. See ztriangle.py. */'
|
||||
print >> code, ''
|
||||
code = open('ztriangle_code_%s.h' % (codeSeg), 'w')
|
||||
print('/* This file is generated code--do not edit. See ztriangle.py. */', file=code)
|
||||
print('', file=code)
|
||||
|
||||
# Also generate ztriangle_*.cxx, to include the above file.
|
||||
zt = open('ztriangle_%s.cxx' % (codeSeg), 'wb')
|
||||
print >> zt, ZTriangleStub % (codeSeg)
|
||||
zt = open('ztriangle_%s.cxx' % (codeSeg), 'w')
|
||||
print(ZTriangleStub % (codeSeg), file=zt)
|
||||
|
||||
# First, generate the code.
|
||||
count = 0
|
||||
|
|
@ -189,14 +190,14 @@ try:
|
|||
|
||||
for i in range(len(ops)):
|
||||
keyword = Options[i][ops[i]]
|
||||
print >> code, CodeTable[keyword]
|
||||
print(CodeTable[keyword], file=code)
|
||||
|
||||
# This reference gets just the initial fname: omitting the
|
||||
# ExtraOptions, which are implicit in ztriangle_two.h.
|
||||
fname = getFname(ops)
|
||||
print >> code, '#define FNAME(name) %s_ ## name' % (fname)
|
||||
print >> code, '#include "ztriangle_two.h"'
|
||||
print >> code, ''
|
||||
print('#define FNAME(name) %s_ ## name' % (fname), file=code)
|
||||
print('#include "ztriangle_two.h"', file=code)
|
||||
print('', file=code)
|
||||
|
||||
# We store the full fnames generated by the above lines
|
||||
# (including the ExtraOptions) in the fnameDict and fnameList
|
||||
|
|
@ -220,22 +221,22 @@ closeCode()
|
|||
|
||||
# The external reference for the table containing the above function
|
||||
# pointers gets written here.
|
||||
table_decl = open('ztriangle_table.h', 'wb')
|
||||
print >> table_decl, '/* This file is generated code--do not edit. See ztriangle.py. */'
|
||||
print >> table_decl, ''
|
||||
table_decl = open('ztriangle_table.h', 'w')
|
||||
print('/* This file is generated code--do not edit. See ztriangle.py. */', file=table_decl)
|
||||
print('', file=table_decl)
|
||||
|
||||
# The actual table definition gets written here.
|
||||
table_def = open('ztriangle_table.cxx', 'wb')
|
||||
print >> table_def, '/* This file is generated code--do not edit. See ztriangle.py. */'
|
||||
print >> table_def, ''
|
||||
print >> table_def, '#include "pandabase.h"'
|
||||
print >> table_def, '#include "zbuffer.h"'
|
||||
print >> table_def, '#include "ztriangle_table.h"'
|
||||
print >> table_def, ''
|
||||
table_def = open('ztriangle_table.cxx', 'w')
|
||||
print('/* This file is generated code--do not edit. See ztriangle.py. */', file=table_def)
|
||||
print('', file=table_def)
|
||||
print('#include "pandabase.h"', file=table_def)
|
||||
print('#include "zbuffer.h"', file=table_def)
|
||||
print('#include "ztriangle_table.h"', file=table_def)
|
||||
print('', file=table_def)
|
||||
|
||||
for i in range(NumSegments):
|
||||
print >> table_def, 'extern ZB_fillTriangleFunc ztriangle_code_%s[];' % (i + 1)
|
||||
print >> table_def, ''
|
||||
print('extern ZB_fillTriangleFunc ztriangle_code_%s[];' % (i + 1), file=table_def)
|
||||
print('', file=table_def)
|
||||
|
||||
def writeTableEntry(ops):
|
||||
indent = ' ' * (len(ops) + 1)
|
||||
|
|
@ -245,27 +246,27 @@ def writeTableEntry(ops):
|
|||
if i + 1 == len(FullOptions):
|
||||
# The last level: write out the actual function names.
|
||||
for j in range(numOps - 1):
|
||||
print >> table_def, indent + getFref(ops + [j]) + ','
|
||||
print >> table_def, indent + getFref(ops + [numOps - 1])
|
||||
print(indent + getFref(ops + [j]) + ',', file=table_def)
|
||||
print(indent + getFref(ops + [numOps - 1]), file=table_def)
|
||||
|
||||
else:
|
||||
# Intermediate levels: write out a nested reference.
|
||||
for j in range(numOps - 1):
|
||||
print >> table_def, indent + '{'
|
||||
print(indent + '{', file=table_def)
|
||||
writeTableEntry(ops + [j])
|
||||
print >> table_def, indent + '},'
|
||||
print >> table_def, indent + '{'
|
||||
print(indent + '},', file=table_def)
|
||||
print(indent + '{', file=table_def)
|
||||
writeTableEntry(ops + [numOps - 1])
|
||||
print >> table_def, indent + '}'
|
||||
print(indent + '}', file=table_def)
|
||||
|
||||
arraySizeList = []
|
||||
for opList in FullOptions:
|
||||
arraySizeList.append('[%s]' % (len(opList)))
|
||||
arraySize = ''.join(arraySizeList)
|
||||
|
||||
print >> table_def, 'const ZB_fillTriangleFunc fill_tri_funcs%s = {' % (arraySize)
|
||||
print >> table_decl, 'extern const ZB_fillTriangleFunc fill_tri_funcs%s;' % (arraySize)
|
||||
print('const ZB_fillTriangleFunc fill_tri_funcs%s = {' % (arraySize), file=table_def)
|
||||
print('extern const ZB_fillTriangleFunc fill_tri_funcs%s;' % (arraySize), file=table_decl)
|
||||
|
||||
writeTableEntry([])
|
||||
print >> table_def, '};'
|
||||
print('};', file=table_def)
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ def color_region(request, graphics_pipe):
|
|||
'host',
|
||||
0,
|
||||
host_fbprops,
|
||||
core.WindowProperties.size(32, 32),
|
||||
core.WindowProperties.size(8, 8),
|
||||
core.GraphicsPipe.BF_refuse_window,
|
||||
)
|
||||
engine.open_windows()
|
||||
|
|
@ -89,7 +89,7 @@ def color_region(request, graphics_pipe):
|
|||
'buffer',
|
||||
0,
|
||||
fbprops,
|
||||
core.WindowProperties.size(32, 32),
|
||||
core.WindowProperties.size(8, 8),
|
||||
core.GraphicsPipe.BF_refuse_window,
|
||||
host.gsg,
|
||||
host
|
||||
|
|
@ -111,7 +111,7 @@ def color_region(request, graphics_pipe):
|
|||
engine.remove_window(buffer)
|
||||
|
||||
|
||||
def render_color_pixel(region, state, vertex_color=None):
|
||||
def render_color_pixel(region, state, vertex_color=None, clear_color=(0, 0, 0, 1)):
|
||||
"""Renders a fragment using the specified render settings, and returns the
|
||||
resulting color value."""
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ def render_color_pixel(region, state, vertex_color=None):
|
|||
if sattr and sattr.auto_shader():
|
||||
pytest.skip("Cannot test auto-shader without Cg shader support")
|
||||
|
||||
# Set up the scene with a blank card rendering at specified distance.
|
||||
# Set up the scene with a blank triangle rendering at specified distance.
|
||||
scene = core.NodePath("root")
|
||||
scene.set_attrib(core.DepthTestAttrib.make(core.RenderAttrib.M_always))
|
||||
|
||||
|
|
@ -134,46 +134,46 @@ def render_color_pixel(region, state, vertex_color=None):
|
|||
else:
|
||||
format = core.GeomVertexFormat.get_v3()
|
||||
|
||||
vdata = core.GeomVertexData("card", format, core.Geom.UH_static)
|
||||
vdata.unclean_set_num_rows(4)
|
||||
vdata = core.GeomVertexData("triangle", format, core.Geom.UH_static)
|
||||
vdata.unclean_set_num_rows(3)
|
||||
|
||||
vertex = core.GeomVertexWriter(vdata, "vertex")
|
||||
vertex.set_data3(core.Vec3.rfu(-1, 0, 1))
|
||||
vertex.set_data3(core.Vec3.rfu(-1, 0, -1))
|
||||
vertex.set_data3(core.Vec3.rfu(1, 0, 1))
|
||||
vertex.set_data3(core.Vec3.rfu(1, 0, -1))
|
||||
vertex.set_data3(core.Vec3.rfu(-1, 0, -3))
|
||||
vertex.set_data3(core.Vec3.rfu(3, 0, 1))
|
||||
|
||||
if vertex_color is not None:
|
||||
color = core.GeomVertexWriter(vdata, "color")
|
||||
color.set_data4(vertex_color)
|
||||
color.set_data4(vertex_color)
|
||||
color.set_data4(vertex_color)
|
||||
color.set_data4(vertex_color)
|
||||
|
||||
strip = core.GeomTristrips(core.Geom.UH_static)
|
||||
strip = core.GeomTriangles(core.Geom.UH_static)
|
||||
strip.set_shade_model(core.Geom.SM_uniform)
|
||||
strip.add_next_vertices(4)
|
||||
strip.close_primitive()
|
||||
strip.add_next_vertices(3)
|
||||
|
||||
geom = core.Geom(vdata)
|
||||
geom.add_primitive(strip)
|
||||
|
||||
gnode = core.GeomNode("card")
|
||||
gnode = core.GeomNode("triangle")
|
||||
gnode.add_geom(geom, state)
|
||||
card = scene.attach_new_node(gnode)
|
||||
card.set_pos(0, 2, 0)
|
||||
card.set_scale(60)
|
||||
triangle = scene.attach_new_node(gnode)
|
||||
triangle.set_pos(0, 2, 0)
|
||||
|
||||
region.active = True
|
||||
region.camera = camera
|
||||
|
||||
color_texture = core.Texture("color")
|
||||
region.window.add_render_texture(color_texture,
|
||||
core.GraphicsOutput.RTM_copy_ram,
|
||||
core.GraphicsOutput.RTP_color)
|
||||
region.window.set_clear_color(clear_color)
|
||||
try:
|
||||
color_texture = core.Texture("color")
|
||||
region.window.add_render_texture(color_texture,
|
||||
core.GraphicsOutput.RTM_copy_ram,
|
||||
core.GraphicsOutput.RTP_color)
|
||||
|
||||
region.window.engine.render_frame()
|
||||
region.window.clear_render_textures()
|
||||
region.window.engine.render_frame()
|
||||
finally:
|
||||
region.window.clear_render_textures()
|
||||
region.window.set_clear_color((0, 0, 0, 1))
|
||||
|
||||
col = core.LColor()
|
||||
color_texture.peek().lookup(col, 0.5, 0.5)
|
||||
|
|
@ -188,6 +188,104 @@ def test_color_write_mask(color_region):
|
|||
assert result == (0, 1, 0, 1)
|
||||
|
||||
|
||||
OP_NAMES = ['zero', 'one',
|
||||
'incoming_color', 'one_minus_incoming_color',
|
||||
'fbuffer_color', 'one_minus_fbuffer_color',
|
||||
'incoming_alpha', 'one_minus_incoming_alpha',
|
||||
'fbuffer_alpha', 'one_minus_fbuffer_alpha',
|
||||
'constant_color', 'one_minus_constant_color',
|
||||
'constant_alpha', 'one_minus_constant_alpha'
|
||||
]
|
||||
@pytest.mark.parametrize('op_name_a', OP_NAMES)
|
||||
@pytest.mark.parametrize('op_name_b', OP_NAMES)
|
||||
def test_color_blend_add(color_region, op_name_a, op_name_b):
|
||||
fbuffer = core.LColor(0.2, 0.4, 0.6, 0.8)
|
||||
incoming = core.LColor(0.3, 0.5, 0.7, 0.1)
|
||||
const = core.LColor(0.0, 1.0, 0.5, 0.25)
|
||||
|
||||
op_a = getattr(core.ColorBlendAttrib, 'O_' + op_name_a)
|
||||
op_b = getattr(core.ColorBlendAttrib, 'O_' + op_name_b)
|
||||
state = core.RenderState.make(
|
||||
core.ColorAttrib.make_flat(incoming),
|
||||
core.ColorBlendAttrib.make(core.ColorBlendAttrib.M_add, op_a, op_b, const),
|
||||
)
|
||||
|
||||
# Calculate what it should be.
|
||||
def calc_op(op):
|
||||
if op == core.ColorBlendAttrib.O_zero:
|
||||
return core.LColor(0.0)
|
||||
if op == core.ColorBlendAttrib.O_one:
|
||||
return core.LColor(1.0)
|
||||
if op == core.ColorBlendAttrib.O_incoming_color:
|
||||
return incoming
|
||||
if op == core.ColorBlendAttrib.O_one_minus_incoming_color:
|
||||
return core.LColor(1.0) - incoming
|
||||
if op == core.ColorBlendAttrib.O_fbuffer_color:
|
||||
return fbuffer
|
||||
if op == core.ColorBlendAttrib.O_one_minus_fbuffer_color:
|
||||
return core.LColor(1.0) - fbuffer
|
||||
if op == core.ColorBlendAttrib.O_incoming_alpha:
|
||||
return core.LColor(incoming.w)
|
||||
if op == core.ColorBlendAttrib.O_one_minus_incoming_alpha:
|
||||
return core.LColor(1.0 - incoming.w)
|
||||
if op == core.ColorBlendAttrib.O_fbuffer_alpha:
|
||||
return core.LColor(fbuffer.w)
|
||||
if op == core.ColorBlendAttrib.O_one_minus_fbuffer_alpha:
|
||||
return core.LColor(1.0 - fbuffer.w)
|
||||
if op == core.ColorBlendAttrib.O_constant_color:
|
||||
return const
|
||||
if op == core.ColorBlendAttrib.O_one_minus_constant_color:
|
||||
return core.LColor(1.0) - const
|
||||
if op == core.ColorBlendAttrib.O_constant_alpha:
|
||||
return core.LColor(const.w)
|
||||
if op == core.ColorBlendAttrib.O_one_minus_constant_alpha:
|
||||
return core.LColor(1.0 - const.w)
|
||||
|
||||
term_a = core.LColor(incoming)
|
||||
term_a.componentwise_mult(calc_op(op_a))
|
||||
term_b = core.LColor(fbuffer)
|
||||
term_b.componentwise_mult(calc_op(op_b))
|
||||
expected = term_a + term_b
|
||||
expected = expected.fmax(core.LColor(0)).fmin(core.LColor(1))
|
||||
|
||||
result = render_color_pixel(color_region, state, clear_color=fbuffer)
|
||||
assert result.almost_equal(expected, FUZZ)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('rgb_mode', ['min', 'max'])
|
||||
@pytest.mark.parametrize('alpha_mode', ['min', 'max'])
|
||||
def test_color_blend_min_max(color_region, rgb_mode, alpha_mode):
|
||||
fbuffer = core.LColor(0.2, 0.5, 0.6, 0.8)
|
||||
incoming = core.LColor(0.3, 0.4, 0.7, 0.1)
|
||||
|
||||
# Note that operands are ignored for M_min and M_max
|
||||
state = core.RenderState.make(
|
||||
core.ColorAttrib.make_flat(incoming),
|
||||
core.ColorBlendAttrib.make(
|
||||
getattr(core.ColorBlendAttrib, 'M_' + rgb_mode),
|
||||
core.ColorBlendAttrib.O_one,
|
||||
core.ColorBlendAttrib.O_one,
|
||||
getattr(core.ColorBlendAttrib, 'M_' + alpha_mode),
|
||||
core.ColorBlendAttrib.O_one,
|
||||
core.ColorBlendAttrib.O_one,
|
||||
),
|
||||
)
|
||||
|
||||
if rgb_mode == 'min':
|
||||
expected = fbuffer.fmin(incoming)
|
||||
elif rgb_mode == 'max':
|
||||
expected = fbuffer.fmax(incoming)
|
||||
|
||||
if rgb_mode != alpha_mode:
|
||||
if alpha_mode == 'min':
|
||||
expected.w = min(fbuffer.w, incoming.w)
|
||||
elif alpha_mode == 'max':
|
||||
expected.w = max(fbuffer.w, incoming.w)
|
||||
|
||||
result = render_color_pixel(color_region, state, clear_color=fbuffer)
|
||||
assert result.almost_equal(expected, FUZZ)
|
||||
|
||||
|
||||
def test_color_empty(color_region, shader_attrib, material_attrib):
|
||||
state = core.RenderState.make(
|
||||
shader_attrib,
|
||||
|
|
@ -321,6 +419,7 @@ def test_color_transparency(color_region, shader_attrib, light_attrib):
|
|||
)
|
||||
result = render_color_pixel(color_region, state)
|
||||
assert result.x == pytest.approx(0.75, 0.1)
|
||||
assert result.w == pytest.approx(1.0, 0.1)
|
||||
|
||||
|
||||
def test_color_transparency_flat(color_region, shader_attrib, light_attrib):
|
||||
|
|
@ -337,6 +436,7 @@ def test_color_transparency_flat(color_region, shader_attrib, light_attrib):
|
|||
)
|
||||
result = render_color_pixel(color_region, state)
|
||||
assert result.x == pytest.approx(0.75, 0.1)
|
||||
assert result.w == pytest.approx(1.0, 0.1)
|
||||
|
||||
|
||||
def test_color_transparency_vertex(color_region, shader_attrib, light_attrib):
|
||||
|
|
@ -353,6 +453,7 @@ def test_color_transparency_vertex(color_region, shader_attrib, light_attrib):
|
|||
)
|
||||
result = render_color_pixel(color_region, state, vertex_color=(1, 1, 1, 0.5))
|
||||
assert result.x == pytest.approx(0.75, 0.1)
|
||||
assert result.w == pytest.approx(1.0, 0.1)
|
||||
|
||||
|
||||
def test_color_transparency_no_light(color_region, shader_attrib):
|
||||
|
|
@ -367,6 +468,7 @@ def test_color_transparency_no_light(color_region, shader_attrib):
|
|||
)
|
||||
result = render_color_pixel(color_region, state)
|
||||
assert result.x == pytest.approx(1.0, 0.1)
|
||||
assert result.w == pytest.approx(1.0, 0.1)
|
||||
|
||||
|
||||
def test_texture_occlusion(color_region):
|
||||
|
|
|
|||
|
|
@ -47,8 +47,12 @@ def depth_region(request, graphics_pipe):
|
|||
if buffer is None:
|
||||
pytest.skip("Cannot make depth buffer")
|
||||
|
||||
if buffer.get_fb_properties().depth_bits != request.param:
|
||||
pytest.skip("Could not make buffer with desired bit count")
|
||||
got_depth_bits = buffer.get_fb_properties().depth_bits
|
||||
if got_depth_bits < 24 and request.param == 16:
|
||||
# We'll accept this - tinydisplay exclusively supports 20-bit depth.
|
||||
pass
|
||||
elif got_depth_bits != request.param:
|
||||
pytest.skip("Could not make buffer with desired depth bit count")
|
||||
|
||||
yield buffer.make_display_region()
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ def run_glsl_compile_check(gsg, vert_path, frag_path, expect_fail=False):
|
|||
assert shader is not None
|
||||
|
||||
if not gsg.supports_glsl:
|
||||
expect_fail = True
|
||||
pytest.skip("GLSL shaders not supported")
|
||||
|
||||
shader.prepare_now(gsg.prepared_objects, gsg)
|
||||
assert shader.is_prepared(gsg.prepared_objects)
|
||||
|
|
@ -633,16 +633,17 @@ def test_glsl_state_light_source(gsg):
|
|||
assert(p3d_LightSource[0].shadowViewMatrix[0][1] == 0);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[0][2] == 0);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[0][3] == 0);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[1][0] == 0.5);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[1][1] == 0.5);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[1][2] > 1.0);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[1][2] < 1.00002);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[1][3] == 1);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[2][0] == 0);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[2][1] > 0.2886);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[2][1] < 0.2887);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[2][2] == 0);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[2][3] == 0);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[1][0] == 0);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[1][1] > 0.2886);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[1][1] < 0.2887);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[1][2] == 0);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[1][3] == 0);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[2][0] < -0.4999);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[2][0] > -0.5001);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[2][1] < -0.4999);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[2][1] > -0.5001);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[2][2] < -0.9999);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[2][3] < -0.9999);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[3][0] > -16.2736);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[3][0] < -16.2734);
|
||||
assert(p3d_LightSource[0].shadowViewMatrix[3][1] > -16.8510);
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
#ifdef ANDROID
|
||||
// No caching on Android
|
||||
PyRun_SimpleString("import sys; sys.argv.insert(1, '-o cache_dir=/dev/null')");
|
||||
PyRun_SimpleString("import sys; sys.argv.insert(1, '-pno:cacheprovider')");
|
||||
#endif
|
||||
|
||||
return Py_RunMain();
|
||||
|
|
|
|||
Loading…
Reference in New Issue