diff --git a/direct/src/showbase/extend_frozen.c b/direct/src/showbase/extend_frozen.c index 15d259783e..1a562f8a63 100644 --- a/direct/src/showbase/extend_frozen.c +++ b/direct/src/showbase/extend_frozen.c @@ -1,3 +1,4 @@ +#define PY_SSIZE_T_CLEAN #include #ifdef _WIN32 @@ -105,7 +106,7 @@ py_extend_frozen_modules(PyObject *self, PyObject *args) { PyObject *tuple; const char *name; const char *code; - int size; + Py_ssize_t size; tuple = PySequence_GetItem(list, i); if (!PyArg_ParseTuple(tuple, "ss#", &name, &code, &size)) { @@ -178,7 +179,7 @@ py_get_frozen_module_code(PyObject *self, PyObject *args) { if (strcmp(PyImport_FrozenModules[i].name, name) == 0) { int is_package = (PyImport_FrozenModules[i].size < 0); return Py_BuildValue("(s#i)", PyImport_FrozenModules[i].code, - abs(PyImport_FrozenModules[i].size), + (Py_ssize_t) abs(PyImport_FrozenModules[i].size), is_package); } ++i; diff --git a/dtool/Config.pp b/dtool/Config.pp index 77370e6eb7..08e0d31ded 100644 --- a/dtool/Config.pp +++ b/dtool/Config.pp @@ -653,40 +653,6 @@ // space (instead of a dot). Thus, "1 1" means OpenGL version 1.1. #define MIN_GL_VERSION 1 1 -// Is Mesa installed separately from OpenGL? Mesa is an open-source -// software-only OpenGL renderer. Panda can link with it -// independently from OpenGL (and if Mesa is built statically, and/or -// with -DUSE_MGL_NAMESPACE declared to rename gl* to mgl*, it can -// switch between the system OpenGL implementation and the Mesa -// implementation at runtime). - -// Also, Mesa includes some core libraries (in libOSMesa.so) that -// allow totally headless rendering, handy if you want to run a -// renderer as a batch service, and you don't want to insist that a -// user be logged on to the desktop or otherwise deal with X11 or -// Windows. - -// If you define HAVE_MESA here, and the appropriate paths to headers -// and libraries, then Panda will build libmesadisplay, which can be -// used in lieu of libpandagl or libpandadx to do rendering. However, -// for most applications, you don't need to do this, since (a) if you -// have hardware rendering capability, you probably don't want to use -// Mesa, since it's software-only, and (b) if you don't have hardware -// rendering, you can install Mesa as the system's OpenGL -// implementation, so you can just use the normal libpandagl. You -// only need to define HAVE_MESA if you want to run totally headless, -// or if you want to be able to easily switch between Mesa and the -// system OpenGL implementation at runtime. If you compiled Mesa with -// USE_MGL_NAMESPACE defined, define MESA_MGL here. -#define MESA_IPATH -#define MESA_LPATH -#define MESA_LIBS -#define MESA_MGL -#defer HAVE_MESA $[libtest $[MESA_LPATH],$[MESA_LIBS]] - -// Similar to MIN_GL_VERSION, above. -#define MIN_MESA_VERSION 1 1 - // Do you want to build tinydisplay, a light and fast software // renderer built into Panda, based on TinyGL? This isn't as // full-featured as Mesa, but it is many times faster, and in fact diff --git a/dtool/LocalSetup.pp b/dtool/LocalSetup.pp index f177ce2cac..c9b9efddcf 100644 --- a/dtool/LocalSetup.pp +++ b/dtool/LocalSetup.pp @@ -176,11 +176,6 @@ #else #print - Did not find X11 #endif -#if $[HAVE_MESA] -#print + Mesa -#else -#print - Did not find Mesa -#endif #if $[HAVE_OPENCV] #print + OpenCV #else @@ -437,14 +432,6 @@ $[cdefine HAVE_ODE] /* Define if we have AWESOMIUM installed and want to build for AWESOMIUM. */ $[cdefine HAVE_AWESOMIUM] -/* Define if we have Mesa installed and want to build mesadisplay. */ -$[cdefine HAVE_MESA] -$[cdefine MESA_MGL] -#if HAVE_MESA -# define MIN_MESA_VERSION_MAJOR $[word 1,$[MIN_MESA_VERSION]] -# define MIN_MESA_VERSION_MINOR $[word 2,$[MIN_MESA_VERSION]] -#endif - /* Define if we have GLX installed and want to build for GLX. */ $[cdefine HAVE_GLX] diff --git a/dtool/Package.pp b/dtool/Package.pp index 460d176859..64f361ae82 100644 --- a/dtool/Package.pp +++ b/dtool/Package.pp @@ -236,12 +236,6 @@ #set GLES2_LIBS $[GLES2_LIBS] #set HAVE_GLES2 $[HAVE_GLES2] -#set MESA_IPATH $[unixfilename $[MESA_IPATH]] -#set MESA_LPATH $[unixfilename $[MESA_LPATH]] -#set MESA_LIBS $[MESA_LIBS] -#set MESA_MGL $[MESA_MGL] -#set HAVE_MESA $[HAVE_MESA] - #set GLX_IPATH $[unixfilename $[GLX_IPATH]] #set GLX_LPATH $[unixfilename $[GLX_LPATH]] #set HAVE_GLX $[HAVE_GLX] diff --git a/dtool/pptempl/Global.pp b/dtool/pptempl/Global.pp index 667ef24ed4..22adc27ae0 100644 --- a/dtool/pptempl/Global.pp +++ b/dtool/pptempl/Global.pp @@ -185,13 +185,6 @@ #define xcursor_libs $[XCURSOR_LIBS] #endif -#if $[HAVE_MESA] - #define mesa_ipath $[wildcard $[MESA_IPATH]] - #define mesa_lpath $[wildcard $[MESA_LPATH]] - #define mesa_cflags $[MESA_CFLAGS] - #define mesa_libs $[MESA_LIBS] -#endif - #if $[HAVE_GLX] #define glx_ipath $[wildcard $[GLX_IPATH]] #define glx_lpath $[wildcard $[GLX_LPATH]] diff --git a/dtool/src/dtoolbase/atomicAdjust.h b/dtool/src/dtoolbase/atomicAdjust.h index 1bd24d22ea..6ce85c3589 100644 --- a/dtool/src/dtoolbase/atomicAdjust.h +++ b/dtool/src/dtoolbase/atomicAdjust.h @@ -23,7 +23,7 @@ #include "atomicAdjustDummyImpl.h" typedef AtomicAdjustDummyImpl AtomicAdjust; -#elif defined(__i386__) || defined(_M_IX86) +#elif defined(__i386__) || defined(_M_IX86) // For an i386 architecture, we'll always use the i386 implementation. // It should be safe for any OS, and it might be a bit faster than // any OS-provided calls. @@ -39,6 +39,15 @@ typedef AtomicAdjustI386Impl AtomicAdjust; #define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1 #define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1 +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) +// GCC 4.7 and above has built-in __atomic functions for atomic operations. + +#include "atomicAdjustGccImpl.h" +typedef AtomicAdjustGccImpl AtomicAdjust; + +#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1 +#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1 + #elif defined(THREAD_WIN32_IMPL) #include "atomicAdjustWin32Impl.h" diff --git a/dtool/src/dtoolbase/atomicAdjustGccImpl.I b/dtool/src/dtoolbase/atomicAdjustGccImpl.I new file mode 100644 index 0000000000..6831a16a1e --- /dev/null +++ b/dtool/src/dtoolbase/atomicAdjustGccImpl.I @@ -0,0 +1,148 @@ +// Filename: atomicAdjustGccImpl.I +// Created by: rdb (04Jul14) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::inc +// Access: Public, Static +// Description: Atomically increments the indicated variable. +//////////////////////////////////////////////////////////////////// +INLINE void AtomicAdjustGccImpl:: +inc(TVOLATILE AtomicAdjustGccImpl::Integer &var) { + __atomic_fetch_add(&var, 1, __ATOMIC_SEQ_CST); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::dec +// Access: Public, Static +// Description: Atomically decrements the indicated variable and +// returns true if the new value is nonzero, false if it +// is zero. +//////////////////////////////////////////////////////////////////// +INLINE bool AtomicAdjustGccImpl:: +dec(TVOLATILE AtomicAdjustGccImpl::Integer &var) { + return (__atomic_sub_fetch(&var, 1, __ATOMIC_SEQ_CST) != 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::add +// Access: Public, Static +// Description: Atomically computes var += delta. It is legal for +// delta to be negative. +//////////////////////////////////////////////////////////////////// +INLINE void AtomicAdjustGccImpl:: +add(TVOLATILE AtomicAdjustGccImpl::Integer &var, + AtomicAdjustGccImpl::Integer delta) { + __atomic_fetch_add(&var, delta, __ATOMIC_SEQ_CST); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::set +// Access: Public, Static +// Description: Atomically changes the indicated variable and +// returns the original value. +//////////////////////////////////////////////////////////////////// +INLINE AtomicAdjustGccImpl::Integer AtomicAdjustGccImpl:: +set(TVOLATILE AtomicAdjustGccImpl::Integer &var, + AtomicAdjustGccImpl::Integer new_value) { + + return __atomic_exchange_n(&var, new_value, __ATOMIC_SEQ_CST); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::get +// Access: Public, Static +// Description: Atomically retrieves the snapshot value of the +// indicated variable. This is the only guaranteed safe +// way to retrieve the value that other threads might be +// asynchronously setting, incrementing, or decrementing +// (via other AtomicAjust methods). +//////////////////////////////////////////////////////////////////// +INLINE AtomicAdjustGccImpl::Integer AtomicAdjustGccImpl:: +get(const TVOLATILE AtomicAdjustGccImpl::Integer &var) { + return __atomic_load_n(&var, __ATOMIC_SEQ_CST); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::set_ptr +// Access: Public, Static +// Description: Atomically changes the indicated variable and +// returns the original value. +//////////////////////////////////////////////////////////////////// +INLINE AtomicAdjustGccImpl::Pointer AtomicAdjustGccImpl:: +set_ptr(TVOLATILE AtomicAdjustGccImpl::Pointer &var, + AtomicAdjustGccImpl::Pointer new_value) { + + return __atomic_exchange_n(&var, new_value, __ATOMIC_SEQ_CST); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::get_ptr +// Access: Public, Static +// Description: Atomically retrieves the snapshot value of the +// indicated variable. This is the only guaranteed safe +// way to retrieve the value that other threads might be +// asynchronously setting, incrementing, or decrementing +// (via other AtomicAjust methods). +//////////////////////////////////////////////////////////////////// +INLINE AtomicAdjustGccImpl::Pointer AtomicAdjustGccImpl:: +get_ptr(const TVOLATILE AtomicAdjustGccImpl::Pointer &var) { + return __atomic_load_n(&var, __ATOMIC_SEQ_CST); +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::compare_and_exchange +// Access: Public, Static +// Description: Atomic compare and exchange. +// +// If mem is equal to old_value, store new_value in mem. +// In either case, return the original value of mem. +// The caller can test for success by comparing +// return_value == old_value. +// +// The atomic function expressed in pseudo-code: +// +// orig_value = mem; +// if (mem == old_value) { +// mem = new_value; +// } +// return orig_value; +// +//////////////////////////////////////////////////////////////////// +INLINE AtomicAdjustGccImpl::Integer AtomicAdjustGccImpl:: +compare_and_exchange(TVOLATILE AtomicAdjustGccImpl::Integer &mem, + AtomicAdjustGccImpl::Integer old_value, + AtomicAdjustGccImpl::Integer new_value) { + + __atomic_compare_exchange_n(&mem, &old_value, new_value, false, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return old_value; +} + +//////////////////////////////////////////////////////////////////// +// Function: AtomicAdjustGccImpl::compare_and_exchange_ptr +// Access: Public, Static +// Description: Atomic compare and exchange. +// +// As above, but works on pointers instead of integers. +//////////////////////////////////////////////////////////////////// +INLINE AtomicAdjustGccImpl::Pointer AtomicAdjustGccImpl:: +compare_and_exchange_ptr(TVOLATILE AtomicAdjustGccImpl::Pointer &mem, + AtomicAdjustGccImpl::Pointer old_value, + AtomicAdjustGccImpl::Pointer new_value) { + + __atomic_compare_exchange_n(&mem, &old_value, new_value, false, + __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + return old_value; +} diff --git a/dtool/src/dtoolbase/atomicAdjustGccImpl.h b/dtool/src/dtoolbase/atomicAdjustGccImpl.h new file mode 100644 index 0000000000..2c8003948d --- /dev/null +++ b/dtool/src/dtoolbase/atomicAdjustGccImpl.h @@ -0,0 +1,60 @@ +// Filename: atomicAdjustGccImpl.h +// Created by: rdb (04Jul14) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef ATOMICADJUSTGCCIMPL_H +#define ATOMICADJUSTGCCIMPL_H + +#include "dtoolbase.h" +#include "selectThreadImpl.h" + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) + +//////////////////////////////////////////////////////////////////// +// Class : AtomicAdjustGccImpl +// Description : Uses GCC built-ins to implement atomic adjustments. +//////////////////////////////////////////////////////////////////// +class EXPCL_DTOOL AtomicAdjustGccImpl { +public: +#if __GCC_ATOMIC_LONG_LOCK_FREE > __GCC_ATOMIC_INT_LOCK_FREE + // If the long can be more lock-free than int, use it instead. + typedef __attribute__ ((aligned (__SIZEOF_LONG__))) long Integer; +#else + typedef __attribute__ ((aligned (__SIZEOF_INT__))) int Integer; +#endif + typedef void *UnalignedPointer; + typedef __attribute__ ((aligned (__SIZEOF_POINTER__))) UnalignedPointer Pointer; + + INLINE static void inc(TVOLATILE Integer &var); + INLINE static bool dec(TVOLATILE Integer &var); + INLINE static void add(TVOLATILE Integer &var, Integer delta); + INLINE static Integer set(TVOLATILE Integer &var, Integer new_value); + INLINE static Integer get(const TVOLATILE Integer &var); + + INLINE static Pointer set_ptr(TVOLATILE Pointer &var, Pointer new_value); + INLINE static Pointer get_ptr(const TVOLATILE Pointer &var); + + INLINE static Integer compare_and_exchange(TVOLATILE Integer &mem, + Integer old_value, + Integer new_value); + + INLINE static Pointer compare_and_exchange_ptr(TVOLATILE Pointer &mem, + Pointer old_value, + Pointer new_value); +}; + +#include "atomicAdjustGccImpl.I" + +#endif // HAVE_POSIX_THREADS + +#endif diff --git a/dtool/src/dtoolbase/cmath.I b/dtool/src/dtoolbase/cmath.I index 2fd28b6a01..8b975bf924 100644 --- a/dtool/src/dtoolbase/cmath.I +++ b/dtool/src/dtoolbase/cmath.I @@ -336,6 +336,28 @@ cpow(double x, double y) { return pow(x, y); } +//////////////////////////////////////////////////////////////////// +// Function: cpow +// Description: +//////////////////////////////////////////////////////////////////// +INLINE int +cpow(int x, int y) { + int result = 1; + + if (y >= 0) { + for(; y > 0; --y) { + result *= x; + } + return result; + + } else { + for(; y < 0; ++y) { + result *= x; + } + return 1 / result; + } +} + //////////////////////////////////////////////////////////////////// // Function: cnan // Description: @@ -343,7 +365,7 @@ cpow(double x, double y) { INLINE bool cnan(double v) { #ifndef _WIN32 - return (isnan(v) != 0); + return (std::isnan(v) != 0); #else return (_isnan(v) != 0); #endif diff --git a/dtool/src/dtoolbase/cmath.h b/dtool/src/dtoolbase/cmath.h index 23e9d920c9..d4494f81ca 100644 --- a/dtool/src/dtoolbase/cmath.h +++ b/dtool/src/dtoolbase/cmath.h @@ -23,7 +23,7 @@ #include "dtoolbase.h" -#include +#include // Windows defines isnan() in a different place and with a different // name than everyone else. Sheesh. @@ -62,6 +62,8 @@ INLINE double cacos(double v); INLINE double cmod(double x, double y); INLINE double cpow(double x, double y); +INLINE int cpow(int x, int y); + // Returns true if the number is NaN, false if it's a genuine number // or infinity. INLINE bool cnan(double v); diff --git a/dtool/src/dtoolbase/dtoolbase_cc.h b/dtool/src/dtoolbase/dtoolbase_cc.h index ad9e9897dd..06f7ede646 100644 --- a/dtool/src/dtoolbase/dtoolbase_cc.h +++ b/dtool/src/dtoolbase/dtoolbase_cc.h @@ -33,6 +33,7 @@ using namespace std; #define INLINE inline #define TYPENAME typename +#define CONSTEXPR #define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname) @@ -119,6 +120,16 @@ typedef ios::seekdir ios_seekdir; #define INLINE inline #endif +#if defined(__has_extension) // Clang magic. +#if __has_extension(cxx_constexpr) +#define CONSTEXPR constexpr +#endif +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && (__cplusplus >= 201103L) +#define CONSTEXPR constexpr +#else +#define CONSTEXPR INLINE +#endif + #if defined(WIN32_VC) && !defined(LINK_ALL_STATIC) && defined(EXPORT_TEMPLATES) // This macro must be used to export an instantiated template class // from a DLL. If the template class name itself contains commas, it diff --git a/dtool/src/dtoolbase/nearly_zero.h b/dtool/src/dtoolbase/nearly_zero.h index 828dc424e6..0b36d4652d 100644 --- a/dtool/src/dtoolbase/nearly_zero.h +++ b/dtool/src/dtoolbase/nearly_zero.h @@ -35,6 +35,13 @@ get_nearly_zero_value(float) { return 1.0e-6f; } +INLINE int +get_nearly_zero_value(int) { + // This is a bit silly, but we should nevertheless define it in + // case it is called for an integer type. + return 0; +} + // IS_THRESHOLD_ZERO(value, threshold) returns true if the value is // within threshold of zero. @@ -73,7 +80,7 @@ get_nearly_zero_value(float) { // MAYBE_ZERO(value) returns 0 if the value is nearly zero, and the // value itself otherwise. #define MAYBE_ZERO(value) \ - (IS_NEARLY_ZERO(value) ? 0.0 : (value)) + (IS_NEARLY_ZERO(value) ? 0 : (value)) #endif diff --git a/dtool/src/dtoolbase/register_type.cxx b/dtool/src/dtoolbase/register_type.cxx index 719bb8e29d..1eff1fa75e 100644 --- a/dtool/src/dtoolbase/register_type.cxx +++ b/dtool/src/dtoolbase/register_type.cxx @@ -26,6 +26,7 @@ TypeHandle bool_type_handle; TypeHandle double_type_handle; TypeHandle float_type_handle; TypeHandle string_type_handle; +TypeHandle wstring_type_handle; TypeHandle long_p_type_handle; TypeHandle int_p_type_handle; @@ -58,6 +59,7 @@ void init_system_type_handles() { register_type(double_type_handle, "double"); register_type(float_type_handle, "float"); register_type(string_type_handle, "string"); + register_type(wstring_type_handle, "wstring"); register_type(int_p_type_handle, "int*"); register_type(short_p_type_handle, "short*"); @@ -75,5 +77,3 @@ void init_system_type_handles() { register_type(pset_type_handle, "pset"); } } - - diff --git a/dtool/src/dtoolbase/register_type.h b/dtool/src/dtoolbase/register_type.h index 9428d1d235..e7b6a252ee 100644 --- a/dtool/src/dtoolbase/register_type.h +++ b/dtool/src/dtoolbase/register_type.h @@ -92,6 +92,7 @@ extern TypeHandle EXPCL_DTOOL bool_type_handle; extern TypeHandle EXPCL_DTOOL double_type_handle; extern TypeHandle EXPCL_DTOOL float_type_handle; extern TypeHandle EXPCL_DTOOL string_type_handle; +extern TypeHandle EXPCL_DTOOL wstring_type_handle; extern TypeHandle long_p_type_handle; extern TypeHandle int_p_type_handle; @@ -175,6 +176,11 @@ INLINE TypeHandle _get_type_handle(const string *) { return string_type_handle; } +template<> +INLINE TypeHandle _get_type_handle(const wstring *) { + return wstring_type_handle; +} + template<> INLINE TypeHandle _get_type_handle(const long * const *) { return long_p_type_handle; diff --git a/dtool/src/dtoolbase/typeHandle.cxx b/dtool/src/dtoolbase/typeHandle.cxx index c25ee886c7..773cca79ec 100644 --- a/dtool/src/dtoolbase/typeHandle.cxx +++ b/dtool/src/dtoolbase/typeHandle.cxx @@ -16,6 +16,10 @@ #include "typeRegistryNode.h" #include "atomicAdjust.h" +#ifdef HAVE_PYTHON +#include "Python.h" +#endif + // This is initialized to zero by static initialization. TypeHandle TypeHandle::_none; diff --git a/dtool/src/dtoolbase/typeHandle.h b/dtool/src/dtoolbase/typeHandle.h index beecc306ba..5d0bfa34fb 100644 --- a/dtool/src/dtoolbase/typeHandle.h +++ b/dtool/src/dtoolbase/typeHandle.h @@ -66,7 +66,10 @@ class TypedObject; #ifdef HAVE_PYTHON -#include "Python.h" +#ifndef PyObject_HEAD +struct _object; +typedef _object PyObject; +#endif #endif //////////////////////////////////////////////////////////////////// @@ -127,15 +130,15 @@ PUBLISHED: INLINE TypeHandle get_parent_towards(TypeHandle ancestor, TypedObject *object = (TypedObject *)NULL) const; - - INLINE int get_best_parent_from_Set(const std::set< int > &legal_vals) const; + + INLINE int get_best_parent_from_Set(const std::set< int > &legal_vals) const; #ifdef DO_MEMORY_USAGE int get_memory_usage(MemoryClass memory_class) const; void inc_memory_usage(MemoryClass memory_class, int size); void dec_memory_usage(MemoryClass memory_class, int size); #else - INLINE int get_memory_usage(MemoryClass) const { return 0; } + CONSTEXPR int get_memory_usage(MemoryClass) const { return 0; } INLINE void inc_memory_usage(MemoryClass, int) { } INLINE void dec_memory_usage(MemoryClass, int) { } #endif // DO_MEMORY_USAGE @@ -170,4 +173,3 @@ EXPCL_DTOOL ostream &operator << (ostream &out, TypeHandle::MemoryClass mem_clas #include "typeHandle.I" #endif - diff --git a/dtool/src/dtoolbase/typeRegistry.h b/dtool/src/dtoolbase/typeRegistry.h index 3a54961819..10efa40cad 100644 --- a/dtool/src/dtoolbase/typeRegistry.h +++ b/dtool/src/dtoolbase/typeRegistry.h @@ -58,9 +58,11 @@ PUBLISHED: int get_num_typehandles(); TypeHandle get_typehandle(int n); + MAKE_SEQ(get_typehandles, get_num_typehandles, get_typehandle); int get_num_root_classes(); TypeHandle get_root_class(int n); + MAKE_SEQ(get_root_classes, get_num_root_classes, get_root_class); int get_num_parent_classes(TypeHandle child, TypedObject *child_object) const; diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index ec583b082d..eae6299a03 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -50,6 +50,7 @@ FunctionRemap(const InterrogateType &itype, const InterrogateFunction &ifunc, _num_default_parameters = num_default_parameters; _type = T_normal; _flags = 0; + _args_type = 0; _wrapper_index = 0; _return_value_needs_management = false; @@ -303,26 +304,6 @@ make_wrapper_entry(FunctionIndex function_index) { assert(!iwrapper._parameters.empty()); iwrapper._parameters.front()._parameter_flags |= InterrogateFunctionWrapper::PF_is_this; - - if (_parameters.size() >= 2 && _parameters[1]._name == "self" && - TypeManager::is_pointer_to_PyObject(_parameters[1]._remap->get_orig_type())) { - // Here's a special case. If the first parameter of a nonstatic - // method is a PyObject * called "self", then we will - // automatically fill it in from the this pointer, and remove it - // from the generated parameter list. - _parameters.erase(_parameters.begin() + 1); - _flags |= F_explicit_self; - } - - } else if (_type == T_constructor) { - // We also allow "self" to be passed in to a constructor, even - // though the constructor doesn't normally accept a this pointer. - // But this makes sense to Python programmers. - if (_parameters.size() >= 1 && _parameters[0]._name == "self" && - TypeManager::is_pointer_to_PyObject(_parameters[0]._remap->get_orig_type())) { - _parameters.erase(_parameters.begin() + 0); - _flags |= F_explicit_self; - } } if (!_void_return) { @@ -650,12 +631,32 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak } // Check for a special meaning by name and signature. - if (_type == T_normal) { - int first_param = 0; - if (_has_this) { - first_param = 1; - } + int first_param = 0; + if (_has_this) { + first_param = 1; + } + if (_has_this || _type == T_constructor) { + if (_parameters.size() > first_param && _parameters[first_param]._name == "self" && + TypeManager::is_pointer_to_PyObject(_parameters[first_param]._remap->get_orig_type())) { + // Here's a special case. If the first parameter of a nonstatic + // method is a PyObject * called "self", then we will + // automatically fill it in from the this pointer, and remove it + // from the generated parameter list. + _parameters.erase(_parameters.begin() + first_param); + _flags |= F_explicit_self; + } + } + + if (_parameters.size() == first_param) { + _args_type = InterfaceMaker::AT_no_args; + } else if (_parameters.size() == first_param + 1) { + _args_type = InterfaceMaker::AT_single_arg; + } else { + _args_type = InterfaceMaker::AT_varargs; + } + + if (_type == T_normal) { if (fname == "operator []" || fname == "__getitem__") { _flags |= F_getitem; if (_has_this && _parameters.size() == 2) { @@ -671,6 +672,7 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak if (TypeManager::is_integer(_parameters[1]._remap->get_new_type())) { // Its first parameter is an int parameter, presumably an index. _flags |= F_setitem_int; + _args_type = InterfaceMaker::AT_varargs; } } @@ -681,55 +683,69 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak _flags |= F_size; } - } else if (fname == "make_copy" ) { + } else if (fname == "make_copy") { if (_has_this && _parameters.size() == 1 && TypeManager::is_pointer(_return_type->get_new_type())) { // It receives no parameters, and returns a pointer. _flags |= F_make_copy; } - } else if (fname == "__iter__" ) { + } else if (fname == "__iter__") { if (_has_this && _parameters.size() == 1 && TypeManager::is_pointer(_return_type->get_new_type())) { // It receives no parameters, and returns a pointer. _flags |= F_iter; } - } else if (fname == "__getbuffer__" ) { - if (_has_this && _parameters.size() == 4 && + } else if (fname == "__getbuffer__") { + if (_has_this && _parameters.size() == 3 && TypeManager::is_integer(_return_type->get_new_type()) && - TypeManager::is_pointer_to_PyObject(_parameters[1]._remap->get_orig_type()) && - TypeManager::is_pointer_to_Py_buffer(_parameters[2]._remap->get_orig_type()) && - TypeManager::is_integer(_parameters[3]._remap->get_orig_type())) { + TypeManager::is_pointer_to_Py_buffer(_parameters[1]._remap->get_orig_type()) && + TypeManager::is_integer(_parameters[2]._remap->get_orig_type())) { _flags |= F_getbuffer; } - } else if (fname == "__releasebuffer__" ) { - if (_has_this && _parameters.size() == 3 && - TypeManager::is_pointer_to_PyObject(_parameters[1]._remap->get_orig_type()) && - TypeManager::is_pointer_to_Py_buffer(_parameters[2]._remap->get_orig_type())) { + } else if (fname == "__releasebuffer__") { + if (_has_this && _parameters.size() == 2 && + TypeManager::is_pointer_to_Py_buffer(_parameters[1]._remap->get_orig_type())) { _flags |= F_releasebuffer; } - } else if (fname == "compare_to" ) { + } else if (fname == "compare_to") { if (_has_this && _parameters.size() == 2 && TypeManager::is_integer(_return_type->get_new_type())) { // It receives one parameter, and returns an integer. _flags |= F_compare_to; } + + } else if (fname == "operator ()" || fname == "__call__") { + // Call operators always take keyword arguments. + _args_type = InterfaceMaker::AT_keyword_args; + + } else if (fname == "__setattr__" || fname == "__getattr__") { + // Just to prevent these from getting keyword arguments. + + } else { + if (_args_type == InterfaceMaker::AT_varargs) { + // Every other method can take keyword arguments, if they + // take more than one argument. + _args_type = InterfaceMaker::AT_keyword_args; + } } } else if (_type == T_constructor) { - if (!_has_this && _parameters.size() == 1) { - if (TypeManager::unwrap(_parameters[0]._remap->get_orig_type()) == - TypeManager::unwrap(_return_type->get_orig_type())) { - // If this is the only parameter, and it's the same as the - // "this" type, this is a copy constructor. - _flags |= F_copy_constructor; - } + if (!_has_this && _parameters.size() == 1 && + TypeManager::unwrap(_parameters[0]._remap->get_orig_type()) == + TypeManager::unwrap(_return_type->get_orig_type())) { + // If this is the only parameter, and it's the same as the + // "this" type, this is a copy constructor. + _flags |= F_copy_constructor; + } + // Constructors always take varargs and keyword args. + _args_type = InterfaceMaker::AT_keyword_args; } return true; diff --git a/dtool/src/interrogate/functionRemap.h b/dtool/src/interrogate/functionRemap.h index db23ba0139..ed0ef49507 100644 --- a/dtool/src/interrogate/functionRemap.h +++ b/dtool/src/interrogate/functionRemap.h @@ -107,6 +107,7 @@ public: int _num_default_parameters; Type _type; int _flags; + int _args_type; string _expression; string _function_signature; string _hash; diff --git a/dtool/src/interrogate/interfaceMaker.cxx b/dtool/src/interrogate/interfaceMaker.cxx index 717a0993d8..b980f6b8b0 100644 --- a/dtool/src/interrogate/interfaceMaker.cxx +++ b/dtool/src/interrogate/interfaceMaker.cxx @@ -57,6 +57,7 @@ Function(const string &name, { _has_this = false; _flags = 0; + _args_type = AT_unknown; } //////////////////////////////////////////////////////////////////// @@ -632,13 +633,13 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) { CPPInstance *cppfunc = (*ii).second; CPPFunctionType *ftype = cppfunc->_type->as_function_type(); int max_default_parameters = 0; - + if (separate_overloading()) { // Count up the number of default parameters this function might // take. CPPParameterList *parameters = ftype->_parameters; CPPParameterList::Parameters::reverse_iterator pi; - for (pi = parameters->_parameters.rbegin(); + for (pi = parameters->_parameters.rbegin(); pi != parameters->_parameters.rend(); ++pi) { CPPInstance *param = (*pi); @@ -651,7 +652,7 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) { } } } - + // Now make a different wrapper for each combination of default // parameters. This will happen only if separate_overloading(), // tested above, returned true; otherwise, max_default_parameters @@ -663,7 +664,7 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) { make_function_remap(itype, ifunc, cppfunc, num_default_parameters); if (remap != (FunctionRemap *)NULL) { func->_remaps.push_back(remap); - + // If *any* of the variants of this function has a "this" // pointer, the entire set of functions is deemed to have a // "this" pointer. @@ -672,9 +673,10 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) { } func->_flags |= remap->_flags; - + func->_args_type = (ArgsType)((int)func->_args_type | (int)remap->_args_type); + // Make a wrapper for the function. - FunctionWrapperIndex wrapper_index = + FunctionWrapperIndex wrapper_index = remap->make_wrapper_entry(func_index); if (wrapper_index != 0) { InterrogateFunction &mod_ifunc = idb->update_function(func_index); diff --git a/dtool/src/interrogate/interfaceMaker.h b/dtool/src/interrogate/interfaceMaker.h index 9b12054750..fd0e48f38c 100644 --- a/dtool/src/interrogate/interfaceMaker.h +++ b/dtool/src/interrogate/interfaceMaker.h @@ -71,6 +71,28 @@ public: static ostream &indent(ostream &out, int indent_level); public: + // This contains information about the number + // of arguments that the wrapping function should take. + enum ArgsType { + // This is deliberately engineered such that these + // values can be OR'ed together to produce another + // valid enum value. + AT_unknown = 0x00, + + // The method or function takes no arguments. + AT_no_args = 0x01, + + // There is only a single argument. + AT_single_arg = 0x02, + + // The method takes a variable number of arguments. + AT_varargs = 0x03, + + // The method may take keyword arguments, if appropriate + // in the scripting language. Implies AT_varargs. + AT_keyword_args = 0x07, + }; + class Function { public: Function(const string &name, @@ -85,6 +107,7 @@ public: Remaps _remaps; bool _has_this; int _flags; + ArgsType _args_type; }; typedef vector Functions; Functions _functions; diff --git a/dtool/src/interrogate/interfaceMakerPython.cxx b/dtool/src/interrogate/interfaceMakerPython.cxx index b1b5596fcd..213966c900 100644 --- a/dtool/src/interrogate/interfaceMakerPython.cxx +++ b/dtool/src/interrogate/interfaceMakerPython.cxx @@ -36,17 +36,12 @@ InterfaceMakerPython(InterrogateModuleDef *def) : void InterfaceMakerPython:: write_includes(ostream &out) { InterfaceMaker::write_includes(out); - out << "#undef HAVE_LONG_LONG\n" - << "#undef _POSIX_C_SOURCE\n\n" + out << "#undef _POSIX_C_SOURCE\n\n" << "#if PYTHON_FRAMEWORK\n" << " #include \"Python/Python.h\"\n" << "#else\n" << " #include \"Python.h\"\n" - << "#endif\n" - << "#ifdef HAVE_LONG_LONG\n" - << "#undef HAVE_LONG_LONG\n" - << "#endif \n"; - + << "#endif\n"; } //////////////////////////////////////////////////////////////////// diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index 3e1a465e58..10f421ed8d 100755 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -407,6 +407,12 @@ get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def) { return true; } + if (method_name == "__pow__") { + def._answer_location = "tp_as_number->nb_power"; + def._wrapper_type = WT_ternary_operator; + return true; + } + if (method_name == "operator +=") { def._answer_location = "tp_as_number->nb_inplace_add"; def._wrapper_type = WT_one_param; @@ -470,6 +476,13 @@ get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def) { return true; } + if (method_name == "__ipow__") { + def._answer_location = "tp_as_number->nb_inplace_power"; + def._wrapper_type = WT_one_or_two_params; + def._min_version = 0x02000000; + return true; + } + if (obj->_protocol_types & Object::PT_sequence) { if (func->_flags & FunctionRemap::F_getitem_int) { def._answer_location = "tp_as_sequence->sq_item"; @@ -809,7 +822,7 @@ write_functions(ostream &out) { for (fi = _functions.begin(); fi != _functions.end(); ++fi) { Function *func = (*fi); if (!func->_itype.is_global() && is_function_legal(func)) { - write_function_for_top(out, NULL, func, ""); + write_function_for_top(out, NULL, func); } } @@ -860,43 +873,20 @@ write_class_details(ostream &out, Object *obj) { for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) { Function *func = (*fi); if (func) { - SlottedFunctionDef def; - get_slotted_function_def(obj, func, def); - - ostringstream GetThis; - GetThis << " " << cClassName << " *local_this = NULL;\n"; - GetThis << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; - GetThis << " if (local_this == NULL) {\n"; - if (def._wrapper_type == WT_numeric_operator) { - // WT_numeric_operator means we must return NotImplemented, instead - // of raising an exception, if the this pointer doesn't - // match. This is for things like __sub__, which Python - // likes to call on the wrong-type objects. - GetThis << " Py_INCREF(Py_NotImplemented);\n"; - GetThis << " return Py_NotImplemented;\n"; - - } else { - // Other functions should raise an exception if the this - // pointer isn't set or is the wrong type. - GetThis << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n"; - GetThis << " return NULL;\n"; - } - GetThis << " }\n"; - write_function_for_top(out, obj, func, GetThis.str()); + write_function_for_top(out, obj, func); } } if (obj->_constructors.size() == 0) { - std::string fname = "int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)"; - out << fname << " {\n"; - out << " PyErr_SetString(PyExc_TypeError, \"cannot init constant class (" << cClassName << ")\");\n"; - out << " return -1;\n" ; - out << "}\n\n"; + out << "int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds) {\n" + << " PyErr_SetString(PyExc_TypeError, \"cannot init constant class (" << cClassName << ")\");\n" + << " return -1;\n" + << "}\n\n"; - out - << "int Dtool_InitNoCoerce_" << ClassName << "(PyObject *self, PyObject *args, PyObject *kwds) {\n" - << " return Dtool_Init_" << ClassName << "(self, args, kwds);\n" - << "}\n\n"; + out << "int Dtool_InitNoCoerce_" << ClassName << "(PyObject *self, PyObject *args) {\n" + << " PyErr_SetString(PyExc_TypeError, \"cannot init constant class (" << cClassName << ")\");\n" + << " return -1;\n" + << "}\n\n"; } else { bool coercion_attempted = false; @@ -904,7 +894,7 @@ write_class_details(ostream &out, Object *obj) { Function *func = (*fi); std::string fname = "int Dtool_Init_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)"; - write_function_for_name(out, obj, func, fname, "", ClassName, true, coercion_attempted); + write_function_for_name(out, obj, func, fname, true, coercion_attempted, AT_keyword_args, true); } if (coercion_attempted) { // If a coercion attempt was written into the above constructor, @@ -912,18 +902,17 @@ write_class_details(ostream &out, Object *obj) { // coercion. We'll need this for nested coercion calls. for (fi = obj->_constructors.begin(); fi != obj->_constructors.end(); ++fi) { Function *func = (*fi); - std::string fname = "int Dtool_InitNoCoerce_" + ClassName + "(PyObject *self, PyObject *args, PyObject *kwds)"; + std::string fname = "int Dtool_InitNoCoerce_" + ClassName + "(PyObject *self, PyObject *args)"; - write_function_for_name(out, obj, func, fname, "", ClassName, false, coercion_attempted); + write_function_for_name(out, obj, func, fname, false, coercion_attempted, AT_varargs, true); } } else { // Otherwise, since the above constructor didn't involve any // coercion anyway, we can use the same function for both // purposes. Construct a trivial wrapper. - out - << "int Dtool_InitNoCoerce_" << ClassName << "(PyObject *self, PyObject *args, PyObject *kwds) {\n" - << " return Dtool_Init_" << ClassName << "(self, args, kwds);\n" - << "}\n\n"; + out << "int Dtool_InitNoCoerce_" << ClassName << "(PyObject *self, PyObject *args) {\n" + << " return Dtool_Init_" << ClassName << "(self, args, NULL);\n" + << "}\n\n"; } } @@ -1132,11 +1121,34 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) { if (!func->_itype.is_global() && is_function_legal(func)) { string name1 = methodNameFromCppName(func, "", false); string name2 = methodNameFromCppName(func, "", true); + + string flags; + switch (func->_args_type) { + case AT_keyword_args: + flags = "METH_VARARGS | METH_KEYWORDS"; + break; + + case AT_varargs: + flags = "METH_VARARGS"; + break; + + case AT_single_arg: + flags = "METH_O"; + break; + + default: + flags = "METH_NOARGS"; + break; + } + + // Note: we shouldn't add METH_STATIC here, since both METH_STATIC + // and METH_CLASS are illegal for module-level functions. + out << " { \"" << name1 << "\", (PyCFunction) &" - << func->_name << ", METH_VARARGS | METH_KEYWORDS, (char *)" << func->_name << "_comment},\n"; + << func->_name << ", " << flags << ", (const char *)" << func->_name << "_comment},\n"; if (name1 != name2) { out << " { \"" << name2 << "\", (PyCFunction) &" - << func->_name << ", METH_VARARGS | METH_KEYWORDS, (char *)" << func->_name << "_comment},\n"; + << func->_name << ", " << flags << ", (const char *)" << func->_name << "_comment},\n"; } } } @@ -1239,13 +1251,11 @@ write_module_class(ostream &out, Object *obj) { out << "//********************************************************************\n"; out << "PyMethodDef Dtool_Methods_" << ClassName << "[] = {\n"; - std::map static_functions; std::map slotted_functions; // function Table bool got_copy = false; bool got_deepcopy = false; - int x = 0; for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) { Function *func = (*fi); if (func->_name == "__copy__") { @@ -1254,21 +1264,37 @@ write_module_class(ostream &out, Object *obj) { got_deepcopy = true; } - if (!isFunctionWithThis(func)) { - // Save a reference to this static method, so we can add it - // directly to the class. - static_functions[x] = func; - } - string name1 = methodNameFromCppName(func, export_class_name, false); string name2 = methodNameFromCppName(func, export_class_name, true); + + string flags; + switch (func->_args_type) { + case AT_keyword_args: + flags = "METH_VARARGS | METH_KEYWORDS"; + break; + + case AT_varargs: + flags = "METH_VARARGS"; + break; + + case AT_single_arg: + flags = "METH_O"; + break; + + default: + flags = "METH_NOARGS"; + break; + } + + if (!func->_has_this) { + flags += " | METH_STATIC"; + } + out << " { \"" << name1 << "\", (PyCFunction) &" - << func->_name << ", METH_VARARGS | METH_KEYWORDS, (char *) " << func->_name << "_comment},\n"; - ++x; + << func->_name << ", " << flags << ", (char *) " << func->_name << "_comment},\n"; if (name1 != name2) { out << " { \"" << name2 << "\", (PyCFunction) &" - << func->_name << ", METH_VARARGS | METH_KEYWORDS, (char *) " << func->_name << "_comment},\n"; - ++x; + << func->_name << ", " << flags << ", (char *) " << func->_name << "_comment},\n"; } SlottedFunctionDef slotted_def; @@ -1346,20 +1372,46 @@ write_module_class(ostream &out, Object *obj) { { std::map::iterator rfi; // slotted_functions; for (rfi = slotted_functions.begin(); rfi != slotted_functions.end(); rfi++) { + Function *func = rfi->first; + bool func_varargs = true; + string call_func; + + switch (func->_args_type) { + case AT_keyword_args: + call_func = func->_name + "(self, args, NULL)"; + break; + + case AT_varargs: + call_func = func->_name + "(self, args)"; + break; + + case AT_single_arg: + func_varargs = false; + call_func = func->_name + "(self, arg)"; + break; + + default: + func_varargs = false; + call_func = func->_name + "(self)"; + } + switch (rfi->second._wrapper_type) { case WT_no_params: // PyObject *func(PyObject *self) { - Function *func = rfi->first; out << "//////////////////\n"; out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; out << "//////////////////\n"; out << "static PyObject *" << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self) {\n"; - out << " PyObject *args = Py_BuildValue(\"()\");\n"; - out << " PyObject *result = " << func->_name << "(self, args, NULL);\n"; - out << " Py_DECREF(args);\n"; - out << " return result;\n"; + if (func_varargs) { + out << " PyObject *args = PyTuple_New(0);\n"; + out << " PyObject *result = " << call_func << ";\n"; + out << " Py_DECREF(args);\n"; + out << " return result;\n"; + } else { + out << " return " << call_func << ";\n"; + } out << "}\n\n"; } break; @@ -1368,16 +1420,19 @@ write_module_class(ostream &out, Object *obj) { case WT_numeric_operator: // PyObject *func(PyObject *self, PyObject *one) { - Function *func = rfi->first; out << "//////////////////\n"; out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; out << "//////////////////\n"; - out << "static PyObject *" << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, PyObject *one) {\n"; - out << " PyObject *args = Py_BuildValue(\"(O)\", one);\n"; - out << " PyObject *result = " << func->_name << "(self, args, NULL);\n"; - out << " Py_DECREF(args);\n"; - out << " return result;\n"; + out << "static PyObject *" << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, PyObject *arg) {\n"; + if (func_varargs) { + out << " PyObject *args = PyTuple_Pack(1, arg);\n"; + out << " PyObject *result = " << call_func << ";\n"; + out << " Py_DECREF(args);\n"; + out << " return result;\n"; + } else { + out << " return " << call_func << ";\n"; + } out << "}\n\n"; } break; @@ -1385,20 +1440,23 @@ write_module_class(ostream &out, Object *obj) { case WT_setattr: // int func(PyObject *self, PyObject *one, PyObject *two = NULL) { - Function *func = rfi->first; out << "//////////////////\n"; out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; out << "//////////////////\n"; - out << "static int " << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, PyObject *one, PyObject *two) {\n"; - out << " PyObject *args;\n"; - out << " if (two == NULL) {\n"; - out << " args = Py_BuildValue(\"(O)\", one);\n"; - out << " } else {\n"; - out << " args = Py_BuildValue(\"(OO)\", one, two);\n"; - out << " }\n"; - out << " PyObject *py_result = " << func->_name << "(self, args, NULL);\n"; - out << " Py_DECREF(args);\n"; + out << "static int " << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, PyObject *arg, PyObject *arg2) {\n"; + if (func_varargs) { + out << " PyObject *args;\n"; + out << " if (arg2 == NULL) {\n"; + out << " args = PyTuple_Pack(1, arg);\n"; + out << " } else {\n"; + out << " args = PyTuple_Pack(2, arg, arg2);\n"; + out << " }\n"; + out << " PyObject *py_result = " << call_func << ";\n"; + out << " Py_DECREF(args);\n"; + } else { + out << " PyObject *py_result = " << call_func << ";\n"; + } out << " if (py_result == NULL) return -1;\n"; out << "#if PY_MAJOR_VERSION >= 3\n"; out << " int result = PyLong_AsLong(py_result);\n"; @@ -1417,18 +1475,21 @@ write_module_class(ostream &out, Object *obj) { // With special handling to pass up to // PyObject_GenericGetAttr() if it returns NULL. { - Function *func = rfi->first; out << "//////////////////\n"; out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; out << "//////////////////\n"; - out << "static PyObject *" << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, PyObject *one) {\n"; - out << " PyObject *args = Py_BuildValue(\"(O)\", one);\n"; - out << " PyObject *result = " << func->_name << "(self, args, NULL);\n"; - out << " Py_DECREF(args);\n"; + out << "static PyObject *" << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, PyObject *arg) {\n"; + if (func_varargs) { + out << " PyObject *args = PyTuple_Pack(1, arg);\n"; + out << " PyObject *result = " << call_func << ";\n"; + out << " Py_DECREF(args);\n"; + } else { + out << " PyObject *result = " << call_func << ";\n"; + } out << " if (result == NULL) {\n"; - out << " PyErr_Clear();\n"; - out << " return PyObject_GenericGetAttr(self, one);\n"; + out << " PyErr_Clear();\n"; + out << " return PyObject_GenericGetAttr(self, arg);\n"; out << " }\n"; out << " return result;\n"; out << "}\n\n"; @@ -1438,16 +1499,43 @@ write_module_class(ostream &out, Object *obj) { case WT_sequence_getitem: // PyObject *func(PyObject *self, Py_ssize_t index) { - Function *func = rfi->first; out << "//////////////////\n"; out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; out << "//////////////////\n"; out << "static PyObject *" << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, Py_ssize_t index) {\n"; - out << " PyObject *args = Py_BuildValue(\"(i)\", index);\n"; - out << " PyObject *result = " << func->_name << "(self, args, NULL);\n"; - out << " Py_DECREF(args);\n"; - out << " return result;\n"; + out << " " << cClassName << " *local_this = NULL;\n"; + out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; + out << " if (local_this == NULL) {\n"; + out << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n"; + out << " return NULL;\n"; + out << " }\n\n"; + + // This is a getitem or setitem of a sequence type. This means we + // *need* to raise IndexError if we're out of bounds. We have to + // assume the bounds are 0 .. this->size() (this is the same + // assumption that Python makes). + out << " if (index < 0 || index >= local_this->size()) {\n"; + out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << " index out of range\");\n"; + out << " return NULL;\n"; + out << " }\n"; + + // Gather the remaps with the F_getitem_int flag. + std::set remaps; + Function::Remaps::const_iterator ri; + for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { + FunctionRemap *remap = (*ri); + if (is_remap_legal(remap) && (remap->_flags & FunctionRemap::F_getitem_int)) { + remaps.insert(remap); + } + } + + string expected_params; + bool coercion_attempted = false; + write_function_forset(out, obj, func, remaps, expected_params, 2, false, false, + coercion_attempted, AT_no_args, false, "index"); + + out << " return NULL;\n"; out << "}\n\n"; } break; @@ -1455,20 +1543,48 @@ write_module_class(ostream &out, Object *obj) { case WT_sequence_setitem: // int_t func(PyObject *self, Py_ssize_t index, PyObject *value) { - Function *func = rfi->first; out << "//////////////////\n"; out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; out << "//////////////////\n"; - out << "static int " << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, Py_ssize_t index, PyObject *value) {\n"; - out << " PyObject *args = Py_BuildValue(\"(iO)\", index, value);\n"; - out << " PyObject *result = " << func->_name << "(self, args, NULL);\n"; - out << " Py_DECREF(args);\n"; - out << " if (result == NULL) {\n"; + out << "static int " << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, Py_ssize_t index, PyObject *arg) {\n"; + out << " " << cClassName << " *local_this = NULL;\n"; + out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; + out << " if (local_this == NULL) {\n"; + out << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n"; + out << " return -1;\n"; + out << " }\n\n"; + + out << " if (index < 0 || index >= local_this->size()) {\n"; + out << " PyErr_SetString(PyExc_IndexError, \"" << ClassName << " index out of range\");\n"; out << " return -1;\n"; out << " }\n"; - out << " Py_DECREF(result);\n"; - out << " return 0;\n"; + + // Gather the remaps with the F_getitem_int flag. + std::set remaps; + Function::Remaps::const_iterator ri; + for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { + FunctionRemap *remap = (*ri); + if (is_remap_legal(remap) && (remap->_flags & FunctionRemap::F_setitem_int)) { + remaps.insert(remap); + } + } + + // Note: we disallow parameter coercion for setitem. It's not clear if anybody + // uses it in this case, and since some people may need to call this function + // very often, it's probably best to disable it for performance. + string expected_params; + bool coercion_attempted = false; + write_function_forset(out, obj, func, remaps, expected_params, 2, false, false, + coercion_attempted, AT_single_arg, true, "index"); + + out << " if (!PyErr_Occurred()) {\n"; + out << " PyErr_SetString(PyExc_TypeError,\n"; + out << " \"Arguments must match:\\n\"\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return -1;\n"; out << "}\n\n"; } break; @@ -1476,25 +1592,20 @@ write_module_class(ostream &out, Object *obj) { case WT_sequence_size: // Py_ssize_t func(PyObject *self) { - Function *func = rfi->first; out << "//////////////////\n"; out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; out << "//////////////////\n"; out << "static Py_ssize_t " << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self) {\n"; - out << " PyObject *args = Py_BuildValue(\"()\");\n"; - out << " PyObject *result = " << func->_name << "(self, args, NULL);\n"; - out << " Py_DECREF(args);\n"; - out << " if (result == NULL) {\n"; + out << " " << cClassName << " *local_this = NULL;\n"; + out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; + out << " if (local_this == NULL) {\n"; + out << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n"; out << " return -1;\n"; - out << " }\n"; - out << "#if PY_MAJOR_VERSION >= 3\n"; - out << " Py_ssize_t num = PyLong_AsSsize_t(result);\n"; - out << "#else\n"; - out << " Py_ssize_t num = PyInt_AsSsize_t(result);\n"; - out << "#endif\n"; - out << " Py_DECREF(result);\n"; - out << " return num;\n"; + out << " }\n\n"; + + // This is a cheap cheat around all of the overhead of calling the wrapper function. + out << " return (Py_ssize_t) local_this->" << func->_ifunc.get_name() << "();\n"; out << "}\n\n"; } break; @@ -1502,15 +1613,18 @@ write_module_class(ostream &out, Object *obj) { case WT_mapping_setitem: // int func(PyObject *self, PyObject *one, PyObject *two) { - Function *func = rfi->first; out << "//////////////////\n"; out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; out << "//////////////////\n"; - out << "static int " << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, PyObject *one, PyObject *two) {\n"; - out << " PyObject *args = Py_BuildValue(\"(OO)\", one, two);\n"; - out << " PyObject *result = " << func->_name << "(self, args, NULL);\n"; - out << " Py_DECREF(args);\n"; + out << "static int " << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, PyObject *arg, PyObject *arg2) {\n"; + if (func_varargs) { + out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n"; + out << " PyObject *result = " << call_func << ";\n"; + out << " Py_DECREF(args);\n"; + } else { + out << " PyObject *result = " << call_func << ";\n"; + } out << " if (result == NULL) {\n"; out << " return -1;\n"; out << " }\n"; @@ -1523,15 +1637,18 @@ write_module_class(ostream &out, Object *obj) { case WT_inquiry: // int func(PyObject *self) { - Function *func = rfi->first; out << "//////////////////\n"; out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; out << "//////////////////\n"; out << "static int " << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self) {\n"; - out << " PyObject *args = Py_BuildValue(\"()\");\n"; - out << " PyObject *result = " << func->_name << "(self, args, NULL);\n"; - out << " Py_DECREF(args);\n"; + if (func_varargs) { + out << " PyObject *args = PyTuple_New(0);\n"; + out << " PyObject *result = " << call_func << ";\n"; + out << " Py_DECREF(args);\n"; + } else { + out << " PyObject *result = " << call_func << ";\n"; + } out << " if (result == NULL) {\n"; out << " return -1;\n"; out << " }\n"; @@ -1555,7 +1672,6 @@ write_module_class(ostream &out, Object *obj) { { has_local_getbuffer = true; - Function *func = rfi->first; out << "//////////////////\n"; out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; @@ -1628,7 +1744,6 @@ write_module_class(ostream &out, Object *obj) { // void __releasebuffer__(PyObject *self, Py_buffer *buffer) // Same story as __getbuffer__ above. { - Function *func = rfi->first; out << "//////////////////\n"; out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; @@ -1705,15 +1820,18 @@ write_module_class(ostream &out, Object *obj) { // PyObject *func(PyObject *self) // However, returns NULL instead of None { - Function *func = rfi->first; out << "//////////////////\n"; out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; out << "//////////////////\n"; out << "static PyObject *" << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self) {\n"; - out << " PyObject *args = Py_BuildValue(\"()\");\n"; - out << " PyObject *result = " << func->_name << "(self, args, NULL);\n"; - out << " Py_DECREF(args);\n"; + if (func_varargs) { + out << " PyObject *args = PyTuple_New(0);\n"; + out << " PyObject *result = " << call_func << ";\n"; + out << " Py_DECREF(args);\n"; + } else { + out << " PyObject *result = " << call_func << ";\n"; + } out << " if (result == Py_None) {\n"; out << " Py_DECREF(Py_None);\n"; out << " return NULL;\n"; @@ -1724,6 +1842,32 @@ write_module_class(ostream &out, Object *obj) { } break; + case WT_one_or_two_params: + case WT_ternary_operator: + // PyObject *func(PyObject *self, PyObject *one, PyObject *two) + { + out << "//////////////////\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " ..." << rfi->second._answer_location << " = " << methodNameFromCppName(func, export_class_name, false) << "\n"; + out << "//////////////////\n"; + out << "static PyObject *" << func->_name << methodNameFromCppName(func, export_class_name, false) << "(PyObject *self, PyObject *arg, PyObject *arg2) {\n"; + if (func_varargs) { + out << " PyObject *args;\n"; + out << " if (arg2 != Py_None) {\n"; + out << " args = PyTuple_Pack(2, arg, arg2);\n"; + out << " } else {\n"; + out << " args = PyTuple_Pack(1, arg);\n"; + out << " }\n\n"; + out << " PyObject *result = " << call_func << ";\n"; + out << " Py_DECREF(args);\n"; + out << " return result;\n"; + } else { + out << " return " << call_func << ";\n"; + } + out << "}\n\n"; + } + break; + case WT_none: break; } @@ -1828,24 +1972,17 @@ write_module_class(ostream &out, Object *obj) { } if (NeedsARichCompareFunction(obj->_itype)) { - // NB. It's a bit inefficient to first pack the 'other' arg into a - // tuple only to be parsed by PyArg_Parse again later, but there's - // no obvious other way to do it. out << "//////////////////\n"; out << "// A rich comparison function\n"; out << "// " << ClassName << "\n"; out << "//////////////////\n"; - out << "static PyObject *Dtool_RichCompare_" << ClassName << "(PyObject *self, PyObject *other, int op) {\n"; - out << " PyObject *kwds = NULL;\n"; + out << "static PyObject *Dtool_RichCompare_" << ClassName << "(PyObject *self, PyObject *arg, int op) {\n"; out << " " << cClassName << " *local_this = NULL;\n"; out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; out << " if (local_this == NULL) {\n"; out << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n"; out << " return NULL;\n"; - out << " }\n"; - out << " PyObject *args = PyTuple_Pack(1, other);\n"; - string args_cleanup = "Py_DECREF(args);"; - out << "\n"; + out << " }\n\n"; out << " switch (op) {\n"; Function *compare_to_func = NULL; @@ -1859,23 +1996,23 @@ write_module_class(ostream &out, Object *obj) { Function::Remaps::const_iterator ri; for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { FunctionRemap *remap = (*ri); - if (is_remap_legal(*remap) && remap->_has_this && remap->_parameters.size() == 2) { + if (is_remap_legal(remap) && remap->_has_this && (remap->_args_type == AT_single_arg)) { remaps.insert(remap); } } const string &fname = func->_ifunc.get_name(); if (fname == "operator <") { - out << " case Py_LT:\n"; + out << " case Py_LT: {\n"; } else if (fname == "operator <=") { - out << " case Py_LE:\n"; + out << " case Py_LE: {\n"; } else if (fname == "operator ==") { - out << " case Py_EQ:\n"; + out << " case Py_EQ: {\n"; } else if (fname == "operator !=") { - out << " case Py_NE:\n"; + out << " case Py_NE: {\n"; } else if (fname == "operator >") { - out << " case Py_GT:\n"; + out << " case Py_GT: {\n"; } else if (fname == "operator >=") { - out << " case Py_GE:\n"; + out << " case Py_GE: {\n"; } else if (fname == "compare_to") { compare_to_func = func; continue; @@ -1883,21 +2020,21 @@ write_module_class(ostream &out, Object *obj) { continue; } - ostringstream forward_decl; string expected_params; bool coercion_attempted = false; - write_function_forset(out, obj, func, remaps, expected_params, 2, forward_decl, false, true, coercion_attempted, args_cleanup); + write_function_forset(out, obj, func, remaps, expected_params, 4, false, true, + coercion_attempted, AT_single_arg, false); - out << " if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError)) {\n"; - out << " PyErr_Clear();\n"; + out << " if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError)) {\n"; + out << " PyErr_Clear();\n"; + out << " }\n"; + out << " break;\n"; out << " }\n"; - out << " break;\n"; has_local_richcompare = true; } out << " }\n\n"; - out << " " << args_cleanup << "\n"; out << " if (PyErr_Occurred()) {\n"; out << " return (PyObject *)NULL;\n"; out << " }\n\n"; @@ -1905,7 +2042,7 @@ write_module_class(ostream &out, Object *obj) { if (compare_to_func != NULL) { out << "#if PY_MAJOR_VERSION >= 3\n"; out << " // All is not lost; we still have the compare_to function to fall back onto.\n"; - out << " PyObject *result = " << compare_to_func->_name << "(self, args, kwds);\n"; + out << " PyObject *result = " << compare_to_func->_name << "(self, arg);\n"; out << " if (result != NULL) {\n"; out << " if (PyLong_Check(result)) {;\n"; out << " long cmpval = PyLong_AsLong(result);\n"; @@ -1976,23 +2113,21 @@ write_module_class(ostream &out, Object *obj) { // add bases/// if (bases.size() > 0) { out << " // Dependent objects\n"; - std::string format1 = ""; - std::string format2 = ""; - for (std::vector::iterator bi = bases.begin(); bi != bases.end(); bi++) { - format1 += "O"; - format2 += ", &Dtool_" + *bi + ".As_PyTypeObject()"; + string baseargs; + for (vector::iterator bi = bases.begin(); bi != bases.end(); ++bi) { + baseargs += ", &Dtool_" + *bi + ".As_PyTypeObject()"; out << " Dtool_" << make_safe_name(*bi) << "._Dtool_ClassInit(NULL);\n"; } - out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_bases = Py_BuildValue(\"(" << format1 << ")\"" << format2 << ");\n"; + out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_bases = PyTuple_Pack(" << bases.size() << baseargs << ");\n"; } // get dictionary out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_dict = PyDict_New();\n"; - out << " PyDict_SetItemString(Dtool_" <::const_iterator rfi; + map::const_iterator rfi; int prev_min_version = 0; for (rfi = slotted_functions.begin(); rfi != slotted_functions.end(); rfi++) { @@ -2077,7 +2212,14 @@ write_module_class(ostream &out, Object *obj) { int enum_count = nested_obj->_itype.number_of_enum_values(); for (int xx = 0; xx < enum_count; xx++) { string name1 = classNameFromCppName(nested_obj->_itype.get_enum_value_name(xx), false); - string name2 = classNameFromCppName(nested_obj->_itype.get_enum_value_name(xx), true); + string name2; + if (nested_obj->_itype.has_true_name()) { + name2 = classNameFromCppName(nested_obj->_itype.get_enum_value_name(xx), true); + } else { + // Don't generate the alternative syntax for anonymous enums, since we added support + // for those after we started deprecating the alternative syntax. + name2 = name1; + } int enum_value = nested_obj->_itype.get_enum_value(xx); out << "#if PY_MAJOR_VERSION >= 3\n"; out << " PyDict_SetItemString(Dtool_" << ClassName << ".As_PyTypeObject().tp_dict, \"" << name1 << "\", PyLong_FromLong(" << enum_value << "));\n"; @@ -2106,25 +2248,6 @@ write_module_class(ostream &out, Object *obj) { // Why make the class a member of itself? //out << " PyDict_SetItemString(Dtool_" <::iterator sfi; - for (sfi = static_functions.begin(); sfi != static_functions.end(); sfi++) { - out << " // Static Method " << methodNameFromCppName(sfi->second, export_class_name, false) << "\n"; - string name1 = methodNameFromCppName(sfi->second, export_class_name, false); - string name2 = methodNameFromCppName(sfi->second, export_class_name, true); - out << " PyDict_SetItemString(Dtool_" << ClassName - << ".As_PyTypeObject().tp_dict, \"" << name1 - << "\", PyCFunction_New(&Dtool_Methods_" << ClassName << "[" << sfi->first - << "], &Dtool_" << ClassName << ".As_PyObject()));\n"; - if (name1 != name2) { - out << " PyDict_SetItemString(Dtool_" << ClassName - << ".As_PyTypeObject().tp_dict, \"" << name2 - << "\", PyCFunction_New(&Dtool_Methods_" << ClassName << "[" << sfi->first - << "], &Dtool_" << ClassName << ".As_PyObject()));\n"; - } - } - bool is_runtime_typed = IsPandaTypedObject(obj->_itype._cpptype->as_struct_type()); if (HasAGetClassTypeFunction(obj->_itype)) { is_runtime_typed = true; @@ -2243,11 +2366,37 @@ write_prototype_for_name(ostream &out, InterfaceMaker::Function *func, const std // the indicated C++ function or method. //////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: -write_function_for_top(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker::Function *func, const std::string &PreProcess) { - std::string fname = "static PyObject *" + func->_name + "(PyObject *self, PyObject *args, PyObject *kwds)"; +write_function_for_top(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker::Function *func) { + std::string fname; + + if (func->_ifunc.is_unary_op()) { + assert(func->_args_type == AT_no_args); + } + + fname = "static PyObject *" + func->_name + "(PyObject *"; + + // This will be NULL for static funcs, so prevent code from using it. + if (func->_has_this) { + fname += "self"; + } + + switch (func->_args_type) { + case AT_keyword_args: + fname += ", PyObject *args, PyObject *kwds"; + break; + + case AT_varargs: + fname += ", PyObject *args"; + break; + + case AT_single_arg: + fname += ", PyObject *arg"; + break; + } + fname += ")"; bool coercion_attempted = false; - write_function_for_name(out, obj, func, fname, PreProcess, "", true, coercion_attempted); + write_function_for_name(out, obj, func, fname, true, coercion_attempted, func->_args_type, false); } //////////////////////////////////////////////////////////////////// @@ -2256,11 +2405,10 @@ write_function_for_top(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker // Wrap a complete name override function for Py..... //////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: -write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMaker::Function *func, - const std::string &function_name, - const std::string &PreProcess, - const std::string &ClassName, bool coercion_allowed, bool &coercion_attempted) { - ostringstream forward_decl; +write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMaker::Function *func, + const std::string &function_name, + bool coercion_allowed, bool &coercion_attempted, + ArgsType args_type, bool return_int) { ostringstream out; std::map > MapSets; @@ -2271,10 +2419,11 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak out1 << "/******************************************************************\n" << " * Python type method wrapper for\n"; for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { FunctionRemap *remap = (*ri); - if (is_remap_legal(*remap)) { + if (is_remap_legal(remap)) { int parameter_size = remap->_parameters.size(); - if (remap->_has_this && remap->_type != FunctionRemap::T_constructor) + if (remap->_has_this && remap->_type != FunctionRemap::T_constructor) { parameter_size --; + } MapSets[parameter_size].insert(remap); out1 << " * "; @@ -2290,8 +2439,33 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak out1 << " *******************************************************************/\n"; out << function_name << " {\n"; - if (isFunctionWithThis(func)) { - out << PreProcess; + + if (func->_has_this) { + // Extract pointer from 'self' parameter. + std::string ClassName = make_safe_name(obj->_itype.get_scoped_name()); + std::string cClassName = obj->_itype.get_true_name(); + + SlottedFunctionDef def; + get_slotted_function_def(obj, func, def); + + out << " " << cClassName << " *local_this = NULL;\n"; + out << " DTOOL_Call_ExtractThisPointerForType(self, &Dtool_" << ClassName << ", (void **)&local_this);\n"; + out << " if (local_this == NULL) {\n"; + if (def._wrapper_type == WT_numeric_operator || def._wrapper_type == WT_ternary_operator) { + // WT_numeric_operator means we must return NotImplemented, instead + // of raising an exception, if the this pointer doesn't + // match. This is for things like __sub__, which Python + // likes to call on the wrong-type objects. + out << " Py_INCREF(Py_NotImplemented);\n"; + out << " return Py_NotImplemented;\n"; + + } else { + // Other functions should raise an exception if the this + // pointer isn't set or is the wrong type. + out << " PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n"; + out << " return NULL;\n"; + } + out << " }\n"; } bool is_inplace = isInplaceFunction(func); @@ -2306,35 +2480,47 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak FunctionComment += "\n"; } - bool constructor = false; - if (MapSets.size() > 1) { string expected_params; - indent(out, 2) << "int parameter_count = 1;\n"; - indent(out, 2) << "if (PyTuple_Check(args)) {\n"; - indent(out, 2) << " parameter_count = PyTuple_Size(args);\n"; - indent(out, 2) << " if (kwds != NULL && PyDict_Check(kwds)) {\n"; - indent(out, 2) << " parameter_count += PyDict_Size(kwds);\n"; - indent(out, 2) << " }\n"; - indent(out, 2) << "}\n"; + switch (args_type) { + case AT_keyword_args: + indent(out, 2) << "int parameter_count = PyTuple_Size(args);\n"; + + if (args_type == AT_keyword_args) { + indent(out, 2) << "if (kwds != NULL && PyDict_Check(kwds)) {\n"; + indent(out, 2) << " parameter_count += PyDict_Size(kwds);\n"; + indent(out, 2) << "}\n"; + } + break; + + case AT_varargs: + indent(out, 2) << "int parameter_count = PyTuple_Size(args);\n"; + break; + + case AT_single_arg: + // It shouldÅ„'t get here, but we'll handle these cases nonetheless. + indent(out, 2) << "const int parameter_count = 1;\n"; + break; + + default: + indent(out, 2) << "const int parameter_count = 0;\n"; + break; + } indent(out, 2) << "switch (parameter_count) {\n"; for (mii = MapSets.begin(); mii != MapSets.end(); mii ++) { indent(out, 2) << "case " << mii->first << ": {\n"; - write_function_forset(out, obj, func, mii->second, expected_params, 4, forward_decl, is_inplace, coercion_allowed, coercion_attempted, ""); - if ((*mii->second.begin())->_type == FunctionRemap::T_constructor) { - constructor = true; - } + write_function_forset(out, obj, func, mii->second, expected_params, 4, is_inplace, + coercion_allowed, coercion_attempted, args_type, return_int); - indent(out, 4) << "}\n"; indent(out, 4) << "break;\n"; + indent(out, 2) << "}\n"; } indent(out, 2) << "default:\n"; - indent(out, 4) << "{\n"; - indent(out, 6) + indent(out, 4) << "PyErr_Format(PyExc_TypeError, \"" << methodNameFromCppName(func, "", false) << "() takes "; @@ -2361,13 +2547,12 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak out << " arguments (%d given)\", parameter_count + " << add_self << ");\n"; - if (constructor) - indent(out, 6) << "return -1;\n"; - else - indent(out, 6) << "return (PyObject *) NULL;\n"; + if (return_int) { + indent(out, 4) << "return -1;\n"; + } else { + indent(out, 4) << "return (PyObject *) NULL;\n"; + } - indent(out, 4) << "}\n"; - indent(out, 4) << "break;\n"; indent(out, 2) << "}\n"; out << " if (!PyErr_Occurred()) { // Let error pass on\n"; @@ -2377,7 +2562,7 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak out << ");\n"; out << " }\n"; - if (constructor) { + if (return_int) { indent(out, 2) << "return -1;\n"; } else { indent(out, 2) << "return (PyObject *) NULL;\n"; @@ -2392,10 +2577,8 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak } else { string expected_params = ""; for (mii = MapSets.begin(); mii != MapSets.end(); mii++) { - write_function_forset(out, obj, func, mii->second, expected_params, 2, forward_decl, is_inplace, coercion_allowed, coercion_attempted, ""); - if ((*mii->second.begin())->_type == FunctionRemap::T_constructor) { - constructor = true; - } + write_function_forset(out, obj, func, mii->second, expected_params, 2, is_inplace, + coercion_allowed, coercion_attempted, args_type, return_int); } out << " if (!PyErr_Occurred()) {\n"; @@ -2404,7 +2587,8 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak output_quoted(out, 6, expected_params); out << ");\n"; out << " }\n"; - if (constructor) { + + if (return_int) { indent(out, 2) << "return -1;\n"; } else { indent(out, 2) << "return (PyObject *) NULL;\n"; @@ -2423,7 +2607,7 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak FunctionComment = FunctionComment1 + "\n" + FunctionComment; } - if (!constructor) { + if (!return_int) { // Write out the function doc string. We only do this if it is // not a constructor, since we don't have a place to put the // constructor doc string. @@ -2439,7 +2623,6 @@ write_function_for_name(ostream &out1, InterfaceMaker::Object *obj, InterfaceMak out << "\n"; - out1 << forward_decl.str(); out1 << out.str(); } @@ -2492,20 +2675,41 @@ int GetParnetDepth(CPPType *type) { //////////////////////////////////////////////////////// // The Core sort function for remap calling orders.. ////////////////////////////////////////////////////////// -int RemapCompareLess(FunctionRemap *in1, FunctionRemap *in2) { +bool RemapCompareLess(FunctionRemap *in1, FunctionRemap *in2) { + assert(in1 != NULL); + assert(in2 != NULL); + if (in1->_parameters.size() != in2->_parameters.size()) { - return (in1->_parameters.size() > in2->_parameters.size()); + return (in1->_parameters.size() > in2->_parameters.size()); } int pcount = in1->_parameters.size(); - for (int x = 0; x< pcount; x++) { + for (int x = 0; x < pcount; x++) { CPPType *orig_type1 = in1->_parameters[x]._remap->get_orig_type(); CPPType *orig_type2 = in2->_parameters[x]._remap->get_orig_type(); + // Hack to make int sort before float and double. We do + // this by letting everything compare less than float types. + // But if there's a double variant, prefer it over the float variant. + if (TypeManager::is_float(orig_type1) && + !TypeManager::is_double(orig_type1)) { + return false; + } + if (TypeManager::is_float(orig_type2) && + !TypeManager::is_double(orig_type2)) { + return true; + } + if (TypeManager::is_float(orig_type1)) { + return false; + } + if (TypeManager::is_float(orig_type2)) { + return true; + } + int pd1 = GetParnetDepth(orig_type1); int pd2 = GetParnetDepth(orig_type2); if (pd1 != pd2) { - return pd1 > pd2; + return (pd1 > pd2); } } @@ -2514,20 +2718,6 @@ int RemapCompareLess(FunctionRemap *in1, FunctionRemap *in2) { return false; } -////////////////////////////////////////////////////////// -// Convience for the sort behavior.. -/////////////////////////////////////////////////////////// -std::vector -SortFunctionSet(std::set &remaps) { - std::vector out; - for (std::set::iterator ii = remaps.begin(); ii!= remaps.end(); ii++) { - out.push_back(*ii); - } - - std::sort(out.begin(), out.end(), RemapCompareLess); - return out; -} - /////////////////////////////////////////////////////////// // Function : write_function_forset // @@ -2538,10 +2728,10 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, InterfaceMaker::Function *func, std::set &remapsin, string &expected_params, int indent_level, - ostream &forward_decl, bool is_inplace, - bool coercion_allowed, + bool is_inplace, bool coercion_allowed, bool &coercion_attempted, - const string &args_cleanup) { + ArgsType args_type, + bool return_int, const string &first_pexpr) { // Do we accept any parameters that are class objects? If so, we // might need to check for parameter coercion. bool coercion_possible = false; @@ -2549,27 +2739,25 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, std::set::const_iterator sii; for (sii = remapsin.begin(); sii != remapsin.end() && !coercion_possible; ++sii) { FunctionRemap *remap = (*sii); - if (is_remap_legal(*remap)) { - int pn = 0; - if (remap->_has_this) { - // Skip the "this" parameter. It's never coercible. - ++pn; - } - while (pn < (int)remap->_parameters.size()) { - CPPType *type = remap->_parameters[pn]._remap->get_new_type(); + int pn = 0; + if (remap->_has_this) { + // Skip the "this" parameter. It's never coercible. + ++pn; + } + while (pn < (int)remap->_parameters.size()) { + CPPType *type = remap->_parameters[pn]._remap->get_new_type(); - if (TypeManager::is_char_pointer(type)) { - } else if (TypeManager::is_wchar_pointer(type)) { - } else if (TypeManager::is_pointer_to_PyObject(type)) { - } else if (TypeManager::is_pointer_to_Py_buffer(type)) { - } else if (TypeManager::is_pointer(type)) { - // This is a pointer to an object, so we - // might be able to coerce a parameter to it. - coercion_possible = true; - break; - } - ++pn; + if (TypeManager::is_char_pointer(type)) { + } else if (TypeManager::is_wchar_pointer(type)) { + } else if (TypeManager::is_pointer_to_PyObject(type)) { + } else if (TypeManager::is_pointer_to_Py_buffer(type)) { + } else if (TypeManager::is_pointer(type)) { + // This is a pointer to an object, so we + // might be able to coerce a parameter to it. + coercion_possible = true; + break; } + ++pn; } } } @@ -2589,36 +2777,38 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, indent(out, indent_level) << "while (true) {\n"; indent_level += 2; + } else { + out << "\n"; } if (remapsin.size() > 1) { // There are multiple different overloads for this number of // parameters. Sort them all into order from most-specific to // least-specific, then try them one at a time. - std::vector remaps = SortFunctionSet(remapsin); + std::vector remaps (remapsin.begin(), remapsin.end()); + std::sort(remaps.begin(), remaps.end(), RemapCompareLess); std::vector::iterator sii; for (sii = remaps.begin(); sii != remaps.end(); sii ++) { FunctionRemap *remap = (*sii); - if (is_remap_legal(*remap)) { - if (remap->_has_this && !remap->_const_method) { - // If it's a non-const method, we only allow a - // non-const this. - indent(out, indent_level) - << "if (!((Dtool_PyInstDef *)self)->_is_const) {\n"; - } else { - indent(out, indent_level) - << "{\n"; - } - - indent(out, indent_level) << "// -2 "; - remap->write_orig_prototype(out, 0); out << "\n"; - - write_function_instance(out, obj, func, remap, expected_params, indent_level + 2, false, forward_decl, func->_name, is_inplace, coercion_possible, coercion_attempted, args_cleanup); - - indent(out, indent_level + 2) << "PyErr_Clear();\n"; - indent(out, indent_level) << "}\n\n"; + if (remap->_has_this && !remap->_const_method) { + // If it's a non-const method, we only allow a + // non-const this. + indent(out, indent_level) + << "if (!((Dtool_PyInstDef *)self)->_is_const) {\n"; + } else { + indent(out, indent_level) + << "{\n"; } + + indent(out, indent_level) << "// -2 "; + remap->write_orig_prototype(out, 0); out << "\n"; + + write_function_instance(out, obj, func, remap, expected_params, indent_level + 2, is_inplace, + coercion_possible, coercion_attempted, args_type, return_int, first_pexpr); + + indent(out, indent_level + 2) << "PyErr_Clear();\n"; + indent(out, indent_level) << "}\n\n"; } } else { // There is only one possible overload with this number of @@ -2626,46 +2816,46 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, std::set::iterator sii; for (sii = remapsin.begin(); sii != remapsin.end(); sii ++) { FunctionRemap *remap = (*sii); - if (is_remap_legal(*remap)) { - if (remap->_has_this && !remap->_const_method) { - // If it's a non-const method, we only allow a - // non-const this. + if (remap->_has_this && !remap->_const_method) { + // If it's a non-const method, we only allow a + // non-const this. + indent(out, indent_level) + << "if (!((Dtool_PyInstDef *)self)->_is_const) {\n"; + indent_level += 2; + } + + indent(out, indent_level) + << "// 1-" ; + remap->write_orig_prototype(out, 0); + out << "\n" ; + write_function_instance(out, obj, func, remap, expected_params, indent_level, is_inplace, + coercion_possible, coercion_attempted, args_type, return_int, first_pexpr); + + if (remap->_has_this && !remap->_const_method) { + indent(out, indent_level - 2) + << "} else {\n"; + indent(out, indent_level) + << "PyErr_SetString(PyExc_TypeError,\n"; + string class_name = remap->_cpptype->get_simple_name(); + indent(out, indent_level) + << " \"Cannot call " + << classNameFromCppName(class_name, false) + << "." << methodNameFromCppName(func, class_name, false) + << "() on a const object.\");\n"; + + if (return_int) { indent(out, indent_level) - << "if (!((Dtool_PyInstDef *)self)->_is_const) {\n"; + << "return -1;\n"; } else { indent(out, indent_level) - << "{\n"; - } - - indent(out, indent_level + 2) - << "// 1-" ; - remap->write_orig_prototype(out, 0); - out << "\n" ; - write_function_instance(out, obj, func, remap, expected_params, indent_level + 2, true, forward_decl, func->_name, is_inplace, coercion_possible, coercion_attempted, args_cleanup); - - if (remap->_has_this && !remap->_const_method) { - indent(out, indent_level) - << "} else {\n"; - indent(out, indent_level + 2) - << "PyErr_SetString(PyExc_TypeError,\n"; - string class_name = remap->_cpptype->get_simple_name(); - indent(out, indent_level + 2) - << " \"Cannot call " - << classNameFromCppName(class_name, false) - << "." << methodNameFromCppName(func, class_name, false) - << "() on a const object.\");\n"; - if (!args_cleanup.empty()) { - indent(out, indent_level + 2) - << args_cleanup << "\n"; - } - indent(out, indent_level + 2) << "return (PyObject *) NULL;\n"; - indent(out, indent_level) - << "}\n\n"; - } else { - indent(out, indent_level) - << "}\n\n"; } + + indent_level -= 2; + indent(out, indent_level) + << "}\n\n"; + } else { + out << "\n"; } } } @@ -2718,13 +2908,12 @@ write_function_forset(ostream &out, InterfaceMaker::Object *obj, //////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: write_function_instance(ostream &out, InterfaceMaker::Object *obj, - InterfaceMaker::Function *func1, + InterfaceMaker::Function *func, FunctionRemap *remap, string &expected_params, - int indent_level, bool errors_fatal, - ostream &ForwardDeclrs, - const std::string &functionnamestr, bool is_inplace, + int indent_level, bool is_inplace, bool coercion_possible, bool &coercion_attempted, - const string &args_cleanup) { + ArgsType args_type, bool return_int, + const string &first_pexpr) { string format_specifiers; std::string keyword_list; string parameter_list; @@ -2733,13 +2922,9 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, string extra_convert; string extra_param_check; string extra_cleanup; - string pname_for_pyobject; + string direct_assign; - bool is_constructor = false; - - if (remap->_type == FunctionRemap::T_constructor) { - is_constructor = true; - } + bool is_constructor = (remap->_type == FunctionRemap::T_constructor); if (is_constructor && (remap->_flags & FunctionRemap::F_explicit_self) != 0) { // If we'll be passing "self" to the constructor, we need to @@ -2764,15 +2949,26 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, // simultaneously building the ParseTuple() function call and also // the parameter expression list for call_function(). - expected_params += methodNameFromCppName(func1, "", false); + expected_params += methodNameFromCppName(func, "", false); expected_params += "("; + int num_params = 0; + bool only_pyobjects = true; + bool check_exceptions = false; + int pn; - for (pn = 0; pn < (int)remap->_parameters.size(); pn++) { + for (pn = 0; pn < (int)remap->_parameters.size(); ++pn) { if (pn > 0) { expected_params += ", "; } + if (((remap->_has_this && pn == 1) || + (!remap->_has_this && pn == 0)) && !first_pexpr.empty()) { + // The first param was already converted. + pexprs.push_back(first_pexpr); + continue; + } + CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type(); CPPType *type = remap->_parameters[pn]._remap->get_new_type(); string param_name = remap->get_parameter_name(pn); @@ -2791,6 +2987,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, indent(out, indent_level) << "char *" << param_name << ";\n"; format_specifiers += "s"; parameter_list += ", &" + param_name; + expected_params += "str"; } else if (TypeManager::is_wchar_pointer(orig_type)) { out << "#if PY_MAJOR_VERSION >= 3\n"; @@ -2802,13 +2999,14 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, format_specifiers += "U"; parameter_list += ", &" + param_name; - extra_convert += " int " + param_name + "_len = PyUnicode_GetSize((PyObject *)" + param_name + ");" + extra_convert += " Py_ssize_t " + param_name + "_len = PyUnicode_GetSize((PyObject *)" + param_name + ");" " wchar_t *" + param_name + "_str = new wchar_t[" + param_name + "_len + 1];" " PyUnicode_AsWideChar(" + param_name + ", " + param_name + "_str, " + param_name + "_len);" " " + param_name + "_str[" + param_name + "_len] = 0;"; pexpr_string = param_name + "_str"; extra_cleanup += " delete[] " + param_name + "_str;"; + expected_params += "unicode"; } else if (TypeManager::is_wstring(orig_type)) { out << "#if PY_MAJOR_VERSION >= 3\n"; @@ -2819,7 +3017,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, format_specifiers += "U"; parameter_list += ", &" + param_name; - extra_convert += " int " + param_name + "_len = PyUnicode_GetSize((PyObject *)" + param_name + ");" + extra_convert += " Py_ssize_t " + param_name + "_len = PyUnicode_GetSize((PyObject *)" + param_name + ");" " wchar_t *" + param_name + "_str = new wchar_t[" + param_name + "_len];" " PyUnicode_AsWideChar(" + param_name + ", " + param_name + "_str, " + param_name + "_len);"; @@ -2828,6 +3026,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, param_name + "_len)"; extra_cleanup += " delete[] " + param_name + "_str;"; + expected_params += "unicode"; } else if (TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) { out << "#if PY_MAJOR_VERSION >= 3\n"; @@ -2838,7 +3037,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, format_specifiers += "U"; parameter_list += ", &" + param_name; - extra_convert += " int " + param_name + "_len = PyUnicode_GetSize((PyObject *)" + param_name + ");" + extra_convert += " Py_ssize_t " + param_name + "_len = PyUnicode_GetSize((PyObject *)" + param_name + ");" " wchar_t *" + param_name + "_str = new wchar_t[" + param_name + "_len];" " PyUnicode_AsWideChar(" + param_name + ", " + param_name + "_str, " + param_name + "_len);"; @@ -2847,106 +3046,181 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, param_name + "_len)"; extra_cleanup += " delete[] " + param_name + "_str;"; - - } else if (TypeManager::is_const_ptr_to_basic_string_char(orig_type)) { - indent(out, indent_level) << "char *" << param_name << "_str;\n"; - indent(out, indent_level) << "int " << param_name << "_len;\n"; - format_specifiers += "s#"; - parameter_list += ", &" + param_name - + "_str, &" + param_name + "_len"; - pexpr_string = "&basic_string(" + - param_name + "_str, " + - param_name + "_len)"; + expected_params += "unicode"; } else { indent(out, indent_level) << "char *" << param_name << "_str;\n"; - indent(out, indent_level) << "int " << param_name << "_len;\n"; - format_specifiers += "s#"; - parameter_list += ", &" + param_name - + "_str, &" + param_name + "_len"; - pexpr_string = "basic_string(" + - param_name + "_str, " + - param_name + "_len)"; + indent(out, indent_level) << "Py_ssize_t " << param_name << "_len;\n"; + if (args_type == AT_single_arg) { + out << "#if PY_MAJOR_VERSION >= 3\n"; + indent(out, indent_level) + << param_name << "_str = PyUnicode_AsUTF8AndSize(arg, &" + << param_name << "_len);\n"; + out << "#else\n"; + indent(out, indent_level) << "if (PyString_AsStringAndSize(arg, &" + << param_name << "_str, &" << param_name << "_len) == -1) {\n"; + indent(out, indent_level + 2) << param_name << "_str = NULL;\n"; + indent(out, indent_level) << "}\n"; + out << "#endif\n"; + + extra_param_check = " && " + param_name + "_str != NULL"; + } else { + format_specifiers += "s#"; + parameter_list += ", &" + param_name + + "_str, &" + param_name + "_len"; + } + + if (TypeManager::is_const_ptr_to_basic_string_char(orig_type)) { + pexpr_string = "&basic_string(" + + param_name + "_str, " + + param_name + "_len)"; + } else { + pexpr_string = "basic_string(" + + param_name + "_str, " + + param_name + "_len)"; + } + expected_params += "str"; } - expected_params += "string"; + ++num_params; + only_pyobjects = false; } else if (TypeManager::is_bool(type)) { - indent(out, indent_level) << "PyObject *" << param_name << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; + if (args_type == AT_single_arg) { + param_name = "arg"; + } else { + indent(out, indent_level) << "PyObject *" << param_name << ";\n"; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + } pexpr_string = "(PyObject_IsTrue(" + param_name + ") != 0)"; expected_params += "bool"; - pname_for_pyobject += param_name; + ++num_params; } else if (TypeManager::is_unsigned_longlong(type)) { - indent(out, indent_level) << "PyObject *" << param_name << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; + if (args_type == AT_single_arg) { + param_name = "arg"; + } else { + indent(out, indent_level) << "PyObject *" << param_name << ";\n"; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + } extra_convert += "PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");"; - extra_param_check += " || (" + param_name + "_long == NULL)"; + extra_param_check += " && " + param_name + "_long != NULL"; pexpr_string = "PyLong_AsUnsignedLongLong(" + param_name + "_long)"; extra_cleanup += "Py_XDECREF(" + param_name + "_long);"; expected_params += "unsigned long long"; - pname_for_pyobject += param_name; + ++num_params; } else if (TypeManager::is_longlong(type)) { - indent(out, indent_level) << "PyObject *" << param_name << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; + if (args_type == AT_single_arg) { + param_name = "arg"; + } else { + indent(out, indent_level) << "PyObject *" << param_name << ";\n"; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + } extra_convert += "PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");"; - extra_param_check += " || (" + param_name + "_long == NULL)"; + extra_param_check += " && " + param_name + "_long != NULL"; pexpr_string = "PyLong_AsLongLong(" + param_name + "_long)"; extra_cleanup += "Py_XDECREF(" + param_name + "_long);"; expected_params += "long long"; - pname_for_pyobject += param_name; + ++num_params; } else if (TypeManager::is_unsigned_integer(type)) { - indent(out, indent_level) << "PyObject *" << param_name << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - extra_convert += "PyObject *" + param_name + "_uint = PyNumber_Long(" + param_name + ");"; - extra_param_check += " || (" + param_name + "_uint == NULL)"; - pexpr_string = "PyLong_AsUnsignedLong(" + param_name + "_uint)"; - extra_cleanup += "Py_XDECREF(" + param_name + "_uint);"; + if (args_type == AT_single_arg) { + param_name = "arg"; + } else { + indent(out, indent_level) << "PyObject *" << param_name << ";\n"; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + } + extra_convert += "PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");"; + extra_param_check += " && " + param_name + "_long != NULL"; + pexpr_string = "PyLong_AsUnsignedLong(" + param_name + "_long)"; + extra_cleanup += "Py_XDECREF(" + param_name + "_long);"; expected_params += "unsigned int"; - pname_for_pyobject += param_name; + ++num_params; } else if (TypeManager::is_integer(type)) { - indent(out, indent_level) << "int " << param_name << ";\n"; - format_specifiers += "i"; - parameter_list += ", &" + param_name; + if (args_type == AT_single_arg) { + pexpr_string = "(" + type->get_local_name(&parser) + ")PyInt_AS_LONG(arg)"; + extra_param_check += " && PyInt_Check(arg)"; + } else { + indent(out, indent_level) << "int " << param_name << ";\n"; + format_specifiers += "i"; + parameter_list += ", &" + param_name; + } expected_params += "int"; + only_pyobjects = false; + ++num_params; + + } else if (TypeManager::is_double(type)) { + if (args_type == AT_single_arg) { + pexpr_string = "PyFloat_AsDouble(arg)"; + extra_param_check += " && PyNumber_Check(arg)"; + } else { + indent(out, indent_level) << "double " << param_name << ";\n"; + format_specifiers += "d"; + parameter_list += ", &" + param_name; + } + expected_params += "double"; + only_pyobjects = false; + ++num_params; } else if (TypeManager::is_float(type)) { - indent(out, indent_level) << "double " << param_name << ";\n"; - format_specifiers += "d"; - parameter_list += ", &" + param_name; + if (args_type == AT_single_arg) { + pexpr_string = "(float) PyFloat_AsDouble(arg)"; + extra_param_check += " && PyNumber_Check(arg)"; + } else { + indent(out, indent_level) << "float " << param_name << ";\n"; + format_specifiers += "f"; + parameter_list += ", &" + param_name; + } expected_params += "float"; + only_pyobjects = false; + ++num_params; } else if (TypeManager::is_char_pointer(type)) { indent(out, indent_level) << "char *" << param_name << ";\n"; format_specifiers += "s"; parameter_list += ", &" + param_name; expected_params += "string"; + only_pyobjects = false; + ++num_params; } else if (TypeManager::is_pointer_to_PyObject(type)) { - indent(out, indent_level) << "PyObject *" << param_name << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; + if (args_type == AT_single_arg) { + // This is a single-arg function, so there's no need + // to convert anything. + param_name = "arg"; + } else { + indent(out, indent_level) << "PyObject *" << param_name << ";\n"; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + } pexpr_string = param_name; - pname_for_pyobject += param_name; expected_params += "any"; + ++num_params; + + // It's reasonable to assume that a function taking a PyObject + // might also throw a TypeError if the type is incorrect. + check_exceptions = true; } else if (TypeManager::is_pointer_to_Py_buffer(type)) { - indent(out, indent_level) << "PyObject *" << param_name << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; + if (args_type == AT_single_arg) { + param_name = "arg"; + } else { + indent(out, indent_level) << "PyObject *" << param_name << ";\n"; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + } extra_convert += "PyObject *" + param_name + "_buffer = PyMemoryView_FromObject(" + param_name + ");"; - extra_param_check += " || (" + param_name + "_buffer == NULL)"; + extra_param_check += " && " + param_name + "_buffer != NULL"; pexpr_string = "PyMemoryView_GET_BUFFER(" + param_name + "_buffer)"; extra_cleanup += "Py_XDECREF(" + param_name + "_buffer);"; expected_params += "memoryview"; - pname_for_pyobject += param_name; + ++num_params; + check_exceptions = true; } else if (TypeManager::is_pointer(type)) { CPPType *obj_type = TypeManager::unwrap(TypeManager::resolve_type(type)); @@ -2954,17 +3228,21 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, if (const_ok) { expected_params += "const "; - } else { - expected_params += "non-const "; + //} else { + // expected_params += "non-const "; } expected_params += classNameFromCppName(obj_type->get_simple_name(), false); if (!remap->_has_this || pn != 0) { - indent(out, indent_level) - << "PyObject *" << param_name << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; - pname_for_pyobject += param_name; + if (args_type == AT_single_arg) { + param_name = "arg"; + } else { + indent(out, indent_level) << "PyObject *" << param_name << ";\n"; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + } + + ++num_params; TypeIndex p_type_index = builder.get_type(obj_type, false); InterrogateDatabase *idb = InterrogateDatabase::get_ptr(); @@ -2984,7 +3262,6 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, // need to a forward scope for this class.. if (!isExportThisRun(p_itype._cpptype)) { _external_imports.insert(make_safe_name(p_itype.get_scoped_name())); - //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(p_itype.get_scoped_name()) << ";\n"; } string class_name; @@ -2998,7 +3275,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, str << "DTOOL_Call_GetPointerThisClass(" << param_name << ", &Dtool_" << make_safe_name(p_itype.get_scoped_name()) << ", " << pn << ", \"" - << method_prefix << methodNameFromCppName(func1, class_name, false) + << method_prefix << methodNameFromCppName(func, class_name, false) << "\", " << const_ok; if (coercion_possible && !is_copy_constructor) { // We never attempt to coerce a copy constructor parameter. @@ -3011,17 +3288,21 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, str << ");\n"; extra_convert += str.str(); - extra_param_check += " || (" + param_name + "_this == NULL)"; + extra_param_check += " && " + param_name + "_this != NULL"; pexpr_string = param_name + "_this"; } } else { // Ignore a parameter. - indent(out, indent_level) << "PyObject *" << param_name << ";\n"; - format_specifiers += "O"; - parameter_list += ", &" + param_name; + if (args_type == AT_single_arg) { + param_name = "arg"; + } else { + indent(out, indent_level) << "PyObject *" << param_name << ";\n"; + format_specifiers += "O"; + parameter_list += ", &" + param_name; + } expected_params += "any"; - pname_for_pyobject += param_name; + ++num_params; } if (remap->_parameters[pn]._has_name) { @@ -3040,83 +3321,81 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, } expected_params += ")\n"; - // If we got what claimed to be a unary operator, don't check for - // parameters, since we won't be getting any anyway. - if (!func1->_ifunc.is_unary_op()) { + // If this is the only overload, don't bother checking for type errors. + // Any type error that is raised will simply pass through to below. + if (func->_remaps.size() == 1) { + check_exceptions = false; + } + + // Track how many curly braces we've opened. + short open_scopes = 0; + + if (!format_specifiers.empty()) { std::string format_specifiers1 = format_specifiers + ":" + - methodNameFromCppName(func1, "", false); - indent(out, indent_level) - << "static char *keyword_list[] = {" << keyword_list << "NULL};\n"; + methodNameFromCppName(func, "", false); - if (remap->_parameters.size() == 1 || - (remap->_has_this && remap->_parameters.size() == 2)) { + switch (args_type) { + case AT_keyword_args: + // Wrapper takes a varargs tuple and a keyword args dict. indent(out, indent_level) - << "// Special case to make operators work\n"; - indent(out, indent_level) - << "if (PyTuple_Check(args) || (kwds != NULL && PyDict_Check(kwds))) {\n"; - indent(out, indent_level) - << " PyArg_ParseTupleAndKeywords(args, kwds, \"" - << format_specifiers1 << "\", keyword_list" << parameter_list - << ");\n"; - indent(out, indent_level) - << "} else {\n"; - indent(out, indent_level) - << " PyArg_Parse(args, \"" << format_specifiers1 << "\"" - << parameter_list << ");\n"; - indent(out, indent_level) - << "}\n"; - indent(out, indent_level) - << "if (!PyErr_Occurred()) {\n"; - - } else { + << "static char *keyword_list[] = {" << keyword_list << "NULL};\n"; indent(out, indent_level) << "if (PyArg_ParseTupleAndKeywords(args, kwds, \"" - << format_specifiers1 << "\", keyword_list" - << parameter_list << ")) {\n"; + << format_specifiers1 << "\", keyword_list" << parameter_list + << ")) {\n"; + + ++open_scopes; + indent_level += 2; + break; + + case AT_varargs: + // Wrapper takes a varargs tuple. + if (only_pyobjects) { + // All parameters are PyObject*, so we can use the slightly + // more efficient PyArg_UnpackTuple function instead. + indent(out, indent_level) + << "if (PyArg_UnpackTuple(args, \"" + << methodNameFromCppName(func, "", false) + << "\", " << num_params + << ", " << num_params + << parameter_list << ")) {\n"; + } else { + indent(out, indent_level) + << "if (PyArg_ParseTuple(args, \"" + << format_specifiers1 << "\"" + << parameter_list << ")) {\n"; + } + ++open_scopes; + indent_level += 2; + break; + + case AT_single_arg: + // Wrapper takes a single PyObject* argument. + if (!only_pyobjects && format_specifiers != "O") { + indent(out, indent_level) + << "if (PyArg_Parse(arg, \"" << format_specifiers << "\"" + << parameter_list << ")) {\n"; + + ++open_scopes; + indent_level += 2; + } } - } else { - indent(out, indent_level) << "{\n"; } if (!extra_convert.empty()) { - indent(out, indent_level + 2) + indent(out, indent_level) << extra_convert << "\n"; } - int extra_indent_level = indent_level + 2; - if (!extra_param_check.empty()) { - indent(out, extra_indent_level) - << "if (!(" << extra_param_check.substr(3) << ")) {\n"; - extra_indent_level += 2; - } - - if ((remap->_flags & (FunctionRemap::F_getitem_int | FunctionRemap::F_setitem_int)) && - (obj != (Object *)NULL && (obj->_protocol_types & Object::PT_sequence))) { - // This is a getitem or setitem of a sequence type. This means we - // *need* to raise IndexError if we're out of bounds. We have to - // assume the bounds are 0 .. this->size() (this is the same - // assumption that Python makes). - string pexpr_string = pexprs[1]; - indent(out, extra_indent_level) - << "if ((" << pexpr_string << ") < 0 || (" << pexpr_string << ") >= (" - << container << ")->size()) {\n"; - if (coercion_possible) { - indent(out, extra_indent_level + 2) - << "Py_XDECREF(coerced);\n"; - } - if (!args_cleanup.empty()) { - indent(out, extra_indent_level + 2) - << args_cleanup << "\n"; - } - indent(out, extra_indent_level + 2) - << "PyErr_SetString(PyExc_IndexError, \"Out of bounds.\");\n"; - indent(out, extra_indent_level + 2) - << "return NULL;\n"; - indent(out, extra_indent_level) - << "}\n"; + indent(out, indent_level) + << "if (" << extra_param_check.substr(4) << ") {\n"; + + ++open_scopes; + indent_level += 2; } + string return_expr; if (!remap->_void_return && remap->_return_type->new_type_is_atomic_string()) { // Treat strings as a special case. We don't want to format the @@ -3125,117 +3404,175 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj, // With SIMPLE_THREADS, it's important that we never release the // interpreter lock. out << "#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)\n"; - indent(out, extra_indent_level) + indent(out, indent_level) << "PyThreadState *_save;\n"; - indent(out, extra_indent_level) + indent(out, indent_level) << "Py_UNBLOCK_THREADS\n"; out << "#endif // HAVE_THREADS && !SIMPLE_THREADS\n"; } if (track_interpreter) { - indent(out, extra_indent_level) << "in_interpreter = 0;\n"; + indent(out, indent_level) << "in_interpreter = 0;\n"; } string tt; - string return_expr = remap->call_function(out, extra_indent_level, false, container, pexprs); + return_expr = remap->call_function(out, indent_level, false, container, pexprs); CPPType *type = remap->_return_type->get_orig_type(); - indent(out, extra_indent_level); + indent(out, indent_level); type->output_instance(out, "return_value", &parser); // type->output_instance(tt, "return_value", &parser); out << " = " << return_expr << ";\n"; if (track_interpreter) { - indent(out, extra_indent_level) << "in_interpreter = 1;\n"; + indent(out, indent_level) << "in_interpreter = 1;\n"; } if (remap->_blocking) { out << "#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)\n"; - indent(out, extra_indent_level) + indent(out, indent_level) << "Py_BLOCK_THREADS\n"; out << "#endif // HAVE_THREADS && !SIMPLE_THREADS\n"; } if (!extra_cleanup.empty()) { - indent(out, extra_indent_level) << extra_cleanup << "\n"; + indent(out, indent_level) << extra_cleanup << "\n"; } return_expr = manage_return_value(out, 4, remap, "return_value"); - do_assert_init(out, extra_indent_level, is_constructor, args_cleanup); - pack_return_value(out, extra_indent_level, remap, return_expr, is_inplace); } else { if (remap->_blocking) { out << "#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)\n"; - indent(out, extra_indent_level) + indent(out, indent_level) << "PyThreadState *_save;\n"; - indent(out, extra_indent_level) + indent(out, indent_level) << "Py_UNBLOCK_THREADS\n"; out << "#endif // HAVE_THREADS && !SIMPLE_THREADS\n"; } if (track_interpreter) { - indent(out, extra_indent_level) << "in_interpreter = 0;\n"; + indent(out, indent_level) << "in_interpreter = 0;\n"; } - string return_expr = remap->call_function(out, extra_indent_level, true, container, pexprs); + return_expr = remap->call_function(out, indent_level, true, container, pexprs); if (return_expr.empty()) { if (track_interpreter) { - indent(out, extra_indent_level) << "in_interpreter = 1;\n"; + indent(out, indent_level) << "in_interpreter = 1;\n"; } if (remap->_blocking) { out << "#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)\n"; - indent(out, extra_indent_level) + indent(out, indent_level) << "Py_BLOCK_THREADS\n"; out << "#endif // HAVE_THREADS && !SIMPLE_THREADS\n"; } if (!extra_cleanup.empty()) { - indent(out, extra_indent_level) << extra_cleanup << "\n"; + indent(out, indent_level) << extra_cleanup << "\n"; } if (coercion_possible) { - indent(out, extra_indent_level) + indent(out, indent_level) << "Py_XDECREF(coerced);\n"; } - do_assert_init(out, extra_indent_level, is_constructor, args_cleanup); - indent(out, extra_indent_level) << "return Py_BuildValue(\"\");\n"; } else { CPPType *type = remap->_return_type->get_temporary_type(); if (!is_inplace) { - indent(out, extra_indent_level); + indent(out, indent_level); type->output_instance(out, "return_value", &parser); out << " = " << return_expr << ";\n"; } if (track_interpreter) { - indent(out, extra_indent_level) << "in_interpreter = 1;\n"; + indent(out, indent_level) << "in_interpreter = 1;\n"; } if (remap->_blocking) { out << "#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)\n"; - indent(out, extra_indent_level) + indent(out, indent_level) << "Py_BLOCK_THREADS\n"; out << "#endif // HAVE_THREADS && !SIMPLE_THREADS\n"; } if (!extra_cleanup.empty()) { - indent(out, extra_indent_level) << extra_cleanup << "\n"; + indent(out, indent_level) << extra_cleanup << "\n"; } if (!is_inplace) { - return_expr = manage_return_value(out, extra_indent_level, remap, "return_value"); + return_expr = manage_return_value(out, indent_level, remap, "return_value"); } if (coercion_possible) { - indent(out, extra_indent_level) + indent(out, indent_level) << "Py_XDECREF(coerced);\n"; } - do_assert_init(out, extra_indent_level, is_constructor, args_cleanup); - pack_return_value(out, extra_indent_level, remap, remap->_return_type->temporary_to_return(return_expr), is_inplace); + return_expr = remap->_return_type->temporary_to_return(return_expr); } } - // Close the extra brace opened within do_assert_init(). - extra_indent_level -= 2; - indent(out, extra_indent_level) - << "}\n"; + // If a method raises TypeError, continue. + if (check_exceptions) { + indent(out, indent_level) + << "if (PyErr_Occurred()) {\n"; + if (return_int && !return_expr.empty()) { + indent(out, indent_level + 2) + << "delete return_value;\n"; + } + indent(out, indent_level) + << " if (PyErr_ExceptionMatches(PyExc_TypeError)) {\n"; + indent(out, indent_level) + << " // TypeError raised; continue to next overload type.\n"; + indent(out, indent_level) + << " } else {\n"; + if (return_int) { + indent(out, indent_level + 2) + << " return -1;\n"; + } else { + indent(out, indent_level + 2) + << " return (PyObject *)NULL;\n"; + } + indent(out, indent_level) + << " }\n"; + indent(out, indent_level) + << "} else {\n"; - if (!extra_param_check.empty()) { - extra_indent_level -= 2; - indent(out, extra_indent_level) << "}\n"; + ++open_scopes; + indent_level += 2; } - indent(out, indent_level) << "}\n"; + // Outputs code to check to see if an assertion has failed while + // the C++ code was executing, and report this failure back to Python. + if (watch_asserts) { + out << "#ifndef NDEBUG\n"; + indent(out, indent_level) + << "Notify *notify = Notify::ptr();\n"; + indent(out, indent_level) + << "if (notify->has_assert_failed()) {\n"; + indent(out, indent_level + 2) + << "PyErr_SetString(PyExc_AssertionError, notify->get_assert_error_message().c_str());\n"; + indent(out, indent_level + 2) + << "notify->clear_assert_failed();\n"; + if (return_int) { + if (!return_expr.empty()) { + indent(out, indent_level + 2) << "delete return_value;\n"; + } + indent(out, indent_level + 2) << "return -1;\n"; + } else { + indent(out, indent_level + 2) << "return (PyObject *)NULL;\n"; + } + + indent(out, indent_level) + << "}\n"; + out << "#endif\n"; + } + + if (return_expr.empty()) { + if (return_int) { + indent(out, indent_level) << "return 0;\n"; + } else { + indent(out, indent_level) << "Py_INCREF(Py_None);\n"; + indent(out, indent_level) << "return Py_None;\n"; + } + } else { + pack_return_value(out, indent_level, remap, return_expr, is_inplace); + } + + // Close the extra braces opened earlier. + while (open_scopes > 0) { + indent_level -= 2; + indent(out, indent_level) << "}\n"; + + --open_scopes; + } } //////////////////////////////////////////////////////////////////// @@ -3276,7 +3613,8 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap, //////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, - ParameterRemap *return_type, const string &return_expr, const string &assign_to, bool is_inplace) { + ParameterRemap *return_type, const string &return_expr, + const string &assign_to, bool is_inplace) { CPPType *orig_type = return_type->get_orig_type(); CPPType *type = return_type->get_new_type(); @@ -3456,7 +3794,6 @@ pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, if (!isExportThisRun(itype._cpptype)) { _external_imports.insert(make_safe_name(itype.get_scoped_name())); - //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; } write_python_instance(out, indent_level, return_expr, assign_to, owns_memory_flag, itype.get_scoped_name(), itype._cpptype, is_inplace, const_flag); @@ -3476,10 +3813,8 @@ pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, if (!isExportThisRun(itype._cpptype)) { _external_imports.insert(make_safe_name(itype.get_scoped_name())); - //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; } - // ForwardDeclrs << "extern \"C\" struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; write_python_instance(out, indent_level, return_expr, assign_to, owns_memory_flag, itype.get_scoped_name(), itype._cpptype, is_inplace, const_flag); } else { TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false); @@ -3488,10 +3823,8 @@ pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, if (!isExportThisRun(itype._cpptype)) { _external_imports.insert(make_safe_name(itype.get_scoped_name())); - //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; } - // ForwardDeclrs << "extern \"C\" struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; write_python_instance(out, indent_level, return_expr, assign_to, owns_memory_flag, itype.get_scoped_name(), itype._cpptype, is_inplace, const_flag); } } @@ -3509,10 +3842,8 @@ pack_python_value(ostream &out, int indent_level, FunctionRemap *remap, if (!isExportThisRun(itype._cpptype)) { _external_imports.insert(make_safe_name(itype.get_scoped_name())); - //ForwardDeclrs << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; } - // ForwardDeclrs << "extern \"C\" struct Dtool_PyTypedObject Dtool_" << make_safe_name(itype.get_scoped_name()) << ";\n"; write_python_instance(out, indent_level, return_expr, assign_to, owns_memory_flag, itype.get_scoped_name(), itype._cpptype, is_inplace, const_flag); } else { @@ -3799,21 +4130,25 @@ isExportThisRun(Function *func) { // Function : is_remap_legal ////////////////////////////////////////////// bool InterfaceMakerPythonNative:: -is_remap_legal(FunctionRemap &remap) { +is_remap_legal(FunctionRemap *remap) { + if (remap == NULL) { + return false; + } + // return must be legal and managable.. - if (!is_cpp_type_legal(remap._return_type->get_orig_type())) { -// printf(" is_remap_legal Return Is Bad %s\n",remap._return_type->get_orig_type()->get_fully_scoped_name().c_str()); + if (!is_cpp_type_legal(remap->_return_type->get_orig_type())) { +// printf(" is_remap_legal Return Is Bad %s\n",remap->_return_type->get_orig_type()->get_fully_scoped_name().c_str()); return false; } // ouch .. bad things will happen here .. do not even try.. - if (remap._ForcedVoidReturn) { + if (remap->_ForcedVoidReturn) { return false; } // all params must be legal - for (int pn = 0; pn < (int)remap._parameters.size(); pn++) { - CPPType *orig_type = remap._parameters[pn]._remap->get_orig_type(); + for (int pn = 0; pn < (int)remap->_parameters.size(); pn++) { + CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type(); if (!is_cpp_type_legal(orig_type)) { return false; } @@ -3831,7 +4166,7 @@ is_function_legal(Function *func) { Function::Remaps::const_iterator ri; for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { FunctionRemap *remap = (*ri); - if (is_remap_legal(*remap)) { + if (is_remap_legal(remap)) { // printf(" Function Is Marked Legal %s\n",func->_name.c_str()); return true; @@ -3842,82 +4177,6 @@ is_function_legal(Function *func) { return false; } -//////////////////////////////////////////////////////////////////////// -// Function : isFunctionWithThis -// -// If any rempas have a this .. this function has a this..( of self) to python.. -//////////////////////////////////////////////////////////////////////// -bool InterfaceMakerPythonNative:: -isFunctionWithThis(Function *func) { - Function::Remaps::const_iterator ri; - for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) { - FunctionRemap *remap = (*ri); - if (remap->_has_this) { - return true; - } - } - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: InterfaceMakerPython::test_assert -// Access: Protected -// Description: Outputs code to check to see if an assertion has -// failed while the C++ code was executing, and report -// this failure back to Python. -//////////////////////////////////////////////////////////////////// -void InterfaceMakerPythonNative::do_assert_init(ostream &out, int &indent_level, bool constructor, const string &args_cleanup) const { - // If a method raises TypeError, continue. - indent(out, indent_level) - << "if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError)) {\n"; - indent(out, indent_level + 2) - << "// TypeError raised; continue to next overload type.\n"; - if (constructor) { - indent(out, indent_level + 2) - << "delete return_value;\n"; - } - indent(out, indent_level) - << "} else {\n"; - indent_level += 2; - - if (!args_cleanup.empty()) { - indent(out, indent_level) - << args_cleanup << "\n"; - } - - if (watch_asserts) { - out << "#ifndef NDEBUG\n"; - indent(out, indent_level) - << "Notify *notify = Notify::ptr();\n"; - indent(out, indent_level) - << "if (notify->has_assert_failed()) {\n"; - indent(out, indent_level + 2) - << "PyErr_SetString(PyExc_AssertionError, notify->get_assert_error_message().c_str());\n"; - indent(out, indent_level + 2) - << "notify->clear_assert_failed();\n"; - if (constructor) { - indent(out, indent_level + 2) << "delete return_value;\n"; - indent(out, indent_level + 2) << "return -1;\n"; - } else { - indent(out, indent_level + 2) << "return (PyObject *)NULL;\n"; - } - - indent(out, indent_level) - << "}\n"; - out << "#endif\n"; - indent(out, indent_level) - << "if (PyErr_Occurred()) {\n"; - if (constructor) { - indent(out, indent_level + 2) << "delete return_value;\n"; - indent(out, indent_level + 2) << "return -1;\n"; - } else { - indent(out, indent_level + 2) << "return (PyObject *)NULL;\n"; - } - - indent(out, indent_level) - << "}\n"; - } -} //////////////////////////////////////////////////////// // Function : IsRunTimeTyped /////////////////////////////////////////////////////// diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h index 3bcb9d3b04..a7c20598db 100755 --- a/dtool/src/interrogate/interfaceMakerPythonNative.h +++ b/dtool/src/interrogate/interfaceMakerPythonNative.h @@ -27,8 +27,7 @@ class FunctionRemap; // Description : An InterfaceMaker for generating complex Python // function wrappers around C++ code. //////////////////////////////////////////////////////////////////// -class InterfaceMakerPythonNative : public InterfaceMakerPython -{ +class InterfaceMakerPythonNative : public InterfaceMakerPython { public: InterfaceMakerPythonNative(InterrogateModuleDef *def); virtual ~InterfaceMakerPythonNative(); @@ -77,6 +76,8 @@ private: WT_getbuffer, WT_releasebuffer, WT_iter_next, + WT_one_or_two_params, + WT_ternary_operator, }; class SlottedFunctionDef { @@ -87,25 +88,28 @@ private: }; static bool get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def); - + void write_prototype_for_name(ostream &out, Function *func, const std::string &name); void write_prototype_for(ostream &out, Function *func); - void write_function_for_name(ostream &out, Object *obj, Function *func, const std::string &name, const std::string &PreProcess, const std::string &ClassName, - bool coercion_allowed, bool &coercion_attempted); - void write_function_for_top(ostream &out, Object *obj, Function *func, const std::string &PreProcess); - void write_function_instance(ostream &out, Object *obj, Function *func, - FunctionRemap *remap, string &expected_params, - int indent_level, bool errors_fatal, - ostream &forwarddecl, const std::string &functionnamestr, - bool is_inplace, bool coercion_allowed, - bool &coercion_attempted, - const string &args_cleanup); - + void write_function_for_top(ostream &out, Object *obj, Function *func); + void write_function_for_name(ostream &out, Object *obj, Function *func, + const std::string &name, + bool coercion_allowed, bool &coercion_attempted, + ArgsType args_type, bool return_int); + void write_function_forset(ostream &out, Object *obj, Function *func, std::set &remaps, string &expected_params, - int indent_level, ostream &forwarddecl, bool inplace, - bool coercion_allowed, bool &coercion_attempted, - const string &args_cleanup); + int indent_level, bool inplace, + bool coercion_allowed, bool &coercion_attempted, + ArgsType args_type, bool return_int, + const string &first_expr = string()); + + void write_function_instance(ostream &out, Object *obj, Function *func, + FunctionRemap *remap, string &expected_params, + int indent_level, bool is_inplace, + bool coercion_allowed, bool &coercion_attempted, + ArgsType args_type, bool return_int, + const string &first_pexpr = string()); void pack_return_value(ostream &out, int indent_level, FunctionRemap *remap, const std::string &return_expr, bool in_place); @@ -119,17 +123,16 @@ private: void write_class_prototypes(ostream &out) ; void write_class_declarations(ostream &out, ostream *out_h, Object *obj); void write_class_details(ostream &out, Object *obj); - - void do_assert_init(ostream &out, int &indent_level, bool constructor, const string &args_cleanup) const; + public: - bool is_remap_legal(FunctionRemap &remap); + bool is_remap_legal(FunctionRemap *remap); bool is_function_legal( Function *func); bool is_cpp_type_legal(CPPType *ctype); bool isExportThisRun(CPPType *ctype); bool isExportThisRun(Function *func); bool isFunctionWithThis( Function *func); bool IsRunTimeTyped(const InterrogateType &itype); - + // comunicates the cast capabilites among methods.. struct CastDetails { CPPStructType *_structType; diff --git a/dtool/src/interrogate/interrogateBuilder.cxx b/dtool/src/interrogate/interrogateBuilder.cxx index 3624de5352..1d1a3e868d 100644 --- a/dtool/src/interrogate/interrogateBuilder.cxx +++ b/dtool/src/interrogate/interrogateBuilder.cxx @@ -1863,26 +1863,34 @@ get_type(CPPType *type, bool global) { // First, check to see if it's already there. string true_name = type->get_local_name(&parser); - TypesByName::const_iterator tni = _types_by_name.find(true_name); - if (tni != _types_by_name.end()) { - // It's already here, so update the global flag. - index = (*tni).second; - if (index == 0) { - // This is an invalid type; we don't know anything about it. - return 0; - } - InterrogateType &itype = InterrogateDatabase::get_ptr()->update_type(index); - if (global) { - itype._flags |= InterrogateType::F_global; - } + if (true_name.empty()) { + // Whoops, it's an anonymous type. That's okay, because we'll + // usually only encounter them once anyway, so let's go ahead and + // define it without checking in _types_by_name. - if ((itype._flags & InterrogateType::F_fully_defined) != 0) { - return index; - } + } else { + TypesByName::const_iterator tni = _types_by_name.find(true_name); + if (tni != _types_by_name.end()) { + // It's already here, so update the global flag. + index = (*tni).second; + if (index == 0) { + // This is an invalid type; we don't know anything about it. + return 0; + } - // But wait--it's not fully defined yet! We'll go ahead and - // define it now. + InterrogateType &itype = InterrogateDatabase::get_ptr()->update_type(index); + if (global) { + itype._flags |= InterrogateType::F_global; + } + + if ((itype._flags & InterrogateType::F_fully_defined) != 0) { + return index; + } + + // But wait--it's not fully defined yet! We'll go ahead and + // define it now. + } } bool forced = in_forcetype(true_name); @@ -1890,7 +1898,9 @@ get_type(CPPType *type, bool global) { if (index == 0) { // It isn't already there, so we have to define it. index = InterrogateDatabase::get_ptr()->get_next_index(); - _types_by_name[true_name] = index; + if (!true_name.empty()) { + _types_by_name[true_name] = index; + } InterrogateType itype; if (global) { @@ -1904,7 +1914,7 @@ get_type(CPPType *type, bool global) { InterrogateDatabase::get_ptr()->update_type(index); itype._name = get_preferred_name(type); - + int num_alt_names = type->get_num_alt_names(); if (num_alt_names != 0) { itype._alt_names.clear(); @@ -1954,23 +1964,19 @@ get_type(CPPType *type, bool global) { } } - if (forced || !in_ignoretype(true_name)) - { + if (forced || !in_ignoretype(true_name)) { itype._flags |= InterrogateType::F_fully_defined; - if (type->as_simple_type() != (CPPSimpleType *)NULL) - { + if (type->as_simple_type() != (CPPSimpleType *)NULL) { define_atomic_type(itype, type->as_simple_type()); - } else if (type->as_pointer_type() != (CPPPointerType *)NULL) - { + } else if (type->as_pointer_type() != (CPPPointerType *)NULL) { define_wrapped_type(itype, type->as_pointer_type()); } else if (type->as_const_type() != (CPPConstType *)NULL) { define_wrapped_type(itype, type->as_const_type()); - } else if (type->as_struct_type() != (CPPStructType *)NULL) - { + } else if (type->as_struct_type() != (CPPStructType *)NULL) { define_struct_type(itype, type->as_struct_type(), index, forced); } else if (type->as_enum_type() != (CPPEnumType *)NULL) { @@ -1984,7 +1990,9 @@ get_type(CPPType *type, bool global) { // Remove the type from the database. InterrogateDatabase::get_ptr()->remove_type(index); - _types_by_name[true_name] = 0; + if (!true_name.empty()) { + _types_by_name[true_name] = 0; + } index = 0; } } @@ -2229,6 +2237,7 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype, for (di = scope->_declarations.begin(); di != scope->_declarations.end(); ++di) { + if ((*di)->get_subtype() == CPPDeclaration::ST_instance) { CPPInstance *inst = (*di)->as_instance(); if (inst->_type->get_subtype() == CPPDeclaration::ST_function) { @@ -2243,15 +2252,12 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype, } } - } else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) - { + } else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) { CPPType *type = (*di)->as_type_declaration()->_type; - if ((*di)->_vis <= min_vis || in_forcetype(type->get_local_name(&parser))) - { + if ((*di)->_vis <= min_vis || in_forcetype(type->get_local_name(&parser))) { if (type->as_struct_type() != (CPPStructType *)NULL || - type->as_enum_type() != (CPPEnumType *)NULL) - { + type->as_enum_type() != (CPPEnumType *)NULL) { // Here's a nested class or enum definition. type->_vis = (*di)->_vis; @@ -2259,13 +2265,20 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype, assert(nested_type != (CPPExtensionType *)NULL); // Only try to export named types. - if (nested_type->_ident != (CPPIdentifier *)NULL) - { + if (nested_type->_ident != (CPPIdentifier *)NULL) { TypeIndex nested_index = get_type(nested_type, false); itype._nested_types.push_back(nested_index); } } } + } else if ((*di)->get_subtype() == CPPDeclaration::ST_enum) { + CPPType *type = (*di)->as_enum_type(); + + // An anonymous enum type. + if ((*di)->_vis <= min_vis) { + TypeIndex nested_index = get_type(type, false); + itype._nested_types.push_back(nested_index); + } } } diff --git a/dtool/src/interrogate/typeManager.cxx b/dtool/src/interrogate/typeManager.cxx index 03b742e6a3..245724b6ef 100644 --- a/dtool/src/interrogate/typeManager.cxx +++ b/dtool/src/interrogate/typeManager.cxx @@ -934,7 +934,7 @@ bool TypeManager:: is_double(CPPType *type) { switch (type->get_subtype()) { case CPPDeclaration::ST_const: - return is_float(type->as_const_type()->_wrapped_around); + return is_double(type->as_const_type()->_wrapped_around); case CPPDeclaration::ST_simple: { @@ -1199,7 +1199,8 @@ is_PyObject(CPPType *type) { return is_PyObject(type->as_const_type()->_wrapped_around); case CPPDeclaration::ST_extension: - return (type->get_local_name(&parser) == "PyObject"); + return (type->get_local_name(&parser) == "PyObject" || + type->get_local_name(&parser) == "_object"); default: return false; diff --git a/dtool/src/interrogatedb/dtool_super_base.cxx b/dtool/src/interrogatedb/dtool_super_base.cxx index 8b780e11f2..b92ce15f94 100644 --- a/dtool/src/interrogatedb/dtool_super_base.cxx +++ b/dtool/src/interrogatedb/dtool_super_base.cxx @@ -83,7 +83,7 @@ int Dtool_Init_DTOOL_SUPER_BASE(PyObject *self, PyObject *args, PyObject *kwds) return -1; } -int Dtool_InitNoCoerce_DTOOL_SUPER_BASE(PyObject *self, PyObject *args, PyObject *kwds) { +int Dtool_InitNoCoerce_DTOOL_SUPER_BASE(PyObject *self, PyObject *args) { PyErr_SetString(PyExc_TypeError, "cannot init super base"); return -1; } diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index f0123e459e..f7606ec407 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/dtool/src/interrogatedb/py_panda.cxx @@ -79,9 +79,21 @@ attempt_coercion(PyObject *self, Dtool_PyTypedObject *classdef, if (classdef->_PyType.tp_new != NULL) { obj = classdef->_PyType.tp_new(&classdef->_PyType, self, NULL); assert(obj != NULL); - if (classdef->_Dtool_InitNoCoerce(obj, self, NULL) != 0) { - Py_DECREF(obj); - obj = NULL; + + if (PyTuple_Check(self)) { + // A tuple was passed, which we assume are the constructor arguments. + if (classdef->_Dtool_InitNoCoerce(obj, self) != 0) { + Py_DECREF(obj); + obj = NULL; + } + } else { + // We need to pack the value into an args tuple. + PyObject *args = PyTuple_Pack(1, self); + if (classdef->_Dtool_InitNoCoerce(obj, args) != 0) { + Py_DECREF(obj); + obj = NULL; + } + Py_DECREF(args); } } if (obj == NULL) { @@ -93,7 +105,11 @@ attempt_coercion(PyObject *self, Dtool_PyTypedObject *classdef, PyObject *make = PyObject_GetAttrString((PyObject *)classdef, "make"); if (make != NULL) { PyErr_Clear(); - obj = PyObject_Call(make, self, NULL); + if (PyTuple_Check(self)) { + obj = PyObject_CallObject(make, self); + } else { + obj = PyObject_CallFunctionObjArgs(make, self, NULL); + } Py_DECREF(make); } } @@ -598,7 +614,7 @@ int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2) { PyErr_Clear(); } else { PyObject *res = NULL; - PyObject *args = Py_BuildValue("(O)", v2); + PyObject *args = PyTuple_Pack(1, v2); if (args != NULL) { res = PyObject_Call(func, args, NULL); Py_DECREF(args); diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index a9779300f4..0811c6c795 100755 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -42,18 +42,23 @@ #if defined(HAVE_PYTHON) && !defined(CPPPARSER) -#ifdef HAVE_LONG_LONG -#undef HAVE_LONG_LONG -#endif #ifdef _POSIX_C_SOURCE #undef _POSIX_C_SOURCE #endif +#define PY_SSIZE_T_CLEAN 1 + #include "Python.h" #include "structmember.h" -#ifdef HAVE_LONG_LONG -#undef HAVE_LONG_LONG -#endif + +#ifndef HAVE_LONG_LONG +#define PyLong_FromLongLong(x) PyLong_FromLong((long) (x)) +#define PyLong_FromUnsignedLongLong(x) PyLong_FromUnsignedLong((unsigned long) (x)) +#define PyLong_AsLongLong(x) PyLong_AsLong(x) +#define PyLong_AsUnsignedLongLong(x) PyLong_AsUnsignedLong(x) +#define PyLong_AsUnsignedLongLongMask(x) PyLong_AsUnsignedLongMask(x) +#define PyLong_AsLongLongAndOverflow(x) PyLong_AsLongAndOverflow(x) +#endif #if PY_VERSION_HEX < 0x02050000 @@ -139,7 +144,7 @@ typedef void * ( * ConvertFunctionType )(PyObject *,Dtool_PyTypedObject * ); typedef void * ( * ConvertFunctionType1 )(void *, Dtool_PyTypedObject *); typedef void ( *FreeFunction )(PyObject *); typedef void ( *PyModuleClassInit)(PyObject *module); -typedef int ( *InitNoCoerce)(PyObject *self, PyObject *args, PyObject *kwds); +typedef int ( *InitNoCoerce)(PyObject *self, PyObject *args); //inline Dtool_PyTypedObject * Dtool_RuntimeTypeDtoolType(int type); inline void Dtool_Deallocate_General(PyObject * self); @@ -369,7 +374,7 @@ EXPCL_DTOOLCONFIG PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTyp extern EXPORT_THIS Dtool_PyTypedObject Dtool_##CLASS_NAME;\ extern struct PyMethodDef Dtool_Methods_##CLASS_NAME[];\ int Dtool_Init_##CLASS_NAME(PyObject *self, PyObject *args, PyObject *kwds);\ -int Dtool_InitNoCoerce_##CLASS_NAME(PyObject *self, PyObject *args, PyObject *kwds);\ +int Dtool_InitNoCoerce_##CLASS_NAME(PyObject *self, PyObject *args);\ PyObject * Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *kwds);\ void * Dtool_UpcastInterface_##CLASS_NAME(PyObject *self, Dtool_PyTypedObject *requested_type);\ void * Dtool_DowncastInterface_##CLASS_NAME(void *self, Dtool_PyTypedObject *requested_type);\ diff --git a/dtool/src/parser-inc/Python.h b/dtool/src/parser-inc/Python.h index d63928fdfe..a059adca2c 100755 --- a/dtool/src/parser-inc/Python.h +++ b/dtool/src/parser-inc/Python.h @@ -20,7 +20,9 @@ #ifndef PYTHON_H #define PYTHON_H -class PyObject; +struct _object; +typedef _object PyObject; + class PyThreadState; typedef int Py_ssize_t; struct Py_buffer; diff --git a/dtool/src/prc/configVariableCore.h b/dtool/src/prc/configVariableCore.h index 6ca5ab3665..96cf536c8f 100644 --- a/dtool/src/prc/configVariableCore.h +++ b/dtool/src/prc/configVariableCore.h @@ -66,15 +66,19 @@ PUBLISHED: bool has_value() const; int get_num_declarations() const; const ConfigDeclaration *get_declaration(int n) const; + MAKE_SEQ(get_declarations, get_num_declarations, get_declaration); INLINE int get_num_references() const; INLINE const ConfigDeclaration *get_reference(int n) const; + MAKE_SEQ(get_references, get_num_references, get_reference); INLINE int get_num_trusted_references() const; INLINE const ConfigDeclaration *get_trusted_reference(int n) const; + MAKE_SEQ(get_trusted_references, get_num_trusted_references, get_trusted_reference); INLINE int get_num_unique_references() const; INLINE const ConfigDeclaration *get_unique_reference(int n) const; + MAKE_SEQ(get_unique_references, get_num_unique_references, get_unique_reference); void output(ostream &out) const; void write(ostream &out) const; diff --git a/dtool/src/prc/configVariableManager.h b/dtool/src/prc/configVariableManager.h index 9448287e39..9ac9c18250 100644 --- a/dtool/src/prc/configVariableManager.h +++ b/dtool/src/prc/configVariableManager.h @@ -47,6 +47,7 @@ PUBLISHED: INLINE int get_num_variables() const; INLINE ConfigVariableCore *get_variable(int n) const; + MAKE_SEQ(get_variables, get_num_variables, get_variable); string get_variable_name(int n) const; bool is_variable_used(int n) const; diff --git a/dtool/src/prc/notifyCategory.I b/dtool/src/prc/notifyCategory.I index 7a47e85926..579c492e93 100644 --- a/dtool/src/prc/notifyCategory.I +++ b/dtool/src/prc/notifyCategory.I @@ -106,7 +106,7 @@ is_debug() const { // methods are redefined to be static to make it more // obvious to the compiler. //////////////////////////////////////////////////////////////////// -INLINE bool NotifyCategory:: +CONSTEXPR bool NotifyCategory:: is_spam() { return false; } @@ -119,7 +119,7 @@ is_spam() { // methods are redefined to be static to make it more // obvious to the compiler. //////////////////////////////////////////////////////////////////// -INLINE bool NotifyCategory:: +CONSTEXPR bool NotifyCategory:: is_debug() { return false; } diff --git a/dtool/src/prc/notifyCategory.h b/dtool/src/prc/notifyCategory.h index ff7b366bd2..30539ec3b8 100644 --- a/dtool/src/prc/notifyCategory.h +++ b/dtool/src/prc/notifyCategory.h @@ -56,8 +56,8 @@ PUBLISHED: INLINE bool is_spam() const; INLINE bool is_debug() const; #else - INLINE static bool is_spam(); - INLINE static bool is_debug(); + CONSTEXPR static bool is_spam(); + CONSTEXPR static bool is_debug(); #endif INLINE bool is_info() const; INLINE bool is_warning() const; diff --git a/dtool/src/prc/notifyCategoryProxy.I b/dtool/src/prc/notifyCategoryProxy.I index 2dff5ce76d..10b956f763 100644 --- a/dtool/src/prc/notifyCategoryProxy.I +++ b/dtool/src/prc/notifyCategoryProxy.I @@ -80,30 +80,38 @@ is_on(NotifySeverity severity) { // Access: Public // Description: //////////////////////////////////////////////////////////////////// +#ifdef NOTIFY_DEBUG template INLINE bool NotifyCategoryProxy:: is_spam() { -#ifdef NOTIFY_DEBUG return get_unsafe_ptr()->is_spam(); -#else - return false; -#endif } +#else +template +CONSTEXPR bool NotifyCategoryProxy:: +is_spam() { + return false; +} +#endif //////////////////////////////////////////////////////////////////// // Function: NotifyCategoryProxy::is_debug // Access: Public // Description: //////////////////////////////////////////////////////////////////// +#ifdef NOTIFY_DEBUG template INLINE bool NotifyCategoryProxy:: is_debug() { -#ifdef NOTIFY_DEBUG return get_unsafe_ptr()->is_debug(); -#else - return false; -#endif } +#else +template +CONSTEXPR bool NotifyCategoryProxy:: +is_debug() { + return false; +} +#endif //////////////////////////////////////////////////////////////////// // Function: NotifyCategoryProxy::is_info diff --git a/dtool/src/prc/notifyCategoryProxy.h b/dtool/src/prc/notifyCategoryProxy.h index 37b9383c00..5a306497cd 100644 --- a/dtool/src/prc/notifyCategoryProxy.h +++ b/dtool/src/prc/notifyCategoryProxy.h @@ -85,8 +85,8 @@ public: INLINE bool is_spam(); INLINE bool is_debug(); #else - INLINE static bool is_spam(); - INLINE static bool is_debug(); + CONSTEXPR static bool is_spam(); + CONSTEXPR static bool is_debug(); #endif INLINE bool is_info(); INLINE bool is_warning(); diff --git a/dtool/src/pystub/pystub.cxx b/dtool/src/pystub/pystub.cxx index 9118c15209..214ea01ba0 100644 --- a/dtool/src/pystub/pystub.cxx +++ b/dtool/src/pystub/pystub.cxx @@ -18,6 +18,7 @@ extern "C" { EXPCL_PYSTUB int PyArg_Parse(...); EXPCL_PYSTUB int PyArg_ParseTuple(...); EXPCL_PYSTUB int PyArg_ParseTupleAndKeywords(...); + EXPCL_PYSTUB int PyArg_UnpackTuple(...); EXPCL_PYSTUB int PyBool_FromLong(...); EXPCL_PYSTUB int PyBuffer_Release(...); EXPCL_PYSTUB int PyBytes_AsString(...); @@ -84,11 +85,14 @@ extern "C" { EXPCL_PYSTUB int PyModule_AddObject(...); EXPCL_PYSTUB int PyModule_AddStringConstant(...); EXPCL_PYSTUB int PyModule_Create2(...); + EXPCL_PYSTUB int PyNumber_Check(...); EXPCL_PYSTUB int PyNumber_Float(...); + EXPCL_PYSTUB int PyNumber_Int(...); EXPCL_PYSTUB int PyNumber_Long(...); EXPCL_PYSTUB int PyObject_ASCII(...); EXPCL_PYSTUB int PyObject_Call(...); EXPCL_PYSTUB int PyObject_CallFunction(...); + EXPCL_PYSTUB int PyObject_CallFunctionObjArgs(...); EXPCL_PYSTUB int PyObject_CallMethod(...); EXPCL_PYSTUB int PyObject_CallMethodObjArgs(...); EXPCL_PYSTUB int PyObject_CallObject(...); @@ -152,8 +156,14 @@ extern "C" { EXPCL_PYSTUB int Py_InitModule4(...); EXPCL_PYSTUB int Py_InitModule4_64(...); EXPCL_PYSTUB int Py_InitModule4TraceRefs(...); + EXPCL_PYSTUB int _PyArg_ParseTuple_SizeT(...); + EXPCL_PYSTUB int _PyArg_ParseTupleAndKeywords_SizeT(...); + EXPCL_PYSTUB int _PyArg_Parse_SizeT(...); + EXPCL_PYSTUB int _PyObject_CallFunction_SizeT(...); + EXPCL_PYSTUB int _PyObject_CallMethod_SizeT(...); EXPCL_PYSTUB int _PyObject_DebugFree(...); EXPCL_PYSTUB int _PyObject_Del(...); + EXPCL_PYSTUB int _Py_BuildValue_SizeT(...); EXPCL_PYSTUB int _Py_Dealloc(...); EXPCL_PYSTUB int _Py_NegativeRefcount(...); EXPCL_PYSTUB int _Py_RefTotal(...); @@ -182,6 +192,7 @@ extern "C" { int PyArg_Parse(...) { return 0; }; int PyArg_ParseTuple(...) { return 0; } int PyArg_ParseTupleAndKeywords(...) { return 0; } +int PyArg_UnpackTuple(...) { return 0; }; int PyBool_FromLong(...) { return 0; } int PyBuffer_Release(...) { return 0; } int PyBytes_AsString(...) { return 0; } @@ -248,11 +259,14 @@ int PyModule_AddIntConstant(...) { return 0; }; int PyModule_AddObject(...) { return 0; }; int PyModule_AddStringConstant(...) { return 0; }; int PyModule_Create2(...) { return 0; }; +int PyNumber_Check(...) { return 0; } int PyNumber_Float(...) { return 0; } +int PyNumber_Int(...) { return 0; } int PyNumber_Long(...) { return 0; } int PyObject_ASCII(...) { return 0; } int PyObject_Call(...) { return 0; } int PyObject_CallFunction(...) { return 0; } +int PyObject_CallFunctionObjArgs(...) { return 0; } int PyObject_CallMethod(...) { return 0; } int PyObject_CallMethodObjArgs(...) { return 0; } int PyObject_CallObject(...) { return 0; } @@ -316,8 +330,14 @@ int Py_BuildValue(...) { return 0; } int Py_InitModule4(...) { return 0; } int Py_InitModule4_64(...) { return 0; } int Py_InitModule4TraceRefs(...) { return 0; }; +int _PyArg_ParseTuple_SizeT(...) { return 0; }; +int _PyArg_ParseTupleAndKeywords_SizeT(...) { return 0; }; +int _PyArg_Parse_SizeT(...) { return 0; }; +int _PyObject_CallFunction_SizeT(...) { return 0; }; +int _PyObject_CallMethod_SizeT(...) { return 0; }; int _PyObject_DebugFree(...) { return 0; }; int _PyObject_Del(...) { return 0; }; +int _Py_BuildValue_SizeT(...) { return 0; }; int _Py_Dealloc(...) { return 0; }; int _Py_NegativeRefcount(...) { return 0; }; int _Py_RefTotal(...) { return 0; }; diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 84642aa48f..71aac8d25d 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -92,7 +92,7 @@ PkgListSet(["PYTHON", "DIRECT", # Python support "GTK2", "WX", "FLTK", # Toolkit support "ROCKET", # GUI libraries "CARBON", "COCOA", # Mac OS X toolkits - "OSMESA", "X11", "XF86DGA", "XRANDR", "XCURSOR", # Unix platform support + "X11", "XF86DGA", "XRANDR", "XCURSOR", # Unix platform support "PANDATOOL", "PVIEW", "DEPLOYTOOLS", # Toolchain "SKEL", # Example SKEL project "PANDAFX", # Some distortion special lenses @@ -697,7 +697,6 @@ if (COMPILER=="GCC"): SmartPkgEnable("GLES", "glesv1_cm", ("GLESv1_CM"), ("GLES/gl.h"), framework = "OpenGLES") SmartPkgEnable("GLES2", "glesv2", ("GLESv2"), ("GLES2/gl2.h")) #framework = "OpenGLES"? SmartPkgEnable("EGL", "egl", ("EGL"), ("EGL/egl.h")) - SmartPkgEnable("OSMESA", "osmesa", ("OSMesa"), ("GL/osmesa.h")) SmartPkgEnable("NVIDIACG", "", ("Cg"), "Cg/cg.h", framework = "Cg") SmartPkgEnable("ODE", "", ("ode"), "ode/ode.h", tool = "ode-config") SmartPkgEnable("OPENAL", "openal", ("openal"), "AL/al.h", framework = "OpenAL") @@ -1901,9 +1900,6 @@ DTOOL_CONFIG=[ ("HAVE_GL", '1', 'UNDEF'), ("HAVE_GLES", 'UNDEF', 'UNDEF'), ("HAVE_GLES2", 'UNDEF', 'UNDEF'), - ("HAVE_MESA", 'UNDEF', 'UNDEF'), - ("MESA_MGL", 'UNDEF', 'UNDEF'), - ("HAVE_SGIGL", 'UNDEF', 'UNDEF'), ("HAVE_GLX", 'UNDEF', '1'), ("HAVE_EGL", 'UNDEF', 'UNDEF'), ("HAVE_WGL", '1', 'UNDEF'), @@ -3828,15 +3824,16 @@ if (PkgSkip("OPENSSL")==0 and not RTDIST and not RUNTIME and PkgSkip("DEPLOYTOOL TargetAdd('build_patch.exe', input=COMMON_PANDA_LIBS_PYSTUB) TargetAdd('build_patch.exe', opts=OPTS) - TargetAdd('check_adler_check_adler.obj', opts=OPTS, input='check_adler.cxx') - TargetAdd('check_adler.exe', input=['check_adler_check_adler.obj']) - TargetAdd('check_adler.exe', input=COMMON_PANDA_LIBS_PYSTUB) - TargetAdd('check_adler.exe', opts=OPTS) + if not PkgSkip("ZLIB"): + TargetAdd('check_adler_check_adler.obj', opts=OPTS, input='check_adler.cxx') + TargetAdd('check_adler.exe', input=['check_adler_check_adler.obj']) + TargetAdd('check_adler.exe', input=COMMON_PANDA_LIBS_PYSTUB) + TargetAdd('check_adler.exe', opts=OPTS) - TargetAdd('check_crc_check_crc.obj', opts=OPTS, input='check_crc.cxx') - TargetAdd('check_crc.exe', input=['check_crc_check_crc.obj']) - TargetAdd('check_crc.exe', input=COMMON_PANDA_LIBS_PYSTUB) - TargetAdd('check_crc.exe', opts=OPTS) + TargetAdd('check_crc_check_crc.obj', opts=OPTS, input='check_crc.cxx') + TargetAdd('check_crc.exe', input=['check_crc_check_crc.obj']) + TargetAdd('check_crc.exe', input=COMMON_PANDA_LIBS_PYSTUB) + TargetAdd('check_crc.exe', opts=OPTS) TargetAdd('check_md5_check_md5.obj', opts=OPTS, input='check_md5.cxx') TargetAdd('check_md5.exe', input=['check_md5_check_md5.obj']) @@ -4035,20 +4032,6 @@ if (not RUNTIME): TargetAdd('egg.pyd', input=COMMON_PANDA_LIBS) TargetAdd('egg.pyd', opts=['PYTHON']) -# -# DIRECTORY: panda/src/mesadisplay/ -# - -if (GetTarget() != 'windows' and PkgSkip("GL")==0 and PkgSkip("OSMESA")==0 and not RUNTIME): - OPTS=['DIR:panda/src/mesadisplay', 'DIR:panda/src/glstuff', 'BUILDING:PANDAMESA', 'NVIDIACG', 'GL', 'OSMESA'] - TargetAdd('p3mesadisplay_composite1.obj', opts=OPTS, input='p3mesadisplay_composite1.cxx') - OPTS=['DIR:panda/metalibs/pandagl', 'BUILDING:PANDAMESA', 'NVIDIACG', 'GL'] - TargetAdd('libpandamesa.dll', input='p3mesadisplay_composite1.obj') - if (PkgSkip('PANDAFX')==0): - TargetAdd('libpandamesa.dll', input='libpandafx.dll') - TargetAdd('libpandamesa.dll', input=COMMON_PANDA_LIBS) - TargetAdd('libpandamesa.dll', opts=['MODULE', 'GL', 'OSMESA']) - # # DIRECTORY: panda/src/x11display/ # @@ -5539,15 +5522,17 @@ if (PkgSkip("PANDATOOL")==0): # DIRECTORY: pandatool/src/miscprogs/ # -if (PkgSkip("PANDATOOL")==0): - OPTS=['DIR:pandatool/src/miscprogs'] - TargetAdd('bin2c_binToC.obj', opts=OPTS, input='binToC.cxx') - TargetAdd('bin2c.exe', input='bin2c_binToC.obj') - TargetAdd('bin2c.exe', input='libp3progbase.lib') - TargetAdd('bin2c.exe', input='libp3pandatoolbase.lib') - TargetAdd('bin2c.exe', input=COMMON_PANDA_LIBS) - TargetAdd('bin2c.exe', input='libp3pystub.lib') - TargetAdd('bin2c.exe', opts=['ADVAPI']) +# This is a bit of an esoteric tool, and it causes issues because +# it conflicts with tools of the same name in different packages. +#if (PkgSkip("PANDATOOL")==0): +# OPTS=['DIR:pandatool/src/miscprogs'] +# TargetAdd('bin2c_binToC.obj', opts=OPTS, input='binToC.cxx') +# TargetAdd('bin2c.exe', input='bin2c_binToC.obj') +# TargetAdd('bin2c.exe', input='libp3progbase.lib') +# TargetAdd('bin2c.exe', input='libp3pandatoolbase.lib') +# TargetAdd('bin2c.exe', input=COMMON_PANDA_LIBS) +# TargetAdd('bin2c.exe', input='libp3pystub.lib') +# TargetAdd('bin2c.exe', opts=['ADVAPI']) # # DIRECTORY: pandatool/src/pstatserver/ diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 93c2ba3bf6..5ee36e6c91 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -2328,15 +2328,20 @@ def SetupBuildEnvironment(compiler): ######################################################################## def CopyFile(dstfile, srcfile): - if (dstfile[-1]=='/'): + if dstfile[-1] == '/': dstdir = dstfile fnl = srcfile.rfind("/") - if (fnl < 0): fn = srcfile - else: fn = srcfile[fnl+1:] + if fnl < 0: + fn = srcfile + else: + fn = srcfile[fnl+1:] dstfile = dstdir + fn + if NeedsBuild([dstfile], [srcfile]): if os.path.islink(srcfile): # Preserve symlinks + if os.path.exists(dstfile): + os.unlink(dstfile) os.symlink(os.readlink(srcfile), dstfile) else: WriteBinaryFile(dstfile, ReadBinaryFile(srcfile)) diff --git a/panda/src/androiddisplay/androidGraphicsStateGuardian.cxx b/panda/src/androiddisplay/androidGraphicsStateGuardian.cxx index d987cbe0fc..aa6b502e0b 100644 --- a/panda/src/androiddisplay/androidGraphicsStateGuardian.cxx +++ b/panda/src/androiddisplay/androidGraphicsStateGuardian.cxx @@ -405,8 +405,6 @@ get_extra_extensions() { // not defined. //////////////////////////////////////////////////////////////////// void *AndroidGraphicsStateGuardian:: -do_get_extension_func(const char *prefix, const char *name) { - string fullname = string(prefix) + string(name); - - return (void *)eglGetProcAddress(fullname.c_str()); +do_get_extension_func(const char *name) { + return (void *)eglGetProcAddress(name); } diff --git a/panda/src/androiddisplay/androidGraphicsStateGuardian.h b/panda/src/androiddisplay/androidGraphicsStateGuardian.h index 5e82cf3159..d9824ff6fd 100644 --- a/panda/src/androiddisplay/androidGraphicsStateGuardian.h +++ b/panda/src/androiddisplay/androidGraphicsStateGuardian.h @@ -61,7 +61,7 @@ protected: virtual void query_gl_version(); virtual void get_extra_extensions(); - virtual void *do_get_extension_func(const char *prefix, const char *name); + virtual void *do_get_extension_func(const char *name); private: int _egl_version_major, _egl_version_minor; diff --git a/panda/src/cocoadisplay/Sources.pp b/panda/src/cocoadisplay/Sources.pp index 0a3a5b4e44..f0e136fe61 100644 --- a/panda/src/cocoadisplay/Sources.pp +++ b/panda/src/cocoadisplay/Sources.pp @@ -3,7 +3,7 @@ #define OTHER_LIBS p3interrogatedb:c p3dconfig:c p3dtoolconfig:m \ p3dtoolutil:c p3dtoolbase:c p3dtool:m -#define OSX_SYS_FRAMEWORKS ApplicationServices AppKit +#define OSX_SYS_FRAMEWORKS ApplicationServices AppKit Carbon #begin lib_target #define TARGET p3cocoadisplay diff --git a/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h b/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h index d70061a813..2d88c9753d 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h +++ b/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h @@ -46,7 +46,7 @@ public: protected: virtual void query_gl_version(); - virtual void *do_get_extension_func(const char *prefix, const char *name); + virtual void *do_get_extension_func(const char *name); public: static TypeHandle get_class_type() { diff --git a/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.mm b/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.mm index 01301c4847..d16b5795c1 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsStateGuardian.mm @@ -276,10 +276,9 @@ query_gl_version() { // not defined. //////////////////////////////////////////////////////////////////// void *CocoaGraphicsStateGuardian:: -do_get_extension_func(const char *prefix, const char *name) { - char* fullname = (char*) malloc(strlen(prefix) + strlen(name) + 2); - strcpy(fullname + 1, prefix); - strcpy(fullname + 1 + strlen(prefix), name); +do_get_extension_func(const char *name) { + char* fullname = (char*) malloc(strlen(name) + 2); + strcpy(fullname + 1, name); fullname[0] = '_'; // Believe it or not, but this is actually the @@ -292,7 +291,7 @@ do_get_extension_func(const char *prefix, const char *name) { } cocoadisplay_cat.warning() << - "do_get_extension_func failed for " << prefix << name << "!\n"; + "do_get_extension_func failed for " << fullname << "!\n"; free(fullname); return NULL; diff --git a/panda/src/display/config_display.cxx b/panda/src/display/config_display.cxx index e89a7df768..6cfa88dec8 100644 --- a/panda/src/display/config_display.cxx +++ b/panda/src/display/config_display.cxx @@ -405,6 +405,17 @@ ConfigVariableBool framebuffer_stereo PRC_DESC("True if FM_stereo should be added to the default framebuffer " "properties, which requests a stereo-capable display, if " "supported by the graphics driver.")); +ConfigVariableBool framebuffer_srgb +("framebuffer-srgb", false, + PRC_DESC("Set this to request an sRGB framebuffer, which will " + "convert all values to linear space before blending. This " + "means that the output will be properly gamma-corrected, as " + "long as all the input textures are either converted from " + "original sRGB to linear or sRGB textures are used.")); +ConfigVariableBool framebuffer_float +("framebuffer-float", false, + PRC_DESC("Set this to request a framebuffer that uses floating-point " + "storage for the color channel.")); ConfigVariableInt depth_bits ("depth-bits", 0, diff --git a/panda/src/display/config_display.h b/panda/src/display/config_display.h index 2cd7569f02..d36f24c5bf 100644 --- a/panda/src/display/config_display.h +++ b/panda/src/display/config_display.h @@ -92,6 +92,8 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_alpha; extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_stencil; extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_accum; extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_stereo; +extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_srgb; +extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_float; extern EXPCL_PANDA_DISPLAY ConfigVariableInt depth_bits; extern EXPCL_PANDA_DISPLAY ConfigVariableInt color_bits; extern EXPCL_PANDA_DISPLAY ConfigVariableInt alpha_bits; diff --git a/panda/src/display/displayRegion.I b/panda/src/display/displayRegion.I index bb549873c0..1e30c2c55b 100644 --- a/panda/src/display/displayRegion.I +++ b/panda/src/display/displayRegion.I @@ -38,6 +38,34 @@ get_lens_index() const { return cdata->_lens_index; } +/////////////////////////////////////////////////////////////////// +// Function: DisplayRegion::get_num_regions +// Access: Published +// Description: Returns the number of regions, see set_num_regions. +//////////////////////////////////////////////////////////////////// +INLINE int DisplayRegion:: +get_num_regions() const { + CDReader cdata(_cycler); + return cdata->_regions.size(); +} + +/////////////////////////////////////////////////////////////////// +// Function: DisplayRegion::set_num_regions +// Access: Published +// Description: Sets the number of regions that this DisplayRegion +// indicates. Usually, this number is 1 (and it is +// always at least 1), and only the first is used for +// rendering. However, if more than one is provided, +// you may select which one to render into using a +// geometry shader (gl_ViewportIndex in GLSL). +//////////////////////////////////////////////////////////////////// +INLINE void DisplayRegion:: +set_num_regions(int i) { + nassertv(i >= 1); + CDWriter cdata(_cycler); + cdata->_regions.resize(i); +} + /////////////////////////////////////////////////////////////////// // Function: DisplayRegion::get_dimensions // Access: Published @@ -47,11 +75,24 @@ get_lens_index() const { //////////////////////////////////////////////////////////////////// INLINE void DisplayRegion:: get_dimensions(PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const { + get_dimensions(0, l, r, b, t); +} + +/////////////////////////////////////////////////////////////////// +// Function: DisplayRegion::get_dimensions +// Access: Published +// Description: Retrieves the coordinates of the DisplayRegion's +// rectangle within its GraphicsOutput. These numbers +// will be in the range [0..1]. +//////////////////////////////////////////////////////////////////// +INLINE void DisplayRegion:: +get_dimensions(int i, PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const { CDReader cdata(_cycler); - l = cdata->_dimensions[0]; - r = cdata->_dimensions[1]; - b = cdata->_dimensions[2]; - t = cdata->_dimensions[3]; + const Region ®ion = cdata->_regions[i]; + l = region._dimensions[0]; + r = region._dimensions[1]; + b = region._dimensions[2]; + t = region._dimensions[3]; } /////////////////////////////////////////////////////////////////// @@ -62,9 +103,9 @@ get_dimensions(PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) c // will be in the range [0..1]. //////////////////////////////////////////////////////////////////// INLINE LVecBase4 DisplayRegion:: -get_dimensions() const { +get_dimensions(int i) const { CDReader cdata(_cycler); - return cdata->_dimensions; + return cdata->_regions[i]._dimensions; } //////////////////////////////////////////////////////////////////// @@ -75,9 +116,9 @@ get_dimensions() const { // will be in the range [0..1]. //////////////////////////////////////////////////////////////////// INLINE PN_stdfloat DisplayRegion:: -get_left() const { +get_left(int i) const { CDReader cdata(_cycler); - return cdata->_dimensions[0]; + return cdata->_regions[i]._dimensions[0]; } //////////////////////////////////////////////////////////////////// @@ -88,9 +129,9 @@ get_left() const { // will be in the range [0..1]. //////////////////////////////////////////////////////////////////// INLINE PN_stdfloat DisplayRegion:: -get_right() const { +get_right(int i) const { CDReader cdata(_cycler); - return cdata->_dimensions[1]; + return cdata->_regions[i]._dimensions[1]; } //////////////////////////////////////////////////////////////////// @@ -101,9 +142,9 @@ get_right() const { // number will be in the range [0..1]. //////////////////////////////////////////////////////////////////// INLINE PN_stdfloat DisplayRegion:: -get_bottom() const { +get_bottom(int i) const { CDReader cdata(_cycler); - return cdata->_dimensions[2]; + return cdata->_regions[i]._dimensions[2]; } //////////////////////////////////////////////////////////////////// @@ -114,9 +155,9 @@ get_bottom() const { // will be in the range [0..1]. //////////////////////////////////////////////////////////////////// INLINE PN_stdfloat DisplayRegion:: -get_top() const { +get_top(int i) const { CDReader cdata(_cycler); - return cdata->_dimensions[3]; + return cdata->_regions[i]._dimensions[3]; } //////////////////////////////////////////////////////////////////// @@ -130,7 +171,35 @@ get_top() const { //////////////////////////////////////////////////////////////////// INLINE void DisplayRegion:: set_dimensions(PN_stdfloat l, PN_stdfloat r, PN_stdfloat b, PN_stdfloat t) { - set_dimensions(LVecBase4(l, r, b, t)); + set_dimensions(0, LVecBase4(l, r, b, t)); +} + +//////////////////////////////////////////////////////////////////// +// Function: DisplayRegion::set_dimensions +// Access: Published, Virtual +// Description: Changes the portion of the framebuffer this +// DisplayRegion corresponds to. The parameters range +// from 0 to 1, where 0,0 is the lower left corner and +// 1,1 is the upper right; (0, 1, 0, 1) represents the +// whole screen. +//////////////////////////////////////////////////////////////////// +INLINE void DisplayRegion:: +set_dimensions(int i, PN_stdfloat l, PN_stdfloat r, PN_stdfloat b, PN_stdfloat t) { + set_dimensions(i, LVecBase4(l, r, b, t)); +} + +//////////////////////////////////////////////////////////////////// +// Function: DisplayRegion::set_dimensions +// Access: Published, Virtual +// Description: Changes the portion of the framebuffer this +// DisplayRegion corresponds to. The parameters range +// from 0 to 1, where 0,0 is the lower left corner and +// 1,1 is the upper right; (0, 1, 0, 1) represents the +// whole screen. +//////////////////////////////////////////////////////////////////// +INLINE void DisplayRegion:: +set_dimensions(const LVecBase4 &dimensions) { + set_dimensions(0, dimensions); } //////////////////////////////////////////////////////////////////// @@ -387,9 +456,9 @@ get_draw_callback() const { // Description: Returns the width of the DisplayRegion in pixels. //////////////////////////////////////////////////////////////////// INLINE int DisplayRegion:: -get_pixel_width() const { +get_pixel_width(int i) const { CDReader cdata(_cycler); - return cdata->_pr - cdata->_pl; + return cdata->_regions[i]._pixels[1] - cdata->_regions[i]._pixels[0]; } //////////////////////////////////////////////////////////////////// @@ -398,9 +467,9 @@ get_pixel_width() const { // Description: Returns the height of the DisplayRegion in pixels. //////////////////////////////////////////////////////////////////// INLINE int DisplayRegion:: -get_pixel_height() const { +get_pixel_height(int i) const { CDReader cdata(_cycler); - return cdata->_pt - cdata->_pb; + return cdata->_regions[i]._pixels[3] - cdata->_regions[i]._pixels[2]; } //////////////////////////////////////////////////////////////////// @@ -411,11 +480,23 @@ get_pixel_height() const { //////////////////////////////////////////////////////////////////// INLINE void DisplayRegion:: get_pixels(int &pl, int &pr, int &pb, int &pt) const { + get_pixels(0, pl, pr, pb, pt); +} + +//////////////////////////////////////////////////////////////////// +// Function: DisplayRegion::get_pixels +// Access: Public +// Description: Retrieves the coordinates of the DisplayRegion within +// its window, in pixels. +//////////////////////////////////////////////////////////////////// +INLINE void DisplayRegion:: +get_pixels(int i, int &pl, int &pr, int &pb, int &pt) const { CDReader cdata(_cycler); - pl = cdata->_pl; - pr = cdata->_pr; - pb = cdata->_pb; - pt = cdata->_pt; + const Region ®ion = cdata->_regions[i]; + pl = region._pixels[0]; + pr = region._pixels[1]; + pb = region._pixels[2]; + pt = region._pixels[3]; } //////////////////////////////////////////////////////////////////// @@ -427,11 +508,24 @@ get_pixels(int &pl, int &pr, int &pb, int &pt) const { //////////////////////////////////////////////////////////////////// INLINE void DisplayRegion:: get_region_pixels(int &xo, int &yo, int &w, int &h) const { + get_region_pixels(0, xo, yo, w, h); +} + +//////////////////////////////////////////////////////////////////// +// Function: DisplayRegion::get_region_pixels +// Access: Public +// Description: Retrieves the coordinates of the DisplayRegion within +// its window, as the pixel location of its bottom-left +// corner, along with a pixel width and height. +//////////////////////////////////////////////////////////////////// +INLINE void DisplayRegion:: +get_region_pixels(int i, int &xo, int &yo, int &w, int &h) const { CDReader cdata(_cycler); - xo = cdata->_pl; - yo = cdata->_pb; - w = cdata->_pr - cdata->_pl; - h = cdata->_pt - cdata->_pb; + const Region ®ion = cdata->_regions[i]; + xo = region._pixels[0]; + yo = region._pixels[2]; + w = region._pixels[1] - xo; + h = region._pixels[3] - yo; } //////////////////////////////////////////////////////////////////// @@ -444,11 +538,25 @@ get_region_pixels(int &xo, int &yo, int &w, int &h) const { //////////////////////////////////////////////////////////////////// INLINE void DisplayRegion:: get_region_pixels_i(int &xo, int &yo, int &w, int &h) const { + get_region_pixels_i(0, xo, yo, w, h); +} + +//////////////////////////////////////////////////////////////////// +// Function: DisplayRegion::get_region_pixels_i +// Access: Public +// Description: Similar to get_region_pixels(), but returns the upper +// left corner, and the pixel numbers are numbered from +// the top-left corner down, in the DirectX way of +// things. +//////////////////////////////////////////////////////////////////// +INLINE void DisplayRegion:: +get_region_pixels_i(int i, int &xo, int &yo, int &w, int &h) const { CDReader cdata(_cycler); - xo = cdata->_pl; - yo = cdata->_pti; - w = cdata->_pr - cdata->_pl; - h = cdata->_pbi - cdata->_pti; + const Region ®ion = cdata->_regions[i]; + xo = region._pixels_i[0]; + yo = region._pixels_i[2]; + w = region._pixels_i[1] - xo; + h = region._pixels_i[3] - yo; } //////////////////////////////////////////////////////////////////// @@ -522,6 +630,18 @@ get_draw_region_pcollector() { return _draw_region_pcollector; } +//////////////////////////////////////////////////////////////////// +// Function: DisplayRegion::Region::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE DisplayRegion::Region:: +Region() : + _dimensions(0, 1, 0, 1), + _pixels(0), + _pixels_i(0) { +} + //////////////////////////////////////////////////////////////////// // Function: DisplayRegion::CDataCull::Constructor // Access: Public @@ -633,6 +753,16 @@ is_any_clear_active() const { return _object->is_any_clear_active(); } +/////////////////////////////////////////////////////////////////// +// Function: DisplayRegionPipelineReader::get_num_regions +// Access: Published +// Description: Returns the number of regions, see set_num_regions. +//////////////////////////////////////////////////////////////////// +INLINE int DisplayRegionPipelineReader:: +get_num_regions() const { + return _cdata->_regions.size(); +} + //////////////////////////////////////////////////////////////////// // Function: DisplayRegionPipelineReader::get_dimensions // Access: Public @@ -642,10 +772,23 @@ is_any_clear_active() const { //////////////////////////////////////////////////////////////////// INLINE void DisplayRegionPipelineReader:: get_dimensions(PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const { - l = _cdata->_dimensions[0]; - r = _cdata->_dimensions[1]; - b = _cdata->_dimensions[2]; - t = _cdata->_dimensions[3]; + return get_dimensions(0, l, r, b, t); +} + +//////////////////////////////////////////////////////////////////// +// Function: DisplayRegionPipelineReader::get_dimensions +// Access: Public +// Description: Retrieves the coordinates of the DisplayRegion's +// rectangle within its GraphicsOutput. These numbers +// will be in the range [0..1]. +//////////////////////////////////////////////////////////////////// +INLINE void DisplayRegionPipelineReader:: +get_dimensions(int i, PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const { + const DisplayRegion::Region ®ion = _cdata->_regions[i]; + l = region._dimensions[0]; + r = region._dimensions[1]; + b = region._dimensions[2]; + t = region._dimensions[3]; } //////////////////////////////////////////////////////////////////// @@ -656,8 +799,8 @@ get_dimensions(PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) c // will be in the range [0..1]. //////////////////////////////////////////////////////////////////// INLINE const LVecBase4 &DisplayRegionPipelineReader:: -get_dimensions() const { - return _cdata->_dimensions; +get_dimensions(int i) const { + return _cdata->_regions[i]._dimensions; } //////////////////////////////////////////////////////////////////// @@ -668,8 +811,8 @@ get_dimensions() const { // will be in the range [0..1]. //////////////////////////////////////////////////////////////////// INLINE PN_stdfloat DisplayRegionPipelineReader:: -get_left() const { - return _cdata->_dimensions[0]; +get_left(int i) const { + return _cdata->_regions[i]._dimensions[0]; } //////////////////////////////////////////////////////////////////// @@ -680,8 +823,8 @@ get_left() const { // will be in the range [0..1]. //////////////////////////////////////////////////////////////////// INLINE PN_stdfloat DisplayRegionPipelineReader:: -get_right() const { - return _cdata->_dimensions[1]; +get_right(int i) const { + return _cdata->_regions[i]._dimensions[1]; } //////////////////////////////////////////////////////////////////// @@ -692,8 +835,8 @@ get_right() const { // number will be in the range [0..1]. //////////////////////////////////////////////////////////////////// INLINE PN_stdfloat DisplayRegionPipelineReader:: -get_bottom() const { - return _cdata->_dimensions[2]; +get_bottom(int i) const { + return _cdata->_regions[i]._dimensions[2]; } //////////////////////////////////////////////////////////////////// @@ -704,8 +847,8 @@ get_bottom() const { // will be in the range [0..1]. //////////////////////////////////////////////////////////////////// INLINE PN_stdfloat DisplayRegionPipelineReader:: -get_top() const { - return _cdata->_dimensions[3]; +get_top(int i) const { + return _cdata->_regions[i]._dimensions[3]; } //////////////////////////////////////////////////////////////////// @@ -816,10 +959,22 @@ get_draw_callback() const { //////////////////////////////////////////////////////////////////// INLINE void DisplayRegionPipelineReader:: get_pixels(int &pl, int &pr, int &pb, int &pt) const { - pl = _cdata->_pl; - pr = _cdata->_pr; - pb = _cdata->_pb; - pt = _cdata->_pt; + get_pixels(0, pl, pr, pb, pt); +} + +//////////////////////////////////////////////////////////////////// +// Function: DisplayRegionPipelineReader::get_pixels +// Access: Public +// Description: Retrieves the coordinates of the DisplayRegion within +// its window, in pixels. +//////////////////////////////////////////////////////////////////// +INLINE void DisplayRegionPipelineReader:: +get_pixels(int i, int &pl, int &pr, int &pb, int &pt) const { + const DisplayRegion::Region ®ion = _cdata->_regions[i]; + pl = region._pixels[0]; + pr = region._pixels[1]; + pb = region._pixels[2]; + pt = region._pixels[3]; } //////////////////////////////////////////////////////////////////// @@ -831,10 +986,23 @@ get_pixels(int &pl, int &pr, int &pb, int &pt) const { //////////////////////////////////////////////////////////////////// INLINE void DisplayRegionPipelineReader:: get_region_pixels(int &xo, int &yo, int &w, int &h) const { - xo = _cdata->_pl; - yo = _cdata->_pb; - w = _cdata->_pr - _cdata->_pl; - h = _cdata->_pt - _cdata->_pb; + get_region_pixels(0, xo, yo, w, h); +} + +//////////////////////////////////////////////////////////////////// +// Function: DisplayRegionPipelineReader::get_region_pixels +// Access: Public +// Description: Retrieves the coordinates of the DisplayRegion within +// its window, as the pixel location of its bottom-left +// corner, along with a pixel width and height. +//////////////////////////////////////////////////////////////////// +INLINE void DisplayRegionPipelineReader:: +get_region_pixels(int i, int &xo, int &yo, int &w, int &h) const { + const DisplayRegion::Region ®ion = _cdata->_regions[i]; + xo = region._pixels[0]; + yo = region._pixels[2]; + w = region._pixels[1] - xo; + h = region._pixels[3] - yo; } //////////////////////////////////////////////////////////////////// @@ -847,10 +1015,24 @@ get_region_pixels(int &xo, int &yo, int &w, int &h) const { //////////////////////////////////////////////////////////////////// INLINE void DisplayRegionPipelineReader:: get_region_pixels_i(int &xo, int &yo, int &w, int &h) const { - xo = _cdata->_pl; - yo = _cdata->_pti; - w = _cdata->_pr - _cdata->_pl; - h = _cdata->_pbi - _cdata->_pti; + get_region_pixels_i(0, xo, yo, w, h); +} + +//////////////////////////////////////////////////////////////////// +// Function: DisplayRegionPipelineReader::get_region_pixels_i +// Access: Public +// Description: Similar to get_region_pixels(), but returns the upper +// left corner, and the pixel numbers are numbered from +// the top-left corner down, in the DirectX way of +// things. +//////////////////////////////////////////////////////////////////// +INLINE void DisplayRegionPipelineReader:: +get_region_pixels_i(int i, int &xo, int &yo, int &w, int &h) const { + const DisplayRegion::Region ®ion = _cdata->_regions[i]; + xo = region._pixels_i[0]; + yo = region._pixels_i[2]; + w = region._pixels_i[1] - xo; + h = region._pixels_i[3] - yo; } //////////////////////////////////////////////////////////////////// @@ -859,8 +1041,8 @@ get_region_pixels_i(int &xo, int &yo, int &w, int &h) const { // Description: Returns the width of the DisplayRegion in pixels. //////////////////////////////////////////////////////////////////// INLINE int DisplayRegionPipelineReader:: -get_pixel_width() const { - return _cdata->_pr - _cdata->_pl; +get_pixel_width(int i) const { + return _cdata->_regions[i]._pixels[1] - _cdata->_regions[i]._pixels[0]; } //////////////////////////////////////////////////////////////////// @@ -869,8 +1051,7 @@ get_pixel_width() const { // Description: Gets the index into a lens_node lens array. 0 default //////////////////////////////////////////////////////////////////// INLINE int DisplayRegionPipelineReader:: -get_lens_index() const -{ +get_lens_index() const { return _cdata->_lens_index; } @@ -880,6 +1061,6 @@ get_lens_index() const // Description: Returns the height of the DisplayRegion in pixels. //////////////////////////////////////////////////////////////////// INLINE int DisplayRegionPipelineReader:: -get_pixel_height() const { - return _cdata->_pt - _cdata->_pb; +get_pixel_height(int i) const { + return _cdata->_regions[i]._pixels[3] - _cdata->_regions[i]._pixels[2]; } diff --git a/panda/src/display/displayRegion.cxx b/panda/src/display/displayRegion.cxx index 5bf57bf2fa..c540d5ac5f 100644 --- a/panda/src/display/displayRegion.cxx +++ b/panda/src/display/displayRegion.cxx @@ -42,7 +42,8 @@ DisplayRegion(GraphicsOutput *window, const LVecBase4 &dimensions) : { _screenshot_buffer_type = window->get_draw_buffer_type(); _draw_buffer_type = window->get_draw_buffer_type(); - set_dimensions(dimensions); + set_num_regions(1); + set_dimensions(0, dimensions); compute_pixels_all_stages(); _window->add_display_region(this); @@ -127,15 +128,15 @@ set_lens_index(int index) { // whole screen. //////////////////////////////////////////////////////////////////// void DisplayRegion:: -set_dimensions(const LVecBase4 &dimensions) { +set_dimensions(int i, const LVecBase4 &dimensions) { int pipeline_stage = Thread::get_current_pipeline_stage(); nassertv(pipeline_stage == 0); CDWriter cdata(_cycler); - cdata->_dimensions = dimensions; + cdata->_regions[i]._dimensions = dimensions; if (_window != (GraphicsOutput *)NULL && _window->has_size()) { - do_compute_pixels(_window->get_fb_x_size(), _window->get_fb_y_size(), cdata); + do_compute_pixels(i, _window->get_fb_x_size(), _window->get_fb_y_size(), cdata); } } @@ -419,9 +420,8 @@ set_target_tex_page(int page) { void DisplayRegion:: output(ostream &out) const { CDReader cdata(_cycler); - out << "DisplayRegion(" << cdata->_dimensions << ")=pixels(" << cdata->_pl - << " " << cdata->_pr << " " << cdata->_pb << " " << cdata->_pt - << ")"; + out << "DisplayRegion(" << cdata->_regions[0]._dimensions + << ")=pixels(" << cdata->_regions[0]._pixels << ")"; } //////////////////////////////////////////////////////////////////// @@ -636,8 +636,10 @@ void DisplayRegion:: compute_pixels() { if (_window != (GraphicsOutput *)NULL) { CDWriter cdata(_cycler, false); - do_compute_pixels(_window->get_fb_x_size(), _window->get_fb_y_size(), - cdata); + for (int i = 0; i < cdata->_regions.size(); ++i) { + do_compute_pixels(i, _window->get_fb_x_size(), _window->get_fb_y_size(), + cdata); + } } } @@ -656,8 +658,10 @@ compute_pixels_all_stages() { if (_window != (GraphicsOutput *)NULL) { OPEN_ITERATE_ALL_STAGES(_cycler) { CDStageWriter cdata(_cycler, pipeline_stage); - do_compute_pixels(_window->get_fb_x_size(), _window->get_fb_y_size(), - cdata); + for (int i = 0; i < cdata->_regions.size(); ++i) { + do_compute_pixels(i, _window->get_fb_x_size(), _window->get_fb_y_size(), + cdata); + } } CLOSE_ITERATE_ALL_STAGES(_cycler); } @@ -673,7 +677,9 @@ compute_pixels_all_stages() { void DisplayRegion:: compute_pixels(int x_size, int y_size) { CDWriter cdata(_cycler, false); - do_compute_pixels(x_size, y_size, cdata); + for (int i = 0; i < cdata->_regions.size(); ++i) { + do_compute_pixels(i, x_size, y_size, cdata); + } } //////////////////////////////////////////////////////////////////// @@ -689,7 +695,9 @@ void DisplayRegion:: compute_pixels_all_stages(int x_size, int y_size) { OPEN_ITERATE_ALL_STAGES(_cycler) { CDStageWriter cdata(_cycler, pipeline_stage); - do_compute_pixels(x_size, y_size, cdata); + for (int i = 0; i < cdata->_regions.size(); ++i) { + do_compute_pixels(i, x_size, y_size, cdata); + } } CLOSE_ITERATE_ALL_STAGES(_cycler); } @@ -741,32 +749,36 @@ win_display_regions_changed() { // assumes that we already have the lock. //////////////////////////////////////////////////////////////////// void DisplayRegion:: -do_compute_pixels(int x_size, int y_size, CData *cdata) { +do_compute_pixels(int i, int x_size, int y_size, CData *cdata) { if (display_cat.is_debug()) { display_cat.debug() << "DisplayRegion::do_compute_pixels(" << x_size << ", " << y_size << ")\n"; } - int old_w = cdata->_pr - cdata->_pl; - int old_h = cdata->_pt - cdata->_pb; + Region ®ion = cdata->_regions[i]; - cdata->_pl = int((cdata->_dimensions[0] * x_size) + 0.5); - cdata->_pr = int((cdata->_dimensions[1] * x_size) + 0.5); + int old_w = region._pixels[1] - region._pixels[0]; + int old_h = region._pixels[3] - region._pixels[2]; + + region._pixels[0] = int((region._dimensions[0] * x_size) + 0.5); + region._pixels[1] = int((region._dimensions[1] * x_size) + 0.5); + region._pixels_i[0] = region._pixels[0]; + region._pixels_i[1] = region._pixels[1]; nassertv(_window != (GraphicsOutput *)NULL); if (_window->get_inverted()) { // The window is inverted; compute the DisplayRegion accordingly. - cdata->_pb = int(((1.0f - cdata->_dimensions[3]) * y_size) + 0.5); - cdata->_pt = int(((1.0f - cdata->_dimensions[2]) * y_size) + 0.5); - cdata->_pbi = int((cdata->_dimensions[3] * y_size) + 0.5); - cdata->_pti = int((cdata->_dimensions[2] * y_size) + 0.5); + region._pixels[2] = int(((1.0f - region._dimensions[3]) * y_size) + 0.5); + region._pixels[3] = int(((1.0f - region._dimensions[2]) * y_size) + 0.5); + region._pixels_i[2] = int((region._dimensions[3] * y_size) + 0.5); + region._pixels_i[3] = int((region._dimensions[2] * y_size) + 0.5); } else { // The window is normal. - cdata->_pb = int((cdata->_dimensions[2] * y_size) + 0.5); - cdata->_pt = int((cdata->_dimensions[3] * y_size) + 0.5); - cdata->_pbi = int(((1.0f - cdata->_dimensions[2]) * y_size) + 0.5); - cdata->_pti = int(((1.0f - cdata->_dimensions[3]) * y_size) + 0.5); + region._pixels[2] = int((region._dimensions[2] * y_size) + 0.5); + region._pixels[3] = int((region._dimensions[3] * y_size) + 0.5); + region._pixels_i[2] = int(((1.0f - region._dimensions[2]) * y_size) + 0.5); + region._pixels_i[3] = int(((1.0f - region._dimensions[3]) * y_size) + 0.5); } } @@ -814,9 +826,7 @@ do_cull(CullHandler *cull_handler, SceneSetup *scene_setup, //////////////////////////////////////////////////////////////////// DisplayRegion::CData:: CData() : - _dimensions(0.0f, 1.0f, 0.0f, 1.0f), - _pl(0), _pr(0), _pb(0), _pt(0), - _pbi(0), _pti(0), _lens_index(0), + _lens_index(0), _camera_node((Camera *)NULL), _active(true), _sort(0), @@ -824,6 +834,7 @@ CData() : _tex_view_offset(0), _target_tex_page(-1) { + _regions.push_back(Region()); } //////////////////////////////////////////////////////////////////// @@ -833,13 +844,7 @@ CData() : //////////////////////////////////////////////////////////////////// DisplayRegion::CData:: CData(const DisplayRegion::CData ©) : - _dimensions(copy._dimensions), - _pl(copy._pl), - _pr(copy._pr), - _pb(copy._pb), - _pt(copy._pt), - _pbi(copy._pbi), - _pti(copy._pti), + _regions(copy._regions), _lens_index(copy._lens_index), _camera(copy._camera), _camera_node(copy._camera_node), diff --git a/panda/src/display/displayRegion.h b/panda/src/display/displayRegion.h index 0de061ab1d..b648fe307b 100644 --- a/panda/src/display/displayRegion.h +++ b/panda/src/display/displayRegion.h @@ -72,14 +72,19 @@ public: INLINE bool operator < (const DisplayRegion &other) const; PUBLISHED: + INLINE int get_num_regions() const; + INLINE void set_num_regions(int i); INLINE void get_dimensions(PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const; - INLINE LVecBase4 get_dimensions() const; - INLINE PN_stdfloat get_left() const; - INLINE PN_stdfloat get_right() const; - INLINE PN_stdfloat get_bottom() const; - INLINE PN_stdfloat get_top() const; + INLINE void get_dimensions(int i, PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const; + INLINE LVecBase4 get_dimensions(int i = 0) const; + INLINE PN_stdfloat get_left(int i = 0) const; + INLINE PN_stdfloat get_right(int i = 0) const; + INLINE PN_stdfloat get_bottom(int i = 0) const; + INLINE PN_stdfloat get_top(int i = 0) const; INLINE void set_dimensions(PN_stdfloat l, PN_stdfloat r, PN_stdfloat b, PN_stdfloat t); - virtual void set_dimensions(const LVecBase4 &dimensions); + INLINE void set_dimensions(int i, PN_stdfloat l, PN_stdfloat r, PN_stdfloat b, PN_stdfloat t); + INLINE void set_dimensions(const LVecBase4 &dimensions); + virtual void set_dimensions(int i, const LVecBase4 &dimensions); INLINE GraphicsOutput *get_window() const; GraphicsPipe *get_pipe() const; @@ -123,8 +128,8 @@ PUBLISHED: INLINE void clear_draw_callback(); INLINE CallbackObject *get_draw_callback() const; - INLINE int get_pixel_width() const; - INLINE int get_pixel_height() const; + INLINE int get_pixel_width(int i = 0) const; + INLINE int get_pixel_height(int i = 0) const; virtual void output(ostream &out) const; @@ -144,8 +149,11 @@ public: void compute_pixels(int x_size, int y_size); void compute_pixels_all_stages(int x_size, int y_size); INLINE void get_pixels(int &pl, int &pr, int &pb, int &pt) const; + INLINE void get_pixels(int i, int &pl, int &pr, int &pb, int &pt) const; INLINE void get_region_pixels(int &xo, int &yo, int &w, int &h) const; + INLINE void get_region_pixels(int i, int &xo, int &yo, int &w, int &h) const; INLINE void get_region_pixels_i(int &xo, int &yo, int &w, int &h) const; + INLINE void get_region_pixels_i(int i, int &xo, int &yo, int &w, int &h) const; virtual bool supports_pixel_zoom() const; @@ -157,11 +165,20 @@ public: INLINE PStatCollector &get_cull_region_pcollector(); INLINE PStatCollector &get_draw_region_pcollector(); + struct Region { + INLINE Region(); + + LVecBase4 _dimensions; // left, right, bottom, top + LVecBase4i _pixels; + LVecBase4i _pixels_i; + }; + typedef pvector Regions; + private: class CData; void win_display_regions_changed(); - void do_compute_pixels(int x_size, int y_size, CData *cdata); + void do_compute_pixels(int i, int x_size, int y_size, CData *cdata); void set_active_index(int index); protected: @@ -194,14 +211,8 @@ private: return DisplayRegion::get_class_type(); } - LVecBase4 _dimensions; // left, right, bottom, top - - int _pl; - int _pr; - int _pb; - int _pt; - int _pbi; - int _pti; + Regions _regions; + int _lens_index; // index into which lens of a camera is associated with this display region. 0 is default NodePath _camera; @@ -293,12 +304,14 @@ public: INLINE bool is_any_clear_active() const; + INLINE int get_num_regions() const; INLINE void get_dimensions(PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const; - INLINE const LVecBase4 &get_dimensions() const; - INLINE PN_stdfloat get_left() const; - INLINE PN_stdfloat get_right() const; - INLINE PN_stdfloat get_bottom() const; - INLINE PN_stdfloat get_top() const; + INLINE void get_dimensions(int i, PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const; + INLINE const LVecBase4 &get_dimensions(int i = 0) const; + INLINE PN_stdfloat get_left(int i = 0) const; + INLINE PN_stdfloat get_right(int i = 0) const; + INLINE PN_stdfloat get_bottom(int i = 0) const; + INLINE PN_stdfloat get_top(int i = 0) const; INLINE GraphicsOutput *get_window() const; GraphicsPipe *get_pipe() const; @@ -313,11 +326,14 @@ public: INLINE CallbackObject *get_draw_callback() const; INLINE void get_pixels(int &pl, int &pr, int &pb, int &pt) const; + INLINE void get_pixels(int i, int &pl, int &pr, int &pb, int &pt) const; INLINE void get_region_pixels(int &xo, int &yo, int &w, int &h) const; + INLINE void get_region_pixels(int i, int &xo, int &yo, int &w, int &h) const; INLINE void get_region_pixels_i(int &xo, int &yo, int &w, int &h) const; + INLINE void get_region_pixels_i(int i, int &xo, int &yo, int &w, int &h) const; - INLINE int get_pixel_width() const; - INLINE int get_pixel_height() const; + INLINE int get_pixel_width(int i = 0) const; + INLINE int get_pixel_height(int i = 0) const; INLINE int get_lens_index() const; diff --git a/panda/src/display/frameBufferProperties.I b/panda/src/display/frameBufferProperties.I index ceb32c2ffe..eb6da4b0ea 100644 --- a/panda/src/display/frameBufferProperties.I +++ b/panda/src/display/frameBufferProperties.I @@ -59,7 +59,7 @@ is_single_buffered() const { //////////////////////////////////////////////////////////////////// INLINE bool FrameBufferProperties:: is_stereo() const { - return (_property[FBP_stereo] != 0); + return (_flags & FBF_stereo) != 0; } //////////////////////////////////////////////////////////////////// @@ -189,9 +189,9 @@ get_back_buffers() const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE int FrameBufferProperties:: +INLINE bool FrameBufferProperties:: get_indexed_color() const { - return _property[FBP_indexed_color]; + return (_flags & FBF_indexed_color) != 0; } //////////////////////////////////////////////////////////////////// @@ -199,9 +199,9 @@ get_indexed_color() const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE int FrameBufferProperties:: +INLINE bool FrameBufferProperties:: get_rgb_color() const { - return _property[FBP_rgb_color]; + return (_flags & FBF_rgb_color) != 0; } //////////////////////////////////////////////////////////////////// @@ -209,9 +209,9 @@ get_rgb_color() const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE int FrameBufferProperties:: +INLINE bool FrameBufferProperties:: get_stereo() const { - return _property[FBP_stereo]; + return (_flags & FBF_stereo) != 0; } //////////////////////////////////////////////////////////////////// @@ -219,9 +219,9 @@ get_stereo() const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE int FrameBufferProperties:: +INLINE bool FrameBufferProperties:: get_force_hardware() const { - return _property[FBP_force_hardware]; + return (_flags & FBF_force_hardware) != 0; } //////////////////////////////////////////////////////////////////// @@ -229,9 +229,39 @@ get_force_hardware() const { // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE int FrameBufferProperties:: +INLINE bool FrameBufferProperties:: get_force_software() const { - return _property[FBP_force_software]; + return (_flags & FBF_force_software) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: FrameBufferProperties::get_srgb_color +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool FrameBufferProperties:: +get_srgb_color() const { + return (_flags & FBF_srgb_color) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: FrameBufferProperties::get_float_color +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool FrameBufferProperties:: +get_float_color() const { + return (_flags & FBF_float_color) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: FrameBufferProperties::get_float_depth +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool FrameBufferProperties:: +get_float_depth() const { + return (_flags & FBF_float_depth) != 0; } //////////////////////////////////////////////////////////////////// @@ -365,9 +395,13 @@ set_back_buffers(int n) { // Description: //////////////////////////////////////////////////////////////////// INLINE void FrameBufferProperties:: -set_indexed_color(int n) { - _property[FBP_indexed_color] = n; - _specified[FBP_indexed_color] = true; +set_indexed_color(bool n) { + if (n) { + _flags |= FBF_indexed_color; + } else { + _flags &= ~FBF_indexed_color; + } + _flags_specified |= FBF_indexed_color; } //////////////////////////////////////////////////////////////////// @@ -376,9 +410,13 @@ set_indexed_color(int n) { // Description: //////////////////////////////////////////////////////////////////// INLINE void FrameBufferProperties:: -set_rgb_color(int n) { - _property[FBP_rgb_color] = n; - _specified[FBP_rgb_color] = true; +set_rgb_color(bool n) { + if (n) { + _flags |= FBF_rgb_color; + } else { + _flags &= ~FBF_rgb_color; + } + _flags_specified |= FBF_rgb_color; } //////////////////////////////////////////////////////////////////// @@ -387,9 +425,13 @@ set_rgb_color(int n) { // Description: //////////////////////////////////////////////////////////////////// INLINE void FrameBufferProperties:: -set_stereo(int n) { - _property[FBP_stereo] = n; - _specified[FBP_stereo] = true; +set_stereo(bool n) { + if (n) { + _flags |= FBF_stereo; + } else { + _flags &= ~FBF_stereo; + } + _flags_specified |= FBF_stereo; } //////////////////////////////////////////////////////////////////// @@ -398,9 +440,13 @@ set_stereo(int n) { // Description: //////////////////////////////////////////////////////////////////// INLINE void FrameBufferProperties:: -set_force_hardware(int n) { - _property[FBP_force_hardware] = n; - _specified[FBP_force_hardware] = true; +set_force_hardware(bool n) { + if (n) { + _flags |= FBF_force_hardware; + } else { + _flags &= ~FBF_force_hardware; + } + _flags_specified |= FBF_force_hardware; } //////////////////////////////////////////////////////////////////// @@ -409,7 +455,56 @@ set_force_hardware(int n) { // Description: //////////////////////////////////////////////////////////////////// INLINE void FrameBufferProperties:: -set_force_software(int n) { - _property[FBP_force_software] = n; - _specified[FBP_force_software] = true; +set_force_software(bool n) { + if (n) { + _flags |= FBF_force_software; + } else { + _flags &= ~FBF_force_software; + } + _flags_specified |= FBF_force_software; +} + +//////////////////////////////////////////////////////////////////// +// Function: FrameBufferProperties::set_srgb_color +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void FrameBufferProperties:: +set_srgb_color(bool n) { + if (n) { + _flags |= FBF_srgb_color; + } else { + _flags &= ~FBF_srgb_color; + } + _flags_specified |= FBF_srgb_color; +} + +//////////////////////////////////////////////////////////////////// +// Function: FrameBufferProperties::set_float_color +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void FrameBufferProperties:: +set_float_color(bool n) { + if (n) { + _flags |= FBF_float_color; + } else { + _flags &= ~FBF_float_color; + } + _flags_specified |= FBF_float_color; +} + +//////////////////////////////////////////////////////////////////// +// Function: FrameBufferProperties::set_float_depth +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void FrameBufferProperties:: +set_float_depth(bool n) { + if (n) { + _flags |= FBF_float_depth; + } else { + _flags &= ~FBF_float_depth; + } + _flags_specified |= FBF_float_depth; } diff --git a/panda/src/display/frameBufferProperties.cxx b/panda/src/display/frameBufferProperties.cxx index 7182b756e6..50053169dd 100644 --- a/panda/src/display/frameBufferProperties.cxx +++ b/panda/src/display/frameBufferProperties.cxx @@ -34,7 +34,10 @@ FrameBufferProperties() { //////////////////////////////////////////////////////////////////// void FrameBufferProperties:: operator = (const FrameBufferProperties ©) { - for (int i=0; i _property[i]) { return false; } } + return true; } @@ -73,9 +82,9 @@ get_default() { return default_props; } - default_props.set_rgb_color(1); + default_props.set_rgb_color(true); default_props.set_back_buffers(back_buffers); - + int num_words = framebuffer_mode.get_num_words(); if (num_words > 0) { display_cat.error() @@ -99,10 +108,10 @@ get_default() { } if (framebuffer_hardware) { - default_props.set_force_hardware(1); + default_props.set_force_hardware(true); } if (framebuffer_software) { - default_props.set_force_software(1); + default_props.set_force_software(true); } if (framebuffer_depth) { default_props.set_depth_bits(1); @@ -120,7 +129,13 @@ get_default() { default_props.set_multisamples(1); } if (framebuffer_stereo) { - default_props.set_stereo(1); + default_props.set_stereo(true); + } + if (framebuffer_srgb) { + default_props.set_srgb_color(true); + } + if (framebuffer_float) { + default_props.set_float_color(true); } if (depth_bits > 0) { default_props.set_depth_bits(depth_bits); @@ -141,10 +156,9 @@ get_default() { default_props.set_multisamples(multisamples); } - if ((default_props._property[FBP_force_software])&& - (default_props._property[FBP_force_hardware])) { - default_props._property[FBP_force_software] = 0; - default_props._property[FBP_force_hardware] = 0; + if ((default_props._flags & FBF_force_software) != 0 && + (default_props._flags & FBF_force_hardware) != 0){ + default_props._flags &= ~(FBF_force_software | FBF_force_hardware); } default_ready = true; @@ -158,7 +172,11 @@ get_default() { //////////////////////////////////////////////////////////////////// bool FrameBufferProperties:: operator == (const FrameBufferProperties &other) const { - for (int i=0; i 0) { out << "depth_bits=" << _property[FBP_depth_bits] << " "; } + if ((_flags & FBF_float_color) != 0) { + out << "float_color "; + } + if ((_flags & FBF_srgb_color) != 0) { + out << "srgb_color "; + } + if ((_flags & FBF_indexed_color) != 0) { + out << "indexed_color "; + } if (_property[FBP_color_bits] > 0) { out << "color_bits=" << _property[FBP_color_bits] << " "; } @@ -243,17 +278,14 @@ output(ostream &out) const { if (_property[FBP_back_buffers] > 0) { out << "back_buffers=" << _property[FBP_back_buffers] << " "; } - if (_property[FBP_indexed_color] > 0) { - out << "indexed_color=" << _property[FBP_indexed_color] << " "; + if ((_flags & FBF_stereo) != 0) { + out << "stereo "; } - if (_property[FBP_stereo] > 0) { - out << "stereo=" << _property[FBP_stereo] << " "; + if ((_flags & FBF_force_hardware) != 0) { + out << "force_hardware "; } - if (_property[FBP_force_hardware] > 0) { - out << "force_hardware=" << _property[FBP_force_hardware] << " "; - } - if (_property[FBP_force_software] > 0) { - out << "force_software=" << _property[FBP_force_software] << " "; + if ((_flags & FBF_force_software) != 0) { + out << "force_software "; } } @@ -287,7 +319,7 @@ get_aux_mask() const { int FrameBufferProperties:: get_buffer_mask() const { int mask = 0; - + if (_property[FBP_back_buffers] > 0) { mask = RenderBuffer::T_front | RenderBuffer::T_back; } else { @@ -310,7 +342,11 @@ get_buffer_mask() const { //////////////////////////////////////////////////////////////////// bool FrameBufferProperties:: is_any_specified() const { - for (int i=0; i 0) { return false; } - if (_property[FBP_indexed_color] > 0) { + if ((_flags & FBF_indexed_color) != 0) { return false; } - if (_property[FBP_force_hardware] > 0) { + if ((_flags & FBF_force_hardware) != 0) { return false; } - if (_property[FBP_force_software] > 0) { + if ((_flags & FBF_force_software) != 0) { + return false; + } + if ((_flags & FBF_srgb_color) != 0) { + return false; + } + if ((_flags & FBF_float_color) != 0) { + return false; + } + if ((_flags & FBF_float_depth) != 0) { return false; } return true; @@ -391,7 +438,7 @@ is_basic() const { //////////////////////////////////////////////////////////////////// void FrameBufferProperties:: set_one_bit_per_channel() { - for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; ++prop) { + for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) { if (_property[prop] > 1) { _property[prop] = 1; } @@ -426,13 +473,13 @@ set_one_bit_per_channel() { int FrameBufferProperties:: get_quality(const FrameBufferProperties &reqs) const { - if ((_property[FBP_indexed_color]==0) && (_property[FBP_rgb_color]==0)) { + if (!get_indexed_color() && !get_rgb_color()) { // Nonfunctioning window. return 0; } - - if ((reqs._property[FBP_rgb_color] > _property[FBP_rgb_color])|| - (reqs._property[FBP_indexed_color] > _property[FBP_indexed_color])) { + + if ((reqs.get_rgb_color() && !get_rgb_color()) || + (reqs.get_indexed_color() && !get_indexed_color())) { // These properties are nonnegotiable. return 0; } @@ -441,17 +488,17 @@ get_quality(const FrameBufferProperties &reqs) const { // Deduct for using the wrong kind of renderer (hardware or software). // Cost: 10,000,000 - - if ((reqs._property[FBP_force_hardware] > _property[FBP_force_hardware])|| - (reqs._property[FBP_force_software] > _property[FBP_force_software])) { + + if ((reqs._flags & FBF_force_hardware) > (_flags & FBF_force_hardware) || + (reqs._flags & FBF_force_software) > (_flags & FBF_force_software)) { quality -= 10000000; } // Deduct for missing depth, color, alpha, stencil, or accum. // Cost: 1,000,000 - for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) { - if ((reqs._property[prop]) && (_property[prop]==0)) { + for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) { + if (reqs._property[prop] && _property[prop] == 0) { quality -= 1000000; } } @@ -459,7 +506,7 @@ get_quality(const FrameBufferProperties &reqs) const { // Deduct for missing aux bitplanes. // Cost: 100,000 - for (int prop=FBP_aux_rgba; prop<=FBP_aux_float; prop++) { + for (int prop = FBP_aux_rgba; prop <= FBP_aux_float; ++prop) { if (reqs._property[prop] > _property[prop]) { quality -= 100000; } @@ -468,13 +515,31 @@ get_quality(const FrameBufferProperties &reqs) const { // Deduct for stereo not enabled. // Cost: 100,000 - if (reqs._property[FBP_stereo] > _property[FBP_stereo]) { + if (reqs.get_stereo() && !get_stereo()) { + quality -= 100000; + } + + // Deduct for not being sRGB-capable. + // Cost: 100,000 + + if (reqs.get_srgb_color() && !get_srgb_color()) { + quality -= 100000; + } + + // Deduct for not having a floating-point format if we requested it. + // Cost: 100,000 + + if (reqs.get_float_color() && !get_float_color()) { + quality -= 100000; + } + + if (reqs.get_float_depth() && !get_float_depth()) { quality -= 100000; } // Deduct for insufficient back-buffers. // Cost: 100,000 - + if (reqs._property[FBP_back_buffers] > _property[FBP_back_buffers]) { quality -= 100000; } @@ -488,7 +553,7 @@ get_quality(const FrameBufferProperties &reqs) const { // Deduct for not enough bits in depth, color, alpha, stencil, or accum. // Cost: 10,000 - for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) { + for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) { if (_property[prop] != 0 && reqs._property[prop] > _property[prop]) { quality -= 10000; } @@ -497,33 +562,33 @@ get_quality(const FrameBufferProperties &reqs) const { // deduct for insufficient multisamples. // Cost: 1,000 - if (_property[FBP_multisamples] != 0 && + if (_property[FBP_multisamples] != 0 && reqs._property[FBP_multisamples] > _property[FBP_multisamples]) { quality -= 1000; } // Deduct for unrequested bitplanes. // Cost: 50 - - for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) { + + for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) { if ((_property[prop]) && (reqs._property[prop] == 0)) { quality -= 50; } } - for (int prop=FBP_aux_rgba; prop<=FBP_aux_float; prop++) { + for (int prop = FBP_aux_rgba; prop <= FBP_aux_float; ++prop) { int extra = _property[prop] > reqs._property[prop]; if (extra > 0) { extra = min(extra, 3); quality -= extra*50; } } - + // Deduct for excessive resolution in any bitplane (unless we asked // for only 1 bit, which is the convention for any amount). // Cost: 50 - - for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) { + + for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) { if (reqs._property[prop] > 1 && _property[prop] > reqs._property[prop]) { quality -= 50; @@ -555,9 +620,9 @@ get_quality(const FrameBufferProperties &reqs) const { quality += _property[prop]; } } - + return quality; -}; +} //////////////////////////////////////////////////////////////////// // Function: FrameBufferProperties::verify_hardware_software @@ -594,8 +659,6 @@ verify_hardware_software(const FrameBufferProperties &props, const string &rende << "hardware/software configuration in your Config.prc file.\n"; return false; } - + return true; } - - diff --git a/panda/src/display/frameBufferProperties.h b/panda/src/display/frameBufferProperties.h index 1d6b68463f..dea4926238 100644 --- a/panda/src/display/frameBufferProperties.h +++ b/panda/src/display/frameBufferProperties.h @@ -44,18 +44,28 @@ private: FBP_multisamples, FBP_coverage_samples, FBP_back_buffers, - FBP_indexed_color, - FBP_rgb_color, - FBP_stereo, - FBP_force_hardware, - FBP_force_software, - + // This is a sentinel value. FBP_COUNT }; - + + enum FrameBufferFlag { + FBF_indexed_color = 0x001, + FBF_rgb_color = 0x002, + FBF_stereo = 0x004, + FBF_force_hardware = 0x008, + FBF_force_software = 0x010, + FBF_srgb_color = 0x020, + FBF_float_color = 0x040, + FBF_float_depth = 0x080, + FBF_all = 0x100-1, + }; + int _property[FBP_COUNT]; - int _specified[FBP_COUNT]; + bool _specified[FBP_COUNT]; + + int _flags; + int _flags_specified; PUBLISHED: @@ -71,11 +81,14 @@ PUBLISHED: INLINE int get_multisamples() const; INLINE int get_coverage_samples() const; INLINE int get_back_buffers() const; - INLINE int get_indexed_color() const; - INLINE int get_rgb_color() const; - INLINE int get_stereo() const; - INLINE int get_force_hardware() const; - INLINE int get_force_software() const; + INLINE bool get_indexed_color() const; + INLINE bool get_rgb_color() const; + INLINE bool get_stereo() const; + INLINE bool get_force_hardware() const; + INLINE bool get_force_software() const; + INLINE bool get_srgb_color() const; + INLINE bool get_float_color() const; + INLINE bool get_float_depth() const; // Individual assigners. INLINE void set_depth_bits(int n); @@ -89,11 +102,14 @@ PUBLISHED: INLINE void set_multisamples(int n); INLINE void set_coverage_samples(int n); INLINE void set_back_buffers(int n); - INLINE void set_indexed_color(int n); - INLINE void set_rgb_color(int n); - INLINE void set_stereo(int n); - INLINE void set_force_hardware(int n); - INLINE void set_force_software(int n); + INLINE void set_indexed_color(bool n); + INLINE void set_rgb_color(bool n); + INLINE void set_stereo(bool n); + INLINE void set_force_hardware(bool n); + INLINE void set_force_software(bool n); + INLINE void set_srgb_color(bool n); + INLINE void set_float_color(bool n); + INLINE void set_float_depth(bool n); // Other. @@ -111,9 +127,9 @@ PUBLISHED: void add_properties(const FrameBufferProperties &other); void output(ostream &out) const; void set_one_bit_per_channel(); - - bool is_stereo() const; - bool is_single_buffered() const; + + INLINE bool is_stereo() const; + INLINE bool is_single_buffered() const; int get_quality(const FrameBufferProperties &reqs) const; bool is_any_specified() const; bool is_basic() const; diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index b42c27d13c..ed6ee6a25d 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -1094,7 +1094,58 @@ extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg) { return gsg->extract_texture_data(tex); } } - + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::dispatch_compute +// Access: Published +// Description: Asks the indicated GraphicsStateGuardian to dispatch +// the compute shader in the given ShaderAttrib using +// the given work group counts. This can act as an +// interface for running a one-off compute shader, +// without having to store it in the scene graph using +// a ComputeNode. +// +// Since this requires a round-trip to the draw thread, +// it may require waiting for the current thread to +// finish rendering if it is called in a multithreaded +// environment. However, you can call this several +// consecutive times on different textures for little +// additional cost. +// +// The return value is true if the operation is +// successful, false otherwise. +//////////////////////////////////////////////////////////////////// +void GraphicsEngine:: +dispatch_compute(const LVecBase3i &work_groups, const ShaderAttrib *sattr, GraphicsStateGuardian *gsg) { + ReMutexHolder holder(_lock); + + CPT(RenderState) state = RenderState::make(sattr); + + string draw_name = gsg->get_threading_model().get_draw_name(); + if (draw_name.empty()) { + // A single-threaded environment. No problem. + + } else { + // A multi-threaded environment. We have to wait until the draw + // thread has finished its current task. + WindowRenderer *wr = get_window_renderer(draw_name, 0); + RenderThread *thread = (RenderThread *)wr; + MutexHolder holder2(thread->_cv_mutex); + + while (thread->_thread_state != TS_wait) { + thread->_cv_done.wait(); + } + + // OK, now the draw thread is idle. That's really good enough for + // our purposes; we don't *actually* need to make the draw thread + // do the work--it's sufficient that it's not doing anything else + // while we access the GSG. + } + + gsg->set_state_and_transform(state, TransformState::make_identity()); + gsg->dispatch_compute(work_groups[0], work_groups[1], work_groups[2]); +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsEngine::get_global_ptr // Access: Published, Static diff --git a/panda/src/display/graphicsEngine.h b/panda/src/display/graphicsEngine.h index 7428a35da1..7933f73350 100644 --- a/panda/src/display/graphicsEngine.h +++ b/panda/src/display/graphicsEngine.h @@ -108,6 +108,9 @@ PUBLISHED: BLOCKING void flip_frame(); bool extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg); + void dispatch_compute(const LVecBase3i &work_groups, + const ShaderAttrib *sattr, + GraphicsStateGuardian *gsg); static GraphicsEngine *get_global_ptr(); diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 4bcc120f72..900e349254 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -655,6 +655,17 @@ get_supports_tessellation_shaders() const { return _supports_tessellation_shaders; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_supports_compute_shaders +// Access: Published +// Description: Returns true if this particular GSG supports +// compute shaders. +//////////////////////////////////////////////////////////////////// +INLINE bool GraphicsStateGuardian:: +get_supports_compute_shaders() const { + return _supports_compute_shaders; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_supports_glsl // Access: Published diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 715d1a7fee..1cbd3f49c6 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -754,6 +754,17 @@ end_occlusion_query() { return result; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::dispatch_compute +// Access: Public, Virtual +// Description: Dispatches a currently bound compute shader using +// the given work group counts. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +dispatch_compute(int num_groups_x, int num_groups_y, int num_groups_z) { + nassertv(false /* Compute shaders not supported by GSG */); +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_geom_munger // Access: Public, Virtual @@ -1145,9 +1156,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 & return &t; } case Shader::SMO_mat_constant_x: { - const NodePath &np = _target_shader->get_shader_input_nodepath(name); - nassertr(!np.is_empty(), &LMatrix4::ident_mat()); - return &(np.node()->get_transform()->get_mat()); + return &_target_shader->get_shader_input_matrix(name, t); } case Shader::SMO_vec_constant_x: { const LVecBase4 &input = _target_shader->get_shader_input_vector(name); @@ -1169,8 +1178,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 & return &(get_external_transform()->get_mat()); } case Shader::SMO_view_to_model: { - // DANGER: SLOW AND NOT CACHEABLE! - t.invert_from(get_external_transform()->get_mat()); + t = get_external_transform()->get_inverse()->get_mat(); return &t; } case Shader::SMO_apiview_to_view: { @@ -1216,7 +1224,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 & const NodePath &np = _target_shader->get_shader_input_nodepath(name); nassertr(!np.is_empty(), &LMatrix4::ident_mat()); t = get_scene()->get_camera_transform()->get_mat() * - invert(np.get_net_transform()->get_mat()); + np.get_net_transform()->get_inverse()->get_mat(); return &t; } case Shader::SMO_apiview_x_to_view: { @@ -1231,7 +1239,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 & const NodePath &np = _target_shader->get_shader_input_nodepath(name); nassertr(!np.is_empty(), &LMatrix4::ident_mat()); t = (get_scene()->get_camera_transform()->get_mat() * - invert(np.get_net_transform()->get_mat()) * + np.get_net_transform()->get_inverse()->get_mat() * LMatrix4::convert_mat(_coordinate_system, _internal_coordinate_system)); return &t; } @@ -1252,21 +1260,35 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 & nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat()); Lens *lens = DCAST(LensNode, np.node())->get_lens(); t = get_scene()->get_camera_transform()->get_mat() * - invert(np.get_net_transform()->get_mat()) * + np.get_net_transform()->get_inverse()->get_mat() * LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system()) * lens->get_projection_mat(_current_stereo_channel); return &t; } case Shader::SMO_apiclip_x_to_view: { - // NOT IMPLEMENTED - return &LMatrix4::ident_mat(); + const NodePath &np = _target_shader->get_shader_input_nodepath(name); + nassertr(!np.is_empty(), &LMatrix4::ident_mat()); + nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat()); + Lens *lens = DCAST(LensNode, np.node())->get_lens(); + t = calc_projection_mat(lens)->get_inverse()->get_mat() * + get_cs_transform_for(lens->get_coordinate_system())->get_inverse()->get_mat() * + np.get_net_transform()->get_mat() * + get_scene()->get_world_transform()->get_mat(); + return &t; } case Shader::SMO_view_to_apiclip_x: { - // NOT IMPLEMENTED - return &LMatrix4::ident_mat(); + const NodePath &np = _target_shader->get_shader_input_nodepath(name); + nassertr(!np.is_empty(), &LMatrix4::ident_mat()); + nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat()); + Lens *lens = DCAST(LensNode, np.node())->get_lens(); + t = get_scene()->get_camera_transform()->get_mat() * + np.get_net_transform()->get_inverse()->get_mat() * + get_cs_transform_for(lens->get_coordinate_system())->get_mat() * + calc_projection_mat(lens)->get_mat(); + return &t; } default: - // should never get here + nassertr(false /*should never get here*/, &LMatrix4::ident_mat()); return &LMatrix4::ident_mat(); } } diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 3f7efa8297..996d5cfc2e 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -145,6 +145,7 @@ PUBLISHED: INLINE bool get_supports_basic_shaders() const; INLINE bool get_supports_geometry_shaders() const; INLINE bool get_supports_tessellation_shaders() const; + INLINE bool get_supports_compute_shaders() const; INLINE bool get_supports_glsl() const; INLINE bool get_supports_stencil() const; INLINE bool get_supports_two_sided_stencil() const; @@ -225,6 +226,8 @@ public: virtual void begin_occlusion_query(); virtual PT(OcclusionQueryContext) end_occlusion_query(); + virtual void dispatch_compute(int size_x, int size_y, int size_z); + virtual PT(GeomMunger) get_geom_munger(const RenderState *state, Thread *current_thread); virtual PT(GeomMunger) make_geom_munger(const RenderState *state, @@ -487,10 +490,11 @@ protected: bool _supports_basic_shaders; bool _supports_geometry_shaders; bool _supports_tessellation_shaders; + bool _supports_compute_shaders; bool _supports_glsl; bool _supports_framebuffer_multisample; bool _supports_framebuffer_blit; - + bool _supports_stencil; bool _supports_stencil_wrap; bool _supports_two_sided_stencil; diff --git a/panda/src/display/stereoDisplayRegion.cxx b/panda/src/display/stereoDisplayRegion.cxx index 828ef7756a..1c87590b0a 100644 --- a/panda/src/display/stereoDisplayRegion.cxx +++ b/panda/src/display/stereoDisplayRegion.cxx @@ -109,10 +109,10 @@ set_pixel_zoom(PN_stdfloat pixel_zoom) { // indicated dimensions. //////////////////////////////////////////////////////////////////// void StereoDisplayRegion:: -set_dimensions(const LVecBase4 &dimensions) { - DisplayRegion::set_dimensions(dimensions); - _left_eye->set_dimensions(dimensions); - _right_eye->set_dimensions(dimensions); +set_dimensions(int i, const LVecBase4 &dimensions) { + DisplayRegion::set_dimensions(i, dimensions); + _left_eye->set_dimensions(i, dimensions); + _right_eye->set_dimensions(i, dimensions); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/stereoDisplayRegion.h b/panda/src/display/stereoDisplayRegion.h index 56882d4606..a6a8b0b6cc 100644 --- a/panda/src/display/stereoDisplayRegion.h +++ b/panda/src/display/stereoDisplayRegion.h @@ -51,7 +51,7 @@ PUBLISHED: virtual void set_pixel_zoom(PN_stdfloat pixel_zoom); // Inherited from DisplayRegion - virtual void set_dimensions(const LVecBase4 &dimensions); + virtual void set_dimensions(int i, const LVecBase4 &dimensions); virtual bool is_stereo() const; virtual void set_camera(const NodePath &camera); virtual void set_active(bool active); diff --git a/panda/src/display/windowProperties.I b/panda/src/display/windowProperties.I index afae00b4f2..ca307062a4 100644 --- a/panda/src/display/windowProperties.I +++ b/panda/src/display/windowProperties.I @@ -63,12 +63,38 @@ is_any_specified() const { // including decorations. //////////////////////////////////////////////////////////////////// INLINE void WindowProperties:: -set_origin(int x_origin, int y_origin) { - _x_origin = x_origin; - _y_origin = y_origin; +set_origin(const LPoint2i &origin) { + _origin = origin; _specified |= S_origin; } +//////////////////////////////////////////////////////////////////// +// Function: WindowProperties::set_origin +// Access: Published +// Description: Specifies the origin on the screen (in pixels, +// relative to the top-left corner) at which the window +// should appear. This is the origin of the top-left +// corner of the useful part of the window, not +// including decorations. +//////////////////////////////////////////////////////////////////// +INLINE void WindowProperties:: +set_origin(int x_origin, int y_origin) { + _origin.set(x_origin, y_origin); + _specified |= S_origin; +} + +//////////////////////////////////////////////////////////////////// +// Function: WindowProperties::get_origin +// Access: Published +// Description: Returns the coordinates of the window's top-left +// corner, not including decorations. +//////////////////////////////////////////////////////////////////// +INLINE const LPoint2i &WindowProperties:: +get_origin() const { + nassertr(has_origin(), LPoint2i::zero()); + return _origin; +} + //////////////////////////////////////////////////////////////////// // Function: WindowProperties::get_x_origin // Access: Published @@ -78,7 +104,7 @@ set_origin(int x_origin, int y_origin) { INLINE int WindowProperties:: get_x_origin() const { nassertr(has_origin(), 0); - return _x_origin; + return _origin.get_x(); } //////////////////////////////////////////////////////////////////// @@ -90,7 +116,7 @@ get_x_origin() const { INLINE int WindowProperties:: get_y_origin() const { nassertr(has_origin(), 0); - return _y_origin; + return _origin.get_y(); } //////////////////////////////////////////////////////////////////// @@ -112,8 +138,20 @@ has_origin() const { INLINE void WindowProperties:: clear_origin() { _specified &= ~S_origin; - _x_origin = 0; - _y_origin = 0; + _origin = LPoint2i::zero(); +} + +//////////////////////////////////////////////////////////////////// +// Function: WindowProperties::set_size +// Access: Published +// Description: Specifies the requested size of the window, in +// pixels. This is the size of the useful part of the +// window, not including decorations. +//////////////////////////////////////////////////////////////////// +INLINE void WindowProperties:: +set_size(const LVector2i &size) { + _size = size; + _specified |= S_size; } //////////////////////////////////////////////////////////////////// @@ -125,11 +163,22 @@ clear_origin() { //////////////////////////////////////////////////////////////////// INLINE void WindowProperties:: set_size(int x_size, int y_size) { - _x_size = x_size; - _y_size = y_size; + _size.set(x_size, y_size); _specified |= S_size; } +//////////////////////////////////////////////////////////////////// +// Function: WindowProperties::get_origin +// Access: Published +// Description: Returns size in pixels of the useful part of the +// window, not including decorations. +//////////////////////////////////////////////////////////////////// +INLINE const LVector2i &WindowProperties:: +get_size() const { + nassertr(has_size(), LVector2i::zero()); + return _size; +} + //////////////////////////////////////////////////////////////////// // Function: WindowProperties::get_x_size // Access: Published @@ -140,7 +189,7 @@ set_size(int x_size, int y_size) { INLINE int WindowProperties:: get_x_size() const { nassertr(has_size(), 0); - return _x_size; + return _size.get_x(); } //////////////////////////////////////////////////////////////////// @@ -153,7 +202,7 @@ get_x_size() const { INLINE int WindowProperties:: get_y_size() const { nassertr(has_size(), 0); - return _y_size; + return _size.get_y(); } //////////////////////////////////////////////////////////////////// @@ -175,8 +224,7 @@ has_size() const { INLINE void WindowProperties:: clear_size() { _specified &= ~S_size; - _x_size = 0; - _y_size = 0; + _size = LVector2i::zero(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/windowProperties.cxx b/panda/src/display/windowProperties.cxx index 2e007598ed..d38241f2ce 100644 --- a/panda/src/display/windowProperties.cxx +++ b/panda/src/display/windowProperties.cxx @@ -36,10 +36,8 @@ WindowProperties() { void WindowProperties:: operator = (const WindowProperties ©) { _specified = copy._specified; - _x_origin = copy._x_origin; - _y_origin = copy._y_origin; - _x_size = copy._x_size; - _y_size = copy._y_size; + _origin = copy._origin; + _size = copy._size; _title = copy._title; _icon_filename = copy._icon_filename; _cursor_filename = copy._cursor_filename; @@ -169,10 +167,8 @@ bool WindowProperties:: operator == (const WindowProperties &other) const { return (_specified == other._specified && _flags == other._flags && - _x_origin == other._x_origin && - _y_origin == other._y_origin && - _x_size == other._x_size && - _y_size == other._y_size && + _origin == other._origin && + _size == other._size && _z_order == other._z_order && _title == other._title && _icon_filename == other._icon_filename && @@ -191,10 +187,8 @@ operator == (const WindowProperties &other) const { void WindowProperties:: clear() { _specified = 0; - _x_origin = 0; - _y_origin = 0; - _x_size = 0; - _y_size = 0; + _origin = LPoint2i::zero(); + _size = LVector2i::zero(); _title = string(); _icon_filename = Filename(); _cursor_filename = Filename(); @@ -244,10 +238,10 @@ set_parent_window(size_t parent) { void WindowProperties:: add_properties(const WindowProperties &other) { if (other.has_origin()) { - set_origin(other.get_x_origin(), other.get_y_origin()); + set_origin(other.get_origin()); } if (other.has_size()) { - set_size(other.get_x_size(), other.get_y_size()); + set_size(other.get_size()); } if (other.has_title()) { set_title(other.get_title()); diff --git a/panda/src/display/windowProperties.h b/panda/src/display/windowProperties.h index a7098cb1b8..5f8a6bb32d 100644 --- a/panda/src/display/windowProperties.h +++ b/panda/src/display/windowProperties.h @@ -19,7 +19,9 @@ #include "filename.h" #include "pnotify.h" #include "windowHandle.h" - +#include "lpoint2.h" +#include "lvector2.h" + //////////////////////////////////////////////////////////////////// // Class : WindowProperties // Description : A container for the various kinds of properties we @@ -57,14 +59,18 @@ PUBLISHED: void clear(); INLINE bool is_any_specified() const; - + + INLINE void set_origin(const LPoint2i &origin); INLINE void set_origin(int x_origin, int y_origin); + INLINE const LPoint2i &get_origin() const; INLINE int get_x_origin() const; INLINE int get_y_origin() const; INLINE bool has_origin() const; INLINE void clear_origin(); + INLINE void set_size(const LVector2i &size); INLINE void set_size(int x_size, int y_size); + INLINE const LVector2i &get_size() const; INLINE int get_x_size() const; INLINE int get_y_size() const; INLINE bool has_size() const; @@ -73,7 +79,7 @@ PUBLISHED: INLINE bool has_mouse_mode() const; INLINE void set_mouse_mode(MouseMode mode); INLINE MouseMode get_mouse_mode() const; - INLINE void clear_mouse_mode(); + INLINE void clear_mouse_mode(); INLINE void set_title(const string &title); INLINE const string &get_title() const; @@ -183,10 +189,8 @@ private: }; int _specified; - int _x_origin; - int _y_origin; - int _x_size; - int _y_size; + LPoint2i _origin; + LVector2i _size; MouseMode _mouse_mode; string _title; Filename _cursor_filename; diff --git a/panda/src/egldisplay/eglGraphicsStateGuardian.cxx b/panda/src/egldisplay/eglGraphicsStateGuardian.cxx index 7c5d5d5303..1209a8a482 100644 --- a/panda/src/egldisplay/eglGraphicsStateGuardian.cxx +++ b/panda/src/egldisplay/eglGraphicsStateGuardian.cxx @@ -390,8 +390,6 @@ get_extra_extensions() { // not defined. //////////////////////////////////////////////////////////////////// void *eglGraphicsStateGuardian:: -do_get_extension_func(const char *prefix, const char *name) { - string fullname = string(prefix) + string(name); - - return (void *)eglGetProcAddress(fullname.c_str()); +do_get_extension_func(const char *name) { + return (void *)eglGetProcAddress(name); } diff --git a/panda/src/egldisplay/eglGraphicsStateGuardian.h b/panda/src/egldisplay/eglGraphicsStateGuardian.h index e44ff01d73..ebf00b87e9 100644 --- a/panda/src/egldisplay/eglGraphicsStateGuardian.h +++ b/panda/src/egldisplay/eglGraphicsStateGuardian.h @@ -64,7 +64,7 @@ protected: virtual void query_gl_version(); virtual void get_extra_extensions(); - virtual void *do_get_extension_func(const char *prefix, const char *name); + virtual void *do_get_extension_func(const char *name); private: int _egl_version_major, _egl_version_minor; diff --git a/panda/src/gles2gsg/gles2gsg.h b/panda/src/gles2gsg/gles2gsg.h index 9869257732..cd5444c7ef 100644 --- a/panda/src/gles2gsg/gles2gsg.h +++ b/panda/src/gles2gsg/gles2gsg.h @@ -96,11 +96,29 @@ typedef char GLchar; #define GL_RG16F GL_RG16F_EXT #define GL_RGB16F GL_RGB16F_EXT #define GL_RGBA16F GL_RGBA16F_EXT +#define GL_RGB16F GL_RGB16F_EXT +#define GL_RGBA16F GL_RGBA16F_EXT +#define GL_RGB32F GL_RGB32F_EXT +#define GL_RGBA32F GL_RGBA32F_EXT +#define GL_DEBUG_SEVERITY_HIGH GL_DEBUG_SEVERITY_HIGH_KHR +#define GL_DEBUG_SEVERITY_MEDIUM GL_DEBUG_SEVERITY_MEDIUM_KHR +#define GL_DEBUG_SEVERITY_LOW GL_DEBUG_SEVERITY_LOW_KHR +#define GL_DEBUG_SEVERITY_NOTIFICATION GL_DEBUG_SEVERITY_NOTIFICATION_KHR +#define GL_DEBUG_OUTPUT_SYNCHRONOUS GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR +#define GL_FRAMEBUFFER_SRGB GL_FRAMEBUFFER_SRGB_EXT +#define GL_SRGB GL_SRGB_EXT +#define GL_SRGB_ALPHA GL_SRGB_ALPHA_EXT +#define GL_SRGB8 GL_SRGB8_EXT +#define GL_SRGB8_ALPHA GL_SRGB8_ALPHA_EXT +#define GL_SLUMINANCE GL_SLUMINANCE_NV +#define GL_SLUMINANCE_ALPHA GL_SLUMINANCE_ALPHA_NV +#define GL_SLUMINANCE8 GL_SLUMINANCE8_NV +#define GL_SLUMINANCE8_ALPHA GL_SLUMINANCE8_ALPHA_NV #undef SUPPORT_IMMEDIATE_MODE #define APIENTRY #define APIENTRYP * #include "glstuff_src.h" - + #endif // GLES2GSG_H diff --git a/panda/src/glesgsg/glesgsg.h b/panda/src/glesgsg/glesgsg.h index c397e81f7a..d964b48765 100644 --- a/panda/src/glesgsg/glesgsg.h +++ b/panda/src/glesgsg/glesgsg.h @@ -110,11 +110,15 @@ #define GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT_OES #define GL_FUNC_REVERSE_SUBTRACT GL_FUNC_REVERSE_SUBTRACT_OES #define GL_BGRA GL_BGRA_EXT +#define GL_RGB16F GL_RGB16F_EXT +#define GL_RGBA16F GL_RGBA16F_EXT +#define GL_RGB32F GL_RGB32F_EXT +#define GL_RGBA32F GL_RGBA32F_EXT #undef SUPPORT_IMMEDIATE_MODE #define APIENTRY #define APIENTRYP * #include "glstuff_src.h" - + #endif // GLESGSG_H diff --git a/panda/src/glstuff/glCgShaderContext_src.I b/panda/src/glstuff/glCgShaderContext_src.I new file mode 100755 index 0000000000..c989f99b63 --- /dev/null +++ b/panda/src/glstuff/glCgShaderContext_src.I @@ -0,0 +1,67 @@ +// Filename: glCgShaderContext_src.h +// Created by: rdb (27Jun14) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef OPENGLES_1 + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::valid +// Access: Public +// Description: Returns true if the shader is "valid", ie, if the +// compilation was successful. The compilation could +// fail if there is a syntax error in the shader, or +// if the current video card isn't shader-capable, +// or if no shader languages are compiled into panda. +//////////////////////////////////////////////////////////////////// +INLINE bool CLP(CgShaderContext):: +valid() { + if (_shader->get_error_flag()) return false; + if (_shader->get_language() != Shader::SL_Cg) return false; + if (_cg_context) return true; + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::uses_standard_vertex_arrays +// Access: Public +// Description: Returns true if the shader may need to access +// standard vertex attributes as passed by +// glVertexPointer and the like. +//////////////////////////////////////////////////////////////////// +INLINE bool CLP(CgShaderContext):: +uses_standard_vertex_arrays() { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::uses_custom_vertex_arrays +// Access: Public +// Description: Always true, for now. +//////////////////////////////////////////////////////////////////// +INLINE bool CLP(CgShaderContext):: +uses_custom_vertex_arrays() { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::uses_custom_texture_bindings +// Access: Public +// Description: Always true, for now. +//////////////////////////////////////////////////////////////////// +INLINE bool CLP(CgShaderContext):: +uses_custom_texture_bindings() { + return true; +} + +#endif // OPENGLES_1 + diff --git a/panda/src/glstuff/glCgShaderContext_src.cxx b/panda/src/glstuff/glCgShaderContext_src.cxx new file mode 100755 index 0000000000..50ecab80d0 --- /dev/null +++ b/panda/src/glstuff/glCgShaderContext_src.cxx @@ -0,0 +1,619 @@ +// Filename: glCgShaderContext_src.cxx +// Created by: jyelon (01Sep05) +// Updated by: fperazzi, PandaSE (29Apr10) (updated CLP with note that some +// parameter types only supported under Cg) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#if defined(HAVE_CG) && !defined(OPENGLES) + +#include "Cg/cgGL.h" + +#include "pStatTimer.h" + +TypeHandle CLP(CgShaderContext)::_type_handle; + +#ifndef NDEBUG +#define cg_report_errors() { \ + CGerror err = cgGetError(); \ + if (err != CG_NO_ERROR) { \ + GLCAT.error() << __FILE__ ", line " << __LINE__ << ": " << cgGetErrorString(err) << "\n"; \ + } } +#else +#define cg_report_errors() +#endif + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::Constructor +// Access: Public +// Description: xyz +//////////////////////////////////////////////////////////////////// +CLP(CgShaderContext):: +CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext(s) { + _glgsg = glgsg; + _cg_context = 0; + _cg_vprogram = 0; + _cg_fprogram = 0; + _cg_gprogram = 0; + _cg_vprofile = CG_PROFILE_UNKNOWN; + _cg_fprofile = CG_PROFILE_UNKNOWN; + _cg_gprofile = CG_PROFILE_UNKNOWN; + + nassertv(s->get_language() == Shader::SL_Cg); + + // Ask the shader to compile itself for us and + // to give us the resulting Cg program objects. + if (!s->cg_compile_for(_glgsg->_shader_caps, + _cg_context, + _cg_vprogram, + _cg_fprogram, + _cg_gprogram, + _cg_parameter_map)) { + return; + } + + // Load the program. + if (_cg_vprogram != 0) { + _cg_vprofile = cgGetProgramProfile(_cg_vprogram); + cgGLLoadProgram(_cg_vprogram); + CGerror verror = cgGetError(); + if (verror != CG_NO_ERROR) { + const char *str = cgGetErrorString(verror); + GLCAT.error() + << "Could not load Cg vertex program: " << s->get_filename(Shader::ST_vertex) + << " (" << cgGetProfileString(_cg_vprofile) << " " << str << ")\n"; + release_resources(); + } + } + + if (_cg_fprogram != 0) { + _cg_fprofile = cgGetProgramProfile(_cg_fprogram); + cgGLLoadProgram(_cg_fprogram); + CGerror ferror = cgGetError(); + if (ferror != CG_NO_ERROR) { + const char *str = cgGetErrorString(ferror); + GLCAT.error() + << "Could not load Cg fragment program: " << s->get_filename(Shader::ST_fragment) + << " (" << cgGetProfileString(_cg_fprofile) << " " << str << ")\n"; + release_resources(); + } + } + + if (_cg_gprogram != 0) { + _cg_gprofile = cgGetProgramProfile(_cg_gprogram); + cgGLLoadProgram(_cg_gprogram); + CGerror gerror = cgGetError(); + if (gerror != CG_NO_ERROR) { + const char *str = cgGetErrorString(gerror); + GLCAT.error() + << "Could not load Cg geometry program: " << s->get_filename(Shader::ST_geometry) + << " (" << cgGetProfileString(_cg_gprofile) << " " << str << ")\n"; + release_resources(); + } + } + + _glgsg->report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::Destructor +// Access: Public +// Description: xyz +//////////////////////////////////////////////////////////////////// +CLP(CgShaderContext):: +~CLP(CgShaderContext)() { + release_resources(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::release_resources +// Access: Public +// Description: Should deallocate all system resources (such as +// vertex program handles or Cg contexts). +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +release_resources() { + if (_cg_context) { + cgDestroyContext(_cg_context); + _cg_context = 0; + // Do *NOT* destroy the programs here! It causes problems. +// if (_cg_vprogram != 0) cgDestroyProgram(_cg_vprogram); +// if (_cg_fprogram != 0) cgDestroyProgram(_cg_fprogram); +// if (_cg_gprogram != 0) cgDestroyProgram(_cg_gprogram); + _cg_vprogram = 0; + _cg_fprogram = 0; + _cg_gprogram = 0; + _cg_parameter_map.clear(); + } + if (_glgsg) { + _glgsg->report_my_gl_errors(); + } else if (glGetError() != GL_NO_ERROR) { + GLCAT.error() << "GL error in ShaderContext destructor\n"; + } + + if (!_glgsg) { + return; + } + _glgsg->report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::bind +// Access: Public +// Description: This function is to be called to enable a new +// shader. It also initializes all of the shader's +// input parameters. +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +bind(bool reissue_parameters) { + if (reissue_parameters) { + // Pass in k-parameters and transform-parameters + issue_parameters(Shader::SSD_general); + } + + if (_cg_context != 0) { + // Bind the shaders. + if (_cg_vprogram != 0) { + cgGLEnableProfile(_cg_vprofile); + cgGLBindProgram(_cg_vprogram); + } + if (_cg_fprogram != 0) { + cgGLEnableProfile(_cg_fprofile); + cgGLBindProgram(_cg_fprogram); + } + if (_cg_gprogram != 0) { + cgGLEnableProfile(_cg_gprofile); + cgGLBindProgram(_cg_gprogram); + } + + cg_report_errors(); + _glgsg->report_my_gl_errors(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::unbind +// Access: Public +// Description: This function disables a currently-bound shader. +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +unbind() { + if (_cg_context != 0) { + if (_cg_vprogram != 0) { + cgGLUnbindProgram(_cg_vprofile); + cgGLDisableProfile(_cg_vprofile); + } + if (_cg_fprogram != 0) { + cgGLUnbindProgram(_cg_fprofile); + cgGLDisableProfile(_cg_fprofile); + } + if (_cg_gprogram != 0) { + cgGLUnbindProgram(_cg_gprofile); + cgGLDisableProfile(_cg_gprofile); + } + + cg_report_errors(); + _glgsg->report_my_gl_errors(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::issue_parameters +// Access: Public +// Description: This function gets called whenever the RenderState +// or TransformState has changed, but the Shader +// itself has not changed. It loads new values into the +// shader's parameters. +// +// If "altered" is false, that means you promise that +// the parameters for this shader context have already +// been issued once, and that since the last time the +// parameters were issued, no part of the render +// state has changed except the external and internal +// transforms. +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +issue_parameters(int altered) { + PStatTimer timer(_glgsg->_draw_set_state_shader_parameters_pcollector); + + if (!valid()) { + return; + } + + // Iterate through _ptr parameters + for (int i=0; i<(int)_shader->_ptr_spec.size(); i++) { + if (altered & (_shader->_ptr_spec[i]._dep[0] | _shader->_ptr_spec[i]._dep[1])) { + const Shader::ShaderPtrSpec& _ptr = _shader->_ptr_spec[i]; + Shader::ShaderPtrData* ptr_data = + const_cast< Shader::ShaderPtrData*>(_glgsg->fetch_ptr_parameter(_ptr)); + + if (ptr_data == NULL){ //the input is not contained in ShaderPtrData + release_resources(); + return; + } + //check if the data must be shipped to the GPU + /*if (!ptr_data->_updated) + continue; + ptr_data->_updated = false;*/ + + //Check if the size of the shader input and ptr_data match + int input_size = _ptr._dim[0] * _ptr._dim[1] * _ptr._dim[2]; + + // dimension is negative only if the parameter had the (deprecated)k_ prefix. + if ((input_size > ptr_data->_size) && (_ptr._dim[0] > 0)) { + GLCAT.error() << _ptr._id._name << ": incorrect number of elements, expected " + << input_size <<" got " << ptr_data->_size << "\n"; + release_resources(); + return; + } + CGparameter p = _cg_parameter_map[_ptr._id._seqno]; + + switch (ptr_data->_type) { + case Shader::SPT_float: + switch(_ptr._info._class) { + case Shader::SAC_scalar: cgSetParameter1fv(p,(float*)ptr_data->_ptr); continue; + case Shader::SAC_vector: + switch(_ptr._info._type) { + case Shader::SAT_vec1: cgSetParameter1fv(p,(float*)ptr_data->_ptr); continue; + case Shader::SAT_vec2: cgSetParameter2fv(p,(float*)ptr_data->_ptr); continue; + case Shader::SAT_vec3: cgSetParameter3fv(p,(float*)ptr_data->_ptr); continue; + case Shader::SAT_vec4: cgSetParameter4fv(p,(float*)ptr_data->_ptr); continue; + } + case Shader::SAC_matrix: cgGLSetMatrixParameterfc(p,(float*)ptr_data->_ptr); continue; + case Shader::SAC_array: { + switch(_ptr._info._subclass) { + case Shader::SAC_scalar: + cgGLSetParameterArray1f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; + case Shader::SAC_vector: + switch(_ptr._dim[2]) { + case 1: cgGLSetParameterArray1f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; + case 2: cgGLSetParameterArray2f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; + case 3: cgGLSetParameterArray3f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; + case 4: cgGLSetParameterArray4f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; + } + case Shader::SAC_matrix: + cgGLSetMatrixParameterArrayfc(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; + } + } + } + case Shader::SPT_double: + switch(_ptr._info._class) { + case Shader::SAC_scalar: cgSetParameter1dv(p,(double*)ptr_data->_ptr); continue; + case Shader::SAC_vector: + switch(_ptr._info._type) { + case Shader::SAT_vec1: cgSetParameter1dv(p,(double*)ptr_data->_ptr); continue; + case Shader::SAT_vec2: cgSetParameter2dv(p,(double*)ptr_data->_ptr); continue; + case Shader::SAT_vec3: cgSetParameter3dv(p,(double*)ptr_data->_ptr); continue; + case Shader::SAT_vec4: cgSetParameter4dv(p,(double*)ptr_data->_ptr); continue; + } + case Shader::SAC_matrix: cgGLSetMatrixParameterdc(p,(double*)ptr_data->_ptr); continue; + case Shader::SAC_array: { + switch(_ptr._info._subclass) { + case Shader::SAC_scalar: + cgGLSetParameterArray1d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; + case Shader::SAC_vector: + switch(_ptr._dim[2]) { + case 1: cgGLSetParameterArray1d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; + case 2: cgGLSetParameterArray2d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; + case 3: cgGLSetParameterArray3d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; + case 4: cgGLSetParameterArray4d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; + } + case Shader::SAC_matrix: + cgGLSetMatrixParameterArraydc(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; + } + } + } + case Shader::SPT_int: + switch(_ptr._info._class) { + case Shader::SAC_scalar: cgSetParameter1iv(p,(int*)ptr_data->_ptr); continue; + case Shader::SAC_vector: + switch(_ptr._info._type) { + case Shader::SAT_vec1: cgSetParameter1iv(p,(int*)ptr_data->_ptr); continue; + case Shader::SAT_vec2: cgSetParameter2iv(p,(int*)ptr_data->_ptr); continue; + case Shader::SAT_vec3: cgSetParameter3iv(p,(int*)ptr_data->_ptr); continue; + case Shader::SAT_vec4: cgSetParameter4iv(p,(int*)ptr_data->_ptr); continue; + } + } + default: GLCAT.error() << _ptr._id._name << ":" << "unrecognized parameter type\n"; + release_resources(); + return; + } + } + } + + for (int i=0; i<(int)_shader->_mat_spec.size(); i++) { + if (altered & (_shader->_mat_spec[i]._dep[0] | _shader->_mat_spec[i]._dep[1])) { + const LMatrix4 *val = _glgsg->fetch_specified_value(_shader->_mat_spec[i], altered); + if (!val) continue; +#ifndef STDFLOAT_DOUBLE + // In this case, the data is already single-precision. + const PN_float32 *data = val->get_data(); +#else + // In this case, we have to convert it. + LMatrix4f valf = LCAST(PN_float32, *val); + const PN_float32 *data = valf.get_data(); +#endif + + CGparameter p = _cg_parameter_map[_shader->_mat_spec[i]._id._seqno]; + switch (_shader->_mat_spec[i]._piece) { + case Shader::SMP_whole: GLfc(cgGLSetMatrixParameter)(p, data); continue; + case Shader::SMP_transpose: GLfr(cgGLSetMatrixParameter)(p, data); continue; + case Shader::SMP_col0: GLf(cgGLSetParameter4)(p, data[0], data[4], data[ 8], data[12]); continue; + case Shader::SMP_col1: GLf(cgGLSetParameter4)(p, data[1], data[5], data[ 9], data[13]); continue; + case Shader::SMP_col2: GLf(cgGLSetParameter4)(p, data[2], data[6], data[10], data[14]); continue; + case Shader::SMP_col3: GLf(cgGLSetParameter4)(p, data[3], data[7], data[11], data[15]); continue; + case Shader::SMP_row0: GLfv(cgGLSetParameter4)(p, data+ 0); continue; + case Shader::SMP_row1: GLfv(cgGLSetParameter4)(p, data+ 4); continue; + case Shader::SMP_row2: GLfv(cgGLSetParameter4)(p, data+ 8); continue; + case Shader::SMP_row3: GLfv(cgGLSetParameter4)(p, data+12); continue; + case Shader::SMP_row3x1: GLfv(cgGLSetParameter1)(p, data+12); continue; + case Shader::SMP_row3x2: GLfv(cgGLSetParameter2)(p, data+12); continue; + case Shader::SMP_row3x3: GLfv(cgGLSetParameter3)(p, data+12); continue; + case Shader::SMP_upper3x3: + { + LMatrix3f upper3 = val->get_upper_3(); + GLfc(cgGLSetMatrixParameter)(p, upper3.get_data()); + continue; + } + case Shader::SMP_transpose3x3: + { + LMatrix3f upper3 = val->get_upper_3(); + GLfr(cgGLSetMatrixParameter)(p, upper3.get_data()); + continue; + } + case Shader::SMP_cell15: + GLf(cgGLSetParameter1)(p, data[15]); + continue; + } + } + } + + _glgsg->report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::disable_shader_vertex_arrays +// Access: Public +// Description: Disable all the vertex arrays used by this shader. +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +disable_shader_vertex_arrays() { + if (!valid()) { + return; + } + + for (int i=0; i<(int)_shader->_var_spec.size(); i++) { + CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; + if (p == 0) continue; + cgGLDisableClientState(p); + } + + cg_report_errors(); + _glgsg->report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::update_shader_vertex_arrays +// Access: Public +// Description: Disables all vertex arrays used by the previous +// shader, then enables all the vertex arrays needed +// by this shader. Extracts the relevant vertex array +// data from the gsg. +// The current implementation is inefficient, because +// it may unnecessarily disable arrays then immediately +// reenable them. We may optimize this someday. +//////////////////////////////////////////////////////////////////// +bool CLP(CgShaderContext):: +update_shader_vertex_arrays(ShaderContext *prev, bool force) { + if (prev) { + prev->disable_shader_vertex_arrays(); + } + + if (!valid()) { + return true; + } + + cg_report_errors(); + +#ifdef SUPPORT_IMMEDIATE_MODE + if (_glgsg->_use_sender) { + GLCAT.error() << "immediate mode shaders not implemented yet\n"; + } else +#endif // SUPPORT_IMMEDIATE_MODE + { + const GeomVertexArrayDataHandle *array_reader; + Geom::NumericType numeric_type; + int start, stride, num_values; + int nvarying = _shader->_var_spec.size(); + for (int i = 0; i < nvarying; ++i) { + if (_cg_parameter_map[_shader->_var_spec[i]._id._seqno] == 0) { + continue; + } + + InternalName *name = _shader->_var_spec[i]._name; + int texslot = _shader->_var_spec[i]._append_uv; + if (texslot >= 0 && texslot < _glgsg->_state_texture->get_num_on_stages()) { + TextureStage *stage = _glgsg->_state_texture->get_on_stage(texslot); + InternalName *texname = stage->get_texcoord_name(); + + if (name == InternalName::get_texcoord()) { + name = texname; + } else if (texname != InternalName::get_texcoord()) { + name = name->append(texname->get_basename()); + } + } + if (_glgsg->_data_reader->get_array_info(name, + array_reader, num_values, numeric_type, + start, stride)) { + const unsigned char *client_pointer; + if (!_glgsg->setup_array_data(client_pointer, array_reader, force)) { + return false; + } + + CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; + + if (numeric_type == GeomEnums::NT_packed_dabc) { + cgGLSetParameterPointer(p, GL_BGRA, GL_UNSIGNED_BYTE, + stride, client_pointer + start); + } else { + if (name == InternalName::get_normal() && num_values == 4) { + // In some cases, the normals are aligned to 4 values. + // This would cause an error on some rivers, so we tell it + // to use the first three values only. + num_values = 3; + } + cgGLSetParameterPointer(p, + num_values, _glgsg->get_numeric_type(numeric_type), + stride, client_pointer + start); + } + cgGLEnableClientState(p); + } else { + CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; + cgGLDisableClientState(p); + } + } + } + + cg_report_errors(); + _glgsg->report_my_gl_errors(); + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::disable_shader_texture_bindings +// Access: Public +// Description: Disable all the texture bindings used by this shader. +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +disable_shader_texture_bindings() { + if (!valid()) { + return; + } + +#ifndef OPENGLES_2 + for (int i=0; i<(int)_shader->_tex_spec.size(); i++) { + CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno]; + if (p == 0) continue; + int texunit = cgGetParameterResourceIndex(p); + _glgsg->_glActiveTexture(GL_TEXTURE0 + texunit); + +#ifndef OPENGLES + glBindTexture(GL_TEXTURE_1D, 0); +#endif // OPENGLES + glBindTexture(GL_TEXTURE_2D, 0); +#ifndef OPENGLES_1 + if (_glgsg->_supports_3d_texture) { + glBindTexture(GL_TEXTURE_3D, 0); + } +#endif // OPENGLES_1 +#ifndef OPENGLES + if (_glgsg->_supports_2d_texture_array) { + glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, 0); + } +#endif + if (_glgsg->_supports_cube_map) { + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + } + // This is probably faster - but maybe not as safe? + // cgGLDisableTextureParameter(p); + } +#endif // OPENGLES_2 + + cg_report_errors(); + _glgsg->report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::update_shader_texture_bindings +// Access: Public +// Description: Disables all texture bindings used by the previous +// shader, then enables all the texture bindings needed +// by this shader. Extracts the relevant vertex array +// data from the gsg. +// The current implementation is inefficient, because +// it may unnecessarily disable textures then immediately +// reenable them. We may optimize this someday. +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +update_shader_texture_bindings(ShaderContext *prev) { + if (prev) { + prev->disable_shader_texture_bindings(); + } + + if (!valid()) { + return; + } + + // We get the TextureAttrib directly from the _target_rs, not the + // filtered TextureAttrib in _target_texture. + const TextureAttrib *texattrib = DCAST(TextureAttrib, _glgsg->_target_rs->get_attrib_def(TextureAttrib::get_class_slot())); + nassertv(texattrib != (TextureAttrib *)NULL); + + for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) { + InternalName *id = _shader->_tex_spec[i]._name; + + CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno]; + if (p == 0) { + continue; + } + int texunit = cgGetParameterResourceIndex(p); + + Texture *tex = 0; + int view = _glgsg->get_current_tex_view_offset(); + if (id != 0) { + const ShaderInput *input = _glgsg->_target_shader->get_shader_input(id); + tex = input->get_texture(); + } else { + if (_shader->_tex_spec[i]._stage >= texattrib->get_num_on_stages()) { + continue; + } + TextureStage *stage = texattrib->get_on_stage(_shader->_tex_spec[i]._stage); + tex = texattrib->get_on_texture(stage); + view += stage->get_tex_view_offset(); + } + if (_shader->_tex_spec[i]._suffix != 0) { + // The suffix feature is inefficient. It is a temporary hack. + if (tex == 0) { + continue; + } + tex = tex->load_related(_shader->_tex_spec[i]._suffix); + } + if ((tex == 0) || (tex->get_texture_type() != _shader->_tex_spec[i]._desired_type)) { + continue; + } + + _glgsg->_glActiveTexture(GL_TEXTURE0 + texunit); + + TextureContext *tc = tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg); + if (tc == (TextureContext*)NULL) { + continue; + } + + GLenum target = _glgsg->get_texture_target(tex->get_texture_type()); + if (target == GL_NONE) { + // Unsupported texture mode. + continue; + } + + if (!_glgsg->update_texture(tc, false)) { + continue; + } + + _glgsg->apply_texture(tc); + } + + cg_report_errors(); + _glgsg->report_my_gl_errors(); +} + +#endif // OPENGLES_1 diff --git a/panda/src/glstuff/glCgShaderContext_src.h b/panda/src/glstuff/glCgShaderContext_src.h new file mode 100755 index 0000000000..3e487fbe04 --- /dev/null +++ b/panda/src/glstuff/glCgShaderContext_src.h @@ -0,0 +1,89 @@ +// Filename: glShaderContext_src.h +// Created by: jyelon (01Sep05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#if defined(HAVE_CG) && !defined(OPENGLES) + +#include "pandabase.h" +#include "string_utils.h" +#include "internalName.h" +#include "shader.h" +#include "shaderContext.h" +#include "deletedChain.h" + +#include + +class CLP(GraphicsStateGuardian); + +//////////////////////////////////////////////////////////////////// +// Class : GLShaderContext +// Description : xyz +//////////////////////////////////////////////////////////////////// +class EXPCL_GL CLP(CgShaderContext) : public ShaderContext { +public: + friend class CLP(GraphicsStateGuardian); + + CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s); + ~CLP(CgShaderContext)(); + ALLOC_DELETED_CHAIN(CLP(CgShaderContext)); + + INLINE bool valid(void); + void bind(bool reissue_parameters = true); + void unbind(); + void issue_parameters(int altered); + void disable_shader_vertex_arrays(); + bool update_shader_vertex_arrays(ShaderContext *prev, bool force); + void disable_shader_texture_bindings(); + void update_shader_texture_bindings(ShaderContext *prev); + + INLINE bool uses_standard_vertex_arrays(void); + INLINE bool uses_custom_vertex_arrays(void); + INLINE bool uses_custom_texture_bindings(void); + +private: + CGcontext _cg_context; + CGprogram _cg_vprogram; + CGprogram _cg_fprogram; + CGprogram _cg_gprogram; + CGprofile _cg_vprofile; + CGprofile _cg_fprofile; + CGprofile _cg_gprofile; + + pvector _cg_parameter_map; + + CLP(GraphicsStateGuardian) *_glgsg; + + void release_resources(); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedObject::init_type(); + register_type(_type_handle, CLASSPREFIX_QUOTED "CgShaderContext", + TypedObject::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "glCgShaderContext_src.I" + +#endif // OPENGLES_1 + diff --git a/panda/src/glstuff/glGeomContext_src.cxx b/panda/src/glstuff/glGeomContext_src.cxx index 410f997d2d..272d9727bf 100644 --- a/panda/src/glstuff/glGeomContext_src.cxx +++ b/panda/src/glstuff/glGeomContext_src.cxx @@ -46,7 +46,7 @@ get_display_list(GLuint &index, const CLP(GeomMunger) *munger, DisplayList &dl = _display_lists[(CLP(GeomMunger) *)munger]; bool list_current = (dl._modified == modified); if (dl._index == 0) { - dl._index = GLP(GenLists)(1); + dl._index = glGenLists(1); list_current = false; if (munger != (CLP(GeomMunger) *)NULL) { ((CLP(GeomMunger) *)munger)->_geom_contexts.insert(this); @@ -87,7 +87,7 @@ release_display_lists() { GLCAT.debug() << "releasing index " << (int)dl._index << "\n"; } - GLP(DeleteLists)(dl._index, 1); + glDeleteLists(dl._index, 1); } _display_lists.clear(); diff --git a/panda/src/glstuff/glGeomMunger_src.cxx b/panda/src/glstuff/glGeomMunger_src.cxx index 91888e2822..b4da760703 100644 --- a/panda/src/glstuff/glGeomMunger_src.cxx +++ b/panda/src/glstuff/glGeomMunger_src.cxx @@ -36,9 +36,9 @@ CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state) : _flags = 0; - if (CLP(interleaved_arrays)) { + if (gl_interleaved_arrays) { _flags |= F_interleaved_arrays; - } else if (CLP(parallel_arrays)) { + } else if (gl_parallel_arrays) { _flags |= F_parallel_arrays; } } @@ -46,7 +46,7 @@ CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state) : //////////////////////////////////////////////////////////////////// // Function: CLP(GeomMunger)::Destructor // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// CLP(GeomMunger):: ~CLP(GeomMunger)() { @@ -84,9 +84,13 @@ munge_format_impl(const GeomVertexFormat *orig, PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig); new_format->set_animation(animation); + CLP(GraphicsStateGuardian) *glgsg; + DCAST_INTO_R(glgsg, get_gsg(), NULL); + const GeomVertexColumn *color_type = orig->get_color_column(); if (color_type != (GeomVertexColumn *)NULL && - color_type->get_numeric_type() == NT_packed_dabc) { + color_type->get_numeric_type() == NT_packed_dabc && + !glgsg->_supports_packed_dabc) { // We need to convert the color format; OpenGL doesn't support the // byte order of DirectX's packed ARGB format. int color_array = orig->get_array_with(InternalName::get_color()); @@ -102,7 +106,7 @@ munge_format_impl(const GeomVertexFormat *orig, if (animation.get_animation_type() == AT_hardware) { // If we want hardware animation, we need to reserve space for the // blend weights. - + // Make sure the old weights and indices are removed, just in // case. new_format->remove_column(InternalName::get_transform_weight()); @@ -116,11 +120,11 @@ munge_format_impl(const GeomVertexFormat *orig, new_array_format->add_column (InternalName::get_transform_weight(), animation.get_num_transforms() - 1, NT_stdfloat, C_other); - + if (animation.get_indexed_transforms()) { // Also, if we'll be indexing into the transform table, reserve // space for the index. - + // TODO: We should examine the maximum palette index so we can // decide whether we need 16-bit indices. That implies saving // the maximum palette index, presumably in the AnimationSpec. @@ -129,7 +133,7 @@ munge_format_impl(const GeomVertexFormat *orig, new_array_format->add_column (InternalName::get_transform_index(), animation.get_num_transforms(), NT_uint8, C_index); - } + } new_format->add_array(new_array_format); } @@ -149,16 +153,16 @@ munge_format_impl(const GeomVertexFormat *orig, new_format->add_array(new_array_format); } format = GeomVertexFormat::register_format(new_format); - + } else if ((_flags & F_interleaved_arrays) != 0) { // Combine the primary data columns into a single array. new_format = new GeomVertexFormat(*format); PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat; - + const GeomVertexColumn *column = format->get_vertex_column(); if (column != (const GeomVertexColumn *)NULL) { new_array_format->add_column - (column->get_name(), column->get_num_components(), + (column->get_name(), column->get_num_components(), column->get_numeric_type(), column->get_contents(), -1, column->get_column_alignment()); new_format->remove_column(column->get_name()); @@ -167,7 +171,7 @@ munge_format_impl(const GeomVertexFormat *orig, column = format->get_normal_column(); if (column != (const GeomVertexColumn *)NULL) { new_array_format->add_column - (column->get_name(), column->get_num_components(), + (column->get_name(), column->get_num_components(), column->get_numeric_type(), column->get_contents(), -1, column->get_column_alignment()); new_format->remove_column(column->get_name()); @@ -176,7 +180,7 @@ munge_format_impl(const GeomVertexFormat *orig, column = format->get_color_column(); if (column != (const GeomVertexColumn *)NULL) { new_array_format->add_column - (column->get_name(), column->get_num_components(), + (column->get_name(), column->get_num_components(), column->get_numeric_type(), column->get_contents(), -1, column->get_column_alignment()); new_format->remove_column(column->get_name()); @@ -187,7 +191,7 @@ munge_format_impl(const GeomVertexFormat *orig, if (_texture != (TextureAttrib *)NULL) { typedef pset UsedStages; UsedStages used_stages; - + int num_stages = _texture->get_num_on_stages(); for (int i = 0; i < num_stages; ++i) { TextureStage *stage = _texture->get_on_stage(i); @@ -197,7 +201,7 @@ munge_format_impl(const GeomVertexFormat *orig, if (used_stages.insert(name).second) { // This is the first time we've encountered this texcoord name. const GeomVertexColumn *texcoord_type = format->get_column(name); - + if (texcoord_type != (const GeomVertexColumn *)NULL) { new_array_format->add_column (name, texcoord_type->get_num_values(), NT_stdfloat, C_texcoord, @@ -230,9 +234,13 @@ CPT(GeomVertexFormat) CLP(GeomMunger):: premunge_format_impl(const GeomVertexFormat *orig) { PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig); + CLP(GraphicsStateGuardian) *glgsg; + DCAST_INTO_R(glgsg, get_gsg(), NULL); + const GeomVertexColumn *color_type = orig->get_color_column(); if (color_type != (GeomVertexColumn *)NULL && - color_type->get_numeric_type() == NT_packed_dabc) { + color_type->get_numeric_type() == NT_packed_dabc && + !glgsg->_supports_packed_dabc) { // We need to convert the color format; OpenGL doesn't support the // byte order of DirectX's packed ARGB format. int color_array = orig->get_array_with(InternalName::get_color()); @@ -259,7 +267,7 @@ premunge_format_impl(const GeomVertexFormat *orig) { new_format->add_array(new_array_format); } format = GeomVertexFormat::register_format(new_format); - + } else { // Combine the primary data columns into a single array. Unlike // the munge case, above, in the premunge case, we do this even if @@ -269,11 +277,11 @@ premunge_format_impl(const GeomVertexFormat *orig) { // at run time. new_format = new GeomVertexFormat(*format); PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat; - + const GeomVertexColumn *column = format->get_vertex_column(); if (column != (const GeomVertexColumn *)NULL) { new_array_format->add_column - (column->get_name(), column->get_num_components(), + (column->get_name(), column->get_num_components(), column->get_numeric_type(), column->get_contents(), -1, column->get_column_alignment()); new_format->remove_column(column->get_name()); @@ -282,7 +290,7 @@ premunge_format_impl(const GeomVertexFormat *orig) { column = format->get_normal_column(); if (column != (const GeomVertexColumn *)NULL) { new_array_format->add_column - (column->get_name(), column->get_num_components(), + (column->get_name(), column->get_num_components(), column->get_numeric_type(), column->get_contents(), -1, column->get_column_alignment()); new_format->remove_column(column->get_name()); @@ -291,7 +299,7 @@ premunge_format_impl(const GeomVertexFormat *orig) { column = format->get_color_column(); if (column != (const GeomVertexColumn *)NULL) { new_array_format->add_column - (column->get_name(), column->get_num_components(), + (column->get_name(), column->get_num_components(), column->get_numeric_type(), column->get_contents(), -1, column->get_column_alignment()); new_format->remove_column(column->get_name()); @@ -303,7 +311,7 @@ premunge_format_impl(const GeomVertexFormat *orig) { if (_texture != (TextureAttrib *)NULL) { typedef pset UsedStages; UsedStages used_stages; - + int num_stages = _texture->get_num_on_stages(); for (int i = 0; i < num_stages; ++i) { TextureStage *stage = _texture->get_on_stage(i); @@ -313,7 +321,7 @@ premunge_format_impl(const GeomVertexFormat *orig) { if (used_stages.insert(name).second) { // This is the first time we've encountered this texcoord name. const GeomVertexColumn *texcoord_type = format->get_column(name); - + if (texcoord_type != (const GeomVertexColumn *)NULL) { new_array_format->add_column (name, texcoord_type->get_num_values(), NT_stdfloat, C_texcoord, diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index 0e094f4eef..bc13a435c7 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -73,9 +73,8 @@ CLP(GraphicsBuffer)(GraphicsEngine *engine, GraphicsPipe *pipe, _rb_size_x = 0; _rb_size_y = 0; _rb_size_z = 0; - for (int i=0; i::iterator it; + for (it = _texture_contexts.begin(); it != _texture_contexts.end(); ++it) { + CLP(TextureContext) *gtc = *it; + + if (gtc->needs_barrier(GL_FRAMEBUFFER_BARRIER_BIT)) { + glgsg->issue_memory_barrier(GL_FRAMEBUFFER_BARRIER_BIT); + // If we've done it for one, we've done it for all. + break; + } + } + } } _gsg->set_current_properties(&get_fb_properties()); @@ -248,7 +265,9 @@ rebuild_bitplanes() { DCAST_INTO_V(glgsg, _gsg); if (!_needs_rebuild) { - if (_fbo.size() > 0) { + if (_fbo_multisample != 0) { + glgsg->bind_fbo(_fbo_multisample); + } else if (_fbo.size() > 0) { glgsg->bind_fbo(_fbo[0]); } else { glgsg->bind_fbo(0); @@ -284,6 +303,7 @@ rebuild_bitplanes() { // These variables indicate what should be bound to each bitplane. Texture *attach[RTP_COUNT]; memset(attach, 0, sizeof(Texture *) * RTP_COUNT); + _texture_contexts.clear(); // Sort the textures list into appropriate slots. { @@ -370,6 +390,11 @@ rebuild_bitplanes() { // explicitly bound something to RTP_depth. _use_depth_stencil = false; + } else if (_fb_properties.get_float_depth()) { + // Let's not bother with a depth-stencil buffer + // if a float buffer was requested. + _use_depth_stencil = false; + } else if (_fb_properties.get_depth_bits() > 24) { // We can't give more than 24 depth bits with a depth-stencil buffer. _use_depth_stencil = false; @@ -432,12 +457,13 @@ rebuild_bitplanes() { bind_slot(layer, rb_resize, attach, RTP_color, next++); if (_fb_properties.is_stereo()) { - // The texture has already been initialized, so bind it straight away. + // The second tex view has already been initialized, so bind it straight away. if (attach[RTP_color] != NULL) { attach_tex(layer, 1, attach[RTP_color], next++); } else { //XXX hack: I needed a slot to use, and we don't currently use RTP_stencil - // which is treated as a color attachment below, so this fits the bill. + // and it's treated as a color attachment below, so this fits the bill. + // Eventually, we might want to add RTP_color_left and RTP_color_right. bind_slot(layer, rb_resize, attach, RTP_stencil, next++); } } @@ -548,7 +574,6 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, DCAST_INTO_V(glgsg, _gsg); Texture *tex = attach[slot]; - _tex[slot] = tex; if (tex && layer >= tex->get_z_size()) { // If the requested layer index exceeds the number of layers @@ -582,7 +607,10 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, // Adjust the texture format based on the requested framebuffer settings. switch (slot) { case RTP_depth: - if (_fb_properties.get_depth_bits() > 24) { + if (_fb_properties.get_float_depth()) { + tex->set_format(Texture::F_depth_component32); + tex->set_component_type(Texture::T_float); + } else if (_fb_properties.get_depth_bits() > 24) { tex->set_format(Texture::F_depth_component32); } else if (_fb_properties.get_depth_bits() > 16) { tex->set_format(Texture::F_depth_component24); @@ -594,7 +622,12 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, break; case RTP_depth_stencil: tex->set_format(Texture::F_depth_stencil); - tex->set_component_type(Texture::T_unsigned_int_24_8); + + if (_fb_properties.get_float_depth()) { + tex->set_component_type(Texture::T_float); + } else { + tex->set_component_type(Texture::T_unsigned_int_24_8); + } break; case RTP_aux_hrgba_0: case RTP_aux_hrgba_1: @@ -611,16 +644,24 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, tex->set_component_type(Texture::T_float); break; default: - if (_fb_properties.get_color_bits() > 48) { - tex->set_format(Texture::F_rgba32); - // Currently a float format. Should change. - tex->set_component_type(Texture::T_float); - } else if (_fb_properties.get_color_bits() > 24) { - tex->set_format(Texture::F_rgba16); - // Currently a float format. Should change. - tex->set_component_type(Texture::T_float); + if (_fb_properties.get_srgb_color()) { + if (_fb_properties.get_alpha_bits() == 0) { + tex->set_format(Texture::F_srgb); + } else { + tex->set_format(Texture::F_srgb_alpha); + } } else { - tex->set_format(Texture::F_rgba); + if (_fb_properties.get_float_color()) { + tex->set_component_type(Texture::T_float); + } + if (_fb_properties.get_color_bits() > 16 * 3) { + tex->set_format(Texture::F_rgba32); + tex->set_component_type(Texture::T_float); + } else if (_fb_properties.get_color_bits() > 8 * 3) { + tex->set_format(Texture::F_rgba16); + } else { + tex->set_format(Texture::F_rgba); + } } } @@ -638,7 +679,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, #ifndef OPENGLES GLint depth_size = 0; - GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_DEPTH_SIZE, &depth_size); + glGetTexLevelParameteriv(target, 0, GL_TEXTURE_DEPTH_SIZE, &depth_size); _fb_properties.set_depth_bits(depth_size); #endif @@ -649,7 +690,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, #ifndef OPENGLES GLint stencil_size = 0; - GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_STENCIL_SIZE, &stencil_size); + glGetTexLevelParameteriv(target, 0, GL_TEXTURE_STENCIL_SIZE, &stencil_size); _fb_properties.set_stencil_bits(stencil_size); #endif } @@ -662,10 +703,10 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, #ifndef OPENGLES if (attachpoint == GL_COLOR_ATTACHMENT0_EXT) { GLint red_size = 0, green_size = 0, blue_size = 0, alpha_size = 0; - GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_RED_SIZE, &red_size); - GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_GREEN_SIZE, &green_size); - GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_BLUE_SIZE, &blue_size); - GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size); + glGetTexLevelParameteriv(target, 0, GL_TEXTURE_RED_SIZE, &red_size); + glGetTexLevelParameteriv(target, 0, GL_TEXTURE_GREEN_SIZE, &green_size); + glGetTexLevelParameteriv(target, 0, GL_TEXTURE_BLUE_SIZE, &blue_size); + glGetTexLevelParameteriv(target, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size); _fb_properties.set_color_bits(red_size + green_size + blue_size); _fb_properties.set_alpha_bits(alpha_size); @@ -730,10 +771,16 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, GLuint gl_format = GL_RGBA; switch (slot) { case RTP_depth_stencil: - gl_format = GL_DEPTH_STENCIL_EXT; + if (_fb_properties.get_float_depth()) { + gl_format = GL_DEPTH32F_STENCIL8; + } else { + gl_format = GL_DEPTH24_STENCIL8; + } break; case RTP_depth: - if (_fb_properties.get_depth_bits() > 24) { + if (_fb_properties.get_float_depth()) { + gl_format = GL_DEPTH_COMPONENT32F; + } else if (_fb_properties.get_depth_bits() > 24) { gl_format = GL_DEPTH_COMPONENT32; } else if (_fb_properties.get_depth_bits() > 16) { gl_format = GL_DEPTH_COMPONENT24; @@ -763,7 +810,41 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, break; default: if (_fb_properties.get_alpha_bits() == 0) { - gl_format = GL_RGB; + if (_fb_properties.get_srgb_color()) { + gl_format = GL_SRGB8; + } else if (_fb_properties.get_float_color()) { + if (_fb_properties.get_color_bits() > 16 * 3) { + gl_format = GL_RGB32F_ARB; + } else { + gl_format = GL_RGB16F_ARB; + } + } else { + if (_fb_properties.get_color_bits() > 16 * 3) { + gl_format = GL_RGBA32F_ARB; + } else if (_fb_properties.get_color_bits() > 8 * 3) { + gl_format = GL_RGB16_EXT; + } else { + gl_format = GL_RGB; + } + } + } else { + if (_fb_properties.get_srgb_color()) { + gl_format = GL_SRGB8_ALPHA8; + } else if (_fb_properties.get_float_color()) { + if (_fb_properties.get_color_bits() > 16 * 3) { + gl_format = GL_RGBA32F_ARB; + } else { + gl_format = GL_RGBA16F_ARB; + } + } else { + if (_fb_properties.get_color_bits() > 16 * 3) { + gl_format = GL_RGB32F_ARB; + } else if (_fb_properties.get_color_bits() > 8 * 3) { + gl_format = GL_RGB16_EXT; + } else { + gl_format = GL_RGB; + } + } } }; #endif @@ -986,7 +1067,10 @@ attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) { TextureContext *tc = attach->prepare_now(view, glgsg->get_prepared_objects(), glgsg); nassertv(tc != (TextureContext *)NULL); CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - glgsg->update_texture(tc, true); + + glgsg->update_texture(gtc, true); + gtc->set_active(true); + _texture_contexts.push_back(gtc); #ifndef OPENGLES GLclampf priority = 1.0f; @@ -1037,23 +1121,26 @@ attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) { //////////////////////////////////////////////////////////////////// void CLP(GraphicsBuffer):: generate_mipmaps() { + if (gl_ignore_mipmaps && !gl_force_mipmaps) { + return; + } + CLP(GraphicsStateGuardian) *glgsg; DCAST_INTO_V(glgsg, _gsg); - for (int slot=0; slotuses_mipmaps())) { + pvector::iterator it; + for (it = _texture_contexts.begin(); it != _texture_contexts.end(); ++it) { + CLP(TextureContext) *gtc = *it; + + if (gtc->_generate_mipmaps) { glgsg->_state_texture = 0; - TextureContext *tc = tex->prepare_now(0, glgsg->get_prepared_objects(), glgsg); - nassertv(tc != (TextureContext *)NULL); - CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - glgsg->update_texture(tc, true); - GLenum target = glgsg->get_texture_target(tex->get_texture_type()); - GLP(BindTexture)(target, gtc->_index); - glgsg->_glGenerateMipmap(target); - GLP(BindTexture)(target, 0); + glgsg->update_texture(gtc, true); + glgsg->apply_texture(gtc); + glgsg->_glGenerateMipmap(gtc->_target); + glBindTexture(gtc->_target, 0); } } + report_my_gl_errors(); } @@ -1136,8 +1223,12 @@ select_target_tex_page(int page) { resolve_multisamples(); } } - - glgsg->bind_fbo(_fbo[page]); + + if (_fbo_multisample != 0) { + // TODO: re-issue clears? + } else { + glgsg->bind_fbo(_fbo[page]); + } _bound_tex_page = page; } @@ -1160,7 +1251,7 @@ open_buffer() { // Count total color buffers. int totalcolor = - (_fb_properties.is_stereo() ? 2 : 1) + + (_fb_properties.get_stereo() ? 2 : 1) + _fb_properties.get_aux_rgba() + _fb_properties.get_aux_hrgba() + _fb_properties.get_aux_float(); @@ -1215,12 +1306,37 @@ open_buffer() { _fb_properties.set_alpha_bits(32); } + if (_fb_properties.get_float_depth()) { + // GL_DEPTH_COMPONENT32F seems the only depth float format. + _fb_properties.set_depth_bits(32); + } + + // We currently only support color formats this big as float. + if (_fb_properties.get_color_bits() > 16 * 3) { + _fb_properties.set_color_bits(32 * 3); + _fb_properties.set_float_color(true); + + if (_fb_properties.get_alpha_bits() > 0) { + _fb_properties.set_alpha_bits(32); + } + } + + if (_fb_properties.get_srgb_color()) { + _fb_properties.set_color_bits(24); + _fb_properties.set_float_color(false); + + if (_fb_properties.get_alpha_bits() > 0) { + _fb_properties.set_alpha_bits(32); + } + } + if (!_gsg->get_supports_depth_stencil()) { // At least we know we won't be getting stencil bits. _fb_properties.set_stencil_bits(0); } _fb_properties.set_accum_bits(0); - _fb_properties.set_multisamples(_host->get_fb_properties().get_multisamples()); + + _fb_properties.set_multisamples(_requested_multisamples); // Update aux settings to reflect the GL_MAX_DRAW_BUFFERS limit, // if we exceed it, that is. @@ -1293,7 +1409,6 @@ close_buffer() { glgsg->_glDeleteRenderbuffers(1, &(_rb[i])); _rb[i] = 0; } - _tex[i] = 0; } // Delete the renderbuffers. for (int i=0; i_glDeleteRenderbuffers(1, &(_rbm[i])); _rb[i] = 0; } - _tex[i] = 0; } _rb_size_x = 0; _rb_size_y = 0; @@ -1492,6 +1606,21 @@ resolve_multisamples() { nassertv(_fbo.size() > 0); + if (gl_enable_memory_barriers) { + // Issue memory barriers as necessary to make sure that the + // texture memory is synchronized before we blit to it. + pvector::iterator it; + for (it = _texture_contexts.begin(); it != _texture_contexts.end(); ++it) { + CLP(TextureContext) *gtc = *it; + + if (gtc->needs_barrier(GL_FRAMEBUFFER_BARRIER_BIT)) { + glgsg->issue_memory_barrier(GL_FRAMEBUFFER_BARRIER_BIT); + // If we've done it for one, we've done it for all. + break; + } + } + } + glgsg->report_my_gl_errors(); GLuint fbo = _fbo[0]; if (_bound_tex_page != -1) { @@ -1501,31 +1630,34 @@ resolve_multisamples() { glgsg->_glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, _fbo_multisample); // If the depth buffer is shared, resolve it only on the last to render FBO. - int do_depth_blit = 0; - if (_shared_depth_buffer) { - CLP(GraphicsBuffer) *graphics_buffer = NULL; - CLP(GraphicsBuffer) *highest_sort_graphics_buffer = NULL; - list ::iterator graphics_buffer_iterator; - - int max_sort_order = 0; - for (graphics_buffer_iterator = _shared_depth_buffer_list.begin(); - graphics_buffer_iterator != _shared_depth_buffer_list.end(); - graphics_buffer_iterator++) { - graphics_buffer = (*graphics_buffer_iterator); - if (graphics_buffer) { - // this call removes the entry from the list - if ( graphics_buffer->get_sort() >= max_sort_order ) { - max_sort_order = graphics_buffer->get_sort(); - highest_sort_graphics_buffer = graphics_buffer; + bool do_depth_blit = false; + if (_rbm[RTP_depth_stencil] != 0 || _rbm[RTP_depth] != 0) { + if (_shared_depth_buffer) { + CLP(GraphicsBuffer) *graphics_buffer = NULL; + CLP(GraphicsBuffer) *highest_sort_graphics_buffer = NULL; + list ::iterator graphics_buffer_iterator; + + int max_sort_order = 0; + for (graphics_buffer_iterator = _shared_depth_buffer_list.begin(); + graphics_buffer_iterator != _shared_depth_buffer_list.end(); + graphics_buffer_iterator++) { + graphics_buffer = (*graphics_buffer_iterator); + if (graphics_buffer) { + // this call removes the entry from the list + if (graphics_buffer->get_sort() >= max_sort_order) { + max_sort_order = graphics_buffer->get_sort(); + highest_sort_graphics_buffer = graphics_buffer; + } } } + if (max_sort_order == this->get_sort()) { + do_depth_blit = true; + } + } else { + do_depth_blit = true; } - if (max_sort_order == this->get_sort()) { - do_depth_blit = 1; - } - } else { - do_depth_blit = 1; } + if (do_depth_blit) { glgsg->_glBlitFramebuffer(0, 0, _rb_size_x, _rb_size_y, 0, 0, _rb_size_x, _rb_size_y, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, @@ -1535,7 +1667,6 @@ resolve_multisamples() { GL_COLOR_BUFFER_BIT, GL_NEAREST); } -#ifndef OPENGLES // Now handle the other color buffers. int next = GL_COLOR_ATTACHMENT1_EXT; if (_fb_properties.is_stereo()) { @@ -1545,6 +1676,7 @@ resolve_multisamples() { GL_COLOR_BUFFER_BIT, GL_NEAREST); next += 1; } +#ifndef OPENGLES for (int i = 0; i < _fb_properties.get_aux_rgba(); ++i) { glReadBuffer(next); glDrawBuffer(next); diff --git a/panda/src/glstuff/glGraphicsBuffer_src.h b/panda/src/glstuff/glGraphicsBuffer_src.h index 8a161e3e0e..34d9cfa0a4 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.h +++ b/panda/src/glstuff/glGraphicsBuffer_src.h @@ -120,13 +120,15 @@ private: int _rb_size_y; int _rb_size_z; - // The texture or render buffer bound to each plane. - PT(Texture) _tex[RTP_COUNT]; + // Stores the render buffers for each plane. + // _rbm stores the multisample renderbuffers. GLuint _rb[RTP_COUNT]; - - // The render buffer for _fbo_multisample. GLuint _rbm[RTP_COUNT]; + // List of textures for which we might have to generate mipmaps + // after rendering one frame. + pvector _texture_contexts; + // The cube map face we are currently drawing to or have just // finished drawing to, or -1 if we are not drawing to a cube map. int _bound_tex_page; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.I b/panda/src/glstuff/glGraphicsStateGuardian_src.I index 6d33da158b..9008a3cd23 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.I +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.I @@ -27,7 +27,7 @@ INLINE bool CLP(GraphicsStateGuardian):: report_errors(int line, const char *source_file) { #ifndef NDEBUG - GLenum error_code = GLP(GetError)(); + GLenum error_code = glGetError(); if (error_code != GL_NO_ERROR) { int error_count = 0; return report_errors_loop(line, source_file, error_code, error_count); @@ -45,8 +45,8 @@ report_errors(int line, const char *source_file) { INLINE void CLP(GraphicsStateGuardian):: report_my_errors(int line, const char *source_file) { #ifndef NDEBUG - if (_track_errors) { - GLenum error_code = GLP(GetError)(); + if (_check_errors) { + GLenum error_code = glGetError(); if (error_code != GL_NO_ERROR) { if (!report_errors_loop(line, source_file, error_code, _error_count)) { panic_deactivate(); @@ -69,7 +69,7 @@ report_my_errors(int line, const char *source_file) { //////////////////////////////////////////////////////////////////// INLINE bool CLP(GraphicsStateGuardian):: clear_errors(int line, const char *source_file) { - GLenum error_code = GLP(GetError)(); + GLenum error_code = glGetError(); if (error_code != GL_NO_ERROR) { int error_count = 0; return report_errors_loop(line, source_file, error_code, error_count); @@ -83,7 +83,7 @@ clear_errors(int line, const char *source_file) { // Access: Public // Description: This works like report_my_errors(), except that it // always runs, even in the NDEBUG case (but not when -// _track_errors is false), and it never calls +// _check_errors is false), and it never calls // panic_deactivate(). It is designed to be called when // it is important to clear the error stack (for // instance, because we want to be able to reliably @@ -91,8 +91,8 @@ clear_errors(int line, const char *source_file) { //////////////////////////////////////////////////////////////////// INLINE void CLP(GraphicsStateGuardian):: clear_my_errors(int line, const char *source_file) { - if (_track_errors) { - GLenum error_code = GLP(GetError)(); + if (_check_errors) { + GLenum error_code = glGetError(); if (error_code != GL_NO_ERROR) { int error_count = 0; report_errors_loop(line, source_file, error_code, error_count); @@ -161,8 +161,8 @@ get_gl_version_minor() const { INLINE void CLP(GraphicsStateGuardian):: maybe_gl_finish() const { #ifdef DO_PSTATS - if (CLP(finish)) { - GLP(Finish)(); + if (gl_finish) { + glFinish(); } #endif } @@ -231,12 +231,12 @@ enable_multisample_antialias(bool val) { // Turn off antialias multisample. _multisample_mode &= ~MM_antialias; if (_multisample_mode == 0) { - GLP(Disable)(GL_MULTISAMPLE); + glDisable(GL_MULTISAMPLE); } } else if ((_multisample_mode & MM_antialias) == 0 && val) { // Turn on antialias multisample. if (_multisample_mode == 0) { - GLP(Enable)(GL_MULTISAMPLE); + glEnable(GL_MULTISAMPLE); } _multisample_mode |= MM_antialias; } @@ -258,16 +258,16 @@ enable_multisample_alpha_one(bool val) { if ((_multisample_mode & MM_alpha_one) != 0 && !val) { // Turn off sample_alpha_to_one multisample. _multisample_mode &= ~MM_alpha_one; - GLP(Disable)(GL_SAMPLE_ALPHA_TO_ONE); + glDisable(GL_SAMPLE_ALPHA_TO_ONE); if (_multisample_mode == 0) { - GLP(Disable)(GL_MULTISAMPLE); + glDisable(GL_MULTISAMPLE); } } else if ((_multisample_mode & MM_alpha_one) == 0 && val) { // Turn on sample_alpha_to_one multisample. if (_multisample_mode == 0) { - GLP(Enable)(GL_MULTISAMPLE); + glEnable(GL_MULTISAMPLE); } - GLP(Enable)(GL_SAMPLE_ALPHA_TO_ONE); + glEnable(GL_SAMPLE_ALPHA_TO_ONE); _multisample_mode |= MM_alpha_one; } } @@ -288,16 +288,16 @@ enable_multisample_alpha_mask(bool val) { if ((_multisample_mode & MM_alpha_mask) != 0 && !val) { // Turn off sample_alpha_to_mask multisample. _multisample_mode &= ~MM_alpha_mask; - GLP(Disable)(GL_SAMPLE_ALPHA_TO_COVERAGE); + glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); if (_multisample_mode == 0) { - GLP(Disable)(GL_MULTISAMPLE); + glDisable(GL_MULTISAMPLE); } } else if ((_multisample_mode & MM_alpha_mask) == 0 && val) { // Turn on sample_alpha_to_mask multisample. if (_multisample_mode == 0) { - GLP(Enable)(GL_MULTISAMPLE); + glEnable(GL_MULTISAMPLE); } - GLP(Enable)(GL_SAMPLE_ALPHA_TO_COVERAGE); + glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); _multisample_mode |= MM_alpha_mask; } } @@ -316,9 +316,9 @@ enable_line_smooth(bool val) { _state_mask.clear_bit(TransparencyAttrib::get_class_slot()); _line_smooth_enabled = val; if (val) { - GLP(Enable)(GL_LINE_SMOOTH); + glEnable(GL_LINE_SMOOTH); } else { - GLP(Disable)(GL_LINE_SMOOTH); + glDisable(GL_LINE_SMOOTH); } } #endif @@ -336,9 +336,9 @@ enable_point_smooth(bool val) { _state_mask.clear_bit(TransparencyAttrib::get_class_slot()); _point_smooth_enabled = val; if (val) { - GLP(Enable)(GL_POINT_SMOOTH); + glEnable(GL_POINT_SMOOTH); } else { - GLP(Disable)(GL_POINT_SMOOTH); + glDisable(GL_POINT_SMOOTH); } } #endif @@ -355,9 +355,9 @@ enable_polygon_smooth(bool val) { if (_polygon_smooth_enabled != val) { _polygon_smooth_enabled = val; if (val) { - GLP(Enable)(GL_POLYGON_SMOOTH); + glEnable(GL_POLYGON_SMOOTH); } else { - GLP(Disable)(GL_POLYGON_SMOOTH); + glDisable(GL_POLYGON_SMOOTH); } } #endif // OPENGLES @@ -448,13 +448,13 @@ enable_stencil_test(bool val) { GLCAT.spam() << "glEnable(GL_STENCIL_TEST)" << endl; #endif - GLP(Enable)(GL_STENCIL_TEST); + glEnable(GL_STENCIL_TEST); } else { #ifdef GSG_VERBOSE GLCAT.spam() << "glDisable(GL_STENCIL_TEST)" << endl; #endif - GLP(Disable)(GL_STENCIL_TEST); + glDisable(GL_STENCIL_TEST); } } } @@ -473,13 +473,13 @@ enable_blend(bool val) { GLCAT.spam() << "glEnable(GL_BLEND)" << endl; #endif - GLP(Enable)(GL_BLEND); + glEnable(GL_BLEND); } else { #ifdef GSG_VERBOSE GLCAT.spam() << "glDisable(GL_BLEND)" << endl; #endif - GLP(Disable)(GL_BLEND); + glDisable(GL_BLEND); } } } @@ -498,13 +498,13 @@ enable_depth_test(bool val) { GLCAT.spam() << "glEnable(GL_DEPTH_TEST)" << endl; #endif - GLP(Enable)(GL_DEPTH_TEST); + glEnable(GL_DEPTH_TEST); } else { #ifdef GSG_VERBOSE GLCAT.spam() << "glDisable(GL_DEPTH_TEST)" << endl; #endif - GLP(Disable)(GL_DEPTH_TEST); + glDisable(GL_DEPTH_TEST); } } } @@ -524,13 +524,13 @@ enable_fog(bool val) { GLCAT.spam() << "glEnable(GL_FOG)" << endl; #endif - GLP(Enable)(GL_FOG); + glEnable(GL_FOG); } else { #ifdef GSG_VERBOSE GLCAT.spam() << "glDisable(GL_FOG)" << endl; #endif - GLP(Disable)(GL_FOG); + glDisable(GL_FOG); } } #endif @@ -551,13 +551,13 @@ enable_alpha_test(bool val) { GLCAT.spam() << "glEnable(GL_ALPHA_TEST)" << endl; #endif - GLP(Enable)(GL_ALPHA_TEST); + glEnable(GL_ALPHA_TEST); } else { #ifdef GSG_VERBOSE GLCAT.spam() << "glDisable(GL_ALPHA_TEST)" << endl; #endif - GLP(Disable)(GL_ALPHA_TEST); + glDisable(GL_ALPHA_TEST); } } #endif // OPENGLES_2 @@ -578,17 +578,17 @@ enable_polygon_offset(bool val) { GLCAT.spam() << "glEnable(GL_POLYGON_OFFSET_*)" << endl; #endif - GLP(Enable)(GL_POLYGON_OFFSET_FILL); - //GLP(Enable)(GL_POLYGON_OFFSET_LINE); // not widely supported anyway - //GLP(Enable)(GL_POLYGON_OFFSET_POINT); + glEnable(GL_POLYGON_OFFSET_FILL); + //glEnable(GL_POLYGON_OFFSET_LINE); // not widely supported anyway + //glEnable(GL_POLYGON_OFFSET_POINT); } else { #ifdef GSG_VERBOSE GLCAT.spam() << "glDisable(GL_POLYGON_OFFSET_*)" << endl; #endif - GLP(Disable)(GL_POLYGON_OFFSET_FILL); - //GLP(Disable)(GL_POLYGON_OFFSET_LINE); // not widely supported anyway - //GLP(Disable)(GL_POLYGON_OFFSET_POINT); + glDisable(GL_POLYGON_OFFSET_FILL); + //glDisable(GL_POLYGON_OFFSET_LINE); // not widely supported anyway + //glDisable(GL_POLYGON_OFFSET_POINT); } } } @@ -603,10 +603,10 @@ INLINE void CLP(GraphicsStateGuardian):: call_glFogfv(GLenum pname, const LColor &color) { #ifndef OPENGLES_2 #ifndef STDFLOAT_DOUBLE - GLP(Fogfv)(pname, color.get_data()); + glFogfv(pname, color.get_data()); #else // STDFLOAT_DOUBLE LColorf fcolor = LCAST(float, color); - GLP(Fogfv)(pname, fcolor.get_data()); + glFogfv(pname, fcolor.get_data()); #endif // STDFLOAT_DOUBLE #endif } @@ -621,10 +621,10 @@ INLINE void CLP(GraphicsStateGuardian):: call_glMaterialfv(GLenum face, GLenum pname, const LColor &color) { #ifndef OPENGLES_2 #ifndef STDFLOAT_DOUBLE - GLP(Materialfv)(face, pname, color.get_data()); + glMaterialfv(face, pname, color.get_data()); #else // STDFLOAT_DOUBLE LColorf fcolor = LCAST(float, color); - GLP(Materialfv)(face, pname, fcolor.get_data()); + glMaterialfv(face, pname, fcolor.get_data()); #endif // STDFLOAT_DOUBLE #endif } @@ -639,10 +639,10 @@ INLINE void CLP(GraphicsStateGuardian):: call_glLightfv(GLenum light, GLenum pname, const LVecBase4 &value) { #ifndef OPENGLES_2 #ifndef STDFLOAT_DOUBLE - GLP(Lightfv)(light, pname, value.get_data()); + glLightfv(light, pname, value.get_data()); #else // STDFLOAT_DOUBLE LVecBase4f fvalue = LCAST(float, value); - GLP(Lightfv)(light, pname, fvalue.get_data()); + glLightfv(light, pname, fvalue.get_data()); #endif // STDFLOAT_DOUBLE #endif } @@ -657,10 +657,10 @@ INLINE void CLP(GraphicsStateGuardian):: call_glLightfv(GLenum light, GLenum pname, const LVecBase3 &value) { #ifndef OPENGLES_2 #ifndef STDFLOAT_DOUBLE - GLP(Lightfv)(light, pname, value.get_data()); + glLightfv(light, pname, value.get_data()); #else // STDFLOAT_DOUBLE LVecBase3f fvalue = LCAST(float, value); - GLP(Lightfv)(light, pname, fvalue.get_data()); + glLightfv(light, pname, fvalue.get_data()); #endif // STDFLOAT_DOUBLE #endif } @@ -675,10 +675,10 @@ INLINE void CLP(GraphicsStateGuardian):: call_glLightModelfv(GLenum pname, const LVecBase4 &value) { #ifndef OPENGLES_2 #ifndef STDFLOAT_DOUBLE - GLP(LightModelfv)(pname, value.get_data()); + glLightModelfv(pname, value.get_data()); #else // STDFLOAT_DOUBLE LVecBase4f fvalue = LCAST(float, value); - GLP(LightModelfv)(pname, fvalue.get_data()); + glLightModelfv(pname, fvalue.get_data()); #endif // STDFLOAT_DOUBLE #endif // OPENGLES_2 } @@ -693,10 +693,10 @@ INLINE void CLP(GraphicsStateGuardian):: call_glTexEnvfv(GLenum target, GLenum pname, const LVecBase4 &value) { #ifndef OPENGLES_2 #ifndef STDFLOAT_DOUBLE - GLP(TexEnvfv)(target, pname, value.get_data()); + glTexEnvfv(target, pname, value.get_data()); #else // STDFLOAT_DOUBLE LVecBase4f fvalue = LCAST(float, value); - GLP(TexEnvfv)(target, pname, fvalue.get_data()); + glTexEnvfv(target, pname, fvalue.get_data()); #endif // STDFLOAT_DOUBLE #endif } @@ -710,10 +710,10 @@ call_glTexEnvfv(GLenum target, GLenum pname, const LVecBase4 &value) { INLINE void CLP(GraphicsStateGuardian):: call_glTexParameterfv(GLenum target, GLenum pname, const LVecBase4 &value) { #ifndef STDFLOAT_DOUBLE - GLP(TexParameterfv)(target, pname, value.get_data()); + glTexParameterfv(target, pname, value.get_data()); #else // STDFLOAT_DOUBLE LVecBase4f fvalue = LCAST(float, value); - GLP(TexParameterfv)(target, pname, fvalue.get_data()); + glTexParameterfv(target, pname, fvalue.get_data()); #endif // STDFLOAT_DOUBLE } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index de1a653b1a..6aed4d7335 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -77,6 +77,7 @@ PStatCollector CLP(GraphicsStateGuardian)::_load_display_list_pcollector("Draw:T PStatCollector CLP(GraphicsStateGuardian)::_primitive_batches_display_list_pcollector("Primitive batches:Display lists"); PStatCollector CLP(GraphicsStateGuardian)::_vertices_display_list_pcollector("Vertices:Display lists"); PStatCollector CLP(GraphicsStateGuardian)::_vertices_immediate_pcollector("Vertices:Immediate mode"); +PStatCollector CLP(GraphicsStateGuardian)::_compute_dispatch_pcollector("Draw:Compute dispatch"); #ifdef OPENGLES_2 PT(Shader) CLP(GraphicsStateGuardian)::_default_shader = NULL; @@ -96,7 +97,7 @@ null_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) { // If we don't support glDrawRangeElements(), just use the original // glDrawElements() instead. - GLP(DrawElements)(mode, count, type, indices); + glDrawElements(mode, count, type, indices); } static void APIENTRY @@ -305,12 +306,12 @@ CLP(GraphicsStateGuardian)(GraphicsEngine *engine, GraphicsPipe *pipe) : // the window tells us otherwise. _is_hardware = true; - // calling glGetError() forces a sync, this turns it off if you want to. - _track_errors = !CLP(force_no_error); - _allow_flush = !CLP(force_no_flush); + // calling glGetError() forces a sync, this turns it on if you want to. + _check_errors = gl_check_errors; + _force_flush = gl_force_flush; #ifdef DO_PSTATS - if (CLP(finish)) { + if (gl_finish) { GLCAT.warning() << "The config variable gl-finish is set True. This may have a substantial negative impact your render performance.\n"; } @@ -337,6 +338,51 @@ CLP(GraphicsStateGuardian):: } } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::debug_callback +// Access: Public, Static +// Description: This is called by the GL if an error occurs, if +// gl_debug has been enabled (and the driver supports +// the GL_ARB_debug_output extension). +//////////////////////////////////////////////////////////////////// +#ifndef OPENGLES_1 +void CLP(GraphicsStateGuardian):: +debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam) { + // Determine how to map the severity level. + NotifySeverity level; + switch (severity) { + case GL_DEBUG_SEVERITY_HIGH: + level = NS_error; + break; + + case GL_DEBUG_SEVERITY_MEDIUM: + level = NS_warning; + break; + + case GL_DEBUG_SEVERITY_LOW: + level = NS_info; + break; + + case GL_DEBUG_SEVERITY_NOTIFICATION: + level = NS_debug; + break; + + default: + level = NS_fatal; //??? + break; + } + + string msg_str(message, length); + GLCAT.out(level) << msg_str << "\n"; + +#ifndef NDEBUG + if (level >= gl_debug_abort_level.get_value()) { + abort(); + } +#endif +} +#endif // OPENGLES_1 + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::reset // Access: Public, Virtual @@ -386,10 +432,72 @@ reset() { } // Save the extensions tokens. - save_extensions((const char *)GLP(GetString)(GL_EXTENSIONS)); + _extensions.clear(); + save_extensions((const char *)glGetString(GL_EXTENSIONS)); get_extra_extensions(); report_extensions(); + // Initialize OpenGL debugging output first, if enabled and supported. + _supports_debug = false; +#ifndef OPENGLES_1 + if (gl_debug) { + PFNGLDEBUGMESSAGECALLBACKPROC _glDebugMessageCallback; + PFNGLDEBUGMESSAGECONTROLPROC _glDebugMessageControl; + + if (is_at_least_gl_version(4, 3) || has_extension("GL_KHR_debug")) { +#ifdef OPENGLES + _glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) + get_extension_func("glDebugMessageCallbackKHR"); + _glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) + get_extension_func("glDebugMessageControlKHR"); +#else + _glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) + get_extension_func("glDebugMessageCallback"); + _glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) + get_extension_func("glDebugMessageControl"); +#endif + glEnable(GL_DEBUG_OUTPUT); // Not supported in ARB version + _supports_debug = true; + + } else if (has_extension("GL_ARB_debug_output")) { + _glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) + get_extension_func("glDebugMessageCallbackARB"); + _glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) + get_extension_func("glDebugMessageControlARB"); + _supports_debug = true; + } + + if (_supports_debug) { + // Set the categories we want to listen to. + _glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, + 0, NULL, GLCAT.is_error()); + _glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, + 0, NULL, GLCAT.is_warning()); + _glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, + 0, NULL, GLCAT.is_info()); + _glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, + 0, NULL, GLCAT.is_debug()); + + // Enable the callback. + _glDebugMessageCallback((GLDEBUGPROC) &debug_callback, (void*)this); + if (gl_debug_synchronous) { + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + } + + GLCAT.debug() << "gl-debug enabled.\n"; + } else { + GLCAT.debug() << "gl-debug enabled, but NOT supported.\n"; + } + } else { + GLCAT.debug() << "gl-debug NOT enabled.\n"; + + // However, still check if it is supported. + _supports_debug = is_at_least_gl_version(4, 3) + || has_extension("GL_KHR_debug") + || has_extension("GL_ARB_debug_output"); + } +#endif // OPENGLES_1 + _supported_geom_rendering = Geom::GR_indexed_point | Geom::GR_point | Geom::GR_point_uniform_size | @@ -402,12 +510,12 @@ reset() { if (is_at_least_gl_version(1, 4)) { _supports_point_parameters = true; _glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) - get_extension_func(GLPREFIX_QUOTED, "PointParameterfv"); + get_extension_func("glPointParameterfv"); } else if (has_extension("GL_ARB_point_parameters")) { _supports_point_parameters = true; _glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) - get_extension_func(GLPREFIX_QUOTED, "PointParameterfvARB"); + get_extension_func("glPointParameterfvARB"); } if (_supports_point_parameters) { if (_glPointParameterfv == NULL) { @@ -435,13 +543,13 @@ reset() { if (_supports_vertex_blend) { _glWeightPointer = (PFNGLWEIGHTPOINTERARBPROC) - get_extension_func(GLPREFIX_QUOTED, "WeightPointerARB"); + get_extension_func("glWeightPointerARB"); _glVertexBlend = (PFNGLVERTEXBLENDARBPROC) - get_extension_func(GLPREFIX_QUOTED, "VertexBlendARB"); + get_extension_func("glVertexBlendARB"); _glWeightfv = (PFNGLWEIGHTFVARBPROC) - get_extension_func(GLPREFIX_QUOTED, "WeightfvARB"); + get_extension_func("glWeightfvARB"); _glWeightdv = (PFNGLWEIGHTDVARBPROC) - get_extension_func(GLPREFIX_QUOTED, "WeightdvARB"); + get_extension_func("glWeightdvARB"); if (_glWeightPointer == NULL || _glVertexBlend == NULL || GLfv(_glWeight) == NULL) { @@ -453,10 +561,10 @@ reset() { #ifndef OPENGLES if (_supports_vertex_blend) { - GLP(Enable)(GL_WEIGHT_SUM_UNITY_ARB); + glEnable(GL_WEIGHT_SUM_UNITY_ARB); GLint max_vertex_units = 0; - GLP(GetIntegerv)(GL_MAX_VERTEX_UNITS_ARB, &max_vertex_units); + glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &max_vertex_units); _max_vertex_transforms = max_vertex_units; if (GLCAT.is_debug()) { GLCAT.debug() @@ -470,11 +578,11 @@ reset() { if (has_extension("GL_ARB_matrix_palette")) { _supports_matrix_palette = true; _glCurrentPaletteMatrix = (PFNGLCURRENTPALETTEMATRIXARBPROC) - get_extension_func(GLPREFIX_QUOTED, "CurrentPaletteMatrixARB"); + get_extension_func("glCurrentPaletteMatrixARB"); _glMatrixIndexPointer = (PFNGLMATRIXINDEXPOINTERARBPROC) - get_extension_func(GLPREFIX_QUOTED, "MatrixIndexPointerARB"); + get_extension_func("glMatrixIndexPointerARB"); _glMatrixIndexuiv = (PFNGLMATRIXINDEXUIVARBPROC) - get_extension_func(GLPREFIX_QUOTED, "MatrixIndexuivARB"); + get_extension_func("glMatrixIndexuivARB"); if (_glCurrentPaletteMatrix == NULL || _glMatrixIndexPointer == NULL || @@ -488,9 +596,9 @@ reset() { if (has_extension("GL_OES_matrix_palette")) { _supports_matrix_palette = true; _glCurrentPaletteMatrix = (PFNGLCURRENTPALETTEMATRIXOESPROC) - get_extension_func(GLPREFIX_QUOTED, "CurrentPaletteMatrixOES"); + get_extension_func("glCurrentPaletteMatrixOES"); _glMatrixIndexPointer = (PFNGLMATRIXINDEXPOINTEROESPROC) - get_extension_func(GLPREFIX_QUOTED, "MatrixIndexPointerOES"); + get_extension_func("glMatrixIndexPointerOES"); if (_glCurrentPaletteMatrix == NULL || _glMatrixIndexPointer == NULL) { @@ -510,7 +618,7 @@ reset() { In the meantime, you must put both "matrix-palette 1" and "gl-matrix-palette 1" in your Config.prc to exercise the new code. */ - if (!CLP(matrix_palette)) { + if (!gl_matrix_palette) { if (_supports_matrix_palette) { if (GLCAT.is_debug()) { GLCAT.debug() << "Forcing off matrix palette support.\n"; @@ -522,10 +630,10 @@ reset() { if (_supports_matrix_palette) { GLint max_palette_matrices = 0; #ifdef OPENGLES_1 - GLP(GetIntegerv)(GL_MAX_PALETTE_MATRICES_OES, &max_palette_matrices); + glGetIntegerv(GL_MAX_PALETTE_MATRICES_OES, &max_palette_matrices); #endif #ifndef OPENGLES - GLP(GetIntegerv)(GL_MAX_PALETTE_MATRICES_ARB, &max_palette_matrices); + glGetIntegerv(GL_MAX_PALETTE_MATRICES_ARB, &max_palette_matrices); #endif _max_vertex_transform_indices = max_palette_matrices; if (GLCAT.is_debug()) { @@ -539,12 +647,12 @@ reset() { if (is_at_least_gl_version(1, 2)) { _supports_draw_range_elements = true; _glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) - get_extension_func(GLPREFIX_QUOTED, "DrawRangeElements"); + get_extension_func("glDrawRangeElements"); } else if (has_extension("GL_EXT_draw_range_elements")) { _supports_draw_range_elements = true; _glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) - get_extension_func(GLPREFIX_QUOTED, "DrawRangeElementsEXT"); + get_extension_func("glDrawRangeElementsEXT"); } if (_supports_draw_range_elements) { if (_glDrawRangeElements == NULL) { @@ -571,46 +679,46 @@ reset() { _supports_depth_stencil = has_extension("GL_EXT_packed_depth_stencil") || has_extension("GL_OES_packed_depth_stencil"); } - + _supports_3d_texture = false; if (is_at_least_gl_version(1, 2)) { _supports_3d_texture = true; _glTexImage3D = (PFNGLTEXIMAGE3DPROC_P) - get_extension_func(GLPREFIX_QUOTED, "TexImage3D"); + get_extension_func("glTexImage3D"); _glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) - get_extension_func(GLPREFIX_QUOTED, "TexSubImage3D"); + get_extension_func("glTexSubImage3D"); _glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) - get_extension_func(GLPREFIX_QUOTED, "CopyTexSubImage3D"); + get_extension_func("glCopyTexSubImage3D"); } else if (has_extension("GL_EXT_texture3D")) { _supports_3d_texture = true; _glTexImage3D = (PFNGLTEXIMAGE3DPROC_P) - get_extension_func(GLPREFIX_QUOTED, "TexImage3DEXT"); + get_extension_func("glTexImage3DEXT"); _glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) - get_extension_func(GLPREFIX_QUOTED, "TexSubImage3DEXT"); + get_extension_func("glTexSubImage3DEXT"); _glCopyTexSubImage3D = NULL; if (has_extension("GL_EXT_copy_texture")) { _glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) - get_extension_func(GLPREFIX_QUOTED, "CopyTexSubImage3DEXT"); + get_extension_func("glCopyTexSubImage3DEXT"); } } else if (has_extension("GL_OES_texture_3D")) { _supports_3d_texture = true; _glTexImage3D = (PFNGLTEXIMAGE3DPROC_P) - get_extension_func(GLPREFIX_QUOTED, "TexImage3DOES"); + get_extension_func("glTexImage3DOES"); _glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) - get_extension_func(GLPREFIX_QUOTED, "TexSubImage3DOES"); + get_extension_func("glTexSubImage3DOES"); _glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) - get_extension_func(GLPREFIX_QUOTED, "CopyTexSubImage3DOES"); + get_extension_func("glCopyTexSubImage3DOES"); #ifdef OPENGLES_2 _glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DOES) - get_extension_func(GLPREFIX_QUOTED, "FramebufferTexture3DOES"); + get_extension_func("glFramebufferTexture3DOES"); #endif } @@ -622,12 +730,44 @@ reset() { } } + _supports_tex_storage = false; + + if (is_at_least_gl_version(4, 2) || has_extension("GL_ARB_texture_storage")) { + _supports_tex_storage = true; + + _glTexStorage1D = (PFNGLTEXSTORAGE1DPROC) + get_extension_func("glTexStorage1D"); + _glTexStorage2D = (PFNGLTEXSTORAGE2DPROC) + get_extension_func("glTexStorage2D"); + _glTexStorage3D = (PFNGLTEXSTORAGE3DPROC) + get_extension_func("glTexStorage3D"); + + } else if (has_extension("GL_EXT_texture_storage")) { // GLES case + _supports_tex_storage = true; + + _glTexStorage1D = (PFNGLTEXSTORAGE1DPROC) + get_extension_func("glTexStorage1DEXT"); + _glTexStorage2D = (PFNGLTEXSTORAGE2DPROC) + get_extension_func("glTexStorage2DEXT"); + _glTexStorage3D = (PFNGLTEXSTORAGE3DPROC) + get_extension_func("glTexStorage3DEXT"); + } + + if (_supports_tex_storage) { + if (_glTexStorage1D == NULL || _glTexStorage2D == NULL || _glTexStorage3D == NULL) { + GLCAT.warning() + << "Immutable texture storage advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n"; + _supports_tex_storage = false; + } + } + + _supports_2d_texture_array = false; #ifndef OPENGLES _supports_2d_texture_array = has_extension("GL_EXT_texture_array"); if (_supports_2d_texture_array) { _glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) - get_extension_func(GLPREFIX_QUOTED, "FramebufferTextureLayerEXT"); + get_extension_func("glFramebufferTextureLayerEXT"); } else { // ARB_geometry_shader4 also provides a version. _glFramebufferTextureLayer = NULL; @@ -642,6 +782,14 @@ reset() { has_extension("GL_OES_texture_cube_map"); #endif +#ifndef OPENGLES + if (_supports_cube_map && gl_cube_map_seamless) { + if (is_at_least_gl_version(3, 2) || has_extension("GL_ARB_seamless_cube_map")) { + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + } + } +#endif + _supports_compressed_texture = false; #ifdef OPENGLES @@ -659,9 +807,9 @@ reset() { #ifdef OPENGLES_2 if (_supports_3d_texture) { _glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexImage3DOES"); + get_extension_func("glCompressedTexImage3DOES"); _glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexSubImageOES"); + get_extension_func("glCompressedTexSubImageOES"); } #endif @@ -670,37 +818,37 @@ reset() { _supports_compressed_texture = true; _glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexImage1D"); + get_extension_func("glCompressedTexImage1D"); _glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexImage2D"); + get_extension_func("glCompressedTexImage2D"); _glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexImage3D"); + get_extension_func("glCompressedTexImage3D"); _glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexSubImage1D"); + get_extension_func("glCompressedTexSubImage1D"); _glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexSubImage2D"); + get_extension_func("glCompressedTexSubImage2D"); _glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexSubImage3D"); + get_extension_func("glCompressedTexSubImage3D"); _glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) - get_extension_func(GLPREFIX_QUOTED, "GetCompressedTexImage"); + get_extension_func("glGetCompressedTexImage"); } else if (has_extension("GL_ARB_texture_compression")) { _supports_compressed_texture = true; _glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexImage1DARB"); + get_extension_func("glCompressedTexImage1DARB"); _glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexImage2DARB"); + get_extension_func("glCompressedTexImage2DARB"); _glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexImage3DARB"); + get_extension_func("glCompressedTexImage3DARB"); _glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexSubImage1DARB"); + get_extension_func("glCompressedTexSubImage1DARB"); _glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexSubImage2DARB"); + get_extension_func("glCompressedTexSubImage2DARB"); _glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) - get_extension_func(GLPREFIX_QUOTED, "CompressedTexSubImage3DARB"); + get_extension_func("glCompressedTexSubImage3DARB"); _glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) - get_extension_func(GLPREFIX_QUOTED, "GetCompressedTexImageARB"); + get_extension_func("glGetCompressedTexImageARB"); } if (_supports_compressed_texture) { @@ -724,9 +872,9 @@ reset() { #endif GLint num_compressed_formats = 0; - GLP(GetIntegerv)(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_formats); + glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_formats); GLint *formats = (GLint *)PANDA_MALLOC_ARRAY(num_compressed_formats * sizeof(GLint)); - GLP(GetIntegerv)(GL_COMPRESSED_TEXTURE_FORMATS, formats); + glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats); for (int i = 0; i < num_compressed_formats; ++i) { switch (formats[i]) { #ifndef OPENGLES_1 @@ -777,10 +925,13 @@ reset() { _supports_rescale_normal = true; #else _supports_rescale_normal = - CLP(support_rescale_normal) && + gl_support_rescale_normal && (has_extension("GL_EXT_rescale_normal") || is_at_least_gl_version(1, 2)); #endif + _supports_packed_dabc = /*gl_support_packed_dabc &&*/ + has_extension("GL_ARB_vertex_array_bgra") || has_extension("GL_EXT_vertex_array_bgra"); + _supports_multisample = has_extension("GL_ARB_multisample") || is_at_least_gl_version(1, 3); @@ -793,11 +944,6 @@ reset() { _supports_multitexture = false; - _supports_mesa_6 = false; - if (_gl_version.find("Mesa 6.",0) != string::npos) { - _supports_mesa_6 = true; - } - #ifdef OPENGLES _supports_tex_non_pow2 = has_extension("GL_OES_texture_npot"); @@ -813,49 +959,49 @@ reset() { _supports_multitexture = true; _glActiveTexture = (PFNGLACTIVETEXTUREPROC) - get_extension_func(GLPREFIX_QUOTED, "ActiveTexture"); + get_extension_func("glActiveTexture"); _glClientActiveTexture = (PFNGLACTIVETEXTUREPROC) - get_extension_func(GLPREFIX_QUOTED, "ClientActiveTexture"); + get_extension_func("glClientActiveTexture"); _glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord1f"); + get_extension_func("glMultiTexCoord1f"); _glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord2f"); + get_extension_func("glMultiTexCoord2f"); _glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord3f"); + get_extension_func("glMultiTexCoord3f"); _glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord4f"); + get_extension_func("glMultiTexCoord4f"); _glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord1d"); + get_extension_func("glMultiTexCoord1d"); _glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord2d"); + get_extension_func("glMultiTexCoord2d"); _glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord3d"); + get_extension_func("glMultiTexCoord3d"); _glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord4d"); + get_extension_func("glMultiTexCoord4d"); } else if (has_extension("GL_ARB_multitexture")) { _supports_multitexture = true; _glActiveTexture = (PFNGLACTIVETEXTUREPROC) - get_extension_func(GLPREFIX_QUOTED, "ActiveTextureARB"); + get_extension_func("glActiveTextureARB"); _glClientActiveTexture = (PFNGLACTIVETEXTUREPROC) - get_extension_func(GLPREFIX_QUOTED, "ClientActiveTextureARB"); + get_extension_func("glClientActiveTextureARB"); _glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord1fARB"); + get_extension_func("glMultiTexCoord1fARB"); _glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord2fARB"); + get_extension_func("glMultiTexCoord2fARB"); _glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord3fARB"); + get_extension_func("glMultiTexCoord3fARB"); _glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord4fARB"); + get_extension_func("glMultiTexCoord4fARB"); _glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord1dARB"); + get_extension_func("glMultiTexCoord1dARB"); _glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord2dARB"); + get_extension_func("glMultiTexCoord2dARB"); _glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord3dARB"); + get_extension_func("glMultiTexCoord3dARB"); _glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC) - get_extension_func(GLPREFIX_QUOTED, "MultiTexCoord4dARB"); + get_extension_func("glMultiTexCoord4dARB"); } if (_supports_multitexture) { @@ -904,29 +1050,29 @@ reset() { _supports_buffers = true; _glGenBuffers = (PFNGLGENBUFFERSPROC) - get_extension_func(GLPREFIX_QUOTED, "GenBuffers"); + get_extension_func("glGenBuffers"); _glBindBuffer = (PFNGLBINDBUFFERPROC) - get_extension_func(GLPREFIX_QUOTED, "BindBuffer"); + get_extension_func("glBindBuffer"); _glBufferData = (PFNGLBUFFERDATAPROC) - get_extension_func(GLPREFIX_QUOTED, "BufferData"); + get_extension_func("glBufferData"); _glBufferSubData = (PFNGLBUFFERSUBDATAPROC) - get_extension_func(GLPREFIX_QUOTED, "BufferSubData"); + get_extension_func("glBufferSubData"); _glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) - get_extension_func(GLPREFIX_QUOTED, "DeleteBuffers"); + get_extension_func("glDeleteBuffers"); } else if (has_extension("GL_ARB_vertex_buffer_object")) { _supports_buffers = true; _glGenBuffers = (PFNGLGENBUFFERSPROC) - get_extension_func(GLPREFIX_QUOTED, "GenBuffersARB"); + get_extension_func("glGenBuffersARB"); _glBindBuffer = (PFNGLBINDBUFFERPROC) - get_extension_func(GLPREFIX_QUOTED, "BindBufferARB"); + get_extension_func("glBindBufferARB"); _glBufferData = (PFNGLBUFFERDATAPROC) - get_extension_func(GLPREFIX_QUOTED, "BufferDataARB"); + get_extension_func("glBufferDataARB"); _glBufferSubData = (PFNGLBUFFERSUBDATAPROC) - get_extension_func(GLPREFIX_QUOTED, "BufferSubDataARB"); + get_extension_func("glBufferSubDataARB"); _glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) - get_extension_func(GLPREFIX_QUOTED, "DeleteBuffersARB"); + get_extension_func("glDeleteBuffersARB"); } if (_supports_buffers) { @@ -977,7 +1123,7 @@ reset() { _shader_caps._ultimate_gprofile = (int)CG_PROFILE_GPU_GP; _glBindProgram = (PFNGLBINDPROGRAMARBPROC) - get_extension_func(GLPREFIX_QUOTED, "BindProgramARB"); + get_extension_func("glBindProgramARB"); // Bug workaround for radeons. if (_shader_caps._active_fprofile == CG_PROFILE_ARBFP1) { @@ -991,10 +1137,12 @@ reset() { #ifdef OPENGLES_2 _supports_glsl = true; + _supports_geometry_shaders = false; _supports_tessellation_shaders = false; #else #ifdef OPENGLES_1 _supports_glsl = false; + _supports_geometry_shaders = false; _supports_tessellation_shaders = false; #else _supports_glsl = is_at_least_gl_version(2, 0) || has_extension("GL_ARB_shading_language_100"); @@ -1004,85 +1152,109 @@ reset() { #endif _shader_caps._supports_glsl = _supports_glsl; + _supports_compute_shaders = false; +#ifndef OPENGLES + if (is_at_least_gl_version(4, 3) || has_extension("GL_ARB_compute_shader")) { + _glDispatchCompute = (PFNGLDISPATCHCOMPUTEPROC) + get_extension_func("glDispatchCompute"); + + if (_glDispatchCompute != NULL) { + _supports_compute_shaders = true; + } + } +#endif + #ifndef OPENGLES if (_supports_glsl) { _glAttachShader = (PFNGLATTACHSHADERPROC) - get_extension_func(GLPREFIX_QUOTED, "AttachShader"); + get_extension_func("glAttachShader"); _glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) - get_extension_func(GLPREFIX_QUOTED, "BindAttribLocation"); + get_extension_func("glBindAttribLocation"); _glCompileShader = (PFNGLCOMPILESHADERPROC) - get_extension_func(GLPREFIX_QUOTED, "CompileShader"); + get_extension_func("glCompileShader"); _glCreateProgram = (PFNGLCREATEPROGRAMPROC) - get_extension_func(GLPREFIX_QUOTED, "CreateProgram"); + get_extension_func("glCreateProgram"); _glCreateShader = (PFNGLCREATESHADERPROC) - get_extension_func(GLPREFIX_QUOTED, "CreateShader"); + get_extension_func("glCreateShader"); _glDeleteProgram = (PFNGLDELETEPROGRAMPROC) - get_extension_func(GLPREFIX_QUOTED, "DeleteProgram"); + get_extension_func("glDeleteProgram"); _glDeleteShader = (PFNGLDELETESHADERPROC) - get_extension_func(GLPREFIX_QUOTED, "DeleteShader"); + get_extension_func("glDeleteShader"); _glDetachShader = (PFNGLDETACHSHADERPROC) - get_extension_func(GLPREFIX_QUOTED, "DetachShader"); + get_extension_func("glDetachShader"); _glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) - get_extension_func(GLPREFIX_QUOTED, "DisableVertexAttribArray"); + get_extension_func("glDisableVertexAttribArray"); _glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) - get_extension_func(GLPREFIX_QUOTED, "EnableVertexAttribArray"); + get_extension_func("glEnableVertexAttribArray"); _glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) - get_extension_func(GLPREFIX_QUOTED, "GetActiveAttrib"); + get_extension_func("glGetActiveAttrib"); _glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) - get_extension_func(GLPREFIX_QUOTED, "GetActiveUniform"); + get_extension_func("glGetActiveUniform"); _glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) - get_extension_func(GLPREFIX_QUOTED, "GetAttribLocation"); + get_extension_func("glGetAttribLocation"); _glGetProgramiv = (PFNGLGETPROGRAMIVPROC) - get_extension_func(GLPREFIX_QUOTED, "GetProgramiv"); + get_extension_func("glGetProgramiv"); _glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) - get_extension_func(GLPREFIX_QUOTED, "GetProgramInfoLog"); + get_extension_func("glGetProgramInfoLog"); _glGetShaderiv = (PFNGLGETSHADERIVPROC) - get_extension_func(GLPREFIX_QUOTED, "GetShaderiv"); + get_extension_func("glGetShaderiv"); _glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) - get_extension_func(GLPREFIX_QUOTED, "GetShaderInfoLog"); + get_extension_func("glGetShaderInfoLog"); _glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) - get_extension_func(GLPREFIX_QUOTED, "GetUniformLocation"); + get_extension_func("glGetUniformLocation"); _glLinkProgram = (PFNGLLINKPROGRAMPROC) - get_extension_func(GLPREFIX_QUOTED, "LinkProgram"); + get_extension_func("glLinkProgram"); _glShaderSource = (PFNGLSHADERSOURCEPROC_P) - get_extension_func(GLPREFIX_QUOTED, "ShaderSource"); + get_extension_func("glShaderSource"); _glUseProgram = (PFNGLUSEPROGRAMPROC) - get_extension_func(GLPREFIX_QUOTED, "UseProgram"); + get_extension_func("glUseProgram"); _glUniform4f = (PFNGLUNIFORM4FPROC) - get_extension_func(GLPREFIX_QUOTED, "Uniform4f"); + get_extension_func("glUniform4f"); _glUniform1i = (PFNGLUNIFORM1IPROC) - get_extension_func(GLPREFIX_QUOTED, "Uniform1i"); + get_extension_func("glUniform1i"); _glUniform1fv = (PFNGLUNIFORM1FVPROC) - get_extension_func(GLPREFIX_QUOTED, "Uniform1fv"); + get_extension_func("glUniform1fv"); _glUniform2fv = (PFNGLUNIFORM2FVPROC) - get_extension_func(GLPREFIX_QUOTED, "Uniform2fv"); + get_extension_func("glUniform2fv"); _glUniform3fv = (PFNGLUNIFORM3FVPROC) - get_extension_func(GLPREFIX_QUOTED, "Uniform3fv"); + get_extension_func("glUniform3fv"); _glUniform4fv = (PFNGLUNIFORM4FVPROC) - get_extension_func(GLPREFIX_QUOTED, "Uniform4fv"); + get_extension_func("glUniform4fv"); + _glUniform1iv = (PFNGLUNIFORM1IVPROC) + get_extension_func("glUniform1iv"); + _glUniform2iv = (PFNGLUNIFORM2IVPROC) + get_extension_func("glUniform2iv"); + _glUniform3iv = (PFNGLUNIFORM3IVPROC) + get_extension_func("glUniform3iv"); + _glUniform4iv = (PFNGLUNIFORM4IVPROC) + get_extension_func("glUniform4iv"); _glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) - get_extension_func(GLPREFIX_QUOTED, "UniformMatrix3fv"); + get_extension_func("glUniformMatrix3fv"); _glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) - get_extension_func(GLPREFIX_QUOTED, "UniformMatrix4fv"); + get_extension_func("glUniformMatrix4fv"); _glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) - get_extension_func(GLPREFIX_QUOTED, "ValidateProgram"); + get_extension_func("glValidateProgram"); _glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) - get_extension_func(GLPREFIX_QUOTED, "VertexAttribPointer"); + get_extension_func("glVertexAttribPointer"); + _glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) + get_extension_func("glVertexAttribIPointer"); + _glVertexAttribLPointer = (PFNGLVERTEXATTRIBLPOINTERPROC) + get_extension_func("glVertexAttribLPointer"); if (_supports_geometry_shaders) { _glProgramParameteri = (PFNGLPROGRAMPARAMETERIPROC) - get_extension_func(GLPREFIX_QUOTED, "ProgramParameteri"); + get_extension_func("glProgramParameteri"); _glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREARBPROC) - get_extension_func(GLPREFIX_QUOTED, "FramebufferTextureARB"); + get_extension_func("glFramebufferTextureARB"); if (_glFramebufferTextureLayer == NULL) { _glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) - get_extension_func(GLPREFIX_QUOTED, "FramebufferTextureLayerARB"); + get_extension_func("glFramebufferTextureLayerARB"); } } if (_supports_tessellation_shaders) { _glPatchParameteri = (PFNGLPATCHPARAMETERIPROC) - get_extension_func(GLPREFIX_QUOTED, "PatchParameteri"); + get_extension_func("glPatchParameteri"); } } #endif @@ -1119,6 +1291,8 @@ reset() { _glUniformMatrix4fv = glUniformMatrix4fv; _glValidateProgram = glValidateProgram; _glVertexAttribPointer = glVertexAttribPointer; + _glVertexAttribIPointer = NULL; + _glVertexAttribLPointer = NULL; // We need to have a default shader to apply in case // something didn't happen to have a shader applied, or @@ -1149,78 +1323,80 @@ reset() { _glGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv; _glGenerateMipmap = glGenerateMipmap; #else + //TODO: add ARB/3.0 version + _supports_framebuffer_object = false; if (has_extension("GL_EXT_framebuffer_object")) { _supports_framebuffer_object = true; _glIsRenderbuffer = (PFNGLISRENDERBUFFEREXTPROC) - get_extension_func(GLPREFIX_QUOTED, "IsRenderbufferEXT"); + get_extension_func("glIsRenderbufferEXT"); _glBindRenderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC) - get_extension_func(GLPREFIX_QUOTED, "BindRenderbufferEXT"); + get_extension_func("glBindRenderbufferEXT"); _glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "DeleteRenderbuffersEXT"); + get_extension_func("glDeleteRenderbuffersEXT"); _glGenRenderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "GenRenderbuffersEXT"); + get_extension_func("glGenRenderbuffersEXT"); _glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "RenderbufferStorageEXT"); + get_extension_func("glRenderbufferStorageEXT"); _glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "GetRenderbufferParameterivEXT"); + get_extension_func("glGetRenderbufferParameterivEXT"); _glIsFramebuffer = (PFNGLISFRAMEBUFFEREXTPROC) - get_extension_func(GLPREFIX_QUOTED, "IsFramebufferEXT"); + get_extension_func("glIsFramebufferEXT"); _glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC) - get_extension_func(GLPREFIX_QUOTED, "BindFramebufferEXT"); + get_extension_func("glBindFramebufferEXT"); _glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "DeleteFramebuffersEXT"); + get_extension_func("glDeleteFramebuffersEXT"); _glGenFramebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "GenFramebuffersEXT"); + get_extension_func("glGenFramebuffersEXT"); _glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "CheckFramebufferStatusEXT"); + get_extension_func("glCheckFramebufferStatusEXT"); _glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "FramebufferTexture1DEXT"); + get_extension_func("glFramebufferTexture1DEXT"); _glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "FramebufferTexture2DEXT"); + get_extension_func("glFramebufferTexture2DEXT"); _glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "FramebufferTexture3DEXT"); + get_extension_func("glFramebufferTexture3DEXT"); _glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) - get_extension_func(GLPREFIX_QUOTED, "FramebufferRenderbufferEXT"); + get_extension_func("glFramebufferRenderbufferEXT"); _glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "GetFramebufferAttachmentParameterivEXT"); + get_extension_func("glGetFramebufferAttachmentParameterivEXT"); _glGenerateMipmap = (PFNGLGENERATEMIPMAPEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "GenerateMipmapEXT"); + get_extension_func("glGenerateMipmapEXT"); } #ifdef OPENGLES else if (has_extension("GL_OES_framebuffer_object")) { _supports_framebuffer_object = true; _glIsRenderbuffer = (PFNGLISRENDERBUFFEROESPROC) - get_extension_func(GLPREFIX_QUOTED, "IsRenderbufferOES"); + get_extension_func("glIsRenderbufferOES"); _glBindRenderbuffer = (PFNGLBINDRENDERBUFFEROESPROC) - get_extension_func(GLPREFIX_QUOTED, "BindRenderbufferOES"); + get_extension_func("glBindRenderbufferOES"); _glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSOESPROC) - get_extension_func(GLPREFIX_QUOTED, "DeleteRenderbuffersOES"); + get_extension_func("glDeleteRenderbuffersOES"); _glGenRenderbuffers = (PFNGLGENRENDERBUFFERSOESPROC) - get_extension_func(GLPREFIX_QUOTED, "GenRenderbuffersOES"); + get_extension_func("glGenRenderbuffersOES"); _glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEOESPROC) - get_extension_func(GLPREFIX_QUOTED, "RenderbufferStorageOES"); + get_extension_func("glRenderbufferStorageOES"); _glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVOESPROC) - get_extension_func(GLPREFIX_QUOTED, "GetRenderbufferParameterivOES"); + get_extension_func("glGetRenderbufferParameterivOES"); _glIsFramebuffer = (PFNGLISFRAMEBUFFEROESPROC) - get_extension_func(GLPREFIX_QUOTED, "IsFramebufferOES"); + get_extension_func("glIsFramebufferOES"); _glBindFramebuffer = (PFNGLBINDFRAMEBUFFEROESPROC) - get_extension_func(GLPREFIX_QUOTED, "BindFramebufferOES"); + get_extension_func("glBindFramebufferOES"); _glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSOESPROC) - get_extension_func(GLPREFIX_QUOTED, "DeleteFramebuffersOES"); + get_extension_func("glDeleteFramebuffersOES"); _glGenFramebuffers = (PFNGLGENFRAMEBUFFERSOESPROC) - get_extension_func(GLPREFIX_QUOTED, "GenFramebuffersOES"); + get_extension_func("glGenFramebuffersOES"); _glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSOESPROC) - get_extension_func(GLPREFIX_QUOTED, "CheckFramebufferStatusOES"); + get_extension_func("glCheckFramebufferStatusOES"); _glFramebufferTexture1D = NULL; _glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DOESPROC) - get_extension_func(GLPREFIX_QUOTED, "FramebufferTexture2DOES"); + get_extension_func("glFramebufferTexture2DOES"); _glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEROESPROC) - get_extension_func(GLPREFIX_QUOTED, "FramebufferRenderbufferOES"); + get_extension_func("glFramebufferRenderbufferOES"); _glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC) - get_extension_func(GLPREFIX_QUOTED, "GetFramebufferAttachmentParameterivOES"); + get_extension_func("glGetFramebufferAttachmentParameterivOES"); _glGenerateMipmap = (PFNGLGENERATEMIPMAPOESPROC) - get_extension_func(GLPREFIX_QUOTED, "GenerateMipmapOES"); + get_extension_func("glGenerateMipmapOES"); } #endif // OPENGLES #endif @@ -1229,82 +1405,102 @@ reset() { if ( has_extension("GL_EXT_framebuffer_multisample") ) { _supports_framebuffer_multisample = true; _glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "RenderbufferStorageMultisampleEXT"); + get_extension_func("glRenderbufferStorageMultisampleEXT"); } _supports_framebuffer_multisample_coverage_nv = false; if ( has_extension("GL_NV_framebuffer_multisample_coverage") ) { _supports_framebuffer_multisample_coverage_nv = true; _glRenderbufferStorageMultisampleCoverage = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) - get_extension_func(GLPREFIX_QUOTED, "RenderbufferStorageMultisampleCoverageNV"); + get_extension_func("glRenderbufferStorageMultisampleCoverageNV"); } _supports_framebuffer_blit = false; if ( has_extension("GL_EXT_framebuffer_blit") ) { _supports_framebuffer_blit = true; _glBlitFramebuffer = (PFNGLBLITFRAMEBUFFEREXTPROC) - get_extension_func(GLPREFIX_QUOTED, "BlitFramebufferEXT"); + get_extension_func("glBlitFramebufferEXT"); } _glDrawBuffers = NULL; #ifndef OPENGLES if (is_at_least_gl_version(2, 0)) { _glDrawBuffers = (PFNGLDRAWBUFFERSPROC) - get_extension_func(GLPREFIX_QUOTED, "DrawBuffers"); + get_extension_func("glDrawBuffers"); } else if (has_extension("GL_ARB_draw_buffers")) { _glDrawBuffers = (PFNGLDRAWBUFFERSPROC) - get_extension_func(GLPREFIX_QUOTED, "DrawBuffersARB"); + get_extension_func("glDrawBuffersARB"); } _max_color_targets = 1; if (_glDrawBuffers != 0) { GLint max_draw_buffers = 0; - GLP(GetIntegerv)(GL_MAX_DRAW_BUFFERS, &max_draw_buffers); + glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers); _max_color_targets = max_draw_buffers; } #endif // OPENGLES +#ifndef OPENGLES + _supports_viewport_arrays = false; + + if (is_at_least_gl_version(4, 1) || has_extension("GL_ARB_viewport_array")) { + _glViewportArrayv = (PFNGLVIEWPORTARRAYVPROC) + get_extension_func("glViewportArrayv"); + _glScissorArrayv = (PFNGLSCISSORARRAYVPROC) + get_extension_func("glScissorArrayv"); + _glDepthRangeArrayv = (PFNGLDEPTHRANGEARRAYVPROC) + get_extension_func("glDepthRangeArrayv"); + + if (_glViewportArrayv == NULL || _glScissorArrayv == NULL || _glDepthRangeArrayv == NULL) { + GLCAT.warning() + << "Viewport arrays advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n"; + } else { + _supports_viewport_arrays = true; + } + } +#endif // OPENGLES + _max_fb_samples = 0; #ifndef OPENGLES if (_supports_framebuffer_multisample) { GLint max_samples; - GLP(GetIntegerv)(GL_MAX_SAMPLES_EXT, &max_samples); + glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_samples); _max_fb_samples = max_samples; } #endif _supports_occlusion_query = false; - if (CLP(support_occlusion_query)) { + if (gl_support_occlusion_query) { if (is_at_least_gl_version(1, 5)) { _supports_occlusion_query = true; _glGenQueries = (PFNGLGENQUERIESPROC) - get_extension_func(GLPREFIX_QUOTED, "GenQueries"); + get_extension_func("glGenQueries"); _glBeginQuery = (PFNGLBEGINQUERYPROC) - get_extension_func(GLPREFIX_QUOTED, "BeginQuery"); + get_extension_func("glBeginQuery"); _glEndQuery = (PFNGLENDQUERYPROC) - get_extension_func(GLPREFIX_QUOTED, "EndQuery"); + get_extension_func("glEndQuery"); _glDeleteQueries = (PFNGLDELETEQUERIESPROC) - get_extension_func(GLPREFIX_QUOTED, "DeleteQueries"); + get_extension_func("glDeleteQueries"); _glGetQueryiv = (PFNGLGETQUERYIVPROC) - get_extension_func(GLPREFIX_QUOTED, "GetQueryiv"); + get_extension_func("glGetQueryiv"); _glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) - get_extension_func(GLPREFIX_QUOTED, "GetQueryObjectuiv"); + get_extension_func("glGetQueryObjectuiv"); } else if (has_extension("GL_ARB_occlusion_query")) { _supports_occlusion_query = true; _glGenQueries = (PFNGLGENQUERIESPROC) - get_extension_func(GLPREFIX_QUOTED, "GenQueriesARB"); + get_extension_func("glGenQueriesARB"); _glBeginQuery = (PFNGLBEGINQUERYPROC) - get_extension_func(GLPREFIX_QUOTED, "BeginQueryARB"); + get_extension_func("glBeginQueryARB"); _glEndQuery = (PFNGLENDQUERYPROC) - get_extension_func(GLPREFIX_QUOTED, "EndQueryARB"); + get_extension_func("glEndQueryARB"); _glDeleteQueries = (PFNGLDELETEQUERIESPROC) - get_extension_func(GLPREFIX_QUOTED, "DeleteQueriesARB"); + get_extension_func("glDeleteQueriesARB"); _glGetQueryiv = (PFNGLGETQUERYIVPROC) - get_extension_func(GLPREFIX_QUOTED, "GetQueryivARB"); + get_extension_func("glGetQueryivARB"); _glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) - get_extension_func(GLPREFIX_QUOTED, "GetQueryObjectuivARB"); + get_extension_func("glGetQueryObjectuivARB"); } } @@ -1339,15 +1535,15 @@ reset() { if (is_at_least_gl_version(1, 2)) { supports_blend_equation = true; _glBlendEquation = (PFNGLBLENDEQUATIONPROC) - get_extension_func(GLPREFIX_QUOTED, "BlendEquation"); + get_extension_func("glBlendEquation"); } else if (has_extension("GL_OES_blend_subtract")) { supports_blend_equation = true; _glBlendEquation = (PFNGLBLENDEQUATIONPROC) - get_extension_func(GLPREFIX_QUOTED, "BlendEquationOES"); + get_extension_func("glBlendEquationOES"); } else if (has_extension("GL_EXT_blend_minmax")) { supports_blend_equation = true; _glBlendEquation = (PFNGLBLENDEQUATIONPROC) - get_extension_func(GLPREFIX_QUOTED, "BlendEquationEXT"); + get_extension_func("glBlendEquationEXT"); } if (supports_blend_equation && _glBlendEquation == NULL) { GLCAT.warning() @@ -1367,11 +1563,11 @@ reset() { if (is_at_least_gl_version(1, 2)) { supports_blend_color = true; _glBlendColor = (PFNGLBLENDCOLORPROC) - get_extension_func(GLPREFIX_QUOTED, "BlendColor"); + get_extension_func("glBlendColor"); } else if (has_extension("GL_EXT_blend_color")) { supports_blend_color = true; _glBlendColor = (PFNGLBLENDCOLORPROC) - get_extension_func(GLPREFIX_QUOTED, "BlendColorEXT"); + get_extension_func("glBlendColorEXT"); } if (supports_blend_color && _glBlendColor == NULL) { GLCAT.warning() @@ -1394,7 +1590,7 @@ reset() { _border_clamp = _edge_clamp; #ifndef OPENGLES - if (CLP(support_clamp_to_border) && + if (gl_support_clamp_to_border && (has_extension("GL_ARB_texture_border_clamp") || is_at_least_gl_version(1, 3))) { _border_clamp = GL_CLAMP_TO_BORDER; @@ -1421,7 +1617,7 @@ reset() { if (_supports_multisample) { GLint sample_buffers = 0; - GLP(GetIntegerv)(GL_SAMPLE_BUFFERS, &sample_buffers); + glGetIntegerv(GL_SAMPLE_BUFFERS, &sample_buffers); if (sample_buffers != 1) { // Even if the API supports multisample, we might have ended up // with a framebuffer that doesn't have any multisample bits. @@ -1438,12 +1634,12 @@ reset() { GLint max_2d_texture_array_layers = 0; GLint max_cube_map_size = 0; - GLP(GetIntegerv)(GL_MAX_TEXTURE_SIZE, &max_texture_size); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); _max_texture_dimension = max_texture_size; if (_supports_3d_texture) { #ifndef OPENGLES_1 - GLP(GetIntegerv)(GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size); + glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max_3d_texture_size); #endif _max_3d_texture_dimension = max_3d_texture_size; } else { @@ -1451,12 +1647,12 @@ reset() { } #ifndef OPENGLES if(_supports_2d_texture_array) { - GLP(GetIntegerv)(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, &max_2d_texture_array_layers); + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS_EXT, &max_2d_texture_array_layers); _max_2d_texture_array_layers = max_2d_texture_array_layers; } #endif if (_supports_cube_map) { - GLP(GetIntegerv)(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_size); + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_size); _max_cube_map_dimension = max_cube_map_size; } else { _max_cube_map_dimension = 0; @@ -1464,8 +1660,8 @@ reset() { GLint max_elements_vertices = 0, max_elements_indices = 0; #ifndef OPENGLES - GLP(GetIntegerv)(GL_MAX_ELEMENTS_VERTICES, &max_elements_vertices); - GLP(GetIntegerv)(GL_MAX_ELEMENTS_INDICES, &max_elements_indices); + glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &max_elements_vertices); + glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &max_elements_indices); if (max_elements_vertices > 0) { _max_vertices_per_array = max_elements_vertices; } @@ -1509,7 +1705,7 @@ reset() { } else { GLint num_compressed_formats = 0; - GLP(GetIntegerv)(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_formats); + glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_formats); if (num_compressed_formats == 0) { GLCAT.debug() << "No specific compressed texture formats are supported.\n"; @@ -1517,7 +1713,7 @@ reset() { GLCAT.debug() << "Supported compressed texture formats:\n"; GLint *formats = (GLint *)PANDA_MALLOC_ARRAY(num_compressed_formats * sizeof(GLint)); - GLP(GetIntegerv)(GL_COMPRESSED_TEXTURE_FORMATS, formats); + glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats); for (int i = 0; i < num_compressed_formats; ++i) { switch (formats[i]) { #ifndef OPENGLES_1 @@ -1581,16 +1777,98 @@ reset() { _max_anisotropy = 1.0; if (has_extension("GL_EXT_texture_filter_anisotropic")) { GLfloat max_anisotropy; - GLP(GetFloatv)(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy); + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy); _max_anisotropy = (PN_stdfloat)max_anisotropy; _supports_anisotropy = true; - } + } + + // Check availability of image read/write functionality in shaders. + _max_image_units = 0; +#ifndef OPENGLES + if (is_at_least_gl_version(4, 2) || has_extension("GL_ARB_shader_image_load_store")) { + _glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC) + get_extension_func("glBindImageTexture"); + _glMemoryBarrier = (PFNGLMEMORYBARRIERPROC) + get_extension_func("glMemoryBarrier"); + + glGetIntegerv(GL_MAX_IMAGE_UNITS, &_max_image_units); + + } else if (has_extension("GL_EXT_shader_image_load_store")) { + _glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC) + get_extension_func("glBindImageTextureEXT"); + _glMemoryBarrier = (PFNGLMEMORYBARRIERPROC) + get_extension_func("glMemoryBarrierEXT"); + + glGetIntegerv(GL_MAX_IMAGE_UNITS_EXT, &_max_image_units); + + } else { + _glBindImageTexture = NULL; + _glMemoryBarrier = NULL; + } + + // Check availability of multi-bind functions. + _supports_multi_bind = false; + if (is_at_least_gl_version(4, 4) || has_extension("GL_ARB_multi_bind")) { + _glBindTextures = (PFNGLBINDTEXTURESPROC) + get_extension_func("glBindTextures"); + _glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC) + get_extension_func("glBindImageTextures"); + + if (_glBindTextures != NULL && _glBindImageTextures != NULL) { + _supports_multi_bind = true; + } else { + GLCAT.warning() + << "ARB_multi_bind advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n"; + } + } + + if (is_at_least_gl_version(4, 3) || has_extension("GL_ARB_internalformat_query2")) { + _glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC) + get_extension_func("glGetInternalformativ"); + + if (_glGetInternalformativ == NULL) { + GLCAT.warning() + << "ARB_internalformat_query2 advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n"; + } + } + + _supports_bindless_texture = false; + if (has_extension("GL_ARB_bindless_texture")) { + _glGetTextureHandle = (PFNGLGETTEXTUREHANDLEPROC) + get_extension_func("glGetTextureHandleARB"); + _glMakeTextureHandleResident = (PFNGLMAKETEXTUREHANDLERESIDENTPROC) + get_extension_func("glMakeTextureHandleResidentARB"); + _glUniformHandleui64 = (PFNGLUNIFORMHANDLEUI64PROC) + get_extension_func("glUniformHandleui64ARB"); + + if (_glGetTextureHandle == NULL || _glMakeTextureHandleResident == NULL || + _glUniformHandleui64 == NULL) { + GLCAT.warning() + << "GL_ARB_bindless_texture advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n"; + } else { + _supports_bindless_texture = true; + } + } +#endif + +#ifndef OPENGLES + _supports_get_program_binary = false; + + if (is_at_least_gl_version(4, 1) || has_extension("GL_ARB_get_program_binary")) { + _glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC) + get_extension_func("glGetProgramBinary"); + + if (_glGetProgramBinary != NULL) { + _supports_get_program_binary = true; + } + } +#endif report_my_gl_errors(); if (support_stencil) { GLint num_stencil_bits; - GLP(GetIntegerv)(GL_STENCIL_BITS, &num_stencil_bits); + glGetIntegerv(GL_STENCIL_BITS, &num_stencil_bits); _supports_stencil = (num_stencil_bits != 0); } @@ -1599,7 +1877,7 @@ reset() { _supports_two_sided_stencil = has_extension("GL_EXT_stencil_two_side"); if (_supports_two_sided_stencil) { _glActiveStencilFaceEXT = (PFNGLACTIVESTENCILFACEEXTPROC) - get_extension_func(GLPREFIX_QUOTED, "ActiveStencilFaceEXT"); + get_extension_func("glActiveStencilFaceEXT"); } else { _glActiveStencilFaceEXT = 0; @@ -1609,15 +1887,15 @@ reset() { // Some drivers expose one, some expose the other. ARB seems to be the newer one. if (has_extension("GL_ARB_draw_instanced")) { _glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) - get_extension_func(GLPREFIX_QUOTED, "DrawArraysInstancedARB"); + get_extension_func("glDrawArraysInstancedARB"); _glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) - get_extension_func(GLPREFIX_QUOTED, "DrawElementsInstancedARB"); + get_extension_func("glDrawElementsInstancedARB"); _supports_geometry_instancing = true; } else if (has_extension("GL_EXT_draw_instanced")) { _glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) - get_extension_func(GLPREFIX_QUOTED, "DrawArraysInstancedEXT"); + get_extension_func("glDrawArraysInstancedEXT"); _glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) - get_extension_func(GLPREFIX_QUOTED, "DrawElementsInstancedEXT"); + get_extension_func("glDrawElementsInstancedEXT"); _supports_geometry_instancing = true; } else { _glDrawElementsInstanced = 0; @@ -1631,16 +1909,16 @@ reset() { // cases, we don't want the GL default settings; in others, we have // to force the point with some drivers that aren't strictly // compliant w.r.t. initial settings). - GLP(FrontFace)(GL_CCW); + glFrontFace(GL_CCW); #ifndef OPENGLES_2 - GLP(Disable)(GL_LINE_SMOOTH); - GLP(Disable)(GL_POINT_SMOOTH); + glDisable(GL_LINE_SMOOTH); + glDisable(GL_POINT_SMOOTH); #ifndef OPENGLES - GLP(Disable)(GL_POLYGON_SMOOTH); + glDisable(GL_POLYGON_SMOOTH); #endif // OPENGLES if (_supports_multisample) { - GLP(Disable)(GL_MULTISAMPLE); + glDisable(GL_MULTISAMPLE); } #endif @@ -1662,17 +1940,17 @@ reset() { #ifndef OPENGLES // Dither is on by default in GL; let's turn it off - GLP(Disable)(GL_DITHER); + glDisable(GL_DITHER); #endif // OPENGLES _dithering_enabled = false; #ifndef OPENGLES_1 _current_shader = (Shader *)NULL; - _current_shader_context = (CLP(ShaderContext) *)NULL; + _current_shader_context = (ShaderContext *)NULL; _vertex_array_shader = (Shader *)NULL; - _vertex_array_shader_context = (CLP(ShaderContext) *)NULL; + _vertex_array_shader_context = (ShaderContext *)NULL; _texture_binding_shader = (Shader *)NULL; - _texture_binding_shader_context = (CLP(ShaderContext) *)NULL; + _texture_binding_shader_context = (ShaderContext *)NULL; #endif #ifdef OPENGLES_2 @@ -1680,7 +1958,7 @@ reset() { #else // Count the max number of lights GLint max_lights = 0; - GLP(GetIntegerv)(GL_MAX_LIGHTS, &max_lights); + glGetIntegerv(GL_MAX_LIGHTS, &max_lights); _max_lights = max_lights; if (GLCAT.is_debug()) { @@ -1694,7 +1972,7 @@ reset() { #else // Count the max number of clipping planes GLint max_clip_planes = 0; - GLP(GetIntegerv)(GL_MAX_CLIP_PLANES, &max_clip_planes); + glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes); _max_clip_planes = max_clip_planes; if (GLCAT.is_debug()) { @@ -1706,9 +1984,9 @@ reset() { if (_supports_multitexture) { GLint max_texture_stages = 0; #ifdef OPENGLES_2 - GLP(GetIntegerv)(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_stages); + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_stages); #else - GLP(GetIntegerv)(GL_MAX_TEXTURE_UNITS, &max_texture_stages); + glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_stages); #endif _max_texture_stages = max_texture_stages; @@ -1730,20 +2008,20 @@ reset() { report_my_gl_errors(); #ifndef OPENGLES_2 - if (CLP(cheap_textures)) { + if (gl_cheap_textures) { GLCAT.info() - << "Setting GLP(Hint)() for fastest textures.\n"; - GLP(Hint)(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + << "Setting glHint() for fastest textures.\n"; + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); } // Use per-vertex fog if per-pixel fog requires SW renderer - GLP(Hint)(GL_FOG_HINT, GL_DONT_CARE); + glHint(GL_FOG_HINT, GL_DONT_CARE); #endif GLint num_red_bits = 0; - GLP(GetIntegerv)(GL_RED_BITS, &num_red_bits); + glGetIntegerv(GL_RED_BITS, &num_red_bits); if (num_red_bits < 8) { - GLP(Enable)(GL_DITHER); + glEnable(GL_DITHER); _dithering_enabled = true; if (GLCAT.is_debug()) { GLCAT.debug() @@ -1836,8 +2114,6 @@ reset() { vertex_profile = cgGLGetLatestProfile(CG_GL_VERTEX); pixel_profile = cgGLGetLatestProfile(CG_GL_FRAGMENT); if (GLCAT.is_debug()) { - // Temp ifdef: this crashes Mesa. -#ifndef OSMESA_MAJOR_VERSION #if CG_VERSION_NUM >= 2200 GLCAT.debug() << "Supported Cg profiles:\n"; int num_profiles = cgGetNumSupportedProfiles(); @@ -1854,7 +2130,6 @@ reset() { << "\nCg pixel profile = " << cgGetProfileString(pixel_profile) << " id = " << pixel_profile << "\nshader model = " << _shader_model << "\n"; -#endif } #endif @@ -1883,8 +2158,8 @@ finish() { // from the frame. That will force the graphics card to finish // drawing before it is called char data[4]; - GLP(ReadPixels)(0,0,1,1,GL_RGBA,GL_UNSIGNED_BYTE,&data); - //GLP(Finish); + glReadPixels(0,0,1,1,GL_RGBA,GL_UNSIGNED_BYTE,&data); + //glFinish(); } //////////////////////////////////////////////////////////////////// @@ -1918,9 +2193,9 @@ clear(DrawableRegion *clearable) { int layerbit = RenderBuffer::T_aux_rgba_0 << i; if (clearable->get_clear_active(layerid)) { LColor v = clearable->get_clear_value(layerid); - GLP(ClearColor)(v[0],v[1],v[2],v[3]); + glClearColor(v[0],v[1],v[2],v[3]); set_draw_buffer(layerbit); - GLP(Clear)(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT); } } for (int i=0; i<_current_properties->get_aux_hrgba(); i++) { @@ -1928,9 +2203,9 @@ clear(DrawableRegion *clearable) { int layerbit = RenderBuffer::T_aux_hrgba_0 << i; if (clearable->get_clear_active(layerid)) { LColor v = clearable->get_clear_value(layerid); - GLP(ClearColor)(v[0],v[1],v[2],v[3]); + glClearColor(v[0],v[1],v[2],v[3]); set_draw_buffer(layerbit); - GLP(Clear)(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT); } } for (int i=0; i<_current_properties->get_aux_float(); i++) { @@ -1938,9 +2213,9 @@ clear(DrawableRegion *clearable) { int layerbit = RenderBuffer::T_aux_float_0 << i; if (clearable->get_clear_active(layerid)) { LColor v = clearable->get_clear_value(layerid); - GLP(ClearColor)(v[0],v[1],v[2],v[3]); + glClearColor(v[0],v[1],v[2],v[3]); set_draw_buffer(layerbit); - GLP(Clear)(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT); } } @@ -1957,9 +2232,9 @@ clear(DrawableRegion *clearable) { if (_current_properties->get_color_bits() > 0) { if (clearable->get_clear_color_active()) { LColor v = clearable->get_clear_color(); - GLP(ClearColor)(v[0],v[1],v[2],v[3]); - if (CLP(color_mask)) { - GLP(ColorMask)(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glClearColor(v[0],v[1],v[2],v[3]); + if (gl_color_mask) { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } _state_mask.clear_bit(ColorWriteAttrib::get_class_slot()); mask |= GL_COLOR_BUFFER_BIT; @@ -1968,25 +2243,25 @@ clear(DrawableRegion *clearable) { if (clearable->get_clear_depth_active()) { #ifdef OPENGLES - GLP(ClearDepthf)(clearable->get_clear_depth()); + glClearDepthf(clearable->get_clear_depth()); #else - GLP(ClearDepth)(clearable->get_clear_depth()); + glClearDepth(clearable->get_clear_depth()); #endif // OPENGLES #ifdef GSG_VERBOSE GLCAT.spam() << "glDepthMask(GL_TRUE)" << endl; #endif - GLP(DepthMask)(GL_TRUE); + glDepthMask(GL_TRUE); _state_mask.clear_bit(DepthWriteAttrib::get_class_slot()); mask |= GL_DEPTH_BUFFER_BIT; } if (clearable->get_clear_stencil_active()) { - GLP(ClearStencil)(clearable->get_clear_stencil()); + glClearStencil(clearable->get_clear_stencil()); mask |= GL_STENCIL_BUFFER_BIT; } - GLP(Clear)(mask); + glClear(mask); if (GLCAT.is_spam()) { GLCAT.spam() << "glClear("; @@ -2035,10 +2310,32 @@ prepare_display_region(DisplayRegionPipelineReader *dr) { _draw_buffer_type = dr->get_object()->get_draw_buffer_type() & _current_properties->get_buffer_mask() & _stereo_buffer_mask; _draw_buffer_type |= _current_properties->get_aux_mask(); set_draw_buffer(_draw_buffer_type); - - GLP(Enable)(GL_SCISSOR_TEST); - GLP(Scissor)(x, y, width, height); - GLP(Viewport)(x, y, width, height); + + glEnable(GL_SCISSOR_TEST); + + if (_supports_viewport_arrays) { + int count = dr->get_num_regions(); + GLfloat *viewports = new GLfloat[4 * count]; + GLint *scissors = new GLint[4 * count]; + + for (int i = 0; i < count; ++i) { + GLint *sr = scissors + i * 4; + dr->get_region_pixels(i, sr[0], sr[1], sr[2], sr[3]); + GLfloat *vr = viewports + i * 4; + vr[0] = (GLfloat) sr[0]; + vr[1] = (GLfloat) sr[1]; + vr[2] = (GLfloat) sr[2]; + vr[3] = (GLfloat) sr[3]; + } + _glViewportArrayv(0, count, viewports); + _glScissorArrayv(0, count, scissors); + delete[] viewports; + delete[] scissors; + + } else { + glScissor(x, y, width, height); + glViewport(x, y, width, height); + } report_my_gl_errors(); do_point_size(); @@ -2126,7 +2423,7 @@ prepare_lens() { << "glMatrixMode(GL_PROJECTION): " << _projection_mat->get_mat() << endl; } - GLP(MatrixMode)(GL_PROJECTION); + glMatrixMode(GL_PROJECTION); GLPf(LoadMatrix)(_projection_mat->get_mat().get_data()); report_my_gl_errors(); @@ -2164,7 +2461,7 @@ begin_frame(Thread *current_thread) { #ifndef NDEBUG _show_texture_usage = false; - if (CLP(show_texture_usage)) { + if (gl_show_texture_usage) { // When this is true, then every other second, we show the usage // textures instead of the real textures. double now = ClockObject::get_global_clock()->get_frame_time(); @@ -2173,7 +2470,7 @@ begin_frame(Thread *current_thread) { _show_texture_usage = true; _show_texture_usage_index = this_second >> 1; - int max_size = CLP(show_texture_usage_max_size); + int max_size = gl_show_texture_usage_max_size; if (max_size != _show_texture_usage_max_size) { // Remove the cache of usage textures; we've changed the max // size. @@ -2182,7 +2479,7 @@ begin_frame(Thread *current_thread) { ui != _usage_textures.end(); ++ui) { GLuint index = (*ui).second; - GLP(DeleteTextures)(1, &index); + glDeleteTextures(1, &index); } _usage_textures.clear(); _show_texture_usage_max_size = max_size; @@ -2191,6 +2488,12 @@ begin_frame(Thread *current_thread) { } #endif // NDEBUG +#ifndef OPENGLES_1 + if (_current_properties->get_srgb_color()) { + glEnable(GL_FRAMEBUFFER_SRGB); + } +#endif + report_my_gl_errors(); return true; } @@ -2242,6 +2545,13 @@ end_scene() { void CLP(GraphicsStateGuardian):: end_frame(Thread *current_thread) { report_my_gl_errors(); + +#ifndef OPENGLES_1 + if (_current_properties->get_srgb_color()) { + glDisable(GL_FRAMEBUFFER_SRGB); + } +#endif + #ifdef DO_PSTATS // Check for textures, etc., that are no longer resident. These // calls might be measurably expensive, and they don't have any @@ -2263,19 +2573,19 @@ end_frame(Thread *current_thread) { #ifndef OPENGLES_1 // This breaks shaders across multiple regions. if (_vertex_array_shader_context != 0) { - _vertex_array_shader_context->disable_shader_vertex_arrays(this); + _vertex_array_shader_context->disable_shader_vertex_arrays(); _vertex_array_shader = (Shader *)NULL; - _vertex_array_shader_context = (CLP(ShaderContext) *)NULL; + _vertex_array_shader_context = (ShaderContext *)NULL; } if (_texture_binding_shader_context != 0) { - _texture_binding_shader_context->disable_shader_texture_bindings(this); + _texture_binding_shader_context->disable_shader_texture_bindings(); _texture_binding_shader = (Shader *)NULL; - _texture_binding_shader_context = (CLP(ShaderContext) *)NULL; + _texture_binding_shader_context = (ShaderContext *)NULL; } if (_current_shader_context != 0) { - _current_shader_context->unbind(this); + _current_shader_context->unbind(); _current_shader = (Shader *)NULL; - _current_shader_context = (CLP(ShaderContext) *)NULL; + _current_shader_context = (ShaderContext *)NULL; } #endif @@ -2299,7 +2609,7 @@ end_frame(Thread *current_thread) { GLCAT.debug() << "releasing display list index " << (int)(*ddli) << "\n"; } - GLP(DeleteLists)((*ddli), 1); + glDeleteLists((*ddli), 1); } _deleted_display_lists.clear(); } @@ -2325,14 +2635,46 @@ end_frame(Thread *current_thread) { // necessary if this is a single-buffered visual, so that the frame // will be finished drawing before we return to the application. // It's not clear what effect this has on our total frame time. - if (_allow_flush) { + if (_force_flush || _current_properties->is_single_buffered()) { gl_flush(); } maybe_gl_finish(); - report_my_gl_errors(); -} +#ifndef NDEBUG + if (_check_errors || (_supports_debug && gl_debug)) { + report_my_gl_errors(); + } else { + // If _check_errors is false, we still want to check for errors + // once during this frame, so that we know if anything went wrong. + GLenum error_code = glGetError(); + if (error_code != GL_NO_ERROR) { + int error_count = 0; + bool deactivate = !report_errors_loop(__LINE__, __FILE__, error_code, error_count); + if (error_count == 1) { + GLCAT.error() + << "An OpenGL error (" << get_error_string(error_code) + << ") has occurred."; + } else { + GLCAT.error() + << error_count << " OpenGL errors have occurred."; + } + + if (_supports_debug) { + GLCAT.error(false) << " Set gl-debug #t " + << "in your PRC file to display more information.\n"; + } else { + GLCAT.error(false) << " Set gl-check-errors #t " + << "in your PRC file to display more information.\n"; + } + + if (deactivate) { + panic_deactivate(); + } + } + } +#endif +} //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::begin_draw_primitives @@ -2396,7 +2738,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, if (hardware_animation) { // Set up the transform matrices for vertex blending. nassertr(_supports_vertex_blend, false); - GLP(Enable)(GL_VERTEX_BLEND_ARB); + glEnable(GL_VERTEX_BLEND_ARB); _glVertexBlend(animation.get_num_transforms()); const TransformTable *table = _data_reader->get_transform_table(); @@ -2407,9 +2749,9 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, // to change this interface from that for the list of // nonindexed matrices, to make it easier to load an arbitrary // number of matrices. - GLP(Enable)(GL_MATRIX_PALETTE_ARB); + glEnable(GL_MATRIX_PALETTE_ARB); - GLP(MatrixMode)(GL_MATRIX_PALETTE_ARB); + glMatrixMode(GL_MATRIX_PALETTE_ARB); for (int i = 0; i < table->get_num_transforms(); ++i) { LMatrix4 mat; @@ -2426,7 +2768,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, // little clumsier. if (_supports_matrix_palette) { - GLP(Disable)(GL_MATRIX_PALETTE_ARB); + glDisable(GL_MATRIX_PALETTE_ARB); } // GL_MODELVIEW0 and 1 are different than the rest. @@ -2434,21 +2776,21 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, if (i < table->get_num_transforms()) { LMatrix4 mat; table->get_transform(i)->mult_matrix(mat, _internal_transform->get_mat()); - GLP(MatrixMode)(GL_MODELVIEW0_ARB); + glMatrixMode(GL_MODELVIEW0_ARB); GLPf(LoadMatrix)(mat.get_data()); ++i; } if (i < table->get_num_transforms()) { LMatrix4 mat; table->get_transform(i)->mult_matrix(mat, _internal_transform->get_mat()); - GLP(MatrixMode)(GL_MODELVIEW1_ARB); + glMatrixMode(GL_MODELVIEW1_ARB); GLPf(LoadMatrix)(mat.get_data()); ++i; } while (i < table->get_num_transforms()) { LMatrix4 mat; table->get_transform(i)->mult_matrix(mat, _internal_transform->get_mat()); - GLP(MatrixMode)(GL_MODELVIEW2_ARB + i - 2); + glMatrixMode(GL_MODELVIEW2_ARB + i - 2); GLPf(LoadMatrix)(mat.get_data()); ++i; } @@ -2463,15 +2805,15 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, } else { // We're not using vertex blending. if (_vertex_blending_enabled) { - GLP(Disable)(GL_VERTEX_BLEND_ARB); + glDisable(GL_VERTEX_BLEND_ARB); if (_supports_matrix_palette) { - GLP(Disable)(GL_MATRIX_PALETTE_ARB); + glDisable(GL_MATRIX_PALETTE_ARB); } _vertex_blending_enabled = false; } if (_transform_stale) { - GLP(MatrixMode)(GL_MODELVIEW); + glMatrixMode(GL_MODELVIEW); GLPf(LoadMatrix)(_internal_transform->get_mat().get_data()); } } @@ -2482,12 +2824,12 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, // If the vertex data claims to be already transformed into clip // coordinates, wipe out the current projection and modelview // matrix (so we don't attempt to transform it again). - GLP(MatrixMode)(GL_PROJECTION); - GLP(PushMatrix)(); - GLP(LoadIdentity)(); - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PushMatrix)(); - GLP(LoadIdentity)(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); } #endif @@ -2515,7 +2857,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, << "calling display list " << (int)_geom_display_list << "\n"; } - GLP(CallList)(_geom_display_list); + glCallList(_geom_display_list); #ifdef DO_PSTATS _vertices_display_list_pcollector.add_level(ggc->_num_verts); _primitive_batches_display_list_pcollector.add_level(1); @@ -2538,10 +2880,10 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, // If it has been modified, or this is the first time, then we // need to build the display list up. - if (CLP(compile_and_execute)) { - GLP(NewList)(_geom_display_list, GL_COMPILE_AND_EXECUTE); + if (gl_compile_and_execute) { + glNewList(_geom_display_list, GL_COMPILE_AND_EXECUTE); } else { - GLP(NewList)(_geom_display_list, GL_COMPILE); + glNewList(_geom_display_list, GL_COMPILE); } #ifdef DO_PSTATS @@ -2559,10 +2901,6 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, // extra vertex arrays used by the previous rendering mode. #ifdef SUPPORT_IMMEDIATE_MODE _use_sender = !vertex_arrays; - // This is a workaround for a bug in Mesa 6 vertex array handling. - if ((_supports_mesa_6) && (_current_properties->get_force_software())) { - _use_sender = true; - } #endif #ifdef OPENGLES_1 @@ -2573,7 +2911,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, if (_current_shader_context == 0) { // No shader. if (_vertex_array_shader_context != 0) { - _vertex_array_shader_context->disable_shader_vertex_arrays(this); + _vertex_array_shader_context->disable_shader_vertex_arrays(); } if (!update_standard_vertex_arrays(force)) { return false; @@ -2595,11 +2933,11 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, if (_current_shader_context->uses_custom_vertex_arrays()) { // The current shader also uses custom vertex arrays. if (!_current_shader_context-> - update_shader_vertex_arrays(_vertex_array_shader_context, this, force)) { + update_shader_vertex_arrays(_vertex_array_shader_context, force)) { return false; } } else { - _vertex_array_shader_context->disable_shader_vertex_arrays(this); + _vertex_array_shader_context->disable_shader_vertex_arrays(); } } @@ -2681,7 +3019,7 @@ update_standard_vertex_arrays(bool force) { // Be sure also to disable any texture stages we had enabled before. while (stage_index < _last_max_stage_index) { _glClientActiveTexture(GL_TEXTURE0 + stage_index); - GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); ++stage_index; } _last_max_stage_index = max_stage_index; @@ -2721,32 +3059,36 @@ update_standard_vertex_arrays(bool force) { if (!setup_array_data(client_pointer, array_reader, force)) { return false; } - GLP(NormalPointer)(get_numeric_type(numeric_type), stride, - client_pointer + start); - GLP(EnableClientState)(GL_NORMAL_ARRAY); + glNormalPointer(get_numeric_type(numeric_type), stride, + client_pointer + start); + glEnableClientState(GL_NORMAL_ARRAY); } else { - GLP(DisableClientState)(GL_NORMAL_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); } #ifndef NDEBUG if (_show_texture_usage) { // In show_texture_usage mode, all colors are white, so as not // to contaminate the texture color. - GLP(DisableClientState)(GL_COLOR_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); GLPf(Color4)(1.0f, 1.0f, 1.0f, 1.0f); } else #endif // NDEBUG if (_data_reader->get_color_info(array_reader, num_values, numeric_type, - start, stride) && - numeric_type != Geom::NT_packed_dabc) { + start, stride)) { if (!setup_array_data(client_pointer, array_reader, force)) { return false; } - GLP(ColorPointer)(num_values, get_numeric_type(numeric_type), - stride, client_pointer + start); - GLP(EnableClientState)(GL_COLOR_ARRAY); + if (numeric_type == Geom::NT_packed_dabc) { + glColorPointer(GL_BGRA, GL_UNSIGNED_BYTE, + stride, client_pointer + start); + } else { + glColorPointer(num_values, get_numeric_type(numeric_type), + stride, client_pointer + start); + } + glEnableClientState(GL_COLOR_ARRAY); } else { - GLP(DisableClientState)(GL_COLOR_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); // Since we don't have per-vertex color, the implicit color is // white. @@ -2772,18 +3114,18 @@ update_standard_vertex_arrays(bool force) { if (!setup_array_data(client_pointer, array_reader, force)) { return false; } - GLP(TexCoordPointer)(num_values, get_numeric_type(numeric_type), + glTexCoordPointer(num_values, get_numeric_type(numeric_type), stride, client_pointer + start); - GLP(EnableClientState)(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); } else { // The vertex data doesn't have texcoords for this stage (even // though they're needed). - GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } else { // No texcoords are needed for this stage. - GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } ++stage_index; @@ -2792,7 +3134,7 @@ update_standard_vertex_arrays(bool force) { // Be sure also to disable any texture stages we had enabled before. while (stage_index < _last_max_stage_index) { _glClientActiveTexture(GL_TEXTURE0 + stage_index); - GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); ++stage_index; } _last_max_stage_index = max_stage_index; @@ -2809,9 +3151,9 @@ update_standard_vertex_arrays(bool force) { } _glWeightPointer(num_values, get_numeric_type(numeric_type), stride, client_pointer + start); - GLP(EnableClientState)(GL_WEIGHT_ARRAY_ARB); + glEnableClientState(GL_WEIGHT_ARRAY_ARB); } else { - GLP(DisableClientState)(GL_WEIGHT_ARRAY_ARB); + glDisableClientState(GL_WEIGHT_ARRAY_ARB); } if (animation.get_indexed_transforms()) { @@ -2824,16 +3166,16 @@ update_standard_vertex_arrays(bool force) { } _glMatrixIndexPointer(num_values, get_numeric_type(numeric_type), stride, client_pointer + start); - GLP(EnableClientState)(GL_MATRIX_INDEX_ARRAY_ARB); + glEnableClientState(GL_MATRIX_INDEX_ARRAY_ARB); } else { - GLP(DisableClientState)(GL_MATRIX_INDEX_ARRAY_ARB); + glDisableClientState(GL_MATRIX_INDEX_ARRAY_ARB); } } } else { - GLP(DisableClientState)(GL_WEIGHT_ARRAY_ARB); + glDisableClientState(GL_WEIGHT_ARRAY_ARB); if (_supports_matrix_palette) { - GLP(DisableClientState)(GL_MATRIX_INDEX_ARRAY_ARB); + glDisableClientState(GL_MATRIX_INDEX_ARRAY_ARB); } } } @@ -2846,9 +3188,9 @@ update_standard_vertex_arrays(bool force) { if (!setup_array_data(client_pointer, array_reader, force)) { return false; } - GLP(VertexPointer)(num_values, get_numeric_type(numeric_type), + glVertexPointer(num_values, get_numeric_type(numeric_type), stride, client_pointer + start); - GLP(EnableClientState)(GL_VERTEX_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); } } #endif // OPENGLES_2 @@ -2865,7 +3207,7 @@ update_standard_vertex_arrays(bool force) { void CLP(GraphicsStateGuardian):: unbind_buffers() { if (_current_vbuffer_index != 0) { - if (GLCAT.is_spam() && CLP(debug_buffers)) { + if (GLCAT.is_spam() && gl_debug_buffers) { GLCAT.spam() << "unbinding vertex buffer\n"; } @@ -2873,7 +3215,7 @@ unbind_buffers() { _current_vbuffer_index = 0; } if (_current_ibuffer_index != 0) { - if (GLCAT.is_spam() && CLP(debug_buffers)) { + if (GLCAT.is_spam() && gl_debug_buffers) { GLCAT.spam() << "unbinding index buffer\n"; } @@ -2902,28 +3244,26 @@ disable_standard_vertex_arrays() if (_use_sender) return; #endif - GLP(DisableClientState)(GL_NORMAL_ARRAY); - GLP(DisableClientState)(GL_COLOR_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); GLPf(Color4)(1.0f, 1.0f, 1.0f, 1.0f); - report_my_gl_errors(); for (int stage_index=0; stage_index < _last_max_stage_index; stage_index++) { _glClientActiveTexture(GL_TEXTURE0 + stage_index); - GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } _last_max_stage_index = 0; - report_my_gl_errors(); #ifndef OPENGLES if (_supports_vertex_blend) { - GLP(DisableClientState)(GL_WEIGHT_ARRAY_ARB); + glDisableClientState(GL_WEIGHT_ARRAY_ARB); if (_supports_matrix_palette) { - GLP(DisableClientState)(GL_MATRIX_INDEX_ARRAY_ARB); + glDisableClientState(GL_MATRIX_INDEX_ARRAY_ARB); } } #endif - GLP(DisableClientState)(GL_VERTEX_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); report_my_gl_errors(); #endif } @@ -2984,7 +3324,7 @@ draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) { } else #endif { - GLP(DrawArrays)(GL_TRIANGLES, + glDrawArrays(GL_TRIANGLES, reader->get_first_vertex(), num_vertices); } @@ -3054,7 +3394,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) { } else #endif { - GLP(DrawArrays)(GL_TRIANGLE_STRIP, + glDrawArrays(GL_TRIANGLE_STRIP, reader->get_first_vertex(), num_vertices); } @@ -3109,7 +3449,7 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) { } else #endif { - GLP(DrawArrays)(GL_TRIANGLE_STRIP, first_vertex + start, + glDrawArrays(GL_TRIANGLE_STRIP, first_vertex + start, ends[i] - start); } start = ends[i] + 2; @@ -3189,7 +3529,7 @@ draw_trifans(const GeomPrimitivePipelineReader *reader, bool force) { } else #endif { - GLP(DrawArrays)(GL_TRIANGLE_FAN, first_vertex + start, + glDrawArrays(GL_TRIANGLE_FAN, first_vertex + start, ends[i] - start); } start = ends[i]; @@ -3265,7 +3605,7 @@ draw_patches(const GeomPrimitivePipelineReader *reader, bool force) { } else #endif { - GLP(DrawArrays)(GL_PATCHES, + glDrawArrays(GL_PATCHES, reader->get_first_vertex(), num_vertices); } @@ -3331,7 +3671,7 @@ draw_lines(const GeomPrimitivePipelineReader *reader, bool force) { } else #endif { - GLP(DrawArrays)(GL_LINES, + glDrawArrays(GL_LINES, reader->get_first_vertex(), num_vertices); } @@ -3405,7 +3745,7 @@ draw_points(const GeomPrimitivePipelineReader *reader, bool force) { } else #endif { - GLP(DrawArrays)(GL_POINTS, + glDrawArrays(GL_POINTS, reader->get_first_vertex(), num_vertices); } @@ -3428,11 +3768,11 @@ end_draw_primitives() { #ifndef OPENGLES // Display lists not supported by OpenGL ES. if (_geom_display_list != 0) { // If we were building a display list, close it now. - GLP(EndList)(); + glEndList(); _load_display_list_pcollector.stop(); - if (!CLP(compile_and_execute)) { - GLP(CallList)(_geom_display_list); + if (!gl_compile_and_execute) { + glCallList(_geom_display_list); } _primitive_batches_display_list_pcollector.add_level(1); } @@ -3440,9 +3780,9 @@ end_draw_primitives() { // Clean up the vertex blending state. if (_vertex_blending_enabled) { - GLP(Disable)(GL_VERTEX_BLEND_ARB); + glDisable(GL_VERTEX_BLEND_ARB); if (_supports_matrix_palette) { - GLP(Disable)(GL_MATRIX_PALETTE_ARB); + glDisable(GL_MATRIX_PALETTE_ARB); } _vertex_blending_enabled = false; } @@ -3450,16 +3790,16 @@ end_draw_primitives() { #ifndef OPENGLES_2 if (_transform_stale) { - GLP(MatrixMode)(GL_MODELVIEW); + glMatrixMode(GL_MODELVIEW); GLPf(LoadMatrix)(_internal_transform->get_mat().get_data()); } if (_data_reader->is_vertex_transformed()) { // Restore the matrices that we pushed above. - GLP(MatrixMode)(GL_PROJECTION); - GLP(PopMatrix)(); - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PopMatrix)(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } #endif @@ -3468,6 +3808,54 @@ end_draw_primitives() { report_my_gl_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::issue_memory_barrier +// Access: Public +// Description: Issues the given memory barriers, and clears the +// list of textures marked as incoherent for the given +// bits. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +issue_memory_barrier(GLbitfield barriers) { +#ifndef OPENGLES + if (!gl_enable_memory_barriers || _glMemoryBarrier == NULL) { + return; + } + + if (GLCAT.is_debug()) { + GLCAT.debug() << "Issuing memory barriers:"; + } + + _glMemoryBarrier(barriers); + + // Indicate that barriers no longer need to be issued for + // the relevant lists of textures. + if (barriers & GL_TEXTURE_FETCH_BARRIER_BIT) { + _textures_needing_fetch_barrier.clear(); + GLCAT.debug(false) << " texture_fetch"; + } + + if (barriers & GL_SHADER_IMAGE_ACCESS_BARRIER_BIT) { + _textures_needing_image_access_barrier.clear(); + GLCAT.debug(false) << " shader_image_access"; + } + + if (barriers & GL_TEXTURE_UPDATE_BARRIER_BIT) { + _textures_needing_update_barrier.clear(); + GLCAT.debug(false) << " texture_update"; + } + + if (barriers & GL_FRAMEBUFFER_BARRIER_BIT) { + _textures_needing_framebuffer_barrier.clear(); + GLCAT.debug(false) << " framebuffer"; + } + + GLCAT.debug(false) << "\n"; + + report_my_gl_errors(); +#endif // OPENGLES +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::prepare_texture // Access: Public, Virtual @@ -3514,11 +3902,9 @@ prepare_texture(Texture *tex, int view) { break; } - CLP(TextureContext) *gtc = new CLP(TextureContext)(_prepared_objects, tex, view); - GLP(GenTextures)(1, >c->_index); + CLP(TextureContext) *gtc = new CLP(TextureContext)(this, _prepared_objects, tex, view); report_my_gl_errors(); - apply_texture(gtc); return gtc; } @@ -3540,14 +3926,14 @@ prepare_texture(Texture *tex, int view) { //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: update_texture(TextureContext *tc, bool force) { - apply_texture(tc); - CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - if (gtc->was_image_modified()) { - // If the texture image was modified, reload the texture. This - // means we also re-specify the properties for good measure. - specify_texture(gtc); + if (gtc->was_image_modified() || !gtc->_has_storage) { + // If the texture image was modified, reload the texture. + apply_texture(tc); + if (gtc->was_properties_modified()) { + specify_texture(gtc); + } bool okflag = upload_texture(gtc, force); if (!okflag) { GLCAT.error() @@ -3558,6 +3944,7 @@ update_texture(TextureContext *tc, bool force) { } else if (gtc->was_properties_modified()) { // If only the properties have been modified, we don't necessarily // need to reload the texture. + apply_texture(tc); if (specify_texture(gtc)) { // Actually, looks like the texture *does* need to be reloaded. gtc->mark_needs_reload(); @@ -3574,6 +3961,7 @@ update_texture(TextureContext *tc, bool force) { gtc->mark_loaded(); } } + gtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru); report_my_gl_errors(); @@ -3590,13 +3978,7 @@ update_texture(TextureContext *tc, bool force) { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: release_texture(TextureContext *tc) { - report_my_gl_errors(); CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - - GLP(DeleteTextures)(1, >c->_index); - report_my_gl_errors(); - - gtc->_index = 0; delete gtc; } @@ -3670,29 +4052,48 @@ release_geom(GeomContext *gc) { //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::prepare_shader // Access: Public, Virtual -// Description: yadda. +// Description: //////////////////////////////////////////////////////////////////// ShaderContext *CLP(GraphicsStateGuardian):: prepare_shader(Shader *se) { #ifndef OPENGLES_1 - CLP(ShaderContext) *result = new CLP(ShaderContext)(se, this); - if (result->valid()) return result; - delete result; + ShaderContext *result = NULL; + + switch (se->get_language()) { + case Shader::SL_GLSL: + result = new CLP(ShaderContext)(this, se); + break; + +#if defined(HAVE_CG) && !defined(OPENGLES) + case Shader::SL_Cg: + result = new CLP(CgShaderContext)(this, se); + break; #endif + + default: + GLCAT.error() + << "Tried to load shader with unsupported shader language!\n"; + return NULL; + } + + if (result->valid()) { + return result; + } + + delete result; +#endif // OPENGLES_1 + return NULL; } //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::release_shader // Access: Public, Virtual -// Description: yadda. +// Description: //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: release_shader(ShaderContext *sc) { -#ifndef OPENGLES_1 - CLP(ShaderContext) *gsc = DCAST(CLP(ShaderContext), sc); - delete gsc; -#endif + delete sc; } //////////////////////////////////////////////////////////////////// @@ -3728,7 +4129,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) { CLP(VertexBufferContext) *gvbc = new CLP(VertexBufferContext)(this, _prepared_objects, data); _glGenBuffers(1, &gvbc->_index); - if (GLCAT.is_debug() && CLP(debug_buffers)) { + if (GLCAT.is_debug() && gl_debug_buffers) { GLCAT.debug() << "creating vertex buffer " << (int)gvbc->_index << ": " << data->get_num_rows() << " vertices " @@ -3761,7 +4162,7 @@ apply_vertex_buffer(VertexBufferContext *vbc, CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext), vbc); if (_current_vbuffer_index != gvbc->_index) { - if (GLCAT.is_spam() && CLP(debug_buffers)) { + if (GLCAT.is_spam() && gl_debug_buffers) { GLCAT.spam() << "binding vertex buffer " << (int)gvbc->_index << "\n"; } @@ -3772,7 +4173,7 @@ apply_vertex_buffer(VertexBufferContext *vbc, if (gvbc->was_modified(reader)) { int num_bytes = reader->get_data_size_bytes(); - if (GLCAT.is_debug() && CLP(debug_buffers)) { + if (GLCAT.is_debug() && gl_debug_buffers) { GLCAT.debug() << "copying " << num_bytes << " bytes into vertex buffer " << (int)gvbc->_index << "\n"; @@ -3817,7 +4218,7 @@ release_vertex_buffer(VertexBufferContext *vbc) { CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext), vbc); - if (GLCAT.is_debug() && CLP(debug_buffers)) { + if (GLCAT.is_debug() && gl_debug_buffers) { GLCAT.debug() << "deleting vertex buffer " << (int)gvbc->_index << "\n"; } @@ -3827,7 +4228,7 @@ release_vertex_buffer(VertexBufferContext *vbc) { // help out a flaky driver, and we need to keep our internal state // consistent anyway. if (_current_vbuffer_index == gvbc->_index) { - if (GLCAT.is_spam() && CLP(debug_buffers)) { + if (GLCAT.is_spam() && gl_debug_buffers) { GLCAT.spam() << "unbinding vertex buffer\n"; } @@ -3871,11 +4272,11 @@ setup_array_data(const unsigned char *&client_pointer, return (client_pointer != NULL); } if (!vertex_buffers || _geom_display_list != 0 || - array_reader->get_usage_hint() < CLP(min_buffer_usage_hint)) { + array_reader->get_usage_hint() < gl_min_buffer_usage_hint) { // The array specifies client rendering only, or buffer objects // are configured off. if (_current_vbuffer_index != 0) { - if (GLCAT.is_spam() && CLP(debug_buffers)) { + if (GLCAT.is_spam() && gl_debug_buffers) { GLCAT.spam() << "unbinding vertex buffer\n"; } @@ -3917,7 +4318,7 @@ prepare_index_buffer(GeomPrimitive *data) { CLP(IndexBufferContext) *gibc = new CLP(IndexBufferContext)(this, _prepared_objects, data); _glGenBuffers(1, &gibc->_index); - if (GLCAT.is_debug() && CLP(debug_buffers)) { + if (GLCAT.is_debug() && gl_debug_buffers) { GLCAT.debug() << "creating index buffer " << (int)gibc->_index << ": " << data->get_num_vertices() << " indices (" @@ -3953,7 +4354,7 @@ apply_index_buffer(IndexBufferContext *ibc, CLP(IndexBufferContext) *gibc = DCAST(CLP(IndexBufferContext), ibc); if (_current_ibuffer_index != gibc->_index) { - if (GLCAT.is_spam() && CLP(debug_buffers)) { + if (GLCAT.is_spam() && gl_debug_buffers) { GLCAT.spam() << "binding index buffer " << (int)gibc->_index << "\n"; } @@ -3964,7 +4365,7 @@ apply_index_buffer(IndexBufferContext *ibc, if (gibc->was_modified(reader)) { int num_bytes = reader->get_data_size_bytes(); - if (GLCAT.is_debug() && CLP(debug_buffers)) { + if (GLCAT.is_debug() && gl_debug_buffers) { GLCAT.debug() << "copying " << num_bytes << " bytes into index buffer " << (int)gibc->_index << "\n"; @@ -4009,7 +4410,7 @@ release_index_buffer(IndexBufferContext *ibc) { CLP(IndexBufferContext) *gibc = DCAST(CLP(IndexBufferContext), ibc); - if (GLCAT.is_debug() && CLP(debug_buffers)) { + if (GLCAT.is_debug() && gl_debug_buffers) { GLCAT.debug() << "deleting index buffer " << (int)gibc->_index << "\n"; } @@ -4019,7 +4420,7 @@ release_index_buffer(IndexBufferContext *ibc) { // help out a flaky driver, and we need to keep our internal state // consistent anyway. if (_current_ibuffer_index == gibc->_index) { - if (GLCAT.is_spam() && CLP(debug_buffers)) { + if (GLCAT.is_spam() && gl_debug_buffers) { GLCAT.spam() << "unbinding index buffer\n"; } @@ -4067,7 +4468,7 @@ setup_primitive(const unsigned char *&client_pointer, // The array specifies client rendering only, or buffer objects // are configured off. if (_current_ibuffer_index != 0) { - if (GLCAT.is_spam() && CLP(debug_buffers)) { + if (GLCAT.is_spam() && gl_debug_buffers) { GLCAT.spam() << "unbinding index buffer\n"; } @@ -4179,6 +4580,26 @@ end_occlusion_query() { #endif // OPENGLES } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::dispatch_compute +// Access: Public, Virtual +// Description: Dispatches a currently bound compute shader using +// the given work group counts. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +dispatch_compute(int num_groups_x, int num_groups_y, int num_groups_z) { +#ifndef OPENGLES + maybe_gl_finish(); + + PStatTimer timer(_compute_dispatch_pcollector); + nassertv(_supports_compute_shaders); + nassertv(_current_shader_context != NULL); + _glDispatchCompute(num_groups_x, num_groups_y, num_groups_z); + + maybe_gl_finish(); +#endif +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::make_geom_munger // Access: Public, Virtual @@ -4205,8 +4626,8 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb) { nassertr(tex != NULL && dr != NULL, false); set_read_buffer(rb._buffer_type); - if (CLP(color_mask)) { - GLP(ColorMask)(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + if (gl_color_mask) { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } int xo, yo, w, h; @@ -4274,11 +4695,19 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z, default: // If the texture is a color format, we want to match the - // presence of alpha according to the framebuffer. - if (_current_properties->get_alpha_bits()) { - tex->set_format(Texture::F_rgba); + // presence of sRGB and alpha according to the framebuffer. + if (_current_properties->get_srgb_color()) { + if (_current_properties->get_alpha_bits()) { + tex->set_format(Texture::F_srgb_alpha); + } else { + tex->set_format(Texture::F_srgb); + } } else { - tex->set_format(Texture::F_rgb); + if (_current_properties->get_alpha_bits()) { + tex->set_format(Texture::F_rgba); + } else { + tex->set_format(Texture::F_rgb); + } } } } @@ -4296,19 +4725,19 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z, int height = tex->get_y_size(); int depth = tex->get_z_size(); - bool uses_mipmaps = tex->uses_mipmaps() && !CLP(ignore_mipmaps); + bool uses_mipmaps = tex->uses_mipmaps() && !gl_ignore_mipmaps; if (uses_mipmaps) { -#ifndef OPENGLES_2 if (_supports_generate_mipmap) { - GLP(TexParameteri)(target, GL_GENERATE_MIPMAP, true); - } else { -#endif - // If we can't auto-generate mipmaps, do without mipmaps. - GLP(TexParameteri)(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - uses_mipmaps = false; #ifndef OPENGLES_2 - } + if (_glGenerateMipmap == NULL) { + glTexParameteri(target, GL_GENERATE_MIPMAP, true); + } #endif + } else { + // If we can't auto-generate mipmaps, do without mipmaps. + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + uses_mipmaps = false; + } } bool new_image = needs_reload || gtc->was_image_modified(); @@ -4326,7 +4755,7 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z, } } - if (!gtc->_already_applied || + if (!gtc->_has_storage || internal_format != gtc->_internal_format || uses_mipmaps != gtc->_uses_mipmaps || width != gtc->_width || @@ -4337,6 +4766,18 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z, new_image = true; } + if (new_image && gtc->_immutable) { + gtc->reset_data(); + glBindTexture(target, gtc->_index); + } + +#ifndef OPENGLES + if (gtc->needs_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT)) { + // Make sure that any incoherent writes to this texture have been synced. + issue_memory_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT); + } +#endif + if (z >= 0) { if (new_image) { // These won't be used because we pass a NULL image, but we still @@ -4353,14 +4794,18 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z, // It seems that OpenGL accepts a size higher than the framebuffer, // but if we run into trouble we'll have to replace this with // something smarter. - GLP(CopyTexImage2D)(target, 0, internal_format, xo, yo, width, height, 0); + glCopyTexImage2D(target, 0, internal_format, xo, yo, width, height, 0); } else { // We can overlay the existing image. - GLP(CopyTexSubImage2D)(target, 0, 0, 0, xo, yo, w, h); + glCopyTexSubImage2D(target, 0, 0, 0, xo, yo, w, h); } } - gtc->_already_applied = true; + if (uses_mipmaps && _glGenerateMipmap != NULL) { + _glGenerateMipmap(target); + } + + gtc->_has_storage = true; gtc->_uses_mipmaps = uses_mipmaps; gtc->_internal_format = internal_format; gtc->_width = width; @@ -4394,13 +4839,13 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb) { nassertr(tex != NULL && dr != NULL, false); set_read_buffer(rb._buffer_type); - GLP(PixelStorei)(GL_PACK_ALIGNMENT, 1); - if (CLP(color_mask)) { - GLP(ColorMask)(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + if (gl_color_mask) { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } // Bug fix for RE, RE2, and VTX - need to disable texturing in order - // for GLP(ReadPixels)() to work + // for glReadPixels() to work // NOTE: reading the depth buffer is *much* slower than reading the // color buffer set_state_and_transform(RenderState::make_empty(), _internal_transform); @@ -4414,11 +4859,17 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z, Texture::Format format = tex->get_format(); switch (format) { case Texture::F_depth_stencil: - component_type = Texture::T_unsigned_int_24_8; + if (_current_properties->get_float_depth()) { + component_type = Texture::T_float; + } else { + component_type = Texture::T_unsigned_int_24_8; + } break; case Texture::F_depth_component: - if (_current_properties->get_depth_bits() <= 8) { + if (_current_properties->get_float_depth()) { + component_type = Texture::T_float; + } else if (_current_properties->get_depth_bits() <= 8) { component_type = Texture::T_unsigned_byte; } else if (_current_properties->get_depth_bits() <= 16) { component_type = Texture::T_unsigned_short; @@ -4429,12 +4880,22 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z, default: color_mode = true; - if (_current_properties->get_alpha_bits()) { - format = Texture::F_rgba; + if (_current_properties->get_srgb_color()) { + if (_current_properties->get_alpha_bits()) { + format = Texture::F_srgb_alpha; + } else { + format = Texture::F_srgb; + } } else { - format = Texture::F_rgb; + if (_current_properties->get_alpha_bits()) { + format = Texture::F_rgba; + } else { + format = Texture::F_rgb; + } } - if (_current_properties->get_color_bits() <= 24) { + if (_current_properties->get_float_color()) { + component_type = Texture::T_float; + } else if (_current_properties->get_color_bits() <= 24) { component_type = Texture::T_unsigned_byte; } else { component_type = Texture::T_unsigned_short; @@ -4474,7 +4935,7 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z, case GL_DEPTH_COMPONENT: GLCAT.spam(false) << "GL_DEPTH_COMPONENT, "; break; - case GL_DEPTH_STENCIL_EXT: + case GL_DEPTH_STENCIL: GLCAT.spam(false) << "GL_DEPTH_STENCIL, "; break; case GL_RGB: @@ -4505,6 +4966,9 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z, case GL_FLOAT: GLCAT.spam(false) << "GL_FLOAT"; break; + case GL_INT: + GLCAT.spam(false) << "GL_INT"; + break; default: GLCAT.spam(false) << "unknown"; break; @@ -4525,9 +4989,8 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z, } } - GLP(ReadPixels)(xo, yo, w, h, - external_format, get_component_type(component_type), - image_ptr); + glReadPixels(xo, yo, w, h, external_format, + get_component_type(component_type), image_ptr); // We may have to reverse the byte ordering of the image if GL // didn't do it for us. @@ -4554,17 +5017,17 @@ void CLP(GraphicsStateGuardian):: apply_fog(Fog *fog) { #ifndef OPENGLES_2 Fog::Mode fmode = fog->get_mode(); - GLP(Fogf)(GL_FOG_MODE, get_fog_mode_type(fmode)); + glFogf(GL_FOG_MODE, get_fog_mode_type(fmode)); if (fmode == Fog::M_linear) { PN_stdfloat onset, opaque; fog->get_linear_range(onset, opaque); - GLP(Fogf)(GL_FOG_START, onset); - GLP(Fogf)(GL_FOG_END, opaque); + glFogf(GL_FOG_START, onset); + glFogf(GL_FOG_END, opaque); } else { // Exponential fog is always camera-relative. - GLP(Fogf)(GL_FOG_DENSITY, fog->get_exp_density()); + glFogf(GL_FOG_DENSITY, fog->get_exp_density()); } call_glFogfv(GL_FOG_COLOR, fog->get_color()); @@ -4593,7 +5056,7 @@ do_issue_transform() { } DO_PSTATS_STUFF(_transform_state_pcollector.add_level(1)); - GLP(MatrixMode)(GL_MODELVIEW); + glMatrixMode(GL_MODELVIEW); GLPf(LoadMatrix)(transform->get_mat().get_data()); if (_auto_rescale_normal) { @@ -4604,7 +5067,7 @@ do_issue_transform() { #ifndef OPENGLES_1 if (_current_shader_context) { - _current_shader_context->issue_parameters(this, Shader::SSD_transform); + _current_shader_context->issue_parameters(Shader::SSD_transform); } #endif @@ -4622,12 +5085,12 @@ do_issue_shade_model() { const ShadeModelAttrib *target_shade_model = DCAST(ShadeModelAttrib, _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot())); switch (target_shade_model->get_mode()) { case ShadeModelAttrib::M_smooth: - GLP(ShadeModel)(GL_SMOOTH); + glShadeModel(GL_SMOOTH); _flat_shade_model = false; break; case ShadeModelAttrib::M_flat: - GLP(ShadeModel)(GL_FLAT); + glShadeModel(GL_FLAT); _flat_shade_model = true; break; } @@ -4642,7 +5105,7 @@ do_issue_shade_model() { void CLP(GraphicsStateGuardian):: do_issue_shader(bool state_has_changed) { #ifndef OPENGLES_1 - CLP(ShaderContext) *context = 0; + ShaderContext *context = 0; Shader *shader = (Shader *)(_target_shader->get_shader()); #ifdef OPENGLES_2 @@ -4653,19 +5116,19 @@ do_issue_shader(bool state_has_changed) { #endif if (shader) { - context = (CLP(ShaderContext) *)(shader->prepare_now(get_prepared_objects(), this)); + context = shader->prepare_now(get_prepared_objects(), this); } #ifdef OPENGLES_2 // If it failed, try applying the default shader. if (shader != _default_shader && (context == 0 || !context->valid())) { shader = _default_shader; - context = (CLP(ShaderContext) *)(shader->prepare_now(get_prepared_objects(), this)); + context = shader->prepare_now(get_prepared_objects(), this); } #endif if (context == 0 || (context->valid() == false)) { if (_current_shader_context != 0) { - _current_shader_context->unbind(this); + _current_shader_context->unbind(); _current_shader = 0; _current_shader_context = 0; } @@ -4674,19 +5137,19 @@ do_issue_shader(bool state_has_changed) { // Use a completely different shader than before. // Unbind old shader, bind the new one. if (_current_shader_context != 0) { - _current_shader_context->unbind(this); + _current_shader_context->unbind(); } - context->bind(this); + context->bind(); _current_shader = shader; _current_shader_context = context; - context->issue_parameters(this, Shader::SSD_shaderinputs); + context->issue_parameters(Shader::SSD_shaderinputs); } else { #ifdef OPENGLES_2 - context->bind(this, false); + context->bind(false); #endif if (state_has_changed) { // Use the same shader as before, but with new input arguments. - context->issue_parameters(this, Shader::SSD_shaderinputs); + context->issue_parameters(Shader::SSD_shaderinputs); } } } @@ -4712,15 +5175,15 @@ do_issue_render_mode() { case RenderModeAttrib::M_unchanged: case RenderModeAttrib::M_filled: case RenderModeAttrib::M_filled_flat: - GLP(PolygonMode)(GL_FRONT_AND_BACK, GL_FILL); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break; case RenderModeAttrib::M_wireframe: - GLP(PolygonMode)(GL_FRONT_AND_BACK, GL_LINE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break; case RenderModeAttrib::M_point: - GLP(PolygonMode)(GL_FRONT_AND_BACK, GL_POINT); + glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break; default: @@ -4730,9 +5193,9 @@ do_issue_render_mode() { #endif // OPENGLES // The thickness affects both the line width and the point size. - GLP(LineWidth)(_point_size); + glLineWidth(_point_size); #ifndef OPENGLES_2 - GLP(PointSize)(_point_size); + glPointSize(_point_size); #endif report_my_gl_errors(); @@ -4776,26 +5239,26 @@ do_issue_antialias() { #ifndef OPENGLES_2 switch (target_antialias->get_mode_quality()) { case AntialiasAttrib::M_faster: - GLP(Hint)(GL_LINE_SMOOTH_HINT, GL_FASTEST); - GLP(Hint)(GL_POINT_SMOOTH_HINT, GL_FASTEST); + glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST); + glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST); #ifndef OPENGLES - GLP(Hint)(GL_POLYGON_SMOOTH_HINT, GL_FASTEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST); #endif // OPENGLES break; case AntialiasAttrib::M_better: - GLP(Hint)(GL_LINE_SMOOTH_HINT, GL_NICEST); - GLP(Hint)(GL_POINT_SMOOTH_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); #ifndef OPENGLES - GLP(Hint)(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); #endif // OPENGLES break; default: - GLP(Hint)(GL_LINE_SMOOTH_HINT, GL_DONT_CARE); - GLP(Hint)(GL_POINT_SMOOTH_HINT, GL_DONT_CARE); + glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE); + glHint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE); #ifndef OPENGLES - GLP(Hint)(GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE); + glHint(GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE); #endif // OPENGLES break; } @@ -4819,25 +5282,25 @@ do_issue_rescale_normal() { switch (mode) { case RescaleNormalAttrib::M_none: - GLP(Disable)(GL_NORMALIZE); + glDisable(GL_NORMALIZE); if (_supports_rescale_normal && support_rescale_normal) { - GLP(Disable)(GL_RESCALE_NORMAL); + glDisable(GL_RESCALE_NORMAL); } break; case RescaleNormalAttrib::M_rescale: if (_supports_rescale_normal && support_rescale_normal) { - GLP(Enable)(GL_RESCALE_NORMAL); - GLP(Disable)(GL_NORMALIZE); + glEnable(GL_RESCALE_NORMAL); + glDisable(GL_NORMALIZE); } else { - GLP(Enable)(GL_NORMALIZE); + glEnable(GL_NORMALIZE); } break; case RescaleNormalAttrib::M_normalize: - GLP(Enable)(GL_NORMALIZE); + glEnable(GL_NORMALIZE); if (_supports_rescale_normal && support_rescale_normal) { - GLP(Disable)(GL_RESCALE_NORMAL); + glDisable(GL_RESCALE_NORMAL); } break; @@ -4870,7 +5333,7 @@ do_issue_depth_test() { enable_depth_test(false); } else { enable_depth_test(true); - GLP(DepthFunc)(PANDA_TO_GL_COMPAREFUNC(mode)); + glDepthFunc(PANDA_TO_GL_COMPAREFUNC(mode)); } report_my_gl_errors(); } @@ -4892,7 +5355,7 @@ do_issue_alpha_test() { } else { nassertv(GL_NEVER == (AlphaTestAttrib::M_never-1+0x200)); #ifndef OPENGLES_2 - GLP(AlphaFunc)(PANDA_TO_GL_COMPAREFUNC(mode), target_alpha_test->get_reference_alpha()); + glAlphaFunc(PANDA_TO_GL_COMPAREFUNC(mode), target_alpha_test->get_reference_alpha()); #endif enable_alpha_test(true); } @@ -4913,13 +5376,13 @@ do_issue_depth_write() { GLCAT.spam() << "glDepthMask(GL_FALSE)" << endl; #endif - GLP(DepthMask)(GL_FALSE); + glDepthMask(GL_FALSE); } else { #ifdef GSG_VERBOSE GLCAT.spam() << "glDepthMask(GL_TRUE)" << endl; #endif - GLP(DepthMask)(GL_TRUE); + glDepthMask(GL_TRUE); } report_my_gl_errors(); } @@ -4936,15 +5399,15 @@ do_issue_cull_face() { switch (mode) { case CullFaceAttrib::M_cull_none: - GLP(Disable)(GL_CULL_FACE); + glDisable(GL_CULL_FACE); break; case CullFaceAttrib::M_cull_clockwise: - GLP(Enable)(GL_CULL_FACE); - GLP(CullFace)(GL_BACK); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); break; case CullFaceAttrib::M_cull_counter_clockwise: - GLP(Enable)(GL_CULL_FACE); - GLP(CullFace)(GL_FRONT); + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); break; default: GLCAT.error() @@ -4986,7 +5449,7 @@ do_issue_depth_offset() { if (offset != 0) { // The relationship between these two parameters is a little // unclear and poorly explained in the GL man pages. - GLP(PolygonOffset)((GLfloat) -offset, (GLfloat) -offset); + glPolygonOffset((GLfloat) -offset, (GLfloat) -offset); enable_polygon_offset(true); } else { @@ -5001,10 +5464,10 @@ do_issue_depth_offset() { #endif #ifdef OPENGLES // OpenGL ES uses a single-precision call. - GLP(DepthRangef)((GLclampf)min_value, (GLclampf)max_value); + glDepthRangef((GLclampf)min_value, (GLclampf)max_value); #else // Mainline OpenGL uses a double-precision call. - GLP(DepthRange)((GLclampd)min_value, (GLclampd)max_value); + glDepthRange((GLclampd)min_value, (GLclampd)max_value); #endif // OPENGLES report_my_gl_errors(); @@ -5046,12 +5509,12 @@ do_issue_material() { call_glMaterialfv(face, GL_SPECULAR, material->get_specular()); call_glMaterialfv(face, GL_EMISSION, material->get_emission()); - GLP(Materialf)(face, GL_SHININESS, min(material->get_shininess(), (PN_stdfloat)128.0)); + glMaterialf(face, GL_SHININESS, min(material->get_shininess(), (PN_stdfloat)128.0)); if (material->has_ambient() && material->has_diffuse()) { // The material has both an ambient and diffuse specified. This // means we do not need glMaterialColor(). - GLP(Disable)(GL_COLOR_MATERIAL); + glDisable(GL_COLOR_MATERIAL); call_glMaterialfv(face, GL_AMBIENT, material->get_ambient()); call_glMaterialfv(face, GL_DIFFUSE, material->get_diffuse()); @@ -5060,13 +5523,13 @@ do_issue_material() { // The diffuse component comes from the object's color. call_glMaterialfv(face, GL_AMBIENT, material->get_ambient()); if (has_material_force_color) { - GLP(Disable)(GL_COLOR_MATERIAL); + glDisable(GL_COLOR_MATERIAL); call_glMaterialfv(face, GL_DIFFUSE, _material_force_color); } else { #ifndef OPENGLES - GLP(ColorMaterial)(face, GL_DIFFUSE); + glColorMaterial(face, GL_DIFFUSE); #endif // OPENGLES - GLP(Enable)(GL_COLOR_MATERIAL); + glEnable(GL_COLOR_MATERIAL); } } else if (material->has_diffuse()) { @@ -5074,38 +5537,38 @@ do_issue_material() { // The ambient component comes from the object's color. call_glMaterialfv(face, GL_DIFFUSE, material->get_diffuse()); if (has_material_force_color) { - GLP(Disable)(GL_COLOR_MATERIAL); + glDisable(GL_COLOR_MATERIAL); call_glMaterialfv(face, GL_AMBIENT, _material_force_color); } else { #ifndef OPENGLES - GLP(ColorMaterial)(face, GL_AMBIENT); + glColorMaterial(face, GL_AMBIENT); #endif // OPENGLES - GLP(Enable)(GL_COLOR_MATERIAL); + glEnable(GL_COLOR_MATERIAL); } } else { // The material specifies neither a diffuse nor an ambient // component. Both components come from the object's color. if (has_material_force_color) { - GLP(Disable)(GL_COLOR_MATERIAL); + glDisable(GL_COLOR_MATERIAL); call_glMaterialfv(face, GL_AMBIENT, _material_force_color); call_glMaterialfv(face, GL_DIFFUSE, _material_force_color); } else { #ifndef OPENGLES - GLP(ColorMaterial)(face, GL_AMBIENT_AND_DIFFUSE); + glColorMaterial(face, GL_AMBIENT_AND_DIFFUSE); #endif // OPENGLES - GLP(Enable)(GL_COLOR_MATERIAL); + glEnable(GL_COLOR_MATERIAL); } } #ifndef OPENGLES - GLP(LightModeli)(GL_LIGHT_MODEL_LOCAL_VIEWER, material->get_local()); - GLP(LightModeli)(GL_LIGHT_MODEL_TWO_SIDE, material->get_twoside()); + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, material->get_local()); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, material->get_twoside()); - if (CLP(separate_specular_color)) { - GLP(LightModeli)(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); + if (gl_separate_specular_color) { + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); } else { - GLP(LightModeli)(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); } #endif @@ -5135,18 +5598,18 @@ do_issue_blending() { int color_write_slot = ColorWriteAttrib::get_class_slot(); enable_multisample_alpha_one(false); enable_multisample_alpha_mask(false); - if (CLP(color_mask)) { + if (gl_color_mask) { enable_blend(false); - GLP(ColorMask)(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } else { enable_blend(true); _glBlendEquation(GL_FUNC_ADD); - GLP(BlendFunc)(GL_ZERO, GL_ONE); + glBlendFunc(GL_ZERO, GL_ONE); } return; } else { - if (CLP(color_mask)) { - GLP(ColorMask)((color_channels & ColorWriteAttrib::C_red) != 0, + if (gl_color_mask) { + glColorMask((color_channels & ColorWriteAttrib::C_red) != 0, (color_channels & ColorWriteAttrib::C_green) != 0, (color_channels & ColorWriteAttrib::C_blue) != 0, (color_channels & ColorWriteAttrib::C_alpha) != 0); @@ -5169,7 +5632,7 @@ do_issue_blending() { enable_multisample_alpha_mask(false); enable_blend(true); _glBlendEquation(get_blend_equation_type(color_blend_mode)); - GLP(BlendFunc)(get_blend_func(color_blend->get_operand_a()), + glBlendFunc(get_blend_func(color_blend->get_operand_a()), get_blend_func(color_blend->get_operand_b())); if (_color_blend_involves_color_scale) { @@ -5196,7 +5659,7 @@ do_issue_blending() { enable_multisample_alpha_mask(false); enable_blend(true); _glBlendEquation(GL_FUNC_ADD); - GLP(BlendFunc)(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); return; case TransparencyAttrib::M_multisample: @@ -5225,7 +5688,7 @@ do_issue_blending() { enable_multisample_alpha_mask(false); enable_blend(true); _glBlendEquation(GL_FUNC_ADD); - GLP(BlendFunc)(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); return; } @@ -5276,15 +5739,15 @@ bind_light(PointLight *light_obj, const NodePath &light, int light_id) { // GL_SPOT_DIRECTION is not significant when cutoff == 180 // Exponent == 0 implies uniform light distribution - GLP(Lightf)(id, GL_SPOT_EXPONENT, 0.0f); + glLightf(id, GL_SPOT_EXPONENT, 0.0f); // Cutoff == 180 means uniform point light source - GLP(Lightf)(id, GL_SPOT_CUTOFF, 180.0f); + glLightf(id, GL_SPOT_CUTOFF, 180.0f); const LVecBase3 &att = light_obj->get_attenuation(); - GLP(Lightf)(id, GL_CONSTANT_ATTENUATION, att[0]); - GLP(Lightf)(id, GL_LINEAR_ATTENUATION, att[1]); - GLP(Lightf)(id, GL_QUADRATIC_ATTENUATION, att[2]); + glLightf(id, GL_CONSTANT_ATTENUATION, att[0]); + glLightf(id, GL_LINEAR_ATTENUATION, att[1]); + glLightf(id, GL_QUADRATIC_ATTENUATION, att[2]); report_my_gl_errors(); #endif @@ -5327,16 +5790,16 @@ bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) { // In this case, position x, y, z specifies direction // Exponent == 0 implies uniform light distribution - GLP(Lightf)(id, GL_SPOT_EXPONENT, 0.0f); + glLightf(id, GL_SPOT_EXPONENT, 0.0f); // Cutoff == 180 means uniform point light source - GLP(Lightf)(id, GL_SPOT_CUTOFF, 180.0f); + glLightf(id, GL_SPOT_CUTOFF, 180.0f); // Default attenuation values (only spotlight and point light can // modify these) - GLP(Lightf)(id, GL_CONSTANT_ATTENUATION, 1.0f); - GLP(Lightf)(id, GL_LINEAR_ATTENUATION, 0.0f); - GLP(Lightf)(id, GL_QUADRATIC_ATTENUATION, 0.0f); + glLightf(id, GL_CONSTANT_ATTENUATION, 1.0f); + glLightf(id, GL_LINEAR_ATTENUATION, 0.0f); + glLightf(id, GL_QUADRATIC_ATTENUATION, 0.0f); report_my_gl_errors(); #endif @@ -5376,13 +5839,13 @@ bind_light(Spotlight *light_obj, const NodePath &light, int light_id) { call_glLightfv(id, GL_POSITION, fpos); call_glLightfv(id, GL_SPOT_DIRECTION, dir); - GLP(Lightf)(id, GL_SPOT_EXPONENT, light_obj->get_exponent()); - GLP(Lightf)(id, GL_SPOT_CUTOFF, lens->get_hfov() * 0.5f); + glLightf(id, GL_SPOT_EXPONENT, light_obj->get_exponent()); + glLightf(id, GL_SPOT_CUTOFF, lens->get_hfov() * 0.5f); const LVecBase3 &att = light_obj->get_attenuation(); - GLP(Lightf)(id, GL_CONSTANT_ATTENUATION, att[0]); - GLP(Lightf)(id, GL_LINEAR_ATTENUATION, att[1]); - GLP(Lightf)(id, GL_QUADRATIC_ATTENUATION, att[2]); + glLightf(id, GL_CONSTANT_ATTENUATION, att[0]); + glLightf(id, GL_LINEAR_ATTENUATION, att[1]); + glLightf(id, GL_QUADRATIC_ATTENUATION, att[2]); report_my_gl_errors(); #endif @@ -5399,7 +5862,7 @@ void CLP(GraphicsStateGuardian):: draw_immediate_simple_primitives(const GeomPrimitivePipelineReader *reader, GLenum mode) { int num_vertices = reader->get_num_vertices(); _vertices_immediate_pcollector.add_level(num_vertices); - GLP(Begin)(mode); + glBegin(mode); if (reader->is_indexed()) { for (int v = 0; v < num_vertices; ++v) { @@ -5414,7 +5877,7 @@ draw_immediate_simple_primitives(const GeomPrimitivePipelineReader *reader, GLen } } - GLP(End)(); + glEnd(); } #endif // SUPPORT_IMMEDIATE_MODE @@ -5440,12 +5903,12 @@ draw_immediate_composite_primitives(const GeomPrimitivePipelineReader *reader, G for (ei = ends.begin(); ei != ends.end(); ++ei) { int end = (*ei); - GLP(Begin)(mode); + glBegin(mode); for (int v = begin; v < end; ++v) { _sender.set_vertex(reader->get_vertex(v)); _sender.issue_vertex(); } - GLP(End)(); + glEnd(); begin = end + num_unused_vertices_per_primitive; } @@ -5457,11 +5920,11 @@ draw_immediate_composite_primitives(const GeomPrimitivePipelineReader *reader, G for (ei = ends.begin(); ei != ends.end(); ++ei) { int end = (*ei); - GLP(Begin)(mode); + glBegin(mode); for (int v = begin; v < end; ++v) { _sender.issue_vertex(); } - GLP(End)(); + glEnd(); begin = end + num_unused_vertices_per_primitive; } @@ -5477,9 +5940,7 @@ draw_immediate_composite_primitives(const GeomPrimitivePipelineReader *reader, G void CLP(GraphicsStateGuardian):: gl_flush() const { PStatTimer timer(_flush_pcollector); - if (_allow_flush) { - GLP(Flush)(); - } + glFlush(); } //////////////////////////////////////////////////////////////////// @@ -5489,8 +5950,8 @@ gl_flush() const { //////////////////////////////////////////////////////////////////// GLenum CLP(GraphicsStateGuardian):: gl_get_error() const { - if (_track_errors) { - return GLP(GetError)(); + if (_check_errors) { + return glGetError(); } else { return GL_NO_ERROR; } @@ -5507,13 +5968,13 @@ gl_get_error() const { bool CLP(GraphicsStateGuardian):: report_errors_loop(int line, const char *source_file, GLenum error_code, int &error_count) { - while ((CLP(max_errors) < 0 || error_count < CLP(max_errors)) && + while ((gl_max_errors < 0 || error_count < gl_max_errors) && (error_code != GL_NO_ERROR)) { GLCAT.error() << "at " << line << " of " << source_file << " : " << get_error_string(error_code) << "\n"; - error_code = GLP(GetError)(); + error_code = glGetError(); error_count++; } @@ -5566,7 +6027,7 @@ string CLP(GraphicsStateGuardian):: show_gl_string(const string &name, GLenum id) { string result; - const GLubyte *text = GLP(GetString)(id); + const GLubyte *text = glGetString(id); if (text == (const GLubyte *)NULL) { if (GLCAT.is_debug()) { @@ -5597,7 +6058,7 @@ query_gl_version() { _gl_version_major = 0; _gl_version_minor = 0; - const GLubyte *text = GLP(GetString)(GL_VERSION); + const GLubyte *text = glGetString(GL_VERSION); if (text == (const GLubyte *)NULL) { GLCAT.debug() << "Unable to query GL_VERSION\n"; @@ -5643,7 +6104,7 @@ query_gl_version() { } #ifndef OPENGLES if (_gl_version_major==1) { - const char *extstr = (const char *) GLP(GetString)(GL_EXTENSIONS); + const char *extstr = (const char *) glGetString(GL_EXTENSIONS); if (extstr != NULL) { if (strstr( extstr, "GL_ARB_shading_language_100") != NULL) { @@ -5653,7 +6114,7 @@ query_gl_version() { } } else if (_gl_version_major >= 2) { - const char *verstr = (const char *) GLP(GetString)(GL_SHADING_LANGUAGE_VERSION); + const char *verstr = (const char *) glGetString(GL_SHADING_LANGUAGE_VERSION); if ((verstr == NULL) || (sscanf(verstr, "%d.%d", &_gl_shadlang_ver_major, &_gl_shadlang_ver_minor) != 2)) { GLCAT.warning() << "Invalid GL_SHADING_LANGUAGE_VERSION format.\n"; @@ -5742,7 +6203,7 @@ has_extension(const string &extension) const { // available. //////////////////////////////////////////////////////////////////// void *CLP(GraphicsStateGuardian):: -get_extension_func(const char *prefix, const char *name) { +get_extension_func(const char *name) { // First, look in the static-compiled namespace. If we were // compiled to expect at least a certain minimum runtime version of // OpenGL, then we can expect those extension functions to be @@ -5753,54 +6214,54 @@ get_extension_func(const char *prefix, const char *name) { void *fptr; } compiled_function_table[] = { #ifdef EXPECT_GL_VERSION_1_2 - { "BlendColor", (void *)&GLP(BlendColor) }, - { "BlendEquation", (void *)&GLP(BlendEquation) }, - { "DrawRangeElements", (void *)&GLP(DrawRangeElements) }, - { "TexImage3D", (void *)&GLP(TexImage3D) }, - { "TexSubImage3D", (void *)&GLP(TexSubImage3D) }, - { "CopyTexSubImage3D", (void *)&GLP(CopyTexSubImage3D) }, + { "glBlendColor", (void *)&glBlendColor }, + { "glBlendEquation", (void *)&glBlendEquation }, + { "glDrawRangeElements", (void *)&glDrawRangeElements }, + { "glTexImage3D", (void *)&glTexImage3D }, + { "glTexSubImage3D", (void *)&glTexSubImage3D }, + { "glCopyTexSubImage3D", (void *)&glCopyTexSubImage3D }, #endif #ifdef EXPECT_GL_VERSION_1_3 - { "ActiveTexture", (void *)&GLP(ActiveTexture) }, - { "ClientActiveTexture", (void *)&GLP(ClientActiveTexture) }, - { "CompressedTexImage1D", (void *)&GLP(CompressedTexImage1D) }, - { "CompressedTexImage2D", (void *)&GLP(CompressedTexImage2D) }, - { "CompressedTexImage3D", (void *)&GLP(CompressedTexImage3D) }, - { "CompressedTexSubImage1D", (void *)&GLP(CompressedTexSubImage1D) }, - { "CompressedTexSubImage2D", (void *)&GLP(CompressedTexSubImage2D) }, - { "CompressedTexSubImage3D", (void *)&GLP(CompressedTexSubImage3D) }, - { "GetCompressedTexImage", (void *)&GLP(GetCompressedTexImage) }, - { "MultiTexCoord1f", (void *)&GLP(MultiTexCoord1f) }, - { "MultiTexCoord2", (void *)&GLP(MultiTexCoord2) }, - { "MultiTexCoord3", (void *)&GLP(MultiTexCoord3) }, - { "MultiTexCoord4", (void *)&GLP(MultiTexCoord4) }, + { "glActiveTexture", (void *)&glActiveTexture }, + { "glClientActiveTexture", (void *)&glClientActiveTexture }, + { "glCompressedTexImage1D", (void *)&glCompressedTexImage1D }, + { "glCompressedTexImage2D", (void *)&glCompressedTexImage2D }, + { "glCompressedTexImage3D", (void *)&glCompressedTexImage3D }, + { "glCompressedTexSubImage1D", (void *)&glCompressedTexSubImage1D }, + { "glCompressedTexSubImage2D", (void *)&glCompressedTexSubImage2D }, + { "glCompressedTexSubImage3D", (void *)&glCompressedTexSubImage3D }, + { "glGetCompressedTexImage", (void *)&glGetCompressedTexImage }, + { "glMultiTexCoord1f", (void *)&glMultiTexCoord1f }, + { "glMultiTexCoord2", (void *)&glMultiTexCoord2 }, + { "glMultiTexCoord3", (void *)&glMultiTexCoord3 }, + { "glMultiTexCoord4", (void *)&glMultiTexCoord4 }, #endif #ifdef EXPECT_GL_VERSION_1_4 - { "PointParameterfv", (void *)&GLP(PointParameterfv) }, + { "glPointParameterfv", (void *)&glPointParameterfv }, #endif #ifdef EXPECT_GL_VERSION_1_5 - { "BeginQuery", (void *)&GLP(BeginQuery) }, - { "BindBuffer", (void *)&GLP(BindBuffer) }, - { "BufferData", (void *)&GLP(BufferData) }, - { "BufferSubData", (void *)&GLP(BufferSubData) }, - { "DeleteBuffers", (void *)&GLP(DeleteBuffers) }, - { "DeleteQueries", (void *)&GLP(DeleteQueries) }, - { "EndQuery", (void *)&GLP(EndQuery) }, - { "GenBuffers", (void *)&GLP(GenBuffers) }, - { "GenQueries", (void *)&GLP(GenQueries) }, - { "GetQueryObjectuiv", (void *)&GLP(GetQueryObjectuiv) }, - { "GetQueryiv", (void *)&GLP(GetQueryiv) }, + { "glBeginQuery", (void *)&glBeginQuery }, + { "glBindBuffer", (void *)&glBindBuffer }, + { "glBufferData", (void *)&glBufferData }, + { "glBufferSubData", (void *)&glBufferSubData }, + { "glDeleteBuffers", (void *)&glDeleteBuffers }, + { "glDeleteQueries", (void *)&glDeleteQueries }, + { "glEndQuery", (void *)&glEndQuery }, + { "glGenBuffers", (void *)&glGenBuffers }, + { "glGenQueries", (void *)&glGenQueries }, + { "glGetQueryObjectuiv", (void *)&glGetQueryObjectuiv }, + { "glGetQueryiv", (void *)&glGetQueryiv }, #endif #ifdef OPENGLES - { "ActiveTexture", (void *)&GLP(ActiveTexture) }, + { "glActiveTexture", (void *)&glActiveTexture }, #ifndef OPENGLES_2 - { "ClientActiveTexture", (void *)&GLP(ClientActiveTexture) }, + { "glClientActiveTexture", (void *)&glClientActiveTexture }, #endif - { "BindBuffer", (void *)&GLP(BindBuffer) }, - { "BufferData", (void *)&GLP(BufferData) }, - { "BufferSubData", (void *)&GLP(BufferSubData) }, - { "DeleteBuffers", (void *)&GLP(DeleteBuffers) }, - { "GenBuffers", (void *)&GLP(GenBuffers) }, + { "glBindBuffer", (void *)&glBindBuffer }, + { "glBufferData", (void *)&glBufferData }, + { "glBufferSubData", (void *)&glBufferSubData }, + { "glDeleteBuffers", (void *)&glDeleteBuffers }, + { "glGenBuffers", (void *)&glGenBuffers }, #endif { NULL, NULL } }; @@ -5815,7 +6276,7 @@ get_extension_func(const char *prefix, const char *name) { // If the extension function wasn't compiled in, then go get it from // the runtime. There's a different interface for each API. - return do_get_extension_func(prefix, name); + return do_get_extension_func(name); } //////////////////////////////////////////////////////////////////// @@ -5829,15 +6290,14 @@ get_extension_func(const char *prefix, const char *name) { // not available. //////////////////////////////////////////////////////////////////// void *CLP(GraphicsStateGuardian):: -do_get_extension_func(const char *, const char *) { +do_get_extension_func(const char *) { return NULL; } - //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::set_draw_buffer // Access: Protected -// Description: Sets up the GLP(DrawBuffer) to render into the buffer +// Description: 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 affect the depth, // stencil, accum layers. @@ -5886,39 +6346,39 @@ set_draw_buffer(int rbtype) { switch (rbtype & RenderBuffer::T_color) { case RenderBuffer::T_front: - GLP(DrawBuffer)(GL_FRONT); + glDrawBuffer(GL_FRONT); break; case RenderBuffer::T_back: - GLP(DrawBuffer)(GL_BACK); + glDrawBuffer(GL_BACK); break; case RenderBuffer::T_right: - GLP(DrawBuffer)(GL_RIGHT); + glDrawBuffer(GL_RIGHT); break; case RenderBuffer::T_left: - GLP(DrawBuffer)(GL_LEFT); + glDrawBuffer(GL_LEFT); break; case RenderBuffer::T_front_right: nassertv(_current_properties->is_stereo()); - GLP(DrawBuffer)(GL_FRONT_RIGHT); + glDrawBuffer(GL_FRONT_RIGHT); break; case RenderBuffer::T_front_left: nassertv(_current_properties->is_stereo()); - GLP(DrawBuffer)(GL_FRONT_LEFT); + glDrawBuffer(GL_FRONT_LEFT); break; case RenderBuffer::T_back_right: nassertv(_current_properties->is_stereo()); - GLP(DrawBuffer)(GL_BACK_RIGHT); + glDrawBuffer(GL_BACK_RIGHT); break; case RenderBuffer::T_back_left: nassertv(_current_properties->is_stereo()); - GLP(DrawBuffer)(GL_BACK_LEFT); + glDrawBuffer(GL_BACK_LEFT); break; default: @@ -5928,11 +6388,11 @@ set_draw_buffer(int rbtype) { #endif // OPENGLES // Also ensure that any global color channels are masked out. - if (CLP(color_mask)) { - GLP(ColorMask)((_color_write_mask & ColorWriteAttrib::C_red) != 0, - (_color_write_mask & ColorWriteAttrib::C_green) != 0, - (_color_write_mask & ColorWriteAttrib::C_blue) != 0, - (_color_write_mask & ColorWriteAttrib::C_alpha) != 0); + if (gl_color_mask) { + glColorMask((_color_write_mask & ColorWriteAttrib::C_red) != 0, + (_color_write_mask & ColorWriteAttrib::C_green) != 0, + (_color_write_mask & ColorWriteAttrib::C_blue) != 0, + (_color_write_mask & ColorWriteAttrib::C_alpha) != 0); } report_my_gl_errors(); @@ -5941,7 +6401,7 @@ set_draw_buffer(int rbtype) { //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::set_read_buffer // Access: Protected -// Description: Sets up the GLP(ReadBuffer) to render into the buffer +// Description: Sets up the glReadBuffer to render into the buffer // indicated by the RenderBuffer object. This only sets // up the color bits; it does not affect the depth, // stencil, accum layers. @@ -5981,41 +6441,41 @@ set_read_buffer(int rbtype) { } ++index; } - GLP(ReadBuffer)(buffer); + glReadBuffer(buffer); } else { switch (rbtype & RenderBuffer::T_color) { case RenderBuffer::T_front: - GLP(ReadBuffer)(GL_FRONT); + glReadBuffer(GL_FRONT); break; case RenderBuffer::T_back: - GLP(ReadBuffer)(GL_BACK); + glReadBuffer(GL_BACK); break; case RenderBuffer::T_right: - GLP(ReadBuffer)(GL_RIGHT); + glReadBuffer(GL_RIGHT); break; case RenderBuffer::T_left: - GLP(ReadBuffer)(GL_LEFT); + glReadBuffer(GL_LEFT); break; case RenderBuffer::T_front_right: - GLP(ReadBuffer)(GL_FRONT_RIGHT); + glReadBuffer(GL_FRONT_RIGHT); break; case RenderBuffer::T_front_left: - GLP(ReadBuffer)(GL_FRONT_LEFT); + glReadBuffer(GL_FRONT_LEFT); break; case RenderBuffer::T_back_right: - GLP(ReadBuffer)(GL_BACK_RIGHT); + glReadBuffer(GL_BACK_RIGHT); break; case RenderBuffer::T_back_left: - GLP(ReadBuffer)(GL_BACK_LEFT); + glReadBuffer(GL_BACK_LEFT); break; default: @@ -6118,7 +6578,7 @@ get_texture_target(Texture::TextureType texture_type) const { //////////////////////////////////////////////////////////////////// GLenum CLP(GraphicsStateGuardian):: get_texture_wrap_mode(Texture::WrapMode wm) const { - if (CLP(ignore_clamp)) { + if (gl_ignore_clamp) { return GL_REPEAT; } switch (wm) { @@ -6188,7 +6648,7 @@ get_panda_wrap_mode(GLenum wm) { //////////////////////////////////////////////////////////////////// GLenum CLP(GraphicsStateGuardian):: get_texture_filter_type(Texture::FilterType ft, bool ignore_mipmaps) { - if (CLP(ignore_filters)) { + if (gl_ignore_filters) { return GL_NEAREST; } else if (ignore_mipmaps) { @@ -6280,6 +6740,8 @@ get_component_type(Texture::ComponentType component_type) { } else { return GL_UNSIGNED_BYTE; } + case Texture::T_int: + return GL_INT; default: GLCAT.error() << "Invalid Texture::Type value!\n"; return GL_UNSIGNED_BYTE; @@ -6295,14 +6757,18 @@ get_component_type(Texture::ComponentType component_type) { GLint CLP(GraphicsStateGuardian):: get_external_image_format(Texture *tex) const { Texture::CompressionMode compression = tex->get_ram_image_compression(); + Texture::Format format = tex->get_format(); if (compression != Texture::CM_off && get_supports_compressed_texture_format(compression)) { switch (compression) { case Texture::CM_on: #ifndef OPENGLES - switch (tex->get_format()) { + switch (format) { case Texture::F_color_index: case Texture::F_depth_component: + case Texture::F_depth_component16: + case Texture::F_depth_component24: + case Texture::F_depth_component32: case Texture::F_depth_stencil: // This shouldn't be possible. nassertr(false, GL_RGB); @@ -6313,6 +6779,8 @@ get_external_image_format(Texture *tex) const { case Texture::F_rgba4: case Texture::F_rgba8: case Texture::F_rgba12: + case Texture::F_rgba16: + case Texture::F_rgba32: return GL_COMPRESSED_RGBA; case Texture::F_rgb: @@ -6322,6 +6790,7 @@ get_external_image_format(Texture *tex) const { case Texture::F_rgb12: case Texture::F_rgb332: case Texture::F_rgb16: + case Texture::F_rgb32: return GL_COMPRESSED_RGB; case Texture::F_alpha: @@ -6331,9 +6800,11 @@ get_external_image_format(Texture *tex) const { case Texture::F_green: case Texture::F_blue: case Texture::F_r16: + case Texture::F_r32: return GL_COMPRESSED_RED; case Texture::F_rg16: + case Texture::F_rg32: return GL_COMPRESSED_RG; case Texture::F_luminance: @@ -6342,13 +6813,29 @@ get_external_image_format(Texture *tex) const { case Texture::F_luminance_alpha: case Texture::F_luminance_alphamask: return GL_COMPRESSED_LUMINANCE_ALPHA; + + case Texture::F_srgb: + return GL_COMPRESSED_SRGB; + + case Texture::F_srgb_alpha: + return GL_COMPRESSED_SRGB_ALPHA; + + case Texture::F_sluminance: + return GL_COMPRESSED_SLUMINANCE; + + case Texture::F_sluminance_alpha: + return GL_COMPRESSED_SLUMINANCE_ALPHA; } #endif break; #ifndef OPENGLES_1 case Texture::CM_dxt1: - if (Texture::has_alpha(tex->get_format())) { + if (format == Texture::F_srgb_alpha) { + return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; + } else if (format == Texture::F_srgb) { + return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; + } else if (Texture::has_alpha(format)) { return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; } else { return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; @@ -6357,13 +6844,21 @@ get_external_image_format(Texture *tex) const { #ifndef OPENGLES case Texture::CM_dxt3: - return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + if (format == Texture::F_srgb || format == Texture::F_srgb_alpha) { + return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; + } else { + return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + } case Texture::CM_dxt5: - return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + if (format == Texture::F_srgb || format == Texture::F_srgb_alpha) { + return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + } else { + return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + } case Texture::CM_fxt1: - if (Texture::has_alpha(tex->get_format())) { + if (Texture::has_alpha(format)) { return GL_COMPRESSED_RGBA_FXT1_3DFX; } else { return GL_COMPRESSED_RGB_FXT1_3DFX; @@ -6371,14 +6866,22 @@ get_external_image_format(Texture *tex) const { #else case Texture::CM_pvr1_2bpp: - if (Texture::has_alpha(tex->get_format())) { + if (format == Texture::F_srgb_alpha) { + return GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT; + } else if (format == Texture::F_srgb) { + return GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT; + } else if (Texture::has_alpha(format)) { return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; } else { return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; } case Texture::CM_pvr1_4bpp: - if (Texture::has_alpha(tex->get_format())) { + if (format == Texture::F_srgb_alpha) { + return GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT; + } else if (format == Texture::F_srgb) { + return GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT; + } else if (Texture::has_alpha(format)) { return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; } else { return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; @@ -6395,18 +6898,22 @@ get_external_image_format(Texture *tex) const { } } - switch (tex->get_format()) { + switch (format) { #ifndef OPENGLES case Texture::F_color_index: return GL_COLOR_INDEX; #endif case Texture::F_depth_component: + case Texture::F_depth_component16: + case Texture::F_depth_component24: + case Texture::F_depth_component32: return GL_DEPTH_COMPONENT; case Texture::F_depth_stencil: - return _supports_depth_stencil ? GL_DEPTH_STENCIL_EXT : GL_DEPTH_COMPONENT; + return _supports_depth_stencil ? GL_DEPTH_STENCIL : GL_DEPTH_COMPONENT; #ifndef OPENGLES case Texture::F_red: case Texture::F_r16: + case Texture::F_r32: return GL_RED; case Texture::F_green: return GL_GREEN; @@ -6417,6 +6924,7 @@ get_external_image_format(Texture *tex) const { return GL_ALPHA; #ifndef OPENGLES_1 case Texture::F_rg16: + case Texture::F_rg32: return GL_RG; #endif case Texture::F_rgb: @@ -6425,6 +6933,8 @@ get_external_image_format(Texture *tex) const { case Texture::F_rgb12: case Texture::F_rgb332: case Texture::F_rgb16: + case Texture::F_rgb32: + case Texture::F_srgb: #ifdef OPENGLES return GL_RGB; #else @@ -6438,16 +6948,24 @@ get_external_image_format(Texture *tex) const { case Texture::F_rgba12: case Texture::F_rgba16: case Texture::F_rgba32: + case Texture::F_srgb_alpha: #ifdef OPENGLES_2 return GL_RGBA; #else return _supports_bgr ? GL_BGRA : GL_RGBA; #endif case Texture::F_luminance: + case Texture::F_sluminance: return GL_LUMINANCE; case Texture::F_luminance_alphamask: case Texture::F_luminance_alpha: + case Texture::F_sluminance_alpha: return GL_LUMINANCE_ALPHA; + +#ifndef OPENGLES + case Texture::F_r32i: + return GL_RED_INTEGER; +#endif } GLCAT.error() << "Invalid Texture::Format value in get_external_image_format(): " @@ -6467,6 +6985,7 @@ get_internal_image_format(Texture *tex) const { if (compression == Texture::CM_default) { compression = (compressed_textures) ? Texture::CM_on : Texture::CM_off; } + Texture::Format format = tex->get_format(); if (tex->get_render_to_texture()) { // no compression for render targets compression = Texture::CM_off; @@ -6485,7 +7004,7 @@ get_internal_image_format(Texture *tex) const { // appropriate choice), since that makes saving the result as a // pre-compressed texture more dependable--this way, we will know // which compression algorithm was applied. - switch (tex->get_format()) { + switch (format) { case Texture::F_color_index: case Texture::F_depth_component: case Texture::F_depth_stencil: @@ -6511,6 +7030,8 @@ get_internal_image_format(Texture *tex) const { case Texture::F_rgba: case Texture::F_rgba8: case Texture::F_rgba12: + case Texture::F_rgba16: + case Texture::F_rgba32: if (get_supports_compressed_texture_format(Texture::CM_dxt5) && !is_3d) { return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; } else if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) { @@ -6525,6 +7046,7 @@ get_internal_image_format(Texture *tex) const { case Texture::F_rgb12: case Texture::F_rgb332: case Texture::F_rgb16: + case Texture::F_rgb32: if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) { return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; } else if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) { @@ -6544,6 +7066,7 @@ get_internal_image_format(Texture *tex) const { case Texture::F_green: case Texture::F_blue: case Texture::F_r16: + case Texture::F_r32: if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) { return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; } else if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) { @@ -6552,6 +7075,7 @@ get_internal_image_format(Texture *tex) const { return GL_COMPRESSED_RED; case Texture::F_rg16: + case Texture::F_rg32: if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) { return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; } else if (get_supports_compressed_texture_format(Texture::CM_fxt1) && !is_3d) { @@ -6577,11 +7101,33 @@ get_internal_image_format(Texture *tex) const { return GL_COMPRESSED_LUMINANCE_ALPHA; } break; + + case Texture::F_srgb: + if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) { + return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; + } + return GL_COMPRESSED_SRGB; + + case Texture::F_srgb_alpha: + if (get_supports_compressed_texture_format(Texture::CM_dxt5) && !is_3d) { + return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + } + return GL_COMPRESSED_SRGB_ALPHA; + + case Texture::F_sluminance: + return GL_COMPRESSED_SLUMINANCE; + + case Texture::F_sluminance_alpha: + return GL_COMPRESSED_SLUMINANCE_ALPHA; #endif #ifndef OPENGLES_1 case Texture::CM_dxt1: - if (Texture::has_alpha(tex->get_format())) { + if (format == Texture::F_srgb_alpha) { + return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; + } else if (format == Texture::F_srgb) { + return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; + } else if (Texture::has_alpha(format)) { return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; } else { return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; @@ -6590,27 +7136,43 @@ get_internal_image_format(Texture *tex) const { #ifndef OPENGLES case Texture::CM_dxt3: - return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + if (format == Texture::F_srgb || format == Texture::F_srgb_alpha) { + return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; + } else { + return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + } case Texture::CM_dxt5: - return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + if (format == Texture::F_srgb || format == Texture::F_srgb_alpha) { + return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + } else { + return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + } case Texture::CM_fxt1: - if (Texture::has_alpha(tex->get_format())) { + if (Texture::has_alpha(format)) { return GL_COMPRESSED_RGBA_FXT1_3DFX; } else { return GL_COMPRESSED_RGB_FXT1_3DFX; } #else case Texture::CM_pvr1_2bpp: - if (Texture::has_alpha(tex->get_format())) { + if (format == Texture::F_srgb_alpha) { + return GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT; + } else if (format == Texture::F_srgb) { + return GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT; + } else if (Texture::has_alpha(format)) { return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; } else { return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; } case Texture::CM_pvr1_4bpp: - if (Texture::has_alpha(tex->get_format())) { + if (format == Texture::F_srgb_alpha) { + return GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT; + } else if (format == Texture::F_srgb) { + return GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT; + } else if (Texture::has_alpha(format)) { return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; } else { return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; @@ -6626,11 +7188,22 @@ get_internal_image_format(Texture *tex) const { } } - switch (tex->get_format()) { + switch (format) { #ifndef OPENGLES case Texture::F_color_index: return GL_COLOR_INDEX; #endif + + case Texture::F_depth_stencil: + if (_supports_depth_stencil) { + if (tex->get_component_type() == Texture::T_float) { + return GL_DEPTH32F_STENCIL8; + } else { + return GL_DEPTH_STENCIL; + } + } + // Fall through. + case Texture::F_depth_component: #ifndef OPENGLES if (tex->get_component_type() == Texture::T_float) { @@ -6675,16 +7248,14 @@ get_internal_image_format(Texture *tex) const { } #endif - case Texture::F_depth_stencil: - if (_supports_depth_stencil) { - return GL_DEPTH_STENCIL_EXT; - } else { - return GL_DEPTH_COMPONENT; - } - case Texture::F_rgba: case Texture::F_rgbm: - return GL_RGBA; + if (tex->get_component_type() == Texture::T_float) { + return GL_RGBA16F; + } else { + return GL_RGBA; + } + case Texture::F_rgba4: return GL_RGBA4; @@ -6695,23 +7266,28 @@ get_internal_image_format(Texture *tex) const { return GL_RGBA; #ifndef OPENGLES_1 case Texture::F_rgba16: - return GL_RGBA16F_EXT; + return GL_RGBA16F; #endif // OPENGLES_1 case Texture::F_rgba32: - return GL_RGBA32F_EXT; + return GL_RGBA32F; #else case Texture::F_rgba8: return GL_RGBA8; case Texture::F_rgba12: return GL_RGBA12; case Texture::F_rgba16: - return GL_RGBA16F_ARB; + return GL_RGBA16F; case Texture::F_rgba32: - return GL_RGBA32F_ARB; + return GL_RGBA32F; #endif // OPENGLES case Texture::F_rgb: - return GL_RGB; + if (tex->get_component_type() == Texture::T_float) { + return GL_RGB16F; + } else { + return GL_RGB; + } + case Texture::F_rgb5: #ifdef OPENGLES // Close enough. @@ -6728,7 +7304,7 @@ get_internal_image_format(Texture *tex) const { case Texture::F_rgb12: return GL_RGB; case Texture::F_rgb16: - return GL_RGB16F_EXT; + return GL_RGB16F; #else case Texture::F_rgb8: return GL_RGB8; @@ -6741,6 +7317,8 @@ get_internal_image_format(Texture *tex) const { return GL_RGB16; } #endif // OPENGLES + case Texture::F_rgb32: + return GL_RGB32F; #ifndef OPENGLES case Texture::F_rgb332: @@ -6766,6 +7344,10 @@ get_internal_image_format(Texture *tex) const { return GL_RG16; } #endif + case Texture::F_r32: + return GL_R32F; + case Texture::F_rg32: + return GL_RG32F; case Texture::F_alpha: return GL_ALPHA; @@ -6783,6 +7365,22 @@ get_internal_image_format(Texture *tex) const { case Texture::F_luminance_alphamask: return GL_LUMINANCE_ALPHA; +#ifndef OPENGLES_1 + case Texture::F_srgb: + return GL_SRGB8; + case Texture::F_srgb_alpha: + return GL_SRGB8_ALPHA8; + case Texture::F_sluminance: + return GL_SLUMINANCE8; + case Texture::F_sluminance_alpha: + return GL_SLUMINANCE8_ALPHA8; +#endif + +#ifndef OPENGLES + case Texture::F_r32i: + return GL_R32I; +#endif + default: GLCAT.error() << "Invalid image format in get_internal_image_format(): " @@ -7146,49 +7744,49 @@ print_gfx_visual() { cout << "Graphics Visual Info (# bits of each):" << endl; cout << "RGBA: "; - GLP(GetIntegerv)( GL_RED_BITS, &i ); cout << i << " "; - GLP(GetIntegerv)( GL_GREEN_BITS, &i ); cout << i << " "; - GLP(GetIntegerv)( GL_BLUE_BITS, &i ); cout << i << " "; - GLP(GetIntegerv)( GL_ALPHA_BITS, &i ); cout << i << endl; + glGetIntegerv( GL_RED_BITS, &i ); cout << i << " "; + glGetIntegerv( GL_GREEN_BITS, &i ); cout << i << " "; + glGetIntegerv( GL_BLUE_BITS, &i ); cout << i << " "; + glGetIntegerv( GL_ALPHA_BITS, &i ); cout << i << endl; #ifndef OPENGLES cout << "Accum RGBA: "; - GLP(GetIntegerv)( GL_ACCUM_RED_BITS, &i ); cout << i << " "; - GLP(GetIntegerv)( GL_ACCUM_GREEN_BITS, &i ); cout << i << " "; - GLP(GetIntegerv)( GL_ACCUM_BLUE_BITS, &i ); cout << i << " "; - GLP(GetIntegerv)( GL_ACCUM_ALPHA_BITS, &i ); cout << i << endl; + glGetIntegerv( GL_ACCUM_RED_BITS, &i ); cout << i << " "; + glGetIntegerv( GL_ACCUM_GREEN_BITS, &i ); cout << i << " "; + glGetIntegerv( GL_ACCUM_BLUE_BITS, &i ); cout << i << " "; + glGetIntegerv( GL_ACCUM_ALPHA_BITS, &i ); cout << i << endl; - GLP(GetIntegerv)( GL_INDEX_BITS, &i ); cout << "Color Index: " << i << endl; + glGetIntegerv( GL_INDEX_BITS, &i ); cout << "Color Index: " << i << endl; #endif - GLP(GetIntegerv)( GL_DEPTH_BITS, &i ); cout << "Depth: " << i << endl; - GLP(GetIntegerv)( GL_ALPHA_BITS, &i ); cout << "Alpha: " << i << endl; - GLP(GetIntegerv)( GL_STENCIL_BITS, &i ); cout << "Stencil: " << i << endl; + glGetIntegerv( GL_DEPTH_BITS, &i ); cout << "Depth: " << i << endl; + glGetIntegerv( GL_ALPHA_BITS, &i ); cout << "Alpha: " << i << endl; + glGetIntegerv( GL_STENCIL_BITS, &i ); cout << "Stencil: " << i << endl; #ifndef OPENGLES - GLP(GetBooleanv)( GL_DOUBLEBUFFER, &j ); cout << "DoubleBuffer? " + glGetBooleanv( GL_DOUBLEBUFFER, &j ); cout << "DoubleBuffer? " << (int)j << endl; - GLP(GetBooleanv)( GL_STEREO, &j ); cout << "Stereo? " << (int)j << endl; + glGetBooleanv( GL_STEREO, &j ); cout << "Stereo? " << (int)j << endl; #endif if (_supports_multisample) { #ifndef OPENGLES_2 - GLP(GetBooleanv)( GL_MULTISAMPLE, &j ); cout << "Multisample? " << (int)j << endl; + glGetBooleanv( GL_MULTISAMPLE, &j ); cout << "Multisample? " << (int)j << endl; #endif - GLP(GetIntegerv)( GL_SAMPLES, &i ); cout << "Samples: " << i << endl; + glGetIntegerv( GL_SAMPLES, &i ); cout << "Samples: " << i << endl; } - GLP(GetBooleanv)( GL_BLEND, &j ); cout << "Blend? " << (int)j << endl; + glGetBooleanv( GL_BLEND, &j ); cout << "Blend? " << (int)j << endl; #ifndef OPENGLES_2 - GLP(GetBooleanv)( GL_POINT_SMOOTH, &j ); cout << "Point Smooth? " + glGetBooleanv( GL_POINT_SMOOTH, &j ); cout << "Point Smooth? " << (int)j << endl; - GLP(GetBooleanv)( GL_LINE_SMOOTH, &j ); cout << "Line Smooth? " + glGetBooleanv( GL_LINE_SMOOTH, &j ); cout << "Line Smooth? " << (int)j << endl; #endif #ifndef OPENGLES - GLP(GetIntegerv)( GL_AUX_BUFFERS, &i ); cout << "Aux Buffers: " << i << endl; + glGetIntegerv( GL_AUX_BUFFERS, &i ); cout << "Aux Buffers: " << i << endl; #endif } @@ -7249,9 +7847,9 @@ enable_lighting(bool enable) { // PStatTimer timer(_draw_set_state_light_enable_lighting_pcollector); if (enable) { - GLP(Enable)(GL_LIGHTING); + glEnable(GL_LIGHTING); } else { - GLP(Disable)(GL_LIGHTING); + glDisable(GL_LIGHTING); } #endif } @@ -7292,9 +7890,9 @@ enable_light(int light_id, bool enable) { // PStatTimer timer(_draw_set_state_light_enable_light_pcollector); if (enable) { - GLP(Enable)(get_light_id(light_id)); + glEnable(get_light_id(light_id)); } else { - GLP(Disable)(get_light_id(light_id)); + glDisable(get_light_id(light_id)); } } @@ -7326,8 +7924,8 @@ begin_bind_lights() { CPT(TransformState) render_transform = _cs_transform->compose(_scene_setup->get_world_transform()); - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PushMatrix)(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); GLPf(LoadMatrix)(render_transform->get_mat().get_data()); #endif } @@ -7347,8 +7945,8 @@ end_bind_lights() { // static PStatCollector _draw_set_state_light_end_bind_pcollector("Draw:Set State:Light:End bind"); // PStatTimer timer(_draw_set_state_light_end_bind_pcollector); - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PopMatrix)(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); #endif } @@ -7363,9 +7961,9 @@ end_bind_lights() { void CLP(GraphicsStateGuardian):: enable_clip_plane(int plane_id, bool enable) { if (enable) { - GLP(Enable)(get_clip_plane_id(plane_id)); + glEnable(get_clip_plane_id(plane_id)); } else { - GLP(Disable)(get_clip_plane_id(plane_id)); + glDisable(get_clip_plane_id(plane_id)); } } @@ -7394,8 +7992,8 @@ begin_bind_clip_planes() { CPT(TransformState) render_transform = _cs_transform->compose(_scene_setup->get_world_transform()); - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PushMatrix)(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); GLPf(LoadMatrix)(render_transform->get_mat().get_data()); #endif } @@ -7421,11 +8019,11 @@ bind_clip_plane(const NodePath &plane, int plane_id) { #ifdef OPENGLES // OpenGL ES uses a single-precision call. LPlanef single_plane(LCAST(float, xformed_plane)); - GLP(ClipPlanef)(id, single_plane.get_data()); + glClipPlanef(id, single_plane.get_data()); #else // Mainline OpenGL uses a double-precision call. LPlaned double_plane(LCAST(double, xformed_plane)); - GLP(ClipPlane)(id, double_plane.get_data()); + glClipPlane(id, double_plane.get_data()); #endif // OPENGLES #endif // OPENGLES_2 @@ -7444,8 +8042,8 @@ bind_clip_plane(const NodePath &plane, int plane_id) { void CLP(GraphicsStateGuardian):: end_bind_clip_planes() { #ifndef OPENGLES_2 - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PopMatrix)(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); #endif } @@ -7549,8 +8147,8 @@ set_state_and_transform(const RenderState *target, _state_mask.set_bit(color_scale_slot); #ifndef OPENGLES_1 if (_current_shader_context) { - _current_shader_context->issue_parameters(this, Shader::SSD_color); - _current_shader_context->issue_parameters(this, Shader::SSD_colorscale); + _current_shader_context->issue_parameters(Shader::SSD_color); + _current_shader_context->issue_parameters(Shader::SSD_colorscale); } #endif } @@ -7701,7 +8299,7 @@ set_state_and_transform(const RenderState *target, _state_mask.set_bit(material_slot); #ifndef OPENGLES_1 if (_current_shader_context) { - _current_shader_context->issue_parameters(this, Shader::SSD_material); + _current_shader_context->issue_parameters(Shader::SSD_material); } #endif } @@ -7730,7 +8328,7 @@ set_state_and_transform(const RenderState *target, _state_mask.set_bit(fog_slot); #ifndef OPENGLES_1 if (_current_shader_context) { - _current_shader_context->issue_parameters(this, Shader::SSD_fog); + _current_shader_context->issue_parameters(Shader::SSD_fog); } #endif } @@ -7770,12 +8368,12 @@ do_auto_rescale_normal() { #ifndef OPENGLES_2 if (_internal_transform->has_identity_scale()) { // If there's no scale at all, don't do anything. - GLP(Disable)(GL_NORMALIZE); + glDisable(GL_NORMALIZE); if (GLCAT.is_spam()) { GLCAT.spam() << "glDisable(GL_NORMALIZE)\n"; } if (_supports_rescale_normal && support_rescale_normal) { - GLP(Disable)(GL_RESCALE_NORMAL); + glDisable(GL_RESCALE_NORMAL); if (GLCAT.is_spam()) { GLCAT.spam() << "glDisable(GL_RESCALE_NORMAL)\n"; } @@ -7784,14 +8382,14 @@ do_auto_rescale_normal() { } else if (_internal_transform->has_uniform_scale()) { // There's a uniform scale; use the rescale feature if available. if (_supports_rescale_normal && support_rescale_normal) { - GLP(Enable)(GL_RESCALE_NORMAL); - GLP(Disable)(GL_NORMALIZE); + glEnable(GL_RESCALE_NORMAL); + glDisable(GL_NORMALIZE); if (GLCAT.is_spam()) { GLCAT.spam() << "glEnable(GL_RESCALE_NORMAL)\n"; GLCAT.spam() << "glDisable(GL_NORMALIZE)\n"; } } else { - GLP(Enable)(GL_NORMALIZE); + glEnable(GL_NORMALIZE); if (GLCAT.is_spam()) { GLCAT.spam() << "glEnable(GL_NORMALIZE)\n"; } @@ -7799,12 +8397,12 @@ do_auto_rescale_normal() { } else { // If there's a non-uniform scale, normalize everything. - GLP(Enable)(GL_NORMALIZE); + glEnable(GL_NORMALIZE); if (GLCAT.is_spam()) { GLCAT.spam() << "glEnable(GL_NORMALIZE)\n"; } if (_supports_rescale_normal && support_rescale_normal) { - GLP(Disable)(GL_RESCALE_NORMAL); + glDisable(GL_RESCALE_NORMAL); if (GLCAT.is_spam()) { GLCAT.spam() << "glDisable(GL_RESCALE_NORMAL)\n"; } @@ -7829,16 +8427,16 @@ do_issue_texture() { if (_current_shader_context == 0 || !_current_shader_context->uses_custom_texture_bindings()) { // No shader, or a non-Cg shader. if (_texture_binding_shader_context != 0) { - _texture_binding_shader_context->disable_shader_texture_bindings(this); + _texture_binding_shader_context->disable_shader_texture_bindings(); } update_standard_texture_bindings(); } else { if (_texture_binding_shader_context == 0) { disable_standard_texture_bindings(); - _current_shader_context->update_shader_texture_bindings(NULL,this); + _current_shader_context->update_shader_texture_bindings(NULL); } else { _current_shader_context-> - update_shader_texture_bindings(_texture_binding_shader_context,this); + update_shader_texture_bindings(_texture_binding_shader_context); } } @@ -7911,16 +8509,16 @@ update_standard_texture_bindings() { // First, turn off the previous texture mode. #ifndef OPENGLES_2 #ifndef OPENGLES - GLP(Disable)(GL_TEXTURE_1D); + glDisable(GL_TEXTURE_1D); #endif // OPENGLES - GLP(Disable)(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_2D); if (_supports_3d_texture) { #ifndef OPENGLES_1 - GLP(Disable)(GL_TEXTURE_3D); + glDisable(GL_TEXTURE_3D); #endif // OPENGLES_1 } if (_supports_cube_map) { - GLP(Disable)(GL_TEXTURE_CUBE_MAP); + glDisable(GL_TEXTURE_CUBE_MAP); } #endif // OPENGLES_2 @@ -7944,15 +8542,16 @@ update_standard_texture_bindings() { continue; } #endif - GLP(Enable)(target); + glEnable(target); #endif if (!update_texture(tc, false)) { #ifndef OPENGLES_2 - GLP(Disable)(target); + glDisable(target); #endif continue; } + apply_texture(tc); if (stage->involves_color_scale() && _color_scale_enabled) { LColor color = stage->get_color(); @@ -7971,88 +8570,88 @@ update_standard_texture_bindings() { // Make a special case for 1- and 2-channel decal textures. // OpenGL does not define their use with GL_DECAL for some // reason, so implement them using the combiner instead. - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_RGB_SCALE, 1); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_TEXTURE); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); + glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1); + glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); } else { // Normal 3- and 4-channel decal textures. - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); } } else if (stage->get_mode() == TextureStage::M_combine) { if (!_supports_texture_combine) { GLCAT.warning() << "TextureStage::M_combine mode is not supported.\n"; - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } else { - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_RGB_SCALE, stage->get_rgb_scale()); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_ALPHA_SCALE, stage->get_alpha_scale()); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_COMBINE_RGB, + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); + glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, stage->get_rgb_scale()); + glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, stage->get_alpha_scale()); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, get_texture_combine_type(stage->get_combine_rgb_mode())); switch (stage->get_num_combine_rgb_operands()) { case 3: - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_SRC2_RGB, + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, get_texture_src_type(stage->get_combine_rgb_source2(), last_stage, last_saved_result, i)); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_OPERAND2_RGB, + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, get_texture_operand_type(stage->get_combine_rgb_operand2())); // fall through case 2: - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_SRC1_RGB, + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, get_texture_src_type(stage->get_combine_rgb_source1(), last_stage, last_saved_result, i)); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_OPERAND1_RGB, + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, get_texture_operand_type(stage->get_combine_rgb_operand1())); // fall through case 1: - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_SRC0_RGB, + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, get_texture_src_type(stage->get_combine_rgb_source0(), last_stage, last_saved_result, i)); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_OPERAND0_RGB, + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, get_texture_operand_type(stage->get_combine_rgb_operand0())); // fall through default: break; } - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, get_texture_combine_type(stage->get_combine_alpha_mode())); switch (stage->get_num_combine_alpha_operands()) { case 3: - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_SRC2_ALPHA, + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_ALPHA, get_texture_src_type(stage->get_combine_alpha_source2(), last_stage, last_saved_result, i)); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, get_texture_operand_type(stage->get_combine_alpha_operand2())); // fall through case 2: - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_SRC1_ALPHA, + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, get_texture_src_type(stage->get_combine_alpha_source1(), last_stage, last_saved_result, i)); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, get_texture_operand_type(stage->get_combine_alpha_operand1())); // fall through case 1: - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_SRC0_ALPHA, + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, get_texture_src_type(stage->get_combine_alpha_source0(), last_stage, last_saved_result, i)); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, get_texture_operand_type(stage->get_combine_alpha_operand0())); // fall through @@ -8062,7 +8661,7 @@ update_standard_texture_bindings() { } } else { GLint glmode = get_texture_apply_mode_type(stage->get_mode()); - GLP(TexEnvi)(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, glmode); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, glmode); } if (stage->get_saved_result()) { @@ -8081,16 +8680,16 @@ update_standard_texture_bindings() { for (i = num_stages; i < _num_active_texture_stages; i++) { _glActiveTexture(GL_TEXTURE0 + i); #ifndef OPENGLES - GLP(Disable)(GL_TEXTURE_1D); + glDisable(GL_TEXTURE_1D); #endif // OPENGLES - GLP(Disable)(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_2D); if (_supports_3d_texture) { #ifndef OPENGLES_1 - GLP(Disable)(GL_TEXTURE_3D); + glDisable(GL_TEXTURE_3D); #endif // OPENGLES_1 } if (_supports_cube_map) { - GLP(Disable)(GL_TEXTURE_CUBE_MAP); + glDisable(GL_TEXTURE_CUBE_MAP); } } #endif // OPENGLES_2 @@ -8149,16 +8748,16 @@ update_show_usage_texture_bindings(int show_stage_index) { for (i = 0; i < _num_active_texture_stages; i++) { _glActiveTexture(GL_TEXTURE0 + i); #ifndef OPENGLES - GLP(Disable)(GL_TEXTURE_1D); + glDisable(GL_TEXTURE_1D); #endif // OPENGLES - GLP(Disable)(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_2D); if (_supports_3d_texture) { #ifndef OPENGLES_1 - GLP(Disable)(GL_TEXTURE_3D); + glDisable(GL_TEXTURE_3D); #endif // OPENGLES_1 } if (_supports_cube_map) { - GLP(Disable)(GL_TEXTURE_CUBE_MAP); + glDisable(GL_TEXTURE_CUBE_MAP); } } #endif @@ -8181,7 +8780,7 @@ update_show_usage_texture_bindings(int show_stage_index) { // Choose the corresponding usage texture and apply it. _glActiveTexture(GL_TEXTURE0 + i); #ifndef OPENGLES_2 - GLP(Enable)(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_2D); #endif UsageTextureKey key(texture->get_x_size(), texture->get_y_size()); @@ -8189,15 +8788,17 @@ update_show_usage_texture_bindings(int show_stage_index) { if (ui == _usage_textures.end()) { // Need to create a new texture for this size. GLuint index; - GLP(GenTextures)(1, &index); - GLP(BindTexture)(GL_TEXTURE_2D, index); + glGenTextures(1, &index); + glBindTexture(GL_TEXTURE_2D, index); + //TODO: this could be a lot simpler with glTexStorage2D + // followed by a call to glClearTexImage. upload_usage_texture(texture->get_x_size(), texture->get_y_size()); _usage_textures[key] = index; } else { // Just bind the previously-created texture. GLuint index = (*ui).second; - GLP(BindTexture)(GL_TEXTURE_2D, index); + glBindTexture(GL_TEXTURE_2D, index); } } @@ -8215,10 +8816,10 @@ update_show_usage_texture_bindings(int show_stage_index) { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: upload_usage_texture(int width, int height) { - GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (GLCAT.is_debug()) { GLCAT.debug() @@ -8261,8 +8862,8 @@ upload_usage_texture(int width, int height) { buffer[p] = store.w; } - GLP(TexImage2D)(GL_TEXTURE_2D, n, GL_RGBA, width, height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, buffer); + glTexImage2D(GL_TEXTURE_2D, n, GL_RGBA, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, buffer); if (width == 1 && height == 1) { // That was the last mipmap level. break; @@ -8289,16 +8890,16 @@ disable_standard_texture_bindings() { for (int i = 0; i < _num_active_texture_stages; i++) { _glActiveTexture(GL_TEXTURE0 + i); #ifndef OPENGLES - GLP(Disable)(GL_TEXTURE_1D); + glDisable(GL_TEXTURE_1D); #endif // OPENGLES - GLP(Disable)(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_2D); if (_supports_3d_texture) { #ifndef OPENGLES_1 - GLP(Disable)(GL_TEXTURE_3D); + glDisable(GL_TEXTURE_3D); #endif // OPENGLES_1 } if (_supports_cube_map) { - GLP(Disable)(GL_TEXTURE_CUBE_MAP); + glDisable(GL_TEXTURE_CUBE_MAP); } } @@ -8322,13 +8923,13 @@ do_issue_tex_matrix() { TextureStage *stage = _target_texture->get_on_ff_stage(i); _glActiveTexture(GL_TEXTURE0 + i); - GLP(MatrixMode)(GL_TEXTURE); + glMatrixMode(GL_TEXTURE); const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot())); if (target_tex_matrix->has_stage(stage)) { GLPf(LoadMatrix)(target_tex_matrix->get_mat(stage).get_data()); } else { - GLP(LoadIdentity)(); + glLoadIdentity(); // For some reason, the glLoadIdentity() call doesn't work on // my Dell laptop's IBM OpenGL driver, when used in @@ -8374,18 +8975,18 @@ do_issue_tex_gen() { #ifndef OPENGLES_2 if (_supports_point_sprite) { #ifdef OPENGLES - GLP(TexEnvi)(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_FALSE); + glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_FALSE); #else - GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_FALSE); + glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_FALSE); #endif // OPENGLES } #endif // OPENGLES_2 #ifndef OPENGLES // TexGen not supported by OpenGL ES. - GLP(Disable)(GL_TEXTURE_GEN_S); - GLP(Disable)(GL_TEXTURE_GEN_T); - GLP(Disable)(GL_TEXTURE_GEN_R); - GLP(Disable)(GL_TEXTURE_GEN_Q); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_GEN_Q); TexGenAttrib::Mode mode = _target_tex_gen->get_mode(stage); switch (mode) { @@ -8394,10 +8995,10 @@ do_issue_tex_gen() { break; case TexGenAttrib::M_eye_sphere_map: - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); force_normal = true; break; @@ -8408,19 +9009,19 @@ do_issue_tex_gen() { // by composing a transform onto the texture matrix. LMatrix4 mat = _inv_cs_transform->get_mat(); mat.set_row(3, LVecBase3(0.0f, 0.0f, 0.0f)); - GLP(MatrixMode)(GL_TEXTURE); + glMatrixMode(GL_TEXTURE); GLPf(MultMatrix)(mat.get_data()); // Now we need to reset the texture matrix next time // around to undo this. _tex_gen_modifies_mat = true; - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); force_normal = true; } break; @@ -8437,19 +9038,19 @@ do_issue_tex_gen() { LMatrix4 mat = camera_transform->get_mat(); mat.set_row(3, LVecBase3(0.0f, 0.0f, 0.0f)); - GLP(MatrixMode)(GL_TEXTURE); + glMatrixMode(GL_TEXTURE); GLPf(MultMatrix)(mat.get_data()); // Now we need to reset the texture matrix next time // around to undo this. _tex_gen_modifies_mat = true; - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); force_normal = true; } break; @@ -8461,19 +9062,19 @@ do_issue_tex_gen() { // by composing a transform onto the texture matrix. LMatrix4 mat = _inv_cs_transform->get_mat(); mat.set_row(3, LVecBase3(0.0f, 0.0f, 0.0f)); - GLP(MatrixMode)(GL_TEXTURE); + glMatrixMode(GL_TEXTURE); GLPf(MultMatrix)(mat.get_data()); // Now we need to reset the texture matrix next time // around to undo this. _tex_gen_modifies_mat = true; - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); force_normal = true; } break; @@ -8490,19 +9091,19 @@ do_issue_tex_gen() { LMatrix4 mat = camera_transform->get_mat(); mat.set_row(3, LVecBase3(0.0f, 0.0f, 0.0f)); - GLP(MatrixMode)(GL_TEXTURE); + glMatrixMode(GL_TEXTURE); GLPf(MultMatrix)(mat.get_data()); // Now we need to reset the texture matrix next time // around to undo this. _tex_gen_modifies_mat = true; - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); force_normal = true; } break; @@ -8510,27 +9111,27 @@ do_issue_tex_gen() { case TexGenAttrib::M_eye_position: // To represent eye position correctly, we need to temporarily // load the coordinate-system transform. - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PushMatrix)(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); GLPf(LoadMatrix)(_cs_transform->get_mat().get_data()); - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); GLPfv(TexGen)(GL_S, GL_EYE_PLANE, s_data); GLPfv(TexGen)(GL_T, GL_EYE_PLANE, t_data); GLPfv(TexGen)(GL_R, GL_EYE_PLANE, r_data); GLPfv(TexGen)(GL_Q, GL_EYE_PLANE, q_data); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); - GLP(Enable)(GL_TEXTURE_GEN_Q); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_GEN_Q); - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PopMatrix)(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); break; case TexGenAttrib::M_world_position: @@ -8538,36 +9139,36 @@ do_issue_tex_gen() { // position mode, and loading the transform of the root // node--thus putting the "eye" at the root. { - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PushMatrix)(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); CPT(TransformState) root_transform = _cs_transform->compose(_scene_setup->get_world_transform()); GLPf(LoadMatrix)(root_transform->get_mat().get_data()); - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); GLPfv(TexGen)(GL_S, GL_EYE_PLANE, s_data); GLPfv(TexGen)(GL_T, GL_EYE_PLANE, t_data); GLPfv(TexGen)(GL_R, GL_EYE_PLANE, r_data); GLPfv(TexGen)(GL_Q, GL_EYE_PLANE, q_data); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); - GLP(Enable)(GL_TEXTURE_GEN_Q); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_GEN_Q); - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PopMatrix)(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } break; case TexGenAttrib::M_point_sprite: if (_supports_point_sprite) { #ifdef OPENGLES - GLP(TexEnvi)(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE); + glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE); #else - GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); + glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); #endif got_point_sprites = true; } @@ -8581,10 +9182,10 @@ do_issue_tex_gen() { { const LTexCoord3 &v = _target_tex_gen->get_constant_value(stage); - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); LVecBase4 s(0.0f, 0.0f, 0.0f, v[0]); LVecBase4 t(0.0f, 0.0f, 0.0f, v[1]); @@ -8595,10 +9196,10 @@ do_issue_tex_gen() { GLPfv(TexGen)(GL_R, GL_OBJECT_PLANE, r.get_data()); GLPfv(TexGen)(GL_Q, GL_OBJECT_PLANE, q_data); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); - GLP(Enable)(GL_TEXTURE_GEN_Q); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_GEN_Q); } break; @@ -8613,15 +9214,15 @@ do_issue_tex_gen() { #ifndef OPENGLES_2 #ifdef OPENGLES if (_tex_gen_point_sprite) { - GLP(Enable)(GL_POINT_SPRITE_OES); + glEnable(GL_POINT_SPRITE_OES); } else { - GLP(Disable)(GL_POINT_SPRITE_OES); + glDisable(GL_POINT_SPRITE_OES); } #else if (_tex_gen_point_sprite) { - GLP(Enable)(GL_POINT_SPRITE_ARB); + glEnable(GL_POINT_SPRITE_ARB); } else { - GLP(Disable)(GL_POINT_SPRITE_ARB); + glDisable(GL_POINT_SPRITE_ARB); } #endif // OPENGLES #endif // OPENGLES_2 @@ -8638,6 +9239,8 @@ do_issue_tex_gen() { //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: specify_texture(CLP(TextureContext) *gtc) { + nassertr(gtc->_handle == 0 /* can't modify tex with active handle */, false); + Texture *tex = gtc->get_texture(); GLenum target = get_texture_target(tex->get_texture_type()); @@ -8646,23 +9249,23 @@ specify_texture(CLP(TextureContext) *gtc) { return false; } - GLP(TexParameteri)(target, GL_TEXTURE_WRAP_S, + glTexParameteri(target, GL_TEXTURE_WRAP_S, get_texture_wrap_mode(tex->get_wrap_u())); #ifndef OPENGLES if (target != GL_TEXTURE_1D) { - GLP(TexParameteri)(target, GL_TEXTURE_WRAP_T, + glTexParameteri(target, GL_TEXTURE_WRAP_T, get_texture_wrap_mode(tex->get_wrap_v())); } #endif #ifdef OPENGLES_2 if (target == GL_TEXTURE_3D_OES) { - GLP(TexParameteri)(target, GL_TEXTURE_WRAP_R_OES, + glTexParameteri(target, GL_TEXTURE_WRAP_R_OES, get_texture_wrap_mode(tex->get_wrap_w())); } #endif #ifndef OPENGLES if (target == GL_TEXTURE_3D) { - GLP(TexParameteri)(target, GL_TEXTURE_WRAP_R, + glTexParameteri(target, GL_TEXTURE_WRAP_R, get_texture_wrap_mode(tex->get_wrap_w())); } @@ -8672,10 +9275,10 @@ specify_texture(CLP(TextureContext) *gtc) { Texture::FilterType minfilter = tex->get_effective_minfilter(); Texture::FilterType magfilter = tex->get_effective_magfilter(); - bool uses_mipmaps = Texture::is_mipmap(minfilter) && !CLP(ignore_mipmaps); + bool uses_mipmaps = Texture::is_mipmap(minfilter) && !gl_ignore_mipmaps; #ifndef NDEBUG - if (CLP(force_mipmaps)) { + if (gl_force_mipmaps) { minfilter = Texture::FT_linear_mipmap_linear; magfilter = Texture::FT_linear; uses_mipmaps = true; @@ -8685,20 +9288,17 @@ specify_texture(CLP(TextureContext) *gtc) { if (!tex->might_have_ram_image()) { // If it's a dynamically generated texture (that is, the RAM image // isn't available so it didn't pass through the CPU), we should - // enable GL-generated mipmaps here if we can. - if (_supports_generate_mipmap) { -#ifndef OPENGLES_2 - GLP(TexParameteri)(target, GL_GENERATE_MIPMAP, uses_mipmaps); -#endif - } else { - // Otherwise, don't try to use mipmaps. + // enable GL-generated mipmaps if we can. + if (!_supports_generate_mipmap) { + // However, if the GPU doesn't support mipmap generation, we + // have to turn it off. uses_mipmaps = false; } } - GLP(TexParameteri)(target, GL_TEXTURE_MIN_FILTER, + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, get_texture_filter_type(minfilter, !uses_mipmaps)); - GLP(TexParameteri)(target, GL_TEXTURE_MAG_FILTER, + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, get_texture_filter_type(magfilter, true)); // Set anisotropic filtering. @@ -8706,7 +9306,7 @@ specify_texture(CLP(TextureContext) *gtc) { PN_stdfloat anisotropy = tex->get_effective_anisotropic_degree(); anisotropy = min(anisotropy, _max_anisotropy); anisotropy = max(anisotropy, (PN_stdfloat)1.0); - GLP(TexParameterf)(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy); + glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy); } #ifndef OPENGLES @@ -8715,15 +9315,15 @@ specify_texture(CLP(TextureContext) *gtc) { tex->get_format() == Texture::F_depth_component16 || tex->get_format() == Texture::F_depth_component24 || tex->get_format() == Texture::F_depth_component32) { - GLP(TexParameteri)(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); + glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); if (_supports_shadow_filter) { if ((tex->get_magfilter() == Texture::FT_shadow) || (tex->get_minfilter() == Texture::FT_shadow)) { - GLP(TexParameteri)(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); - GLP(TexParameteri)(target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); } else { - GLP(TexParameteri)(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); - GLP(TexParameteri)(target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); + glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); } } } @@ -8763,7 +9363,7 @@ apply_texture(TextureContext *tc) { gtc->reset_data(); gtc->_target = target; } - GLP(BindTexture)(target, gtc->_index); + glBindTexture(target, gtc->_index); report_my_gl_errors(); return true; @@ -8819,20 +9419,6 @@ upload_texture(CLP(TextureContext) *gtc, bool force) { image_compression = Texture::CM_off; } - if (GLCAT.is_debug()) { - if (image.is_null()) { - GLCAT.debug() - << "Got NULL image: " << tex->get_name() << "\n"; - } - } - - /* - if (image.is_null()) { - // If we don't have an image, we can't upload. - return false; - } - */ - int mipmap_bias = 0; int width = tex->get_x_size(); @@ -8843,6 +9429,23 @@ upload_texture(CLP(TextureContext) *gtc, bool force) { GLint external_format = get_external_image_format(tex); GLenum component_type = get_component_type(tex->get_component_type()); + if (GLCAT.is_debug()) { + if (image.is_null()) { + GLCAT.debug() + << "loading texture with NULL image"; + } else if (image_compression != Texture::CM_off) { + GLCAT.debug() + << "loading pre-compressed texture"; + } else if (is_compressed_format(internal_format)) { + GLCAT.debug() + << "loading compressed texture"; + } else { + GLCAT.debug() + << "loading uncompressed texture"; + } + GLCAT.debug(false) << " " << tex->get_name() << "\n"; + } + // Ensure that the texture fits within the GL's specified limits. // Need to split dimensions because of texture arrays int max_dimension_x; @@ -8908,13 +9511,16 @@ upload_texture(CLP(TextureContext) *gtc, bool force) { } } + width = tex->get_expected_mipmap_x_size(mipmap_bias); + height = tex->get_expected_mipmap_y_size(mipmap_bias); + depth = tex->get_expected_mipmap_z_size(mipmap_bias); + if (mipmap_bias != 0) { GLCAT.info() << "Reducing image " << tex->get_name() - << " from " << width << " x " << height << " x " << depth << " to " - << tex->get_expected_mipmap_x_size(mipmap_bias) << " x " - << tex->get_expected_mipmap_y_size(mipmap_bias) << " x " - << tex->get_expected_mipmap_z_size(mipmap_bias) << "\n"; + << " from " << tex->get_x_size() << " x " << tex->get_y_size() + << " x " << tex->get_z_size() << " to " + << width << " x " << height << " x " << depth << "\n"; } } @@ -8924,34 +9530,162 @@ upload_texture(CLP(TextureContext) *gtc, bool force) { #ifndef OPENGLES switch (quality_level) { case Texture::QL_fastest: - GLP(Hint)(GL_TEXTURE_COMPRESSION_HINT, GL_FASTEST); + glHint(GL_TEXTURE_COMPRESSION_HINT, GL_FASTEST); break; case Texture::QL_default: case Texture::QL_normal: - GLP(Hint)(GL_TEXTURE_COMPRESSION_HINT, GL_DONT_CARE); + glHint(GL_TEXTURE_COMPRESSION_HINT, GL_DONT_CARE); break; case Texture::QL_best: - GLP(Hint)(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); + glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); break; } #endif } - GLP(PixelStorei)(GL_UNPACK_ALIGNMENT, 1); - - bool uses_mipmaps = (tex->uses_mipmaps() && !CLP(ignore_mipmaps)) || CLP(force_mipmaps); - -#ifndef NDEBUG - if (CLP(force_mipmaps)) { - uses_mipmaps = true; - } -#endif - - bool success = true; + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); GLenum target = get_texture_target(tex->get_texture_type()); + bool uses_mipmaps = (tex->uses_mipmaps() && !gl_ignore_mipmaps) || gl_force_mipmaps; + bool needs_reload = false; + if (!gtc->_has_storage || + gtc->_uses_mipmaps != uses_mipmaps || + gtc->_internal_format != internal_format || + gtc->_width != width || + gtc->_height != height || + gtc->_depth != depth) { + // We need to reload a new GL Texture object. + needs_reload = true; + } + + if (needs_reload && gtc->_immutable) { + GLCAT.warning() << "Attempt to modify texture with immutable storage, recreating texture.\n"; + gtc->reset_data(); + glBindTexture(target, gtc->_index); + } + + if (needs_reload) { + gtc->_generate_mipmaps = false; + int num_levels = 1; + CPTA_uchar image = tex->get_ram_mipmap_image(mipmap_bias); + + // Figure out whether mipmaps will be generated by the GPU or by + // Panda (or not at all), and how many mipmap levels should be created. + if (image.is_null()) { + if (uses_mipmaps) { + if (_supports_generate_mipmap) { + num_levels = tex->get_expected_num_mipmap_levels() - mipmap_bias; + gtc->_generate_mipmaps = true; + } else { + // If it can't, do without mipmaps. + num_levels = 1; + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + } + + } else { + if (uses_mipmaps) { + num_levels = tex->get_num_ram_mipmap_images() - mipmap_bias; + + if (num_levels <= 1) { + // No RAM mipmap levels available. Should we generate some? + if (!_supports_generate_mipmap || !driver_generate_mipmaps || + image_compression != Texture::CM_off) { + // Yes, the GL can't or won't generate them, so we need to. + // Note that some drivers (nVidia) will *corrupt memory* if + // you ask them to generate mipmaps for a pre-compressed + // texture. + tex->generate_ram_mipmap_images(); + num_levels = tex->get_num_ram_mipmap_images() - mipmap_bias; + } + } + + if (num_levels <= 1) { + // We don't have mipmap levels in RAM. Ask the GL to generate + // them if it can. + if (_supports_generate_mipmap) { + num_levels = tex->get_expected_num_mipmap_levels() - mipmap_bias; + gtc->_generate_mipmaps = true; + } else { + // If it can't, do without mipmaps. + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + num_levels = 1; + } + } + } + } + +#ifndef OPENGLES // OpenGL ES doesn't have GL_TEXTURE_MAX_LEVEL. + if (is_at_least_gl_version(1, 2)) { + // By the time we get here, we have a pretty good prediction for + // the number of mipmaps we're going to have, so tell the GL that's + // all it's going to get. + glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, num_levels - 1); + } +#endif + +#ifndef OPENGLES_2 + if (gtc->_generate_mipmaps && _glGenerateMipmap == NULL) { + // The old, deprecated way to generate mipmaps. + glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE); + } +#endif + + // Allocate immutable storage for the texture, after which we can subload it. + // Pre-allocating storage using glTexStorage is more efficient than using glTexImage + // to load all of the individual images one by one later, but we are not allowed to + // change the texture size or number of mipmap levels after this point. + if (gl_immutable_texture_storage && _supports_tex_storage && !gtc->_has_storage) { + if (GLCAT.is_debug()) { + GLCAT.debug() + << "allocating storage for texture " << tex->get_name() << ", " << width + << " x " << height << " x " << depth << ", mipmaps " << num_levels + << ", uses_mipmaps = " << uses_mipmaps << "\n"; + } + + switch (tex->get_texture_type()) { + case Texture::TT_1d_texture: + _glTexStorage1D(target, num_levels, internal_format, width); + break; + case Texture::TT_2d_texture: + case Texture::TT_cube_map: + _glTexStorage2D(target, num_levels, internal_format, width, height); + break; + case Texture::TT_3d_texture: + case Texture::TT_2d_texture_array: + _glTexStorage3D(target, num_levels, internal_format, width, height, depth); + break; + } + + gtc->_has_storage = true; + gtc->_immutable = true; + gtc->_uses_mipmaps = uses_mipmaps; + gtc->_internal_format = internal_format; + gtc->_width = width; + gtc->_height = height; + gtc->_depth = depth; + needs_reload = false; + } + } else { + // Maybe we need to generate mipmaps on the CPU. + if (!image.is_null() && uses_mipmaps) { + if (tex->get_num_ram_mipmap_images() - mipmap_bias <= 1) { + // No RAM mipmap levels available. Should we generate some? + if (!_supports_generate_mipmap || !driver_generate_mipmaps || + image_compression != Texture::CM_off) { + // Yes, the GL can't or won't generate them, so we need to. + // Note that some drivers (nVidia) will *corrupt memory* if + // you ask them to generate mipmaps for a pre-compressed + // texture. + tex->generate_ram_mipmap_images(); + } + } + } + } + + bool success = true; if (tex->get_texture_type() == Texture::TT_cube_map) { // A cube map must load six different 2-d images (which are stored // as the six pages of the system ram image). @@ -8962,37 +9696,37 @@ upload_texture(CLP(TextureContext) *gtc, bool force) { nassertr(target == GL_TEXTURE_CUBE_MAP, false); success = success && upload_texture_image - (gtc, uses_mipmaps, mipmap_bias, + (gtc, needs_reload, uses_mipmaps, mipmap_bias, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_POSITIVE_X, internal_format, external_format, component_type, true, 0, image_compression); success = success && upload_texture_image - (gtc, uses_mipmaps, mipmap_bias, + (gtc, needs_reload, uses_mipmaps, mipmap_bias, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, internal_format, external_format, component_type, true, 1, image_compression); success = success && upload_texture_image - (gtc, uses_mipmaps, mipmap_bias, + (gtc, needs_reload, uses_mipmaps, mipmap_bias, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, internal_format, external_format, component_type, true, 2, image_compression); success = success && upload_texture_image - (gtc, uses_mipmaps, mipmap_bias, + (gtc, needs_reload, uses_mipmaps, mipmap_bias, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, internal_format, external_format, component_type, true, 3, image_compression); success = success && upload_texture_image - (gtc, uses_mipmaps, mipmap_bias, + (gtc, needs_reload, uses_mipmaps, mipmap_bias, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, internal_format, external_format, component_type, true, 4, image_compression); success = success && upload_texture_image - (gtc, uses_mipmaps, mipmap_bias, + (gtc, needs_reload, uses_mipmaps, mipmap_bias, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, internal_format, external_format, component_type, true, 5, image_compression); @@ -9000,20 +9734,32 @@ upload_texture(CLP(TextureContext) *gtc, bool force) { } else { // Any other kind of texture can be loaded all at once. success = upload_texture_image - (gtc, uses_mipmaps, mipmap_bias, target, target, - internal_format, external_format, component_type, - false, 0, image_compression); + (gtc, needs_reload, uses_mipmaps, mipmap_bias, target, + target, internal_format, external_format, + component_type, false, 0, image_compression); + } + + if (gtc->_generate_mipmaps && _glGenerateMipmap != NULL) { + if (GLCAT.is_debug()) { + GLCAT.debug() + << "generating mipmaps for texture " << tex->get_name() << ", " + << width << " x " << height << " x " << depth + << ", uses_mipmaps = " << uses_mipmaps << "\n"; + } + _glGenerateMipmap(target); } maybe_gl_finish(); if (success) { - gtc->_already_applied = true; - gtc->_uses_mipmaps = uses_mipmaps; - gtc->_internal_format = internal_format; - gtc->_width = width; - gtc->_height = height; - gtc->_depth = depth; + if (needs_reload) { + gtc->_has_storage = true; + gtc->_uses_mipmaps = uses_mipmaps; + gtc->_internal_format = internal_format; + gtc->_width = width; + gtc->_height = height; + gtc->_depth = depth; + } if (!image.is_null()) { gtc->update_data_size_bytes(get_texture_memory_size(tex)); @@ -9036,7 +9782,6 @@ upload_texture(CLP(TextureContext) *gtc, bool force) { GraphicsEngine *engine = get_engine(); nassertr(engine != (GraphicsEngine *)NULL, false); - nassertr(engine == GraphicsEngine::get_global_ptr(), false); // temp hack engine->texture_uploaded(tex); gtc->mark_loaded(); @@ -9065,7 +9810,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force) { // e.g. GL_TEXTURE_CUBE_MAP_POSITIVE_X. //////////////////////////////////////////////////////////////////// bool CLP(GraphicsStateGuardian):: -upload_texture_image(CLP(TextureContext) *gtc, +upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, bool uses_mipmaps, int mipmap_bias, GLenum texture_target, GLenum page_target, GLint internal_format, @@ -9092,111 +9837,40 @@ upload_texture_image(CLP(TextureContext) *gtc, int height = tex->get_expected_mipmap_y_size(mipmap_bias); int depth = tex->get_expected_mipmap_z_size(mipmap_bias); - if (GLCAT.is_debug()) { - if (image_compression != Texture::CM_off) { - GLCAT.debug() - << "loading pre-compressed texture " << tex->get_name() << "\n"; - } else if (is_compressed_format(internal_format)) { - GLCAT.debug() - << "compressing texture " << tex->get_name() << "\n"; - } else { - GLCAT.debug() - << "loading uncompressed texture " << tex->get_name() << "\n"; - } - GLCAT.debug() - << "page_target " << hex << page_target << dec << "\n"; - } - + // Determine the number of images to upload. int num_ram_mipmap_levels = 0; - bool load_ram_mipmaps = false; - - if (image.is_null()) { - if (GLCAT.is_debug()) { - GLCAT.debug() - << "Not loading NULL image " << tex->get_name() << "\n"; - } - - if (uses_mipmaps) { - if (_supports_generate_mipmap) { -#ifndef OPENGLES_2 - GLP(TexParameteri)(texture_target, GL_GENERATE_MIPMAP, true); -#endif - } else { - // If it can't, do without mipmaps. - GLP(TexParameteri)(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - uses_mipmaps = false; - } - } - - } else { - num_ram_mipmap_levels = 1; + if (!image.is_null()) { if (uses_mipmaps) { num_ram_mipmap_levels = tex->get_num_ram_mipmap_images(); - - if (num_ram_mipmap_levels == 1) { - // No RAM mipmap levels available. Should we generate some? - if (!_supports_generate_mipmap || !driver_generate_mipmaps || - image_compression != Texture::CM_off) { - // Yes, the GL can't or won't generate them, so we need to. - // Note that some drivers (nVidia) will *corrupt memory* if - // you ask them to generate mipmaps for a pre-compressed - // texture. - tex->generate_ram_mipmap_images(); - num_ram_mipmap_levels = tex->get_num_ram_mipmap_images(); - } - } - - if (num_ram_mipmap_levels != 1) { - // We will load the mipmap levels from RAM. Don't ask the GL to - // generate them. -#ifndef OPENGLES_2 - if (_supports_generate_mipmap) { - GLP(TexParameteri)(texture_target, GL_GENERATE_MIPMAP, false); - } -#endif - load_ram_mipmaps = true; - - } else { - // We don't have mipmap levels in RAM. Ask the GL to generate - // them if it can. - if (_supports_generate_mipmap) { -#ifndef OPENGLES_2 - GLP(TexParameteri)(texture_target, GL_GENERATE_MIPMAP, true); -#endif - } else { - // If it can't, do without mipmaps. - GLP(TexParameteri)(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - uses_mipmaps = false; - } - } + } else { + num_ram_mipmap_levels = 1; } } - int highest_level = 0; -#ifdef OPENGLES // OpenGL ES doesn't support texture subloads. - static const bool needs_reload = true; - -#else - bool needs_reload = false; - if (!gtc->_already_applied || - gtc->_uses_mipmaps != uses_mipmaps || - gtc->_internal_format != internal_format || - gtc->_width != width || - gtc->_height != height || - gtc->_depth != depth) { - // We need to reload a new GL Texture object. - needs_reload = true; +#ifndef OPENGLES + if (needs_reload || num_ram_mipmap_levels > 0) { + // Make sure that any incoherent writes to this texture have been synced. + if (gtc->needs_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT)) { + issue_memory_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT); + } } +#endif if (!needs_reload) { // Try to subload the image over the existing GL Texture object, // possibly saving on texture memory fragmentation. if (GLCAT.is_debug()) { - GLCAT.debug() - << "subloading existing texture object, " << width << " x " << height - << " x " << depth << ", z = " << z << ", mipmaps " << num_ram_mipmap_levels - << ", uses_mipmaps = " << uses_mipmaps << "\n"; + if (num_ram_mipmap_levels == 0) { + GLCAT.debug() + << "not loading NULL image for tex " << tex->get_name() << ", " << width << " x " << height + << " x " << depth << ", z = " << z << ", uses_mipmaps = " << uses_mipmaps << "\n"; + } else { + GLCAT.debug() + << "updating image data of texture " << tex->get_name() << ", " << width << " x " << height + << " x " << depth << ", z = " << z << ", mipmaps " << num_ram_mipmap_levels + << ", uses_mipmaps = " << uses_mipmaps << "\n"; + } } for (int n = mipmap_bias; n < num_ram_mipmap_levels; ++n) { @@ -9243,8 +9917,8 @@ upload_texture_image(CLP(TextureContext) *gtc, switch (texture_target) { case GL_TEXTURE_1D: if (image_compression == Texture::CM_off) { - GLP(TexSubImage1D)(page_target, n - mipmap_bias, 0, width, - external_format, component_type, image_ptr); + glTexSubImage1D(page_target, n - mipmap_bias, 0, width, + external_format, component_type, image_ptr); } else { _glCompressedTexSubImage1D(page_target, n - mipmap_bias, 0, width, external_format, view_size, image_ptr); @@ -9295,16 +9969,14 @@ upload_texture_image(CLP(TextureContext) *gtc, // but TexSubImage2D doesn't accept a row-stride parameter. height = tex->get_y_size() - tex->get_pad_y_size(); } - GLP(TexSubImage2D)(page_target, n - mipmap_bias, 0, 0, width, height, - external_format, component_type, image_ptr); + glTexSubImage2D(page_target, n - mipmap_bias, 0, 0, width, height, + external_format, component_type, image_ptr); } else { _glCompressedTexSubImage2D(page_target, n - mipmap_bias, 0, 0, width, height, external_format, view_size, image_ptr); } break; } - - highest_level = n; } // Did that fail? If it did, we'll immediately try again, this @@ -9319,20 +9991,28 @@ upload_texture_image(CLP(TextureContext) *gtc, needs_reload = true; } } -#endif // OPENGLES if (needs_reload) { // Load the image up from scratch, creating a new GL Texture // object. if (GLCAT.is_debug()) { GLCAT.debug() - << "loading new texture object, " << width << " x " << height - << " x " << depth << ", z = " << z << ", mipmaps " << num_ram_mipmap_levels - << ", uses_mipmaps = " << uses_mipmaps << "\n"; + << "loading new texture object for " << tex->get_name() << ", " << width + << " x " << height << " x " << depth << ", z = " << z << ", mipmaps " + << num_ram_mipmap_levels << ", uses_mipmaps = " << uses_mipmaps << "\n"; } + // If there is immutable storage, this is impossible to do, and we should + // not have gotten here at all. + nassertr(!gtc->_immutable, false); + if (num_ram_mipmap_levels == 0) { - if ((external_format == GL_DEPTH_STENCIL_EXT) && get_supports_depth_stencil()) { + if (GLCAT.is_debug()) { + GLCAT.debug() + << " (initializing NULL image)\n"; + } + + if ((external_format == GL_DEPTH_STENCIL) && get_supports_depth_stencil()) { #ifdef OPENGLES component_type = GL_UNSIGNED_INT_24_8_OES; #else @@ -9345,7 +10025,7 @@ upload_texture_image(CLP(TextureContext) *gtc, switch (page_target) { #ifndef OPENGLES case GL_TEXTURE_1D: - GLP(TexImage1D)(page_target, 0, internal_format, width, 0, external_format, component_type, NULL); + glTexImage1D(page_target, 0, internal_format, width, 0, external_format, component_type, NULL); break; case GL_TEXTURE_2D_ARRAY: #endif @@ -9355,7 +10035,7 @@ upload_texture_image(CLP(TextureContext) *gtc, break; #endif default: - GLP(TexImage2D)(page_target, 0, internal_format, width, height, 0, external_format, component_type, NULL); + glTexImage2D(page_target, 0, internal_format, width, height, 0, external_format, component_type, NULL); break; } } @@ -9370,6 +10050,12 @@ upload_texture_image(CLP(TextureContext) *gtc, << "No mipmap level " << n << " defined for " << tex->get_name() << "\n"; // No mipmap level n; stop here. +#ifndef OPENGLES + if (is_at_least_gl_version(1, 2)) { + // Tell the GL we have no more mipmaps for it to use. + glTexParameteri(texture_target, GL_TEXTURE_MAX_LEVEL, n - mipmap_bias); + } +#endif break; } image_ptr = ptimage; @@ -9403,9 +10089,9 @@ upload_texture_image(CLP(TextureContext) *gtc, #ifndef OPENGLES // 1-d textures not supported by OpenGL ES. Fall through. case GL_TEXTURE_1D: if (image_compression == Texture::CM_off) { - GLP(TexImage1D)(page_target, n - mipmap_bias, internal_format, - width, 0, - external_format, component_type, image_ptr); + glTexImage1D(page_target, n - mipmap_bias, internal_format, + width, 0, + external_format, component_type, image_ptr); } else { _glCompressedTexImage1D(page_target, n - mipmap_bias, external_format, width, 0, view_size, image_ptr); @@ -9457,16 +10143,14 @@ upload_texture_image(CLP(TextureContext) *gtc, default: if (image_compression == Texture::CM_off) { - GLP(TexImage2D)(page_target, n - mipmap_bias, internal_format, - width, height, 0, - external_format, component_type, image_ptr); + glTexImage2D(page_target, n - mipmap_bias, internal_format, + width, height, 0, + external_format, component_type, image_ptr); } else { - _glCompressedTexImage2D(page_target, n - mipmap_bias, external_format, width, height, - 0, view_size, image_ptr); + _glCompressedTexImage2D(page_target, n - mipmap_bias, external_format, + width, height, 0, view_size, image_ptr); } } - - highest_level = n; } // Report the error message explicitly if the GL texture creation @@ -9477,29 +10161,11 @@ upload_texture_image(CLP(TextureContext) *gtc, << "GL texture creation failed for " << tex->get_name() << " : " << get_error_string(error_code) << "\n"; - gtc->_already_applied = false; + gtc->_has_storage = false; return false; } } -#ifndef OPENGLES // OpenGL ES doesn't have GL_TEXTURE_MAX_LEVEL. - if (is_at_least_gl_version(1, 2)) { - if (load_ram_mipmaps) { - // By the time we get here, we have successfully loaded a certain - // number of mipmap levels. Tell the GL that's all it's going to - // get. - GLP(TexParameteri)(texture_target, GL_TEXTURE_MAX_LEVEL, highest_level - mipmap_bias); - - } else if (uses_mipmaps) { - // Since the mipmap levels were auto-generated and are therefore - // complete, make sure the GL doesn't remember some previous value - // for GL_TEXTURE_MAX_LEVEL from the above call--set it to the - // full count of mipmap levels. - GLP(TexParameteri)(texture_target, GL_TEXTURE_MAX_LEVEL, tex->get_expected_num_mipmap_levels() - mipmap_bias - 1); - } - } -#endif - report_my_gl_errors(); return true; @@ -9558,7 +10224,7 @@ upload_simple_texture(CLP(TextureContext) *gtc) { // Turn off mipmaps for the simple texture. if (tex->uses_mipmaps()) { if (is_at_least_gl_version(1, 2)) { - GLP(TexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); } } #endif @@ -9567,9 +10233,9 @@ upload_simple_texture(CLP(TextureContext) *gtc) { _data_transferred_pcollector.add_level(image_size); #endif - GLP(TexImage2D)(GL_TEXTURE_2D, 0, internal_format, - width, height, 0, - external_format, component_type, image_ptr); + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, + width, height, 0, + external_format, component_type, image_ptr); gtc->mark_simple_loaded(); @@ -9607,18 +10273,18 @@ get_texture_memory_size(Texture *tex) { } GLint minfilter; - GLP(GetTexParameteriv)(target, GL_TEXTURE_MIN_FILTER, &minfilter); + glGetTexParameteriv(target, GL_TEXTURE_MIN_FILTER, &minfilter); bool has_mipmaps = is_mipmap_filter(minfilter); clear_my_gl_errors(); GLint internal_format; - GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format); + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format); if (is_compressed_format(internal_format)) { // Try to get the compressed size. GLint image_size; - GLP(GetTexLevelParameteriv)(page_target, 0, + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &image_size); GLenum error_code = gl_get_error(); @@ -9638,30 +10304,28 @@ get_texture_memory_size(Texture *tex) { GLint red_size, green_size, blue_size, alpha_size, luminance_size, intensity_size; GLint depth_size = 0; - GLP(GetTexLevelParameteriv)(page_target, 0, + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_RED_SIZE, &red_size); - GLP(GetTexLevelParameteriv)(page_target, 0, + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_GREEN_SIZE, &green_size); - GLP(GetTexLevelParameteriv)(page_target, 0, + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_BLUE_SIZE, &blue_size); - GLP(GetTexLevelParameteriv)(page_target, 0, + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size); - GLP(GetTexLevelParameteriv)(page_target, 0, + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_LUMINANCE_SIZE, &luminance_size); - GLP(GetTexLevelParameteriv)(page_target, 0, + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_INTENSITY_SIZE, &intensity_size); if (_supports_depth_texture) { - // Actually, this seems to cause problems on some Mesa versions, - // even though they advertise GL_ARB_depth_texture. Who needs it. - // GLP(GetTexLevelParameteriv)(page_target, 0, - // GL_TEXTURE_DEPTH_SIZE, &depth_size); + glGetTexLevelParameteriv(page_target, 0, + GL_TEXTURE_DEPTH_SIZE, &depth_size); } GLint width = 1, height = 1, depth = 1; - GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_WIDTH, &width); - GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_HEIGHT, &height); + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_WIDTH, &width); + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_HEIGHT, &height); if (_supports_3d_texture || _supports_2d_texture_array) { - GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_DEPTH, &depth); + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_DEPTH, &depth); } report_my_gl_errors(); @@ -9705,7 +10369,7 @@ check_nonresident_texture(BufferContextChain &chain) { } nassertv(ti == num_textures); GLboolean *results = (GLboolean *)alloca(num_textures * sizeof(GLboolean)); - bool all_resident = (GLP(AreTexturesResident)(num_textures, texture_list, results) != 0); + bool all_resident = (glAreTexturesResident(num_textures, texture_list, results) != 0); report_my_gl_errors(); @@ -9735,7 +10399,15 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { if (target == GL_NONE) { return false; } - GLP(BindTexture)(target, gtc->_index); + +#ifndef OPENGLES + // Make sure any incoherent writes to the texture have been synced. + if (gtc->needs_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT)) { + issue_memory_barrier(GL_TEXTURE_UPDATE_BARRIER_BIT); + } +#endif + + glBindTexture(target, gtc->_index); Texture *tex = gtc->get_texture(); @@ -9743,30 +10415,27 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { GLint minfilter, magfilter; GLfloat border_color[4]; - GLP(GetTexParameteriv)(target, GL_TEXTURE_WRAP_S, &wrap_u); - GLP(GetTexParameteriv)(target, GL_TEXTURE_WRAP_T, &wrap_v); + glGetTexParameteriv(target, GL_TEXTURE_WRAP_S, &wrap_u); + glGetTexParameteriv(target, GL_TEXTURE_WRAP_T, &wrap_v); wrap_w = GL_REPEAT; if (_supports_3d_texture) { #ifdef OPENGLES_2 - GLP(GetTexParameteriv)(target, GL_TEXTURE_WRAP_R_OES, &wrap_w); + glGetTexParameteriv(target, GL_TEXTURE_WRAP_R_OES, &wrap_w); #endif #ifndef OPENGLES - GLP(GetTexParameteriv)(target, GL_TEXTURE_WRAP_R, &wrap_w); + glGetTexParameteriv(target, GL_TEXTURE_WRAP_R, &wrap_w); #endif } if (_supports_2d_texture_array) { #ifndef OPENGLES - GLP(GetTexParameteriv)(target, GL_TEXTURE_WRAP_R, &wrap_w); + glGetTexParameteriv(target, GL_TEXTURE_WRAP_R, &wrap_w); #endif } - GLP(GetTexParameteriv)(target, GL_TEXTURE_MIN_FILTER, &minfilter); - - // Mesa has a bug querying this property. - magfilter = GL_LINEAR; - // GLP(GetTexParameteriv)(target, GL_TEXTURE_MAG_FILTER, &magfilter); + glGetTexParameteriv(target, GL_TEXTURE_MIN_FILTER, &minfilter); + glGetTexParameteriv(target, GL_TEXTURE_MAG_FILTER, &magfilter); #ifndef OPENGLES - GLP(GetTexParameterfv)(target, GL_TEXTURE_BORDER_COLOR, border_color); + glGetTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, border_color); #endif GLenum page_target = target; @@ -9777,17 +10446,17 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { GLint width = gtc->_width, height = gtc->_height, depth = gtc->_depth; #ifndef OPENGLES - GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_WIDTH, &width); + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_WIDTH, &width); if (target != GL_TEXTURE_1D) { - GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_HEIGHT, &height); + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_HEIGHT, &height); } if (_supports_3d_texture && target == GL_TEXTURE_3D) { - GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_DEPTH, &depth); + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_DEPTH, &depth); } #ifndef OPENGLES else if (_supports_2d_texture_array && target == GL_TEXTURE_2D_ARRAY_EXT) { - GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_DEPTH, &depth); + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_DEPTH, &depth); } #endif else if (target == GL_TEXTURE_CUBE_MAP) { @@ -9803,7 +10472,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { GLint internal_format = GL_RGBA; #ifndef OPENGLES - GLP(GetTexLevelParameteriv)(page_target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format); + glGetTexLevelParameteriv(page_target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format); #endif // OPENGLES // Make sure we were able to query those parameters properly. @@ -9841,11 +10510,15 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { format = Texture::F_depth_component; break; #endif - case GL_DEPTH_STENCIL_EXT: - case GL_DEPTH24_STENCIL8_EXT: + case GL_DEPTH_STENCIL: + case GL_DEPTH24_STENCIL8: type = Texture::T_unsigned_int_24_8; format = Texture::F_depth_stencil; break; + case GL_DEPTH32F_STENCIL8: + type = Texture::T_float; + format = Texture::F_depth_stencil; + break; case GL_RGBA: case 4: format = Texture::F_rgba; @@ -9910,6 +10583,22 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { type = Texture::T_float; format = Texture::F_r16; break; + case GL_RGBA32F: + type = Texture::T_float; + format = Texture::F_rgba32; + break; + case GL_RGB32F: + type = Texture::T_float; + format = Texture::F_rgb32; + break; + case GL_RG32F: + type = Texture::T_float; + format = Texture::F_rg32; + break; + case GL_R32F: + type = Texture::T_float; + format = Texture::F_r32; + break; #endif #ifndef OPENGLES @@ -9933,6 +10622,13 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { format = Texture::F_red; break; #endif +#ifndef OPENGLES + case GL_R32I: + type = Texture::T_int; + format = Texture::F_r32i; + break; +#endif + #ifndef OPENGLES case GL_RED: format = Texture::F_red; @@ -9956,6 +10652,25 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { format = Texture::F_luminance_alpha; break; +#ifndef OPENGLES_1 + case GL_SRGB: + case GL_SRGB8: + format = Texture::F_srgb; + break; + case GL_SRGB_ALPHA: + case GL_SRGB8_ALPHA8: + format = Texture::F_srgb_alpha; + break; + case GL_SLUMINANCE: + case GL_SLUMINANCE8: + format = Texture::F_sluminance; + break; + case GL_SLUMINANCE_ALPHA: + case GL_SLUMINANCE8_ALPHA8: + format = Texture::F_sluminance_alpha; + break; +#endif + #ifndef OPENGLES case GL_COMPRESSED_RGB: format = Texture::F_rgb; @@ -9977,6 +10692,23 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { format = Texture::F_luminance_alpha; compression = Texture::CM_on; break; + + case GL_COMPRESSED_SRGB: + format = Texture::F_srgb; + compression = Texture::CM_on; + break; + case GL_COMPRESSED_SRGB_ALPHA: + format = Texture::F_srgb_alpha; + compression = Texture::CM_on; + break; + case GL_COMPRESSED_SLUMINANCE: + format = Texture::F_sluminance; + compression = Texture::CM_on; + break; + case GL_COMPRESSED_SLUMINANCE_ALPHA: + format = Texture::F_sluminance_alpha; + compression = Texture::CM_on; + break; #endif #ifndef OPENGLES_1 @@ -9988,6 +10720,14 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { format = Texture::F_rgbm; compression = Texture::CM_dxt1; break; + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + format = Texture::F_srgb; + compression = Texture::CM_dxt1; + break; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + format = Texture::F_srgb_alpha; + compression = Texture::CM_dxt1; + break; #endif #ifdef OPENGLES case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: @@ -10006,6 +10746,23 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { format = Texture::F_rgba; compression = Texture::CM_pvr1_4bpp; break; + + case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT: + format = Texture::F_srgb; + compression = Texture::CM_pvr1_2bpp; + break; + case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT: + format = Texture::F_srgb_alpha; + compression = Texture::CM_pvr1_2bpp; + break; + case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT: + format = Texture::F_srgb; + compression = Texture::CM_pvr1_4bpp; + break; + case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT: + format = Texture::F_srgb_alpha; + compression = Texture::CM_pvr1_4bpp; + break; #else case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: format = Texture::F_rgba; @@ -10015,6 +10772,14 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { format = Texture::F_rgba; compression = Texture::CM_dxt5; break; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + format = Texture::F_srgb_alpha; + compression = Texture::CM_dxt3; + break; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + format = Texture::F_srgb_alpha; + compression = Texture::CM_dxt5; + break; case GL_COMPRESSED_RGB_FXT1_3DFX: format = Texture::F_rgb; compression = Texture::CM_fxt1; @@ -10064,7 +10829,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { GLint highest_level = num_expected_levels; #ifndef OPENGLES if (is_at_least_gl_version(1, 2)) { - GLP(GetTexParameteriv)(target, GL_TEXTURE_MAX_LEVEL, &highest_level); + glGetTexParameteriv(target, GL_TEXTURE_MAX_LEVEL, &highest_level); highest_level = min(highest_level, num_expected_levels); } #endif @@ -10096,6 +10861,7 @@ extract_texture_image(PTA_uchar &image, size_t &page_size, nassertr(false, false); return false; #else + if (target == GL_TEXTURE_CUBE_MAP) { // A cube map, compressed or uncompressed. This we must extract // one page at a time. @@ -10114,7 +10880,7 @@ extract_texture_image(PTA_uchar &image, size_t &page_size, if (compression != Texture::CM_off) { GLint image_size; - GLP(GetTexLevelParameteriv)(page_target, n, + glGetTexLevelParameteriv(page_target, n, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &image_size); nassertr(image_size <= (int)page_size, false); page_size = image_size; @@ -10126,7 +10892,7 @@ extract_texture_image(PTA_uchar &image, size_t &page_size, page_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + z; if (compression == Texture::CM_off) { - GLP(GetTexImage)(page_target, n, external_format, pixel_type, + glGetTexImage(page_target, n, external_format, pixel_type, image.p() + z * page_size); } else { _glGetCompressedTexImage(page_target, 0, image.p() + z * page_size); @@ -10138,12 +10904,12 @@ extract_texture_image(PTA_uchar &image, size_t &page_size, image = PTA_uchar::empty_array(tex->get_expected_ram_mipmap_image_size(n)); GLenum external_format = get_external_image_format(tex); GLenum pixel_type = get_component_type(type); - GLP(GetTexImage)(target, n, external_format, pixel_type, image.p()); + glGetTexImage(target, n, external_format, pixel_type, image.p()); } else { // A compressed 1-d, 2-d, or 3-d texture. GLint image_size; - GLP(GetTexLevelParameteriv)(target, n, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &image_size); + glGetTexLevelParameteriv(target, n, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &image_size); page_size = image_size / tex->get_z_size(); image = PTA_uchar::empty_array(image_size); @@ -10530,9 +11296,9 @@ do_issue_stencil() { GLbitfield mask = 0; // clear stencil buffer - GLP(ClearStencil)(stencil -> get_render_state (StencilAttrib::SRS_clear_value)); + glClearStencil(stencil -> get_render_state (StencilAttrib::SRS_clear_value)); mask |= GL_STENCIL_BUFFER_BIT; - GLP(Clear)(mask); + glClear(mask); } } else { @@ -10556,6 +11322,6 @@ do_issue_scissor() { int width = (int)(_viewport_width * (frame[1] - frame[0]) + 0.5f); int height = (int)(_viewport_height * (frame[3] - frame[2]) + 0.5f); - GLP(Enable)(GL_SCISSOR_TEST); - GLP(Scissor)(x, y, width, height); + glEnable(GL_SCISSOR_TEST); + glScissor(x, y, width, height); } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index bba06db847..fa3bbcccfd 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -55,6 +55,9 @@ typedef double GLdouble; // functions are defined, and the system gl.h sometimes doesn't // declare these typedefs. #if !defined( __EDG__ ) || defined( __INTEL_COMPILER ) // Protect the following from the Tau instrumentor and expose it for the intel compiler. +typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam); +typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam); +typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img); typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids); typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); @@ -131,6 +134,9 @@ typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXOESPROC) (GLuint matrixpalettei typedef void (APIENTRYP PFNGLLOADPALETTEFROMMODELVIEWMATRIXOESPROC) (void); typedef void (APIENTRYP PFNGLMATRIXINDEXPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRYP PFNGLWEIGHTPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); #ifndef OPENGLES_1 // GLSL shader functions @@ -161,15 +167,44 @@ typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, con typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value); typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); #endif // OPENGLES_1 #ifndef OPENGLES typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); +typedef void (APIENTRYP PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures); +typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +typedef void (APIENTRYP PFNGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures); +typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers); +typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufsize, GLsizei *length, GLenum *binaryFormat, void *binary); +typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); +typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLEPROC) (GLuint texture); +typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEPROC) (GLuint texture, GLuint sampler); +typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTPROC) (GLuint64 handle); +typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLEPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); +typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTPROC) (GLuint64 handle, GLenum access); +typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64PROC) (GLint location, GLuint64 value); +typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64PROC) (GLuint program, GLint location, GLuint64 value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values); +typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTPROC) (GLuint64 handle); +typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTPROC) (GLuint64 handle); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64PROC) (GLuint index, GLuint64EXT x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VPROC) (GLuint index, const GLuint64EXT *v); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VPROC) (GLuint index, GLenum pname, GLuint64EXT *params); #endif // OPENGLES #endif // __EDG__ @@ -193,6 +228,10 @@ public: virtual int get_driver_shader_version_major(); virtual int get_driver_shader_version_minor(); +#ifndef OPENGLES_1 + static void debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam); +#endif + virtual void reset(); virtual void prepare_display_region(DisplayRegionPipelineReader *dr); @@ -225,6 +264,8 @@ public: bool force); virtual void end_draw_primitives(); + void issue_memory_barrier(GLbitfield barrier); + virtual TextureContext *prepare_texture(Texture *tex, int view); virtual bool update_texture(TextureContext *tc, bool force); virtual void release_texture(TextureContext *tc); @@ -260,6 +301,8 @@ public: virtual void begin_occlusion_query(); virtual PT(OcclusionQueryContext) end_occlusion_query(); + virtual void dispatch_compute(int size_x, int size_y, int size_z); + virtual PT(GeomMunger) make_geom_munger(const RenderState *state, Thread *current_thread); @@ -343,8 +386,8 @@ protected: bool has_extension(const string &extension) const; INLINE bool is_at_least_gl_version(int major_version, int minor_version) const; INLINE bool is_at_least_gles_version(int major_version, int minor_version) const; - void *get_extension_func(const char *prefix, const char *name); - virtual void *do_get_extension_func(const char *prefix, const char *name); + void *get_extension_func(const char *name); + virtual void *do_get_extension_func(const char *name); virtual void reissue_transforms(); virtual void enable_lighting(bool enable); @@ -429,7 +472,7 @@ protected: bool specify_texture(CLP(TextureContext) *gtc); bool apply_texture(TextureContext *tc); bool upload_texture(CLP(TextureContext) *gtc, bool force); - bool upload_texture_image(CLP(TextureContext) *gtc, + bool upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, bool uses_mipmaps, int mipmap_bias, GLenum texture_target, GLenum page_target, GLint internal_format, GLint external_format, @@ -487,12 +530,12 @@ protected: bool _vertex_blending_enabled; #ifndef OPENGLES_1 - PT(Shader) _current_shader; - CLP(ShaderContext) *_current_shader_context; - PT(Shader) _vertex_array_shader; - CLP(ShaderContext) *_vertex_array_shader_context; - PT(Shader) _texture_binding_shader; - CLP(ShaderContext) *_texture_binding_shader_context; + PT(Shader) _current_shader; + ShaderContext *_current_shader_context; + PT(Shader) _vertex_array_shader; + ShaderContext *_vertex_array_shader_context; + PT(Shader) _texture_binding_shader; + ShaderContext *_texture_binding_shader_context; #endif #ifdef OPENGLES_2 static PT(Shader) _default_shader; @@ -522,6 +565,9 @@ protected: int _num_active_texture_stages; PN_stdfloat _max_anisotropy; bool _supports_anisotropy; + GLint _max_image_units; + bool _supports_multi_bind; + bool _supports_get_program_binary; #ifdef OPENGLES bool _supports_depth24; @@ -536,6 +582,7 @@ protected: int _gl_version_major, _gl_version_minor; //#--- Zhao Nov/2011 int _gl_shadlang_ver_major, _gl_shadlang_ver_minor; + pset _extensions; public: @@ -567,6 +614,11 @@ public: PFNGLTEXSUBIMAGE3DPROC _glTexSubImage3D; PFNGLCOPYTEXSUBIMAGE3DPROC _glCopyTexSubImage3D; + bool _supports_tex_storage; + PFNGLTEXSTORAGE1DPROC _glTexStorage1D; + PFNGLTEXSTORAGE2DPROC _glTexStorage2D; + PFNGLTEXSTORAGE3DPROC _glTexStorage3D; + PFNGLCOMPRESSEDTEXIMAGE1DPROC _glCompressedTexImage1D; PFNGLCOMPRESSEDTEXIMAGE2DPROC _glCompressedTexImage2D; PFNGLCOMPRESSEDTEXIMAGE3DPROC _glCompressedTexImage3D; @@ -577,8 +629,8 @@ public: bool _supports_bgr; bool _supports_rescale_normal; - bool _supports_mesa_6; - + bool _supports_packed_dabc; + bool _supports_multitexture; PFNGLACTIVETEXTUREPROC _glActiveTexture; PFNGLCLIENTACTIVETEXTUREPROC _glClientActiveTexture; @@ -638,6 +690,8 @@ public: PFNGLBLITFRAMEBUFFEREXTPROC _glBlitFramebuffer; PFNGLDRAWBUFFERSPROC _glDrawBuffers; int _max_fb_samples; + bool _supports_viewport_arrays; + bool _supports_bindless_texture; PFNGLGENQUERIESPROC _glGenQueries; PFNGLBEGINQUERYPROC _glBeginQuery; @@ -677,16 +731,37 @@ public: PFNGLUNIFORM2FVPROC _glUniform2fv; PFNGLUNIFORM3FVPROC _glUniform3fv; PFNGLUNIFORM4FVPROC _glUniform4fv; + PFNGLUNIFORM1IVPROC _glUniform1iv; + PFNGLUNIFORM2IVPROC _glUniform2iv; + PFNGLUNIFORM3IVPROC _glUniform3iv; + PFNGLUNIFORM4IVPROC _glUniform4iv; PFNGLUNIFORMMATRIX3FVPROC _glUniformMatrix3fv; PFNGLUNIFORMMATRIX4FVPROC _glUniformMatrix4fv; PFNGLVALIDATEPROGRAMPROC _glValidateProgram; PFNGLVERTEXATTRIBPOINTERPROC _glVertexAttribPointer; + PFNGLVERTEXATTRIBIPOINTERPROC _glVertexAttribIPointer; + PFNGLVERTEXATTRIBLPOINTERPROC _glVertexAttribLPointer; #endif // OPENGLES_1 #ifndef OPENGLES PFNGLPROGRAMPARAMETERIPROC _glProgramParameteri; PFNGLPATCHPARAMETERIPROC _glPatchParameteri; PFNGLDRAWARRAYSINSTANCEDPROC _glDrawArraysInstanced; PFNGLDRAWELEMENTSINSTANCEDPROC _glDrawElementsInstanced; + PFNGLBINDTEXTURESPROC _glBindTextures; + PFNGLBINDIMAGETEXTUREPROC _glBindImageTexture; + PFNGLBINDIMAGETEXTURESPROC _glBindImageTextures; + PFNGLDISPATCHCOMPUTEPROC _glDispatchCompute; + PFNGLMEMORYBARRIERPROC _glMemoryBarrier; + PFNGLGETPROGRAMBINARYPROC _glGetProgramBinary; + PFNGLGETINTERNALFORMATIVPROC _glGetInternalformativ; + PFNGLVIEWPORTARRAYVPROC _glViewportArrayv; + PFNGLSCISSORARRAYVPROC _glScissorArrayv; + PFNGLDEPTHRANGEARRAYVPROC _glDepthRangeArrayv; + PFNGLGETTEXTUREHANDLEPROC _glGetTextureHandle; + PFNGLMAKETEXTUREHANDLERESIDENTPROC _glMakeTextureHandleResident; + PFNGLMAKETEXTUREHANDLENONRESIDENTPROC _glMakeTextureHandleNonResident; + PFNGLUNIFORMHANDLEUI64PROC _glUniformHandleui64; + PFNGLUNIFORMHANDLEUI64VPROC _glUniformHandleui64v; #endif // OPENGLES GLenum _edge_clamp; @@ -704,10 +779,20 @@ public: DeletedDisplayLists _deleted_display_lists; DeletedDisplayLists _deleted_queries; +#ifndef OPENGLES + // Stores textures for which memory bariers should be issued. + typedef pset TextureSet; + TextureSet _textures_needing_fetch_barrier; + TextureSet _textures_needing_image_access_barrier; + TextureSet _textures_needing_update_barrier; + TextureSet _textures_needing_framebuffer_barrier; +#endif + //RenderState::SlotMask _inv_state_mask; - bool _track_errors; - bool _allow_flush; + bool _check_errors; + bool _force_flush; + bool _supports_debug; #ifndef NDEBUG bool _show_texture_usage; @@ -730,6 +815,7 @@ public: static PStatCollector _primitive_batches_display_list_pcollector; static PStatCollector _vertices_display_list_pcollector; static PStatCollector _vertices_immediate_pcollector; + static PStatCollector _compute_dispatch_pcollector; public: virtual TypeHandle get_type() const { @@ -754,10 +840,9 @@ private: friend class CLP(VertexBufferContext); friend class CLP(IndexBufferContext); friend class CLP(ShaderContext); + friend class CLP(CgShaderContext); friend class CLP(GraphicsBuffer); friend class CLP(OcclusionQueryContext); }; #include "glGraphicsStateGuardian_src.I" - - diff --git a/panda/src/glstuff/glImmediateModeSender_src.cxx b/panda/src/glstuff/glImmediateModeSender_src.cxx index 6e1ca3dd85..347423cbb7 100644 --- a/panda/src/glstuff/glImmediateModeSender_src.cxx +++ b/panda/src/glstuff/glImmediateModeSender_src.cxx @@ -564,7 +564,7 @@ issue_vertex() { //////////////////////////////////////////////////////////////////// void CLP(ImmediateModeSender)::VectorSender2fui:: issue_vertex() { - const int *d = _reader->get_data2i(); + const LVecBase2i &d = _reader->get_data2i(); #ifndef NDEBUG if (GLCAT.is_spam()) { GLCAT.spam() @@ -573,7 +573,7 @@ issue_vertex() { } #endif // NDEBUG - (*_func)(2, (const GLuint *)d); + (*_func)(2, (const GLuint *)d.get_data()); } //////////////////////////////////////////////////////////////////// @@ -583,7 +583,7 @@ issue_vertex() { //////////////////////////////////////////////////////////////////// void CLP(ImmediateModeSender)::VectorSender3fui:: issue_vertex() { - const int *d = _reader->get_data3i(); + const LVecBase3i &d = _reader->get_data3i(); #ifndef NDEBUG if (GLCAT.is_spam()) { GLCAT.spam() @@ -592,7 +592,7 @@ issue_vertex() { } #endif // NDEBUG - (*_func)(3, (const GLuint *)d); + (*_func)(3, (const GLuint *)d.get_data()); } //////////////////////////////////////////////////////////////////// @@ -602,7 +602,7 @@ issue_vertex() { //////////////////////////////////////////////////////////////////// void CLP(ImmediateModeSender)::VectorSender4fui:: issue_vertex() { - const int *d = _reader->get_data4i(); + const LVecBase4i &d = _reader->get_data4i(); #ifndef NDEBUG if (GLCAT.is_spam()) { GLCAT.spam() @@ -611,7 +611,7 @@ issue_vertex() { } #endif // NDEBUG - (*_func)(4, (const GLuint *)d); + (*_func)(4, (const GLuint *)d.get_data()); } #endif // SUPPORT_IMMEDIATE_MODE diff --git a/panda/src/glstuff/glIndexBufferContext_src.cxx b/panda/src/glstuff/glIndexBufferContext_src.cxx index 8111a06dd3..529d6cdad1 100644 --- a/panda/src/glstuff/glIndexBufferContext_src.cxx +++ b/panda/src/glstuff/glIndexBufferContext_src.cxx @@ -35,7 +35,7 @@ evict_lru() { // Make sure the buffer is unbound before we delete it. if (_glgsg->_current_ibuffer_index == _index) { - if (GLCAT.is_debug() && CLP(debug_buffers)) { + if (GLCAT.is_debug() && gl_debug_buffers) { GLCAT.debug() << "unbinding index buffer\n"; } diff --git a/panda/src/glstuff/glOcclusionQueryContext_src.cxx b/panda/src/glstuff/glOcclusionQueryContext_src.cxx index 2d94df0665..f3197ee68d 100644 --- a/panda/src/glstuff/glOcclusionQueryContext_src.cxx +++ b/panda/src/glstuff/glOcclusionQueryContext_src.cxx @@ -75,7 +75,7 @@ is_answer_ready() const { void CLP(OcclusionQueryContext):: waiting_for_answer() { PStatTimer timer(GraphicsStateGuardian::_wait_occlusion_pcollector); - GLP(Flush)(); + glFlush(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glstuff/glShaderContext_src.I b/panda/src/glstuff/glShaderContext_src.I index a6cd94cdbc..c3424b8cca 100755 --- a/panda/src/glstuff/glShaderContext_src.I +++ b/panda/src/glstuff/glShaderContext_src.I @@ -12,7 +12,6 @@ // //////////////////////////////////////////////////////////////////// -#ifndef OPENGLES_1 //////////////////////////////////////////////////////////////////// // Function: GLShaderContext::valid @@ -26,11 +25,10 @@ INLINE bool CLP(ShaderContext):: valid() { if (_shader->get_error_flag()) return false; - if (_shader->get_language() == Shader::SL_none) return false; -#if defined(HAVE_CG) && !defined(OPENGLES) - if (_cg_context) return true; -#endif - if (_shader->get_language() == Shader::SL_GLSL && _glsl_program != 0) { + if (_shader->get_language() != Shader::SL_GLSL) { + return false; + } + if (_glsl_program != 0) { return true; } return false; @@ -67,6 +65,3 @@ INLINE bool CLP(ShaderContext):: uses_custom_texture_bindings() { return true; } - -#endif // OPENGLES_1 - diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index c5abad0675..fc19c31199 100755 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -16,13 +16,8 @@ #ifndef OPENGLES_1 -#if defined(HAVE_CG) && !defined(OPENGLES) -#include "Cg/cgGL.h" -#endif #include "pStatTimer.h" -#define DEBUG_GL_SHADER 0 - TypeHandle CLP(ShaderContext)::_type_handle; #ifndef GL_GEOMETRY_SHADER_EXT @@ -35,19 +30,6 @@ TypeHandle CLP(ShaderContext)::_type_handle; #define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 #endif -#if defined(HAVE_CG) && !defined(OPENGLES) -#ifndef NDEBUG -#define cg_report_errors() { \ - CGerror err = cgGetError(); \ - if (err != CG_NO_ERROR) { \ - GLCAT.error() << __FILE__ ", line " << __LINE__ << ": " << cgGetErrorString(err) << "\n"; \ - } } -#else -#define cg_report_errors() -#endif -#endif - - //////////////////////////////////////////////////////////////////// // Function: GLShaderContext::ParseAndSetShaderUniformVars // Access: Public @@ -70,137 +52,138 @@ TypeHandle CLP(ShaderContext)::_type_handle; //////////////////////////////////////////////////////////////////// bool CLP(ShaderContext):: parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objShader) { - Shader::ShaderArgInfo p; - p._id = arg_id; + Shader::ShaderArgInfo p; + p._id = arg_id; + p._cat = GLCAT; - string basename(arg_id._name); - // Split it at the underscores. - vector_string pieces; - tokenize(basename, pieces, "_"); + string basename(arg_id._name); + // Split it at the underscores. + vector_string pieces; + tokenize(basename, pieces, "_"); - if (pieces[0] == "mstrans") { - pieces[0] = "trans"; - pieces.push_back("to"); - pieces.push_back("model"); - } - if (pieces[0] == "wstrans") { - pieces[0] = "trans"; - pieces.push_back("to"); - pieces.push_back("world"); - } - if (pieces[0] == "vstrans") { - pieces[0] = "trans"; - pieces.push_back("to"); - pieces.push_back("view"); - } - if (pieces[0] == "cstrans") { - pieces[0] = "trans"; - pieces.push_back("to"); - pieces.push_back("clip"); - } - if (pieces[0] == "mspos") { - pieces[0] = "row3"; - pieces.push_back("to"); - pieces.push_back("model"); - } - if (pieces[0] == "wspos") { - pieces[0] = "row3"; - pieces.push_back("to"); - pieces.push_back("world"); - } - if (pieces[0] == "vspos") { - pieces[0] = "row3"; - pieces.push_back("to"); - pieces.push_back("view"); - } - if (pieces[0] == "cspos") { - pieces[0] = "row3"; - pieces.push_back("to"); - pieces.push_back("clip"); - } + if (pieces[0] == "mstrans") { + pieces[0] = "trans"; + pieces.push_back("to"); + pieces.push_back("model"); + } + if (pieces[0] == "wstrans") { + pieces[0] = "trans"; + pieces.push_back("to"); + pieces.push_back("world"); + } + if (pieces[0] == "vstrans") { + pieces[0] = "trans"; + pieces.push_back("to"); + pieces.push_back("view"); + } + if (pieces[0] == "cstrans") { + pieces[0] = "trans"; + pieces.push_back("to"); + pieces.push_back("clip"); + } + if (pieces[0] == "mspos") { + pieces[0] = "row3"; + pieces.push_back("to"); + pieces.push_back("model"); + } + if (pieces[0] == "wspos") { + pieces[0] = "row3"; + pieces.push_back("to"); + pieces.push_back("world"); + } + if (pieces[0] == "vspos") { + pieces[0] = "row3"; + pieces.push_back("to"); + pieces.push_back("view"); + } + if (pieces[0] == "cspos") { + pieces[0] = "row3"; + pieces.push_back("to"); + pieces.push_back("clip"); + } - if ((pieces[0] == "mat") || (pieces[0] == "inv") || - (pieces[0] == "tps") || (pieces[0] == "itp")) { - if (!objShader->cp_errchk_parameter_words(p, 2)) { - return false; - } - string trans = pieces[0]; - string matrix = pieces[1]; - pieces.clear(); - if (matrix == "modelview") { - tokenize("trans_model_to_apiview", pieces, "_"); - } else if (matrix == "projection") { - tokenize("trans_apiview_to_apiclip", pieces, "_"); - } else if (matrix == "modelproj") { - tokenize("trans_model_to_apiclip", pieces, "_"); - } else { - objShader->cp_report_error(p,"unrecognized matrix name"); - return false; - } - if (trans == "mat") { - pieces[0] = "trans"; - } else if (trans == "inv") { - string t = pieces[1]; - pieces[1] = pieces[3]; - pieces[3] = t; - } else if (trans == "tps") { - pieces[0] = "tpose"; - } else if (trans == "itp") { - string t = pieces[1]; - pieces[1] = pieces[3]; - pieces[3] = t; - pieces[0] = "tpose"; - } + if ((pieces[0] == "mat") || (pieces[0] == "inv") || + (pieces[0] == "tps") || (pieces[0] == "itp")) { + if (!objShader->cp_errchk_parameter_words(p, 2)) { + return false; } + string trans = pieces[0]; + string matrix = pieces[1]; + pieces.clear(); + if (matrix == "modelview") { + tokenize("trans_model_to_apiview", pieces, "_"); + } else if (matrix == "projection") { + tokenize("trans_apiview_to_apiclip", pieces, "_"); + } else if (matrix == "modelproj") { + tokenize("trans_model_to_apiclip", pieces, "_"); + } else { + objShader->cp_report_error(p,"unrecognized matrix name"); + return false; + } + if (trans == "mat") { + pieces[0] = "trans"; + } else if (trans == "inv") { + string t = pieces[1]; + pieces[1] = pieces[3]; + pieces[3] = t; + } else if (trans == "tps") { + pieces[0] = "tpose"; + } else if (trans == "itp") { + string t = pieces[1]; + pieces[1] = pieces[3]; + pieces[3] = t; + pieces[0] = "tpose"; + } + } + // Implement the transform-matrix generator. + if ((pieces[0] == "trans") || + (pieces[0] == "tpose") || + (pieces[0] == "row0") || + (pieces[0] == "row1") || + (pieces[0] == "row2") || + (pieces[0] == "row3") || + (pieces[0] == "col0") || + (pieces[0] == "col1") || + (pieces[0] == "col2") || + (pieces[0] == "col3")) { - if ((pieces[0] == "trans") || - (pieces[0] == "tpose") || - (pieces[0] == "row0") || - (pieces[0] == "row1") || - (pieces[0] == "row2") || - (pieces[0] == "row3") || - (pieces[0] == "col0") || - (pieces[0] == "col1") || - (pieces[0] == "col2") || - (pieces[0] == "col3")) { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._func = Shader::SMF_compose; - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._func = Shader::SMF_compose; + int next = 1; + pieces.push_back(""); - int next = 1; - pieces.push_back(""); + // Decide whether this is a matrix or vector. + if (pieces[0] == "trans") bind._piece = Shader::SMP_whole; + else if (pieces[0] == "tpose") bind._piece = Shader::SMP_transpose; + else if (pieces[0] == "row0") bind._piece = Shader::SMP_row0; + else if (pieces[0] == "row1") bind._piece = Shader::SMP_row1; + else if (pieces[0] == "row2") bind._piece = Shader::SMP_row2; + else if (pieces[0] == "row3") bind._piece = Shader::SMP_row3; + else if (pieces[0] == "col0") bind._piece = Shader::SMP_col0; + else if (pieces[0] == "col1") bind._piece = Shader::SMP_col1; + else if (pieces[0] == "col2") bind._piece = Shader::SMP_col2; + else if (pieces[0] == "col3") bind._piece = Shader::SMP_col3; - // Decide whether this is a matrix or vector. - if (pieces[0] == "trans") bind._piece = Shader::SMP_whole; - else if (pieces[0] == "tpose") bind._piece = Shader::SMP_transpose; - else if (pieces[0] == "row0") bind._piece = Shader::SMP_row0; - else if (pieces[0] == "row1") bind._piece = Shader::SMP_row1; - else if (pieces[0] == "row2") bind._piece = Shader::SMP_row2; - else if (pieces[0] == "row3") bind._piece = Shader::SMP_row3; - else if (pieces[0] == "col0") bind._piece = Shader::SMP_col0; - else if (pieces[0] == "col1") bind._piece = Shader::SMP_col1; - else if (pieces[0] == "col2") bind._piece = Shader::SMP_col2; - else if (pieces[0] == "col3") bind._piece = Shader::SMP_col3; - - if (!objShader->cp_parse_coord_sys(p, pieces, next, bind, true)) { - return false; - } - if (!objShader->cp_parse_delimiter(p, pieces, next)) { - return false; - } - if (!objShader->cp_parse_coord_sys(p, pieces, next, bind, false)) { - return false; - } - if (!objShader->cp_parse_eol(p, pieces, next)) { - return false; - } - objShader->cp_optimize_mat_spec(bind); - objShader->_mat_spec.push_back(bind); - return true; + if (!objShader->cp_parse_coord_sys(p, pieces, next, bind, true)) { + return false; } - return false; + if (!objShader->cp_parse_delimiter(p, pieces, next)) { + return false; + } + if (!objShader->cp_parse_coord_sys(p, pieces, next, bind, false)) { + return false; + } + if (!objShader->cp_parse_eol(p, pieces, next)) { + return false; + } + objShader->cp_optimize_mat_spec(bind); + objShader->_mat_spec.push_back(bind); + return true; + } + return false; } //////////////////////////////////////////////////////////////////// @@ -209,390 +192,339 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objSha // Description: xyz //////////////////////////////////////////////////////////////////// CLP(ShaderContext):: -CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { - _last_gsg = gsg; +CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext(s) { + _glgsg = glgsg; _glsl_program = 0; - _glsl_vshader = 0; - _glsl_fshader = 0; - _glsl_gshader = 0; - _glsl_tcshader = 0; - _glsl_teshader = 0; _uses_standard_vertex_arrays = false; -#if defined(HAVE_CG) && !defined(OPENGLES) - _cg_context = 0; - _cg_vprofile = CG_PROFILE_UNKNOWN; - _cg_fprofile = CG_PROFILE_UNKNOWN; - _cg_gprofile = CG_PROFILE_UNKNOWN; - if (s->get_language() == Shader::SL_Cg) { - // Ask the shader to compile itself for us and - // to give us the resulting Cg program objects. + nassertv(s->get_language() == Shader::SL_GLSL); - if (!s->cg_compile_for(gsg->_shader_caps, - _cg_context, - _cg_vprogram, - _cg_fprogram, - _cg_gprogram, - _cg_parameter_map)) { - return; - } - - // Load the program. - if (_cg_vprogram != 0) { - _cg_vprofile = cgGetProgramProfile(_cg_vprogram); - cgGLLoadProgram(_cg_vprogram); - CGerror verror = cgGetError(); - if (verror != CG_NO_ERROR) { - const char *str = cgGetErrorString(verror); - GLCAT.error() - << "Could not load Cg vertex program: " << s->get_filename(Shader::ST_vertex) - << " (" << cgGetProfileString(_cg_vprofile) << " " << str << ")\n"; - release_resources(gsg); - } - } - - if (_cg_fprogram != 0) { - _cg_fprofile = cgGetProgramProfile(_cg_fprogram); - cgGLLoadProgram(_cg_fprogram); - CGerror ferror = cgGetError(); - if (ferror != CG_NO_ERROR) { - const char *str = cgGetErrorString(ferror); - GLCAT.error() - << "Could not load Cg fragment program: " << s->get_filename(Shader::ST_fragment) - << " (" << cgGetProfileString(_cg_fprofile) << " " << str << ")\n"; - release_resources(gsg); - } - } - - if (_cg_gprogram != 0) { - _cg_gprofile = cgGetProgramProfile(_cg_gprogram); - cgGLLoadProgram(_cg_gprogram); - CGerror gerror = cgGetError(); - if (gerror != CG_NO_ERROR) { - const char *str = cgGetErrorString(gerror); - GLCAT.error() - << "Could not load Cg geometry program: " << s->get_filename(Shader::ST_geometry) - << " (" << cgGetProfileString(_cg_gprofile) << " " << str << ")\n"; - release_resources(gsg); - } - } - gsg->report_my_gl_errors(); + // We compile and analyze the shader here, instead of in shader.cxx, to avoid gobj getting a dependency on GL stuff. + if (!glsl_compile_and_link()) { + release_resources(); + s->_error_flag = true; + return; } -#endif + _glgsg->_glUseProgram(_glsl_program); - if (s->get_language() == Shader::SL_GLSL) { - // We compile and analyze the shader here, instead of in shader.cxx, to avoid gobj getting a dependency on GL stuff. - if (_glsl_program == 0) { - gsg->report_my_gl_errors(); - if (!glsl_compile_shader(gsg)) { - release_resources(gsg); - s->_error_flag = true; - return; + // Analyze the uniforms and put them in _glsl_parameter_map + if (_glsl_parameter_map.size() == 0) { + int seqno = 0, texunitno = 0, imgunitno = 0; + string noprefix; + GLint param_count, param_maxlength, param_size; + GLenum param_type; + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, ¶m_count); + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, ¶m_maxlength); + char* param_name_cstr = (char *)alloca(param_maxlength); + + for (int i = 0; i < param_count; ++i) { + param_name_cstr[0] = 0; + _glgsg->_glGetActiveUniform(_glsl_program, i, param_maxlength, NULL, ¶m_size, ¶m_type, param_name_cstr); + string param_name(param_name_cstr); + GLint p = _glgsg->_glGetUniformLocation(_glsl_program, param_name_cstr); + + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Active uniform " << param_name << " with size " << param_size + << " and type " << param_type << " is bound to location " << p << "\n"; } - } - // Analyze the uniforms and put them in _glsl_parameter_map - if (_glsl_parameter_map.size() == 0) { - int seqno = 0, texunitno = 0; - string noprefix; - GLint param_count, param_maxlength, param_size; - GLenum param_type; - gsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, ¶m_count); - gsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, ¶m_maxlength); - char* param_name_cstr = (char *)alloca(param_maxlength); - for (int i = 0; i < param_count; ++i) { - gsg->_glGetActiveUniform(_glsl_program, i, param_maxlength, NULL, ¶m_size, ¶m_type, param_name_cstr); - string param_name(param_name_cstr); - GLint p = gsg->_glGetUniformLocation(_glsl_program, param_name_cstr); - if (p > -1) { - Shader::ShaderArgId arg_id; - arg_id._name = param_name; - arg_id._seqno = seqno++; - _glsl_parameter_map.push_back(p); - // Check for inputs with p3d_ prefix. - if (param_name.substr(0, 4) == "p3d_") { - noprefix = param_name.substr(4); + if (p > -1) { + // Strip off [0] suffix that some drivers append to arrays. + size_t size = param_name.size(); + if (size > 3 && param_name.substr(size - 3, 3) == "[0]") { + param_name = param_name.substr(0, size - 3); + } - // Check for matrix inputs. - bool transpose = false; - bool inverse = false; - string matrix_name (noprefix); - size_t size = matrix_name.size(); + Shader::ShaderArgId arg_id; + arg_id._name = param_name; + arg_id._seqno = seqno++; + _glsl_parameter_map.push_back(p); - // Check for and chop off any "Transpose" or "Inverse" suffix. - if (size > 15 && matrix_name.compare(size - 9, 9, "Transpose") == 0) { - transpose = true; - matrix_name = matrix_name.substr(0, size - 9); - } - size = matrix_name.size(); - if (size > 13 && matrix_name.compare(size - 7, 7, "Inverse") == 0) { - inverse = true; - matrix_name = matrix_name.substr(0, size - 7); - } - size = matrix_name.size(); + // Check for inputs with p3d_ prefix. + if (param_name.substr(0, 4) == "p3d_") { + noprefix = param_name.substr(4); - // Now if the suffix that is left over is "Matrix", - // we know that it is supposed to be a matrix input. - if (size > 6 && matrix_name.compare(size - 6, 6, "Matrix") == 0) { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - if (transpose) { - bind._piece = Shader::SMP_transpose; - } else { - bind._piece = Shader::SMP_whole; - } - bind._arg[0] = NULL; - bind._arg[1] = NULL; + // Check for matrix inputs. + bool transpose = false; + bool inverse = false; + string matrix_name (noprefix); - if (matrix_name == "ModelViewProjectionMatrix") { - bind._func = Shader::SMF_compose; - if (inverse) { - bind._part[0] = Shader::SMO_apiclip_to_view; - bind._part[1] = Shader::SMO_view_to_model; - } else { - bind._part[0] = Shader::SMO_model_to_view; - bind._part[1] = Shader::SMO_view_to_apiclip; - } - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - - } else if (matrix_name == "ModelViewMatrix") { - bind._func = Shader::SMF_compose; - if (inverse) { - bind._part[0] = Shader::SMO_apiview_to_view; - bind._part[1] = Shader::SMO_view_to_model; - } else { - bind._part[0] = Shader::SMO_model_to_view; - bind._part[1] = Shader::SMO_view_to_apiview; - } - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - - } else if (matrix_name == "ProjectionMatrix") { - bind._func = Shader::SMF_compose; - if (inverse) { - bind._part[0] = Shader::SMO_apiclip_to_view; - bind._part[1] = Shader::SMO_view_to_apiview; - } else { - bind._part[0] = Shader::SMO_apiview_to_view; - bind._part[1] = Shader::SMO_view_to_apiclip; - } - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - - } else if (matrix_name == "NormalMatrix") { - // This is really the upper 3x3 of the ModelViewMatrixInverseTranspose. - bind._func = Shader::SMF_compose; - if (inverse) { - bind._part[0] = Shader::SMO_model_to_view; - bind._part[1] = Shader::SMO_view_to_apiview; - } else { - bind._part[0] = Shader::SMO_apiview_to_view; - bind._part[1] = Shader::SMO_view_to_model; - } - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - - if (transpose) { - bind._piece = Shader::SMP_upper3x3; - } else { - bind._piece = Shader::SMP_transpose3x3; - } - - } else { - GLCAT.error() << "Unrecognized uniform matrix name '" << matrix_name << "'!\n"; - continue; - } - s->_mat_spec.push_back(bind); - continue; - } - if (noprefix.substr(0, 7) == "Texture") { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = 0; - bind._desired_type = Texture::TT_2d_texture; - bind._stage = atoi(noprefix.substr(7).c_str()); - s->_tex_spec.push_back(bind); - continue; - } - GLCAT.error() << "Unrecognized uniform name '" << param_name_cstr << "'!\n"; - continue; - - } else if (param_name.substr(0, 4) == "osg_") { - // These inputs are supported by OpenSceneGraph. We can support - // them as well, to increase compatibility. - // Other inputs we may support in the future: - // int osg_FrameNumber + // Check for and chop off any "Transpose" or "Inverse" suffix. + if (size > 15 && matrix_name.compare(size - 9, 9, "Transpose") == 0) { + transpose = true; + matrix_name = matrix_name.substr(0, size - 9); + } + size = matrix_name.size(); + if (size > 13 && matrix_name.compare(size - 7, 7, "Inverse") == 0) { + inverse = true; + matrix_name = matrix_name.substr(0, size - 7); + } + size = matrix_name.size(); + // Now if the suffix that is left over is "Matrix", + // we know that it is supposed to be a matrix input. + if (size > 6 && matrix_name.compare(size - 6, 6, "Matrix") == 0) { Shader::ShaderMatSpec bind; bind._id = arg_id; + if (transpose) { + bind._piece = Shader::SMP_transpose; + } else { + bind._piece = Shader::SMP_whole; + } bind._arg[0] = NULL; bind._arg[1] = NULL; - if (param_name == "osg_ViewMatrix") { - bind._piece = Shader::SMP_whole; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_world_to_view; - bind._part[1] = Shader::SMO_identity; + if (matrix_name == "ModelViewProjectionMatrix") { + bind._func = Shader::SMF_compose; + if (inverse) { + bind._part[0] = Shader::SMO_apiclip_to_view; + bind._part[1] = Shader::SMO_view_to_model; + } else { + bind._part[0] = Shader::SMO_model_to_view; + bind._part[1] = Shader::SMO_view_to_apiclip; + } bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; + bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - } else if (param_name == "osg_InverseViewMatrix") { - bind._piece = Shader::SMP_whole; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_view_to_world; - bind._part[1] = Shader::SMO_identity; + } else if (matrix_name == "ModelViewMatrix") { + bind._func = Shader::SMF_compose; + if (inverse) { + bind._part[0] = Shader::SMO_apiview_to_view; + bind._part[1] = Shader::SMO_view_to_model; + } else { + bind._part[0] = Shader::SMO_model_to_view; + bind._part[1] = Shader::SMO_view_to_apiview; + } bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; + bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - } else if (param_name == "osg_FrameTime") { - bind._piece = Shader::SMP_row3x1; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_frame_time; - bind._part[1] = Shader::SMO_identity; - bind._dep[0] = Shader::SSD_general; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; + } else if (matrix_name == "ProjectionMatrix") { + bind._func = Shader::SMF_compose; + if (inverse) { + bind._part[0] = Shader::SMO_apiclip_to_view; + bind._part[1] = Shader::SMO_view_to_apiview; + } else { + bind._part[0] = Shader::SMO_apiview_to_view; + bind._part[1] = Shader::SMO_view_to_apiclip; + } + bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - } else if (param_name == "osg_DeltaFrameTime") { - bind._piece = Shader::SMP_row3x1; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_frame_delta; - bind._part[1] = Shader::SMO_identity; - bind._dep[0] = Shader::SSD_general; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); + } else if (matrix_name == "NormalMatrix") { + // This is really the upper 3x3 of the ModelViewMatrixInverseTranspose. + bind._func = Shader::SMF_compose; + if (inverse) { + bind._part[0] = Shader::SMO_model_to_view; + bind._part[1] = Shader::SMO_view_to_apiview; + } else { + bind._part[0] = Shader::SMO_apiview_to_view; + bind._part[1] = Shader::SMO_view_to_model; + } + bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; + + if (transpose) { + bind._piece = Shader::SMP_upper3x3; + } else { + bind._piece = Shader::SMP_transpose3x3; + } + + } else { + GLCAT.error() << "Unrecognized uniform matrix name '" << matrix_name << "'!\n"; continue; } - } - - //Tries to parse shorthand notations like mspos_XXX and trans_model_to_clip_of_XXX - if (parse_and_set_short_hand_shader_vars(arg_id, s)) { + s->_mat_spec.push_back(bind); continue; } + if (size > 7 && noprefix.substr(0, 7) == "Texture") { + _glgsg->_glUniform1i(p, s->_tex_spec.size()); + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = 0; + bind._desired_type = Texture::TT_2d_texture; + bind._stage = atoi(noprefix.substr(7).c_str()); + s->_tex_spec.push_back(bind); + continue; + } + if (size > 9 && noprefix.substr(0, 9) == "Material.") { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_attr_material; + bind._arg[0] = NULL; + bind._dep[0] = Shader::SSD_general | Shader::SSD_material; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; - if (param_size == 1) { - switch (param_type) { -#ifndef OPENGLES - case GL_SAMPLER_1D_SHADOW: - case GL_SAMPLER_1D: { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = InternalName::make(param_name); - bind._desired_type = Texture::TT_1d_texture; - bind._stage = texunitno++; - s->_tex_spec.push_back(bind); - continue; } - case GL_SAMPLER_2D_SHADOW: -#endif - case GL_SAMPLER_2D: { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = InternalName::make(param_name); - bind._desired_type = Texture::TT_2d_texture; - bind._stage = texunitno++; - s->_tex_spec.push_back(bind); - continue; } - case GL_SAMPLER_3D: { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = InternalName::make(param_name); - bind._desired_type = Texture::TT_3d_texture; - bind._stage = texunitno++; - s->_tex_spec.push_back(bind); - continue; } - case GL_SAMPLER_CUBE: { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = InternalName::make(param_name); - bind._desired_type = Texture::TT_cube_map; - bind._stage = texunitno++; - s->_tex_spec.push_back(bind); - continue; } - case GL_FLOAT_MAT2: -#ifndef OPENGLES - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT4x3: -#endif - GLCAT.warning() << "GLSL shader requested an unrecognized matrix type\n"; - continue; - case GL_FLOAT_MAT3: { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._piece = Shader::SMP_upper3x3; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_mat_constant_x; - bind._arg[0] = InternalName::make(param_name); - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; } - case GL_FLOAT_MAT4: { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._piece = Shader::SMP_whole; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_mat_constant_x; - bind._arg[0] = InternalName::make(param_name); - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; } - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - switch (param_type) { - case GL_BOOL: - case GL_FLOAT: bind._piece = Shader::SMP_row3x1; break; - case GL_BOOL_VEC2: - case GL_FLOAT_VEC2: bind._piece = Shader::SMP_row3x2; break; - case GL_BOOL_VEC3: - case GL_FLOAT_VEC3: bind._piece = Shader::SMP_row3x3; break; - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: bind._piece = Shader::SMP_row3 ; break; - } - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_vec_constant_x; - bind._arg[0] = InternalName::make(param_name); - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; } - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - GLCAT.warning() << "Panda does not support passing integers to shaders (yet)!\n"; - continue; - default: - GLCAT.warning() << "Ignoring unrecognized GLSL parameter type!\n"; + if (noprefix == "Material.ambient") { + bind._piece = Shader::SMP_row0; + s->_mat_spec.push_back(bind); + continue; + } else if (noprefix == "Material.diffuse") { + bind._piece = Shader::SMP_row1; + s->_mat_spec.push_back(bind); + continue; + } else if (noprefix == "Material.emission") { + bind._piece = Shader::SMP_row2; + s->_mat_spec.push_back(bind); + continue; + } else if (noprefix == "Material.specular") { + bind._piece = Shader::SMP_row3x3; + s->_mat_spec.push_back(bind); + continue; + } else if (noprefix == "Material.shininess") { + bind._piece = Shader::SMP_cell15; + s->_mat_spec.push_back(bind); + continue; } - } else { - switch (param_type) { + } + if (noprefix == "ColorScale") { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._piece = Shader::SMP_row3; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_attr_colorscale; + bind._arg[0] = NULL; + bind._dep[0] = Shader::SSD_general | Shader::SSD_colorscale; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; + } + GLCAT.error() << "Unrecognized uniform name '" << param_name_cstr << "'!\n"; + continue; + + } else if (param_name.substr(0, 4) == "osg_") { + // These inputs are supported by OpenSceneGraph. We can support + // them as well, to increase compatibility. + // Other inputs we may support in the future: + // int osg_FrameNumber + + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._arg[0] = NULL; + bind._arg[1] = NULL; + + if (param_name == "osg_ViewMatrix") { + bind._piece = Shader::SMP_whole; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_world_to_view; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; + + } else if (param_name == "osg_InverseViewMatrix") { + bind._piece = Shader::SMP_whole; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_view_to_world; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; + + } else if (param_name == "osg_FrameTime") { + bind._piece = Shader::SMP_row3x1; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_frame_time; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; + + } else if (param_name == "osg_DeltaFrameTime") { + bind._piece = Shader::SMP_row3x1; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_frame_delta; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; + } + } + + //Tries to parse shorthand notations like mspos_XXX and trans_model_to_clip_of_XXX + if (parse_and_set_short_hand_shader_vars(arg_id, s)) { + continue; + } + + if (param_size == 1) { + switch (param_type) { +#ifndef OPENGLES + case GL_INT_SAMPLER_1D: + case GL_UNSIGNED_INT_SAMPLER_1D: + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_1D: { + _glgsg->_glUniform1i(p, s->_tex_spec.size()); + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = InternalName::make(param_name); + bind._desired_type = Texture::TT_1d_texture; + bind._stage = texunitno++; + s->_tex_spec.push_back(bind); + continue; } + case GL_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_SAMPLER_2D_SHADOW: +#endif + case GL_SAMPLER_2D: { + _glgsg->_glUniform1i(p, s->_tex_spec.size()); + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = InternalName::make(param_name); + bind._desired_type = Texture::TT_2d_texture; + bind._stage = texunitno++; + s->_tex_spec.push_back(bind); + continue; } +#ifndef OPENGLES + case GL_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_3D: +#endif + case GL_SAMPLER_3D: { + _glgsg->_glUniform1i(p, s->_tex_spec.size()); + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = InternalName::make(param_name); + bind._desired_type = Texture::TT_3d_texture; + bind._stage = texunitno++; + s->_tex_spec.push_back(bind); + continue; } +#ifndef OPENGLES + case GL_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_SHADOW: +#endif + case GL_SAMPLER_CUBE: { + _glgsg->_glUniform1i(p, s->_tex_spec.size()); + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = InternalName::make(param_name); + bind._desired_type = Texture::TT_cube_map; + bind._stage = texunitno++; + s->_tex_spec.push_back(bind); + continue; } +#ifndef OPENGLES + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_2D_ARRAY: { + _glgsg->_glUniform1i(p, s->_tex_spec.size()); + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = InternalName::make(param_name); + bind._desired_type = Texture::TT_2d_texture_array; + bind._stage = texunitno++; + s->_tex_spec.push_back(bind); + continue; } +#endif case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3: #ifndef OPENGLES case GL_FLOAT_MAT2x3: case GL_FLOAT_MAT2x4: @@ -601,15 +533,42 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { case GL_FLOAT_MAT4x2: case GL_FLOAT_MAT4x3: #endif - GLCAT.warning() << "GLSL shader requested an unrecognized matrix array type\n"; + GLCAT.warning() << "GLSL shader requested an unrecognized matrix type\n"; continue; + case GL_FLOAT_MAT3: { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._piece = Shader::SMP_upper3x3; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_mat_constant_x; + bind._arg[0] = InternalName::make(param_name); + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; } case GL_FLOAT_MAT4: { - GLCAT.warning() << "GLSL shader does not yet support passing matrix arrays\n"; + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._piece = Shader::SMP_whole; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_mat_constant_x; + bind._arg[0] = InternalName::make(param_name); + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); continue; } case GL_BOOL: case GL_BOOL_VEC2: case GL_BOOL_VEC3: case GL_BOOL_VEC4: + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: case GL_FLOAT: case GL_FLOAT_VEC2: case GL_FLOAT_VEC3: @@ -618,116 +577,209 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { bind._id = arg_id; switch (param_type) { case GL_BOOL: + case GL_INT: case GL_FLOAT: bind._dim[1] = 1; break; case GL_BOOL_VEC2: + case GL_INT_VEC2: case GL_FLOAT_VEC2: bind._dim[1] = 2; break; case GL_BOOL_VEC3: + case GL_INT_VEC3: case GL_FLOAT_VEC3: bind._dim[1] = 3; break; case GL_BOOL_VEC4: + case GL_INT_VEC4: case GL_FLOAT_VEC4: bind._dim[1] = 4; break; + case GL_FLOAT_MAT3: bind._dim[1] = 9; break; + case GL_FLOAT_MAT4: bind._dim[1] = 16; break; } - bind._arg = InternalName::make(param_name);; - bind._dim[0] = param_size; + bind._arg = InternalName::make(param_name); + bind._dim[0] = 1; bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; bind._dep[1] = Shader::SSD_NONE; s->_ptr_spec.push_back(bind); - continue; } - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - GLCAT.warning() << "Panda does not support passing integer arrays to shaders (yet)!\n"; continue; - default: - GLCAT.warning() << "Ignoring unrecognized GLSL parameter array type!\n"; } +#ifndef OPENGLES + case GL_IMAGE_1D_EXT: + case GL_IMAGE_2D_EXT: + case GL_IMAGE_3D_EXT: + case GL_IMAGE_CUBE_EXT: + case GL_IMAGE_2D_ARRAY_EXT: + case GL_INT_IMAGE_1D_EXT: + case GL_INT_IMAGE_2D_EXT: + case GL_INT_IMAGE_3D_EXT: + case GL_INT_IMAGE_CUBE_EXT: + case GL_INT_IMAGE_2D_ARRAY_EXT: + case GL_UNSIGNED_INT_IMAGE_1D_EXT: + case GL_UNSIGNED_INT_IMAGE_2D_EXT: + case GL_UNSIGNED_INT_IMAGE_3D_EXT: + case GL_UNSIGNED_INT_IMAGE_CUBE_EXT: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT: + // This won't really change at runtime, so we might as well + // bind once and then forget about it. + _glgsg->_glUniform1i(p, imgunitno++); + _glsl_img_inputs.push_back(InternalName::make(param_name)); + _glsl_img_textures.push_back(NULL); + continue; +#endif + default: + GLCAT.warning() << "Ignoring unrecognized GLSL parameter type!\n"; } - } - } - - // Now we've processed the uniforms, we'll process the attribs. - gsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTES, ¶m_count); - gsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, ¶m_maxlength); - param_name_cstr = (char *)alloca(param_maxlength); - - for (int i = 0; i < param_count; ++i) { - gsg->_glGetActiveAttrib(_glsl_program, i, param_maxlength, NULL, ¶m_size, ¶m_type, param_name_cstr); - string param_name(param_name_cstr); - - // Get the attrib location. - GLint p = gsg->_glGetAttribLocation(_glsl_program, param_name_cstr); - - GLCAT.debug() << - "Active attribute " << param_name << " is bound to location " << p << "\n"; - - if (p == -1) { - // A gl_ attribute such as gl_Vertex requires us to pass the - // standard vertex arrays as we would do without shader. - // This is not always the case, though -- see below. - _uses_standard_vertex_arrays = true; - continue; - } - - Shader::ShaderArgId arg_id; - arg_id._name = param_name; - arg_id._seqno = seqno++; - _glsl_parameter_map.push_back(p); - - Shader::ShaderVarSpec bind; - bind._id = arg_id; - bind._name = NULL; - bind._append_uv = -1; - - if (param_name.substr(0, 3) == "gl_") { - // Not all drivers return -1 in glGetAttribLocation - // for gl_ prefixed attributes. - _uses_standard_vertex_arrays = true; - continue; - } else if (param_name.substr(0, 4) == "p3d_") { - noprefix = param_name.substr(4); } else { - noprefix = ""; - } - - if (noprefix.empty()) { - // Arbitrarily named attribute. - bind._name = InternalName::make(param_name); - - } else if (noprefix == "Vertex") { - bind._name = InternalName::get_vertex(); - - } else if (noprefix == "Normal") { - bind._name = InternalName::get_normal(); - - } else if (noprefix == "Color") { - bind._name = InternalName::get_color(); - - } else if (noprefix.substr(0, 7) == "Tangent") { - bind._name = InternalName::get_tangent(); - if (noprefix.size() > 7) { - bind._append_uv = atoi(noprefix.substr(7).c_str()); + switch (param_type) { + case GL_FLOAT_MAT2: +#ifndef OPENGLES + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: +#endif + GLCAT.warning() << "GLSL shader requested an unrecognized matrix array type\n"; + continue; + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: { + Shader::ShaderPtrSpec bind; + bind._id = arg_id; + switch (param_type) { + case GL_BOOL: + case GL_INT: + case GL_FLOAT: bind._dim[1] = 1; break; + case GL_BOOL_VEC2: + case GL_INT_VEC2: + case GL_FLOAT_VEC2: bind._dim[1] = 2; break; + case GL_BOOL_VEC3: + case GL_INT_VEC3: + case GL_FLOAT_VEC3: bind._dim[1] = 3; break; + case GL_BOOL_VEC4: + case GL_INT_VEC4: + case GL_FLOAT_VEC4: bind._dim[1] = 4; break; + case GL_FLOAT_MAT3: bind._dim[1] = 9; break; + case GL_FLOAT_MAT4: bind._dim[1] = 16; break; + } + bind._arg = InternalName::make(param_name); + bind._dim[0] = param_size; + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._dep[1] = Shader::SSD_NONE; + s->_ptr_spec.push_back(bind); + continue; } - - } else if (noprefix.substr(0, 8) == "Binormal") { - bind._name = InternalName::get_binormal(); - if (noprefix.size() > 8) { - bind._append_uv = atoi(noprefix.substr(8).c_str()); + default: + GLCAT.warning() << "Ignoring unrecognized GLSL parameter array type!\n"; } - - } else if (noprefix.substr(0, 13) == "MultiTexCoord") { - bind._name = InternalName::get_texcoord(); - bind._append_uv = atoi(noprefix.substr(13).c_str()); - - } else { - GLCAT.error() << "Unrecognized vertex attrib '" << param_name << "'!\n"; - continue; } - s->_var_spec.push_back(bind); } } - } + + // Now we've processed the uniforms, we'll process the attribs. + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTES, ¶m_count); + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, ¶m_maxlength); + param_name_cstr = (char *)alloca(param_maxlength); - gsg->report_my_gl_errors(); + for (int i = 0; i < param_count; ++i) { + param_name_cstr[0] = 0; + _glgsg->_glGetActiveAttrib(_glsl_program, i, param_maxlength, NULL, ¶m_size, ¶m_type, param_name_cstr); + string param_name(param_name_cstr); + + // Get the attrib location. + GLint p = _glgsg->_glGetAttribLocation(_glsl_program, param_name_cstr); + + GLCAT.debug() << + "Active attribute " << param_name << " is bound to location " << p << "\n"; + + if (p == -1) { + // A gl_ attribute such as gl_Vertex requires us to pass the + // standard vertex arrays as we would do without shader. + // This is not always the case, though -- see below. + _uses_standard_vertex_arrays = true; + continue; + } + + Shader::ShaderArgId arg_id; + arg_id._name = param_name; + arg_id._seqno = seqno++; + _glsl_parameter_map.push_back(p); + + Shader::ShaderVarSpec bind; + bind._id = arg_id; + bind._name = NULL; + bind._append_uv = -1; + + if (param_name.substr(0, 3) == "gl_") { + // Not all drivers return -1 in glGetAttribLocation + // for gl_ prefixed attributes. + _uses_standard_vertex_arrays = true; + continue; + } else if (param_name.substr(0, 4) == "p3d_") { + noprefix = param_name.substr(4); + } else { + noprefix = ""; + } + + bind._integer = (param_type == GL_BOOL || + param_type == GL_BOOL_VEC2 || + param_type == GL_BOOL_VEC3 || + param_type == GL_BOOL_VEC4 || + param_type == GL_INT || + param_type == GL_INT_VEC2 || + param_type == GL_INT_VEC3 || + param_type == GL_INT_VEC4 || + param_type == GL_UNSIGNED_INT || + param_type == GL_UNSIGNED_INT_VEC2 || + param_type == GL_UNSIGNED_INT_VEC3 || + param_type == GL_UNSIGNED_INT_VEC4); + + if (noprefix.empty()) { + // Arbitrarily named attribute. + bind._name = InternalName::make(param_name); + + } else if (noprefix == "Vertex") { + bind._name = InternalName::get_vertex(); + + } else if (noprefix == "Normal") { + bind._name = InternalName::get_normal(); + + } else if (noprefix == "Color") { + bind._name = InternalName::get_color(); + + } else if (noprefix.substr(0, 7) == "Tangent") { + bind._name = InternalName::get_tangent(); + if (noprefix.size() > 7) { + bind._append_uv = atoi(noprefix.substr(7).c_str()); + } + + } else if (noprefix.substr(0, 8) == "Binormal") { + bind._name = InternalName::get_binormal(); + if (noprefix.size() > 8) { + bind._append_uv = atoi(noprefix.substr(8).c_str()); + } + + } else if (noprefix.substr(0, 13) == "MultiTexCoord") { + bind._name = InternalName::get_texcoord(); + bind._append_uv = atoi(noprefix.substr(13).c_str()); + + } else { + GLCAT.error() << "Unrecognized vertex attrib '" << param_name << "'!\n"; + continue; + } + s->_var_spec.push_back(bind); + } + } + _glgsg->_glUseProgram(0); + + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -737,7 +789,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { //////////////////////////////////////////////////////////////////// CLP(ShaderContext):: ~CLP(ShaderContext)() { - release_resources(_last_gsg); + release_resources(); } //////////////////////////////////////////////////////////////////// @@ -747,71 +799,27 @@ CLP(ShaderContext):: // vertex program handles or Cg contexts). //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -release_resources(GSG *gsg) { -#if defined(HAVE_CG) && !defined(OPENGLES) - if (_cg_context) { - cgDestroyContext(_cg_context); - _cg_context = 0; - // Do *NOT* destroy the programs here! It causes problems. -// if (_cg_vprogram != 0) cgDestroyProgram(_cg_vprogram); -// if (_cg_fprogram != 0) cgDestroyProgram(_cg_fprogram); -// if (_cg_gprogram != 0) cgDestroyProgram(_cg_gprogram); - _cg_vprogram = 0; - _cg_fprogram = 0; - _cg_gprogram = 0; - _cg_parameter_map.clear(); - } - if (gsg) { - gsg->report_my_gl_errors(); - } else if (glGetError() != GL_NO_ERROR) { - GLCAT.error() << "GL error in ShaderContext destructor\n"; - } -#endif - - if (!gsg) { +release_resources() { + if (!_glgsg) { return; } if (_glsl_program != 0) { - if (_glsl_vshader != 0) { - gsg->_glDetachShader(_glsl_program, _glsl_vshader); + GLSLShaders::const_iterator it; + for (it = _glsl_shaders.begin(); it != _glsl_shaders.end(); ++it) { + _glgsg->_glDetachShader(_glsl_program, *it); } - if (_glsl_fshader != 0) { - gsg->_glDetachShader(_glsl_program, _glsl_fshader); - } - if (_glsl_gshader != 0) { - gsg->_glDetachShader(_glsl_program, _glsl_gshader); - } - if (_glsl_tcshader != 0) { - gsg->_glDetachShader(_glsl_program, _glsl_tcshader); - } - if (_glsl_teshader != 0) { - gsg->_glDetachShader(_glsl_program, _glsl_teshader); - } - gsg->_glDeleteProgram(_glsl_program); + _glgsg->_glDeleteProgram(_glsl_program); _glsl_program = 0; } - if (_glsl_vshader != 0) { - gsg->_glDeleteShader(_glsl_vshader); - _glsl_vshader = 0; - } - if (_glsl_fshader != 0) { - gsg->_glDeleteShader(_glsl_fshader); - _glsl_fshader = 0; - } - if (_glsl_gshader != 0) { - gsg->_glDeleteShader(_glsl_gshader); - _glsl_gshader = 0; - } - if (_glsl_tcshader != 0) { - gsg->_glDeleteShader(_glsl_tcshader); - _glsl_tcshader = 0; - } - if (_glsl_teshader != 0) { - gsg->_glDeleteShader(_glsl_teshader); - _glsl_teshader = 0; + + GLSLShaders::const_iterator it; + for (it = _glsl_shaders.begin(); it != _glsl_shaders.end(); ++it) { + _glgsg->_glDeleteShader(*it); } + + _glsl_shaders.clear(); - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -822,40 +830,18 @@ release_resources(GSG *gsg) { // input parameters. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -bind(GSG *gsg, bool reissue_parameters) { - _last_gsg = gsg; - +bind(bool reissue_parameters) { // GLSL shaders need to be bound before passing parameters. - if (_shader->get_language() == Shader::SL_GLSL && !_shader->get_error_flag()) { - gsg->_glUseProgram(_glsl_program); + if (!_shader->get_error_flag()) { + _glgsg->_glUseProgram(_glsl_program); } if (reissue_parameters) { // Pass in k-parameters and transform-parameters - issue_parameters(gsg, Shader::SSD_general); + issue_parameters(Shader::SSD_general); } -#if defined(HAVE_CG) && !defined(OPENGLES) - if (_cg_context != 0) { - // Bind the shaders. - if (_cg_vprogram != 0) { - cgGLEnableProfile(_cg_vprofile); - cgGLBindProgram(_cg_vprogram); - } - if (_cg_fprogram != 0) { - cgGLEnableProfile(_cg_fprofile); - cgGLBindProgram(_cg_fprogram); - } - if (_cg_gprogram != 0) { - cgGLEnableProfile(_cg_gprofile); - cgGLBindProgram(_cg_gprogram); - } - - cg_report_errors(); - } -#endif - - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -864,32 +850,9 @@ bind(GSG *gsg, bool reissue_parameters) { // Description: This function disables a currently-bound shader. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -unbind(GSG *gsg) { - _last_gsg = gsg; - -#if defined(HAVE_CG) && !defined(OPENGLES) - if (_cg_context != 0) { - if (_cg_vprogram != 0) { - cgGLUnbindProgram(_cg_vprofile); - cgGLDisableProfile(_cg_vprofile); - } - if (_cg_fprogram != 0) { - cgGLUnbindProgram(_cg_fprofile); - cgGLDisableProfile(_cg_fprofile); - } - if (_cg_gprogram != 0) { - cgGLUnbindProgram(_cg_gprofile); - cgGLDisableProfile(_cg_gprofile); - } - - cg_report_errors(); - } -#endif - - if (_shader->get_language() == Shader::SL_GLSL) { - gsg->_glUseProgram(0); - } - gsg->report_my_gl_errors(); +unbind() { + _glgsg->_glUseProgram(0); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -908,10 +871,8 @@ unbind(GSG *gsg) { // transforms. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -issue_parameters(GSG *gsg, int altered) { - _last_gsg = gsg; - - PStatTimer timer(gsg->_draw_set_state_shader_parameters_pcollector); +issue_parameters(int altered) { + PStatTimer timer(_glgsg->_draw_set_state_shader_parameters_pcollector); if (!valid()) { return; @@ -919,119 +880,44 @@ issue_parameters(GSG *gsg, int altered) { // Iterate through _ptr parameters for (int i=0; i<(int)_shader->_ptr_spec.size(); i++) { - if(altered & (_shader->_ptr_spec[i]._dep[0] | _shader->_ptr_spec[i]._dep[1])) { - if (_shader->get_language() == Shader::SL_GLSL) { - const Shader::ShaderPtrSpec& _ptr = _shader->_ptr_spec[i]; - Shader::ShaderPtrData* _ptr_data = - const_cast< Shader::ShaderPtrData*>(gsg->fetch_ptr_parameter(_ptr)); - if (_ptr_data == NULL) { //the input is not contained in ShaderPtrData - release_resources(gsg); - return; - } - GLint p = _glsl_parameter_map[_shader->_ptr_spec[i]._id._seqno]; - switch (_ptr._dim[1]) { - case 1: gsg->_glUniform1fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue; - case 2: gsg->_glUniform2fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue; - case 3: gsg->_glUniform3fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue; - case 4: gsg->_glUniform4fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue; - } - } -#if defined(HAVE_CG) && !defined(OPENGLES) - else if (_shader->get_language() == Shader::SL_Cg) { - const Shader::ShaderPtrSpec& _ptr = _shader->_ptr_spec[i]; - Shader::ShaderPtrData* ptr_data = - const_cast< Shader::ShaderPtrData*>(gsg->fetch_ptr_parameter(_ptr)); - - if (ptr_data == NULL){ //the input is not contained in ShaderPtrData - release_resources(gsg); - return; - } - //check if the data must be shipped to the GPU - /*if (!ptr_data->_updated) - continue; - ptr_data->_updated = false;*/ + const Shader::ShaderPtrSpec& spec = _shader->_ptr_spec[i]; - //Check if the size of the shader input and ptr_data match - int input_size = _ptr._dim[0] * _ptr._dim[1] * _ptr._dim[2]; - - // dimension is negative only if the parameter had the (deprecated)k_ prefix. - if ((input_size > ptr_data->_size) && (_ptr._dim[0] > 0)) { - GLCAT.error() << _ptr._id._name << ": incorrect number of elements, expected " - << input_size <<" got " << ptr_data->_size << "\n"; - release_resources(gsg); - return; - } - CGparameter p = _cg_parameter_map[_ptr._id._seqno]; - - switch (ptr_data->_type) { - case Shader::SPT_float: - switch(_ptr._info._class) { - case Shader::SAC_scalar: cgSetParameter1fv(p,(float*)ptr_data->_ptr); continue; - case Shader::SAC_vector: - switch(_ptr._info._type) { - case Shader::SAT_vec1: cgSetParameter1fv(p,(float*)ptr_data->_ptr); continue; - case Shader::SAT_vec2: cgSetParameter2fv(p,(float*)ptr_data->_ptr); continue; - case Shader::SAT_vec3: cgSetParameter3fv(p,(float*)ptr_data->_ptr); continue; - case Shader::SAT_vec4: cgSetParameter4fv(p,(float*)ptr_data->_ptr); continue; - } - case Shader::SAC_matrix: cgGLSetMatrixParameterfc(p,(float*)ptr_data->_ptr); continue; - case Shader::SAC_array: { - switch(_ptr._info._subclass) { - case Shader::SAC_scalar: - cgGLSetParameterArray1f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; - case Shader::SAC_vector: - switch(_ptr._dim[2]) { - case 1: cgGLSetParameterArray1f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; - case 2: cgGLSetParameterArray2f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; - case 3: cgGLSetParameterArray3f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; - case 4: cgGLSetParameterArray4f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; - } - case Shader::SAC_matrix: - cgGLSetMatrixParameterArrayfc(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; - } - } - } - case Shader::SPT_double: - switch(_ptr._info._class) { - case Shader::SAC_scalar: cgSetParameter1dv(p,(double*)ptr_data->_ptr); continue; - case Shader::SAC_vector: - switch(_ptr._info._type) { - case Shader::SAT_vec1: cgSetParameter1dv(p,(double*)ptr_data->_ptr); continue; - case Shader::SAT_vec2: cgSetParameter2dv(p,(double*)ptr_data->_ptr); continue; - case Shader::SAT_vec3: cgSetParameter3dv(p,(double*)ptr_data->_ptr); continue; - case Shader::SAT_vec4: cgSetParameter4dv(p,(double*)ptr_data->_ptr); continue; - } - case Shader::SAC_matrix: cgGLSetMatrixParameterdc(p,(double*)ptr_data->_ptr); continue; - case Shader::SAC_array: { - switch(_ptr._info._subclass) { - case Shader::SAC_scalar: - cgGLSetParameterArray1d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; - case Shader::SAC_vector: - switch(_ptr._dim[2]) { - case 1: cgGLSetParameterArray1d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; - case 2: cgGLSetParameterArray2d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; - case 3: cgGLSetParameterArray3d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; - case 4: cgGLSetParameterArray4d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; - } - case Shader::SAC_matrix: - cgGLSetMatrixParameterArraydc(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; - } - } - } - default: GLCAT.error() << _ptr._id._name << ":" << "unrecognized parameter type\n"; - release_resources(gsg); - return; - } + if (altered & (spec._dep[0] | spec._dep[1])) { + Shader::ShaderPtrData* ptr_data = + const_cast< Shader::ShaderPtrData*>(_glgsg->fetch_ptr_parameter(spec)); + if (ptr_data == NULL) { //the input is not contained in ShaderPtrData + release_resources(); + return; + } + + GLint p = _glsl_parameter_map[spec._id._seqno]; + switch (ptr_data->_type) { + case Shader::SPT_float: + switch (spec._dim[1]) { + case 1: _glgsg->_glUniform1fv(p, spec._dim[0], (float*)ptr_data->_ptr); continue; + case 2: _glgsg->_glUniform2fv(p, spec._dim[0], (float*)ptr_data->_ptr); continue; + case 3: _glgsg->_glUniform3fv(p, spec._dim[0], (float*)ptr_data->_ptr); continue; + case 4: _glgsg->_glUniform4fv(p, spec._dim[0], (float*)ptr_data->_ptr); continue; + case 9: _glgsg->_glUniformMatrix3fv(p, spec._dim[0], GL_FALSE, (float*)ptr_data->_ptr); continue; + case 16: _glgsg->_glUniformMatrix4fv(p, spec._dim[0], GL_FALSE, (float*)ptr_data->_ptr); continue; + } + case Shader::SPT_int: + switch (spec._dim[1]) { + case 1: _glgsg->_glUniform1iv(p, spec._dim[0], (int*)ptr_data->_ptr); continue; + case 2: _glgsg->_glUniform2iv(p, spec._dim[0], (int*)ptr_data->_ptr); continue; + case 3: _glgsg->_glUniform3iv(p, spec._dim[0], (int*)ptr_data->_ptr); continue; + case 4: _glgsg->_glUniform4iv(p, spec._dim[0], (int*)ptr_data->_ptr); continue; + } + case Shader::SPT_double: + GLCAT.error() << "Passing double-precision shader inputs to GLSL shaders is not currently supported\n"; + continue; } -#endif } } - //FIXME: this could be much faster if we used deferred parameter setting. - for (int i=0; i<(int)_shader->_mat_spec.size(); i++) { if (altered & (_shader->_mat_spec[i]._dep[0] | _shader->_mat_spec[i]._dep[1])) { - const LMatrix4 *val = gsg->fetch_specified_value(_shader->_mat_spec[i], altered); + const LMatrix4 *val = _glgsg->fetch_specified_value(_shader->_mat_spec[i], altered); if (!val) continue; #ifndef STDFLOAT_DOUBLE // In this case, the data is already single-precision. @@ -1042,75 +928,41 @@ issue_parameters(GSG *gsg, int altered) { const PN_float32 *data = valf.get_data(); #endif - if (_shader->get_language() == Shader::SL_GLSL) { - GLint p = _glsl_parameter_map[_shader->_mat_spec[i]._id._seqno]; - switch (_shader->_mat_spec[i]._piece) { - case Shader::SMP_whole: gsg->_glUniformMatrix4fv(p, 1, false, data); continue; - case Shader::SMP_transpose: gsg->_glUniformMatrix4fv(p, 1, true, data); continue; - case Shader::SMP_col0: gsg->_glUniform4f(p, data[0], data[4], data[ 8], data[12]); continue; - case Shader::SMP_col1: gsg->_glUniform4f(p, data[1], data[5], data[ 9], data[13]); continue; - case Shader::SMP_col2: gsg->_glUniform4f(p, data[2], data[6], data[10], data[14]); continue; - case Shader::SMP_col3: gsg->_glUniform4f(p, data[3], data[7], data[11], data[15]); continue; - case Shader::SMP_row0: gsg->_glUniform4fv(p, 1, data+ 0); continue; - case Shader::SMP_row1: gsg->_glUniform4fv(p, 1, data+ 4); continue; - case Shader::SMP_row2: gsg->_glUniform4fv(p, 1, data+ 8); continue; - case Shader::SMP_row3: gsg->_glUniform4fv(p, 1, data+12); continue; - case Shader::SMP_row3x1: gsg->_glUniform1fv(p, 1, data+12); continue; - case Shader::SMP_row3x2: gsg->_glUniform2fv(p, 1, data+12); continue; - case Shader::SMP_row3x3: gsg->_glUniform3fv(p, 1, data+12); continue; - case Shader::SMP_upper3x3: - { - LMatrix3f upper3 = val->get_upper_3(); - gsg->_glUniformMatrix3fv(p, 1, false, upper3.get_data()); - continue; - } - case Shader::SMP_transpose3x3: - { - LMatrix3f upper3 = val->get_upper_3(); - gsg->_glUniformMatrix3fv(p, 1, true, upper3.get_data()); - continue; - } + GLint p = _glsl_parameter_map[_shader->_mat_spec[i]._id._seqno]; + switch (_shader->_mat_spec[i]._piece) { + case Shader::SMP_whole: _glgsg->_glUniformMatrix4fv(p, 1, GL_FALSE, data); continue; + case Shader::SMP_transpose: _glgsg->_glUniformMatrix4fv(p, 1, GL_TRUE, data); continue; + case Shader::SMP_col0: _glgsg->_glUniform4f(p, data[0], data[4], data[ 8], data[12]); continue; + case Shader::SMP_col1: _glgsg->_glUniform4f(p, data[1], data[5], data[ 9], data[13]); continue; + case Shader::SMP_col2: _glgsg->_glUniform4f(p, data[2], data[6], data[10], data[14]); continue; + case Shader::SMP_col3: _glgsg->_glUniform4f(p, data[3], data[7], data[11], data[15]); continue; + case Shader::SMP_row0: _glgsg->_glUniform4fv(p, 1, data+ 0); continue; + case Shader::SMP_row1: _glgsg->_glUniform4fv(p, 1, data+ 4); continue; + case Shader::SMP_row2: _glgsg->_glUniform4fv(p, 1, data+ 8); continue; + case Shader::SMP_row3: _glgsg->_glUniform4fv(p, 1, data+12); continue; + case Shader::SMP_row3x1: _glgsg->_glUniform1fv(p, 1, data+12); continue; + case Shader::SMP_row3x2: _glgsg->_glUniform2fv(p, 1, data+12); continue; + case Shader::SMP_row3x3: _glgsg->_glUniform3fv(p, 1, data+12); continue; + case Shader::SMP_upper3x3: + { + LMatrix3f upper3 = val->get_upper_3(); + _glgsg->_glUniformMatrix3fv(p, 1, false, upper3.get_data()); + continue; } - } -#if defined(HAVE_CG) && !defined(OPENGLES) - else if (_shader->get_language() == Shader::SL_Cg) { - CGparameter p = _cg_parameter_map[_shader->_mat_spec[i]._id._seqno]; - switch (_shader->_mat_spec[i]._piece) { - case Shader::SMP_whole: GLfc(cgGLSetMatrixParameter)(p, data); continue; - case Shader::SMP_transpose: GLfr(cgGLSetMatrixParameter)(p, data); continue; - case Shader::SMP_col0: GLf(cgGLSetParameter4)(p, data[0], data[4], data[ 8], data[12]); continue; - case Shader::SMP_col1: GLf(cgGLSetParameter4)(p, data[1], data[5], data[ 9], data[13]); continue; - case Shader::SMP_col2: GLf(cgGLSetParameter4)(p, data[2], data[6], data[10], data[14]); continue; - case Shader::SMP_col3: GLf(cgGLSetParameter4)(p, data[3], data[7], data[11], data[15]); continue; - case Shader::SMP_row0: GLfv(cgGLSetParameter4)(p, data+ 0); continue; - case Shader::SMP_row1: GLfv(cgGLSetParameter4)(p, data+ 4); continue; - case Shader::SMP_row2: GLfv(cgGLSetParameter4)(p, data+ 8); continue; - case Shader::SMP_row3: GLfv(cgGLSetParameter4)(p, data+12); continue; - case Shader::SMP_row3x1: GLfv(cgGLSetParameter1)(p, data+12); continue; - case Shader::SMP_row3x2: GLfv(cgGLSetParameter2)(p, data+12); continue; - case Shader::SMP_row3x3: GLfv(cgGLSetParameter3)(p, data+12); continue; - case Shader::SMP_upper3x3: - { - LMatrix3f upper3 = val->get_upper_3(); - GLfc(cgGLSetMatrixParameter)(p, upper3.get_data()); - continue; - } - case Shader::SMP_transpose3x3: - { - LMatrix3f upper3 = val->get_upper_3(); - GLfr(cgGLSetMatrixParameter)(p, upper3.get_data()); - continue; - } + case Shader::SMP_transpose3x3: + { + LMatrix3f upper3 = val->get_upper_3(); + _glgsg->_glUniformMatrix3fv(p, 1, true, upper3.get_data()); + continue; } + case Shader::SMP_cell15: + _glgsg->_glUniform1fv(p, 1, data+15); + continue; } -#endif } } -#if defined(HAVE_CG) && !defined(OPENGLES) - cg_report_errors(); -#endif - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -1119,29 +971,18 @@ issue_parameters(GSG *gsg, int altered) { // Description: Disable all the vertex arrays used by this shader. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -disable_shader_vertex_arrays(GSG *gsg) { - _last_gsg = gsg; +disable_shader_vertex_arrays() { if (!valid()) { return; } - if (_shader->get_language() == Shader::SL_GLSL) { - for (int i=0; i<(int)_shader->_var_spec.size(); i++) { - gsg->_glDisableVertexAttribArray(i); - } + for (int i=0; i<(int)_shader->_var_spec.size(); i++) { + const Shader::ShaderVarSpec &bind = _shader->_var_spec[i]; + const GLint p = _glsl_parameter_map[bind._id._seqno]; + _glgsg->_glDisableVertexAttribArray(p); } -#if defined(HAVE_CG) && !defined(OPENGLES) - else if (_shader->get_language() == Shader::SL_Cg) { - for (int i=0; i<(int)_shader->_var_spec.size(); i++) { - CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; - if (p == 0) continue; - cgGLDisableClientState(p); - } - cg_report_errors(); - } -#endif - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -1156,19 +997,16 @@ disable_shader_vertex_arrays(GSG *gsg) { // reenable them. We may optimize this someday. //////////////////////////////////////////////////////////////////// bool CLP(ShaderContext):: -update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, - bool force) { - _last_gsg = gsg; - if (prev) prev->disable_shader_vertex_arrays(gsg); +update_shader_vertex_arrays(ShaderContext *prev, bool force) { + if (prev) { + prev->disable_shader_vertex_arrays(); + } if (!valid()) { return true; } -#if defined(HAVE_CG) && !defined(OPENGLES) - cg_report_errors(); -#endif #ifdef SUPPORT_IMMEDIATE_MODE - if (gsg->_use_sender) { + if (_glgsg->_use_sender) { GLCAT.error() << "immediate mode shaders not implemented yet\n"; } else #endif // SUPPORT_IMMEDIATE_MODE @@ -1177,19 +1015,14 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, Geom::NumericType numeric_type; int start, stride, num_values; int nvarying = _shader->_var_spec.size(); - for (int i = 0; i < nvarying; ++i) { -#if defined(HAVE_CG) && !defined(OPENGLES) - if (_shader->get_language() == Shader::SL_Cg) { - if (_cg_parameter_map[_shader->_var_spec[i]._id._seqno] == 0) { - continue; - } - } -#endif - InternalName *name = _shader->_var_spec[i]._name; - int texslot = _shader->_var_spec[i]._append_uv; - if (texslot >= 0 && texslot < gsg->_state_texture->get_num_on_stages()) { - TextureStage *stage = gsg->_state_texture->get_on_stage(texslot); + for (int i = 0; i < nvarying; ++i) { + const Shader::ShaderVarSpec &bind = _shader->_var_spec[i]; + InternalName *name = bind._name; + int texslot = bind._append_uv; + + if (texslot >= 0 && texslot < _glgsg->_state_texture->get_num_on_stages()) { + TextureStage *stage = _glgsg->_state_texture->get_on_stage(texslot); InternalName *texname = stage->get_texcoord_name(); if (name == InternalName::get_texcoord()) { @@ -1198,44 +1031,39 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, name = name->append(texname->get_basename()); } } - if (gsg->_data_reader->get_array_info(name, - array_reader, num_values, numeric_type, - start, stride)) { + const GLint p = _glsl_parameter_map[bind._id._seqno]; + + if (_glgsg->_data_reader->get_array_info(name, + array_reader, num_values, numeric_type, + start, stride)) { const unsigned char *client_pointer; - if (!gsg->setup_array_data(client_pointer, array_reader, force)) { + if (!_glgsg->setup_array_data(client_pointer, array_reader, force)) { return false; } - if (_shader->get_language() == Shader::SL_GLSL) { - const GLint p = _glsl_parameter_map[_shader->_var_spec[i]._id._seqno]; - gsg->_glEnableVertexAttribArray(p); - gsg->_glVertexAttribPointer(p, num_values, gsg->get_numeric_type(numeric_type), - GL_TRUE, stride, client_pointer + start); + _glgsg->_glEnableVertexAttribArray(p); -#if defined(HAVE_CG) && !defined(OPENGLES) - } else if (_shader->get_language() == Shader::SL_Cg) { - CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; - cgGLSetParameterPointer(p, - num_values, gsg->get_numeric_type(numeric_type), - stride, client_pointer + start); - cgGLEnableClientState(p); +#ifndef OPENGLES + if (bind._integer) { + _glgsg->_glVertexAttribIPointer(p, num_values, _glgsg->get_numeric_type(numeric_type), + stride, client_pointer + start); + } else #endif + if (numeric_type == GeomEnums::NT_packed_dabc) { + _glgsg->_glVertexAttribPointer(p, GL_BGRA, GL_UNSIGNED_BYTE, + GL_TRUE, stride, client_pointer + start); + } else { + _glgsg->_glVertexAttribPointer(p, num_values, _glgsg->get_numeric_type(numeric_type), + GL_TRUE, stride, client_pointer + start); } + } else { + _glgsg->_glDisableVertexAttribArray(p); } -#if defined(HAVE_CG) && !defined(OPENGLES) - else if (_shader->get_language() == Shader::SL_Cg) { - CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; - cgGLDisableClientState(p); - } -#endif } } -#if defined(HAVE_CG) && !defined(OPENGLES) - cg_report_errors(); -#endif - gsg->report_my_gl_errors(); - + _glgsg->report_my_gl_errors(); + return true; } @@ -1245,58 +1073,78 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, // Description: Disable all the texture bindings used by this shader. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -disable_shader_texture_bindings(GSG *gsg) { - _last_gsg = gsg; +disable_shader_texture_bindings() { if (!valid()) { return; } -#ifndef OPENGLES_2 - for (int i=0; i<(int)_shader->_tex_spec.size(); i++) { - if (_shader->get_language() == Shader::SL_GLSL) { - if (_shader->_tex_spec[i]._name == 0) { - gsg->_glActiveTexture(GL_TEXTURE0 + _shader->_tex_spec[i]._stage); - } else { - gsg->_glActiveTexture(GL_TEXTURE0 + _shader->_tex_spec[i]._stage + _stage_offset); - } -#if defined(HAVE_CG) && !defined(OPENGLES) - } else if (_shader->get_language() == Shader::SL_Cg) { - CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno]; - if (p == 0) continue; - int texunit = cgGetParameterResourceIndex(p); - gsg->_glActiveTexture(GL_TEXTURE0 + texunit); -#endif - } else { - return; - } + for (int i = 0; i < _shader->_tex_spec.size(); ++i) { #ifndef OPENGLES - GLP(BindTexture)(GL_TEXTURE_1D, 0); + // Check if bindless was used, if so, there's nothing to unbind. + if (_glgsg->_supports_bindless_texture) { + GLint p = _glsl_parameter_map[_shader->_tex_spec[i]._id._seqno]; + + if (_glsl_uniform_handles.count(p) > 0) { + continue; + } + } + + if (_glgsg->_supports_multi_bind) { + // There are non-bindless textures to unbind, and we're lazy, + // so let's go and unbind everything after this point using one + // multi-bind call, and then break out of the loop. + _glgsg->_glBindTextures(i, _shader->_tex_spec.size() - i, NULL); + break; + } +#endif + + _glgsg->_glActiveTexture(GL_TEXTURE0 + i); + +#ifndef OPENGLES + glBindTexture(GL_TEXTURE_1D, 0); #endif // OPENGLES - GLP(BindTexture)(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_2D, 0); #ifndef OPENGLES_1 - if (gsg->_supports_3d_texture) { - GLP(BindTexture)(GL_TEXTURE_3D, 0); + if (_glgsg->_supports_3d_texture) { + glBindTexture(GL_TEXTURE_3D, 0); } #endif // OPENGLES_1 #ifndef OPENGLES - if (gsg->_supports_2d_texture_array) { - GLP(BindTexture)(GL_TEXTURE_2D_ARRAY_EXT, 0); + if (_glgsg->_supports_2d_texture_array) { + glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, 0); } #endif - if (gsg->_supports_cube_map) { - GLP(BindTexture)(GL_TEXTURE_CUBE_MAP, 0); + if (_glgsg->_supports_cube_map) { + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); } - // This is probably faster - but maybe not as safe? - // cgGLDisableTextureParameter(p); } -#endif // OPENGLES_2 - _stage_offset = 0; -#if defined(HAVE_CG) && !defined(OPENGLES) - cg_report_errors(); +#ifndef OPENGLES + // Now unbind all the image units. Not sure if we *have* to do this. + int num_image_units = min(_glsl_img_inputs.size(), (size_t)_glgsg->_max_image_units); + + if (num_image_units > 0) { + if (_glgsg->_supports_multi_bind) { + _glgsg->_glBindImageTextures(0, num_image_units, NULL); + + } else { + for (int i = 0; i < num_image_units; ++i) { + _glgsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); + } + } + + if (gl_enable_memory_barriers) { + for (int i = 0; i < num_image_units; ++i) { + // We don't distinguish between read-only and read-write/write-only + // image access, so we have to assume that the shader wrote to it. + _glsl_img_textures[i]->mark_incoherent(); + _glsl_img_textures[i] = NULL; + } + } + } #endif - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -1311,56 +1159,97 @@ disable_shader_texture_bindings(GSG *gsg) { // reenable them. We may optimize this someday. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) { - _last_gsg = gsg; - +update_shader_texture_bindings(ShaderContext *prev) { if (prev) { - prev->disable_shader_texture_bindings(gsg); + prev->disable_shader_texture_bindings(); } if (!valid()) { return; } - // We get the TextureAttrib directly from the _target_rs, not the - // filtered TextureAttrib in _target_texture. - const TextureAttrib *texattrib = DCAST(TextureAttrib, gsg->_target_rs->get_attrib_def(TextureAttrib::get_class_slot())); - nassertv(texattrib != (TextureAttrib *)NULL); - _stage_offset = texattrib->get_num_on_stages(); +#ifndef OPENGLES + GLbitfield barriers = 0; - for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) { - InternalName *id = _shader->_tex_spec[i]._name; - int texunit; + // First bind all the 'image units'; a bit of an esoteric OpenGL feature right now. + int num_image_units = min(_glsl_img_inputs.size(), (size_t)_glgsg->_max_image_units); - if (_shader->get_language() == Shader::SL_GLSL) { - texunit = _shader->_tex_spec[i]._stage; - if (id != 0) { - texunit += _stage_offset; + if (num_image_units > 0) { + GLuint *multi_img = NULL; + // If we support multi-bind, prepare an array. + if (_glgsg->_supports_multi_bind) { + multi_img = new GLuint[num_image_units]; + } + + for (int i = 0; i < num_image_units; ++i) { + const InternalName *name = _glsl_img_inputs[i]; + Texture *tex = _glgsg->_target_shader->get_shader_input_texture(name); + + GLuint gl_tex = 0; + if (tex != NULL) { + int view = _glgsg->get_current_tex_view_offset(); + + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg)); + if (gtc != (TextureContext*)NULL) { + _glsl_img_textures[i] = gtc; + + gl_tex = gtc->_index; + _glgsg->update_texture(gtc, true); + + if (gtc->needs_barrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT)) { + barriers |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; + } + } + } + + if (multi_img != NULL) { + // Put in array so we can multi-bind later. + multi_img[i] = gl_tex; + + } else { + // We don't support multi-bind, so bind now in the same way that multi-bind would have done it. + if (gl_tex == 0) { + _glgsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); + } else { + //TODO: automatically convert to sized type instead of plain GL_RGBA + // If a base type is used, it will crash. + GLint internal_format = _glgsg->get_internal_image_format(tex); + _glgsg->_glBindImageTexture(i, gl_tex, 0, GL_TRUE, 0, GL_READ_WRITE, internal_format); + } } } -#if defined(HAVE_CG) && !defined(OPENGLES) - else if (_shader->get_language() == Shader::SL_Cg) { - CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno]; - if (p == 0) { - continue; - } - texunit = cgGetParameterResourceIndex(p); + + if (multi_img != NULL) { + _glgsg->_glBindImageTextures(0, num_image_units, multi_img); + delete[] multi_img; } + } #endif - Texture *tex = 0; - int view = gsg->get_current_tex_view_offset(); - if (id != 0) { - const ShaderInput *input = gsg->_target_shader->get_shader_input(id); + // We get the TextureAttrib directly from the _target_rs, not the + // filtered TextureAttrib in _target_texture. + const TextureAttrib *texattrib = DCAST(TextureAttrib, _glgsg->_target_rs->get_attrib_def(TextureAttrib::get_class_slot())); + nassertv(texattrib != (TextureAttrib *)NULL); + + for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) { + const InternalName *id = _shader->_tex_spec[i]._name; + int texunit = _shader->_tex_spec[i]._stage; + + Texture *tex = NULL; + int view = _glgsg->get_current_tex_view_offset(); + if (id != NULL) { + const ShaderInput *input = _glgsg->_target_shader->get_shader_input(id); tex = input->get_texture(); + } else { - if (_shader->_tex_spec[i]._stage >= texattrib->get_num_on_stages()) { + if (texunit >= texattrib->get_num_on_stages()) { continue; } - TextureStage *stage = texattrib->get_on_stage(_shader->_tex_spec[i]._stage); + TextureStage *stage = texattrib->get_on_stage(texunit); tex = texattrib->get_on_texture(stage); view += stage->get_tex_view_offset(); } + if (_shader->_tex_spec[i]._suffix != 0) { // The suffix feature is inefficient. It is a temporary hack. if (tex == 0) { @@ -1372,34 +1261,65 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) { continue; } - gsg->_glActiveTexture(GL_TEXTURE0 + texunit); - - TextureContext *tc = tex->prepare_now(view, gsg->_prepared_objects, gsg); - if (tc == (TextureContext*)NULL) { + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg)); + if (gtc == NULL) { continue; } - GLenum target = gsg->get_texture_target(tex->get_texture_type()); - if (target == GL_NONE) { - // Unsupported texture mode. - continue; + GLint p = _glsl_parameter_map[_shader->_tex_spec[i]._id._seqno]; + +#ifndef OPENGLES + // If it was recently written to, we will have to issue a memory barrier soon. + if (gtc->needs_barrier(GL_TEXTURE_FETCH_BARRIER_BIT)) { + barriers |= GL_TEXTURE_FETCH_BARRIER_BIT; } - if (_shader->get_language() == Shader::SL_GLSL) { - GLint p = _glsl_parameter_map[_shader->_tex_spec[i]._id._seqno]; - gsg->_glUniform1i(p, texunit); - } + // Try bindless texturing first, if supported. + if (gl_use_bindless_texture && _glgsg->_supports_bindless_texture) { + // We demand the real texture, since we won't be able + // to change the texture properties after this point. + if (!_glgsg->update_texture(gtc, true)) { + continue; + } - if (!gsg->update_texture(tc, false)) { - continue; - } - } + GLuint64 handle = gtc->get_handle(); + if (handle != 0) { + gtc->make_handle_resident(); + gtc->set_active(true); -#if defined(HAVE_CG) && !defined(OPENGLES) - cg_report_errors(); + // Check if we have already specified this texture handle. + // If so, no need to call glUniformHandle again. + pmap::const_iterator it; + it = _glsl_uniform_handles.find(p); + if (it != _glsl_uniform_handles.end() && it->second == handle) { + // Already specified. + continue; + } else { + _glgsg->_glUniformHandleui64(p, handle); + _glsl_uniform_handles[p] = handle; + } + continue; + } + } #endif - gsg->report_my_gl_errors(); + // Bindless texturing wasn't supported or didn't work, so + // let's just bind the texture normally. + _glgsg->_glActiveTexture(GL_TEXTURE0 + i); + if (!_glgsg->update_texture(gtc, false)) { + continue; + } + _glgsg->apply_texture(gtc); + } + +#ifndef OPENGLES + if (barriers != 0) { + // Issue a memory barrier. + _glgsg->issue_memory_barrier(barriers); + } +#endif + + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -1408,16 +1328,16 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) { // Description: This subroutine prints the infolog for a shader. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -glsl_report_shader_errors(GSG *gsg, unsigned int shader) { +glsl_report_shader_errors(GLuint shader) { char *info_log; GLint length = 0; GLint num_chars = 0; - gsg->_glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); + _glgsg->_glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); if (length > 1) { info_log = (char *) malloc(length); - gsg->_glGetShaderInfoLog(shader, length, &num_chars, info_log); + _glgsg->_glGetShaderInfoLog(shader, length, &num_chars, info_log); if (strcmp(info_log, "Success.\n") != 0 && strcmp(info_log, "No errors.\n") != 0) { GLCAT.error(false) << info_log << "\n"; } @@ -1431,16 +1351,16 @@ glsl_report_shader_errors(GSG *gsg, unsigned int shader) { // Description: This subroutine prints the infolog for a program. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -glsl_report_program_errors(GSG *gsg, unsigned int program) { +glsl_report_program_errors(GLuint program) { char *info_log; GLint length = 0; GLint num_chars = 0; - gsg->_glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); + _glgsg->_glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); if (length > 1) { info_log = (char *) malloc(length); - gsg->_glGetProgramInfoLog(program, length, &num_chars, info_log); + _glgsg->_glGetProgramInfoLog(program, length, &num_chars, info_log); if (strcmp(info_log, "Success.\n") != 0 && strcmp(info_log, "No errors.\n") != 0) { GLCAT.error(false) << info_log << "\n"; } @@ -1449,141 +1369,175 @@ glsl_report_program_errors(GSG *gsg, unsigned int program) { } //////////////////////////////////////////////////////////////////// -// Function: Shader::glsl_compile_entry_point +// Function: Shader::glsl_compile_shader // Access: Private // Description: //////////////////////////////////////////////////////////////////// -unsigned int CLP(ShaderContext):: -glsl_compile_entry_point(GSG *gsg, Shader::ShaderType type) { - unsigned int handle = 0; +bool CLP(ShaderContext):: +glsl_compile_shader(Shader::ShaderType type) { + GLuint handle = 0; switch (type) { case Shader::ST_vertex: - handle = gsg->_glCreateShader(GL_VERTEX_SHADER); + handle = _glgsg->_glCreateShader(GL_VERTEX_SHADER); break; case Shader::ST_fragment: - handle = gsg->_glCreateShader(GL_FRAGMENT_SHADER); + handle = _glgsg->_glCreateShader(GL_FRAGMENT_SHADER); break; #ifndef OPENGLES case Shader::ST_geometry: - if (gsg->get_supports_geometry_shaders()) { - handle = gsg->_glCreateShader(GL_GEOMETRY_SHADER); + if (_glgsg->get_supports_geometry_shaders()) { + handle = _glgsg->_glCreateShader(GL_GEOMETRY_SHADER); } break; case Shader::ST_tess_control: - if (gsg->get_supports_tessellation_shaders()) { - handle = gsg->_glCreateShader(GL_TESS_CONTROL_SHADER); + if (_glgsg->get_supports_tessellation_shaders()) { + handle = _glgsg->_glCreateShader(GL_TESS_CONTROL_SHADER); } break; case Shader::ST_tess_evaluation: - if (gsg->get_supports_tessellation_shaders()) { - handle = gsg->_glCreateShader(GL_TESS_EVALUATION_SHADER); + if (_glgsg->get_supports_tessellation_shaders()) { + handle = _glgsg->_glCreateShader(GL_TESS_EVALUATION_SHADER); + } + break; + case Shader::ST_compute: + if (_glgsg->get_supports_compute_shaders()) { + handle = _glgsg->_glCreateShader(GL_COMPUTE_SHADER); } break; #endif } if (!handle) { - gsg->report_my_gl_errors(); - return 0; + GLCAT.error() + << "Could not create a GLSL shader of the requested type.\n"; + _glgsg->report_my_gl_errors(); + return false; } string text_str = _shader->get_text(type); const char* text = text_str.c_str(); - gsg->_glShaderSource(handle, 1, &text, NULL); - gsg->_glCompileShader(handle); + _glgsg->_glShaderSource(handle, 1, &text, NULL); + _glgsg->_glCompileShader(handle); GLint status; - gsg->_glGetShaderiv(handle, GL_COMPILE_STATUS, &status); + _glgsg->_glGetShaderiv(handle, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { GLCAT.error() << "An error occurred while compiling shader " << _shader->get_filename(type) << "\n"; - glsl_report_shader_errors(gsg, handle); - gsg->_glDeleteShader(handle); - gsg->report_my_gl_errors(); - return 0; + glsl_report_shader_errors(handle); + _glgsg->_glDeleteShader(handle); + _glgsg->report_my_gl_errors(); + return false; } - gsg->report_my_gl_errors(); - return handle; + _glgsg->_glAttachShader(_glsl_program, handle); + _glsl_shaders.push_back(handle); + return true; } //////////////////////////////////////////////////////////////////// -// Function: Shader::glsl_compile_shader +// Function: Shader::glsl_compile_and_link // Access: Private // Description: This subroutine compiles a GLSL shader. //////////////////////////////////////////////////////////////////// bool CLP(ShaderContext):: -glsl_compile_shader(GSG *gsg) { - _glsl_program = gsg->_glCreateProgram(); - if (!_glsl_program) return false; +glsl_compile_and_link() { + _glsl_shaders.clear(); + _glsl_program = _glgsg->_glCreateProgram(); + if (!_glsl_program) { + return false; + } + bool valid = true; if (!_shader->get_text(Shader::ST_vertex).empty()) { - _glsl_vshader = glsl_compile_entry_point(gsg, Shader::ST_vertex); - if (!_glsl_vshader) return false; - gsg->_glAttachShader(_glsl_program, _glsl_vshader); + valid &= glsl_compile_shader(Shader::ST_vertex); } if (!_shader->get_text(Shader::ST_fragment).empty()) { - _glsl_fshader = glsl_compile_entry_point(gsg, Shader::ST_fragment); - if (!_glsl_fshader) return false; - gsg->_glAttachShader(_glsl_program, _glsl_fshader); + valid &= glsl_compile_shader(Shader::ST_fragment); } - if (!_shader->get_text(Shader::ST_geometry).empty()) { - _glsl_gshader = glsl_compile_entry_point(gsg, Shader::ST_geometry); - if (!_glsl_gshader) return false; - gsg->_glAttachShader(_glsl_program, _glsl_gshader); - #ifdef OPENGLES nassertr(false, false); // OpenGL ES has no geometry shaders. #else - // Set the vertex output limit to the maximum - nassertr(gsg->_glProgramParameteri != NULL, false); + if (!_shader->get_text(Shader::ST_geometry).empty()) { + valid &= glsl_compile_shader(Shader::ST_geometry); + + // Set the vertex output limit to the maximum. + // This is slow, but it is probably reasonable to require + // the user to override this in his shader using layout(). + nassertr(_glgsg->_glProgramParameteri != NULL, false); GLint max_vertices; glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &max_vertices); - gsg->_glProgramParameteri(_glsl_program, GL_GEOMETRY_VERTICES_OUT_ARB, max_vertices); -#endif - gsg->report_my_gl_errors(); + _glgsg->_glProgramParameteri(_glsl_program, GL_GEOMETRY_VERTICES_OUT_ARB, max_vertices); } +#endif if (!_shader->get_text(Shader::ST_tess_control).empty()) { - _glsl_tcshader = glsl_compile_entry_point(gsg, Shader::ST_tess_control); - if (!_glsl_tcshader) return false; - gsg->_glAttachShader(_glsl_program, _glsl_tcshader); + valid &= glsl_compile_shader(Shader::ST_tess_control); } if (!_shader->get_text(Shader::ST_tess_evaluation).empty()) { - _glsl_teshader = glsl_compile_entry_point(gsg, Shader::ST_tess_evaluation); - if (!_glsl_teshader) return false; - gsg->_glAttachShader(_glsl_program, _glsl_teshader); - } - - // There might be warnings. Only report them for one shader program. - if (_glsl_vshader != 0) { - glsl_report_shader_errors(gsg, _glsl_vshader); - } else if (_glsl_fshader != 0) { - glsl_report_shader_errors(gsg, _glsl_fshader); - } else if (_glsl_gshader != 0) { - glsl_report_shader_errors(gsg, _glsl_gshader); - } else if (_glsl_tcshader != 0) { - glsl_report_shader_errors(gsg, _glsl_tcshader); - } else if (_glsl_teshader != 0) { - glsl_report_shader_errors(gsg, _glsl_teshader); + valid &= glsl_compile_shader(Shader::ST_tess_evaluation); } - gsg->_glLinkProgram(_glsl_program); + if (!_shader->get_text(Shader::ST_compute).empty()) { + valid &= glsl_compile_shader(Shader::ST_compute); + } + + // There might be warnings, so report those. + GLSLShaders::const_iterator it; + for (it = _glsl_shaders.begin(); it != _glsl_shaders.end(); ++it) { + glsl_report_shader_errors(*it); + } + + // If we requested to retrieve the shader, we should indicate that before linking. +#if !defined(NDEBUG) && !defined(OPENGLES) + if (gl_dump_compiled_shaders && _glgsg->_supports_get_program_binary) { + _glgsg->_glProgramParameteri(_glsl_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); + } +#endif + + _glgsg->_glLinkProgram(_glsl_program); GLint status; - gsg->_glGetProgramiv(_glsl_program, GL_LINK_STATUS, &status); + _glgsg->_glGetProgramiv(_glsl_program, GL_LINK_STATUS, &status); if (status != GL_TRUE) { GLCAT.error() << "An error occurred while linking shader program!\n"; - glsl_report_program_errors(gsg, _glsl_program); + glsl_report_program_errors(_glsl_program); return false; } - gsg->report_my_gl_errors(); + // Dump the binary if requested. +#if !defined(NDEBUG) && !defined(OPENGLES) + if (gl_dump_compiled_shaders && _glgsg->_supports_get_program_binary) { + GLint length = 0; + _glgsg->_glGetProgramiv(_glsl_program, GL_PROGRAM_BINARY_LENGTH, &length); + length += 2; + + char filename[64]; + static int gl_dump_count = 0; + sprintf(filename, "glsl_program%d.dump", gl_dump_count++); + + char *binary = new char[length]; + GLenum format; + GLsizei num_bytes; + _glgsg->_glGetProgramBinary(_glsl_program, length, &num_bytes, &format, (void*)binary); + + pofstream s; + s.open(filename, ios::out | ios::binary | ios::trunc); + s.write(binary, num_bytes); + s.close(); + + GLCAT.info() + << "Dumped " << num_bytes << " bytes of program binary with format 0x" + << hex << format << dec << " to " << filename << "\n"; + delete[] binary; + } +#endif // NDEBUG + + _glgsg->report_my_gl_errors(); return true; } #endif // OPENGLES_1 - diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index cb5d1a0065..d7715d8c30 100755 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -21,75 +21,64 @@ #include "shaderContext.h" #include "deletedChain.h" -#if defined(HAVE_CG) && !defined(OPENGLES) -#include -#endif - class CLP(GraphicsStateGuardian); //////////////////////////////////////////////////////////////////// // Class : GLShaderContext // Description : xyz //////////////////////////////////////////////////////////////////// -class EXPCL_GL CLP(ShaderContext): public ShaderContext { +class EXPCL_GL CLP(ShaderContext) : public ShaderContext { public: friend class CLP(GraphicsStateGuardian); - typedef CLP(GraphicsStateGuardian) GSG; - CLP(ShaderContext)(Shader *s, GSG *gsg); + CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s); ~CLP(ShaderContext)(); ALLOC_DELETED_CHAIN(CLP(ShaderContext)); INLINE bool valid(void); - void bind(GSG *gsg, bool reissue_parameters = true); - void unbind(GSG *gsg); - void issue_parameters(GSG *gsg, int altered); - void disable_shader_vertex_arrays(GSG *gsg); - bool update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, - bool force); - void disable_shader_texture_bindings(GSG *gsg); - void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg); + void bind(bool reissue_parameters = true); + void unbind(); + void issue_parameters(int altered); + void disable_shader_vertex_arrays(); + bool update_shader_vertex_arrays(ShaderContext *prev, bool force); + void disable_shader_texture_bindings(); + void update_shader_texture_bindings(ShaderContext *prev); INLINE bool uses_standard_vertex_arrays(void); INLINE bool uses_custom_vertex_arrays(void); INLINE bool uses_custom_texture_bindings(void); private: - -#if defined(HAVE_CG) && !defined(OPENGLES) - CGcontext _cg_context; - CGprogram _cg_vprogram; - CGprogram _cg_fprogram; - CGprogram _cg_gprogram; - CGprofile _cg_vprofile; - CGprofile _cg_fprofile; - CGprofile _cg_gprofile; - - pvector _cg_parameter_map; -#endif - GLuint _glsl_program; - GLuint _glsl_vshader; - GLuint _glsl_fshader; - GLuint _glsl_gshader; - GLuint _glsl_tcshader; - GLuint _glsl_teshader; + typedef pvector GLSLShaders; + GLSLShaders _glsl_shaders; - pvector _glsl_parameter_map; + //struct ParamContext { + // CPT(InternalName) _name; + // GLint _location; + // GLsizei _count; + // WPT(ParamValue) _value; + // UpdateSeq _updated; + //}; + //typedef pvector ParamContexts; + //ParamContexts _params; - int _stage_offset; - // Avoid using this! It merely exists so the - // destructor has access to the extension functions. - WPT(GSG) _last_gsg; + pvector _glsl_parameter_map; + pmap _glsl_uniform_handles; + + pvector _glsl_img_inputs; + pvector _glsl_img_textures; + + CLP(GraphicsStateGuardian) *_glgsg; bool _uses_standard_vertex_arrays; - void glsl_report_shader_errors(GSG *gsg, unsigned int shader); - void glsl_report_program_errors(GSG *gsg, unsigned int program); - unsigned int glsl_compile_entry_point(GSG *gsg, Shader::ShaderType type); - bool glsl_compile_shader(GSG *gsg); + void glsl_report_shader_errors(GLuint shader); + void glsl_report_program_errors(GLuint program); + bool glsl_compile_shader(Shader::ShaderType type); + bool glsl_compile_and_link(); bool parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *s); - void release_resources(GSG *gsg); + void release_resources(); public: static TypeHandle get_class_type() { @@ -112,4 +101,3 @@ private: #include "glShaderContext_src.I" #endif // OPENGLES_1 - diff --git a/panda/src/glstuff/glTextureContext_src.I b/panda/src/glstuff/glTextureContext_src.I index 017ae91399..50704ce14e 100644 --- a/panda/src/glstuff/glTextureContext_src.I +++ b/panda/src/glstuff/glTextureContext_src.I @@ -19,12 +19,20 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE CLP(TextureContext):: -CLP(TextureContext)(PreparedGraphicsObjects *pgo, Texture *tex, int view) : +CLP(TextureContext)(CLP(GraphicsStateGuardian) *glgsg, + PreparedGraphicsObjects *pgo, Texture *tex, int view) : TextureContext(pgo, tex, view) { - _index = 0; - _already_applied = false; + _glgsg = glgsg; + + glGenTextures(1, &_index); + + _handle = 0; + _needs_barrier = false; + _has_storage = false; + _immutable = false; _uses_mipmaps = false; + _generate_mipmaps = false; _internal_format = 0; _width = 0; _height = 0; diff --git a/panda/src/glstuff/glTextureContext_src.cxx b/panda/src/glstuff/glTextureContext_src.cxx index ea58861bd2..30effdd052 100644 --- a/panda/src/glstuff/glTextureContext_src.cxx +++ b/panda/src/glstuff/glTextureContext_src.cxx @@ -16,6 +16,23 @@ TypeHandle CLP(TextureContext)::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: CLP(TextureContext)::Denstructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +CLP(TextureContext):: +~CLP(TextureContext)() { + if (gl_enable_memory_barriers) { + _glgsg->_textures_needing_fetch_barrier.erase(this); + _glgsg->_textures_needing_image_access_barrier.erase(this); + _glgsg->_textures_needing_update_barrier.erase(this); + _glgsg->_textures_needing_framebuffer_barrier.erase(this); + } + + glDeleteTextures(1, &_index); + _index = 0; +} //////////////////////////////////////////////////////////////////// // Function: GLTextureContext::evict_lru @@ -35,7 +52,16 @@ TypeHandle CLP(TextureContext)::_type_handle; void CLP(TextureContext):: evict_lru() { dequeue_lru(); - reset_data(); + + if (_handle != 0) { + if (_handle_resident) { + _glgsg->_glMakeTextureHandleNonResident(_handle); + } + _handle_resident = false; + } else { + reset_data(); + } + update_data_size_bytes(0); mark_unloaded(); } @@ -48,12 +74,113 @@ evict_lru() { //////////////////////////////////////////////////////////////////// void CLP(TextureContext):: reset_data() { + if (_handle != 0 && _handle_resident) { + _glgsg->_glMakeTextureHandleNonResident(_handle); + } + // Free the texture resources. - GLP(DeleteTextures)(1, &_index); + glDeleteTextures(1, &_index); // We still need a valid index number, though, in case we want to // re-load the texture later. - GLP(GenTextures)(1, &_index); + glGenTextures(1, &_index); - _already_applied = false; + _handle = 0; + _handle_resident = false; + _needs_barrier = false; + _has_storage = false; + _immutable = false; + +#ifndef OPENGLES + // Mark the texture as coherent. + if (gl_enable_memory_barriers) { + _glgsg->_textures_needing_fetch_barrier.erase(this); + _glgsg->_textures_needing_image_access_barrier.erase(this); + _glgsg->_textures_needing_update_barrier.erase(this); + _glgsg->_textures_needing_framebuffer_barrier.erase(this); + } +#endif } + +//////////////////////////////////////////////////////////////////// +// Function: GLTextureContext::make_handle_resident +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void CLP(TextureContext):: +make_handle_resident() { + if (_handle != 0) { + if (!_handle_resident) { + _glgsg->_glMakeTextureHandleResident(_handle); + _handle_resident = true; + } + set_resident(true); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CLP(TextureContext)::get_handle +// Access: Public +// Description: Returns a handle for this texture. Once this has +// been created, the texture data may still be updated, +// but its properties may not. +//////////////////////////////////////////////////////////////////// +INLINE GLuint64 CLP(TextureContext):: +get_handle() { +#ifdef OPENGLES + return 0; +#else + if (!_glgsg->_supports_bindless_texture) { + return false; + } + + if (_handle == 0) { + _handle = _glgsg->_glGetTextureHandle(_index); + } + + _immutable = true; + return _handle; +#endif +} + +#ifndef OPENGLES +//////////////////////////////////////////////////////////////////// +// Function: GLTextureContext::needs_barrier +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +bool CLP(TextureContext):: +needs_barrier(GLbitfield barrier) { + if (!gl_enable_memory_barriers) { + return false; + } + + return (((barrier & GL_TEXTURE_FETCH_BARRIER_BIT) && + _glgsg->_textures_needing_fetch_barrier.count(this))) + || (((barrier & GL_SHADER_IMAGE_ACCESS_BARRIER_BIT) && + _glgsg->_textures_needing_image_access_barrier.count(this))) + || (((barrier & GL_TEXTURE_UPDATE_BARRIER_BIT) && + _glgsg->_textures_needing_update_barrier.count(this))) + || (((barrier & GL_FRAMEBUFFER_BARRIER_BIT) && + _glgsg->_textures_needing_framebuffer_barrier.count(this))); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLTextureContext::mark_incoherent +// Access: Public +// Description: Mark a texture as needing a memory barrier, since +// a non-coherent write just happened to it. +//////////////////////////////////////////////////////////////////// +void CLP(TextureContext):: +mark_incoherent() { + if (!gl_enable_memory_barriers) { + return; + } + + _glgsg->_textures_needing_fetch_barrier.insert(this); + _glgsg->_textures_needing_image_access_barrier.insert(this); + _glgsg->_textures_needing_update_barrier.insert(this); + _glgsg->_textures_needing_framebuffer_barrier.insert(this); +} + +#endif // OPENGLES diff --git a/panda/src/glstuff/glTextureContext_src.h b/panda/src/glstuff/glTextureContext_src.h index b03e767dc4..92e90a8276 100644 --- a/panda/src/glstuff/glTextureContext_src.h +++ b/panda/src/glstuff/glTextureContext_src.h @@ -16,32 +16,60 @@ #include "textureContext.h" #include "deletedChain.h" +class CLP(GraphicsStateGuardian); + //////////////////////////////////////////////////////////////////// // Class : GLTextureContext // Description : //////////////////////////////////////////////////////////////////// class EXPCL_GL CLP(TextureContext) : public TextureContext { public: - INLINE CLP(TextureContext)(PreparedGraphicsObjects *pgo, Texture *tex, int view); + INLINE CLP(TextureContext)(CLP(GraphicsStateGuardian) *glgsg, + PreparedGraphicsObjects *pgo, + Texture *tex, int view); ALLOC_DELETED_CHAIN(CLP(TextureContext)); + virtual ~CLP(TextureContext)(); virtual void evict_lru(); void reset_data(); + void make_handle_resident(); + GLuint64 get_handle(); + +#ifdef OPENGLES + CONSTEXPR bool needs_barrier(GLbitfield barrier) { return false; }; +#else + bool needs_barrier(GLbitfield barrier); + void mark_incoherent(); +#endif + // This is the GL "name" of the texture object. GLuint _index; + // This is the bindless "handle" to the texture object. + GLuint64 _handle; + bool _handle_resident; + + // This is true if the texture was recently written to in a + // non-coherent way, and Panda may have to call glMemoryBarrier + // for the results of this write to become visible. + bool _needs_barrier; + // These are the parameters that we specified with the last - // glTexImage2D() call. If none of these have changed, we can - // reload the texture image with a glTexSubImage2D(). - bool _already_applied; + // glTexImage2D() or glTexStorage2D() call. If none of these have + // changed, we can reload the texture image with a glTexSubImage2D(). + bool _has_storage; + bool _immutable; bool _uses_mipmaps; + bool _generate_mipmaps; GLint _internal_format; GLsizei _width; GLsizei _height; GLsizei _depth; GLenum _target; + CLP(GraphicsStateGuardian) *_glgsg; + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/glstuff/glVertexBufferContext_src.cxx b/panda/src/glstuff/glVertexBufferContext_src.cxx index 1323f8dffc..73ef6ffa67 100644 --- a/panda/src/glstuff/glVertexBufferContext_src.cxx +++ b/panda/src/glstuff/glVertexBufferContext_src.cxx @@ -35,7 +35,7 @@ evict_lru() { // Make sure the buffer is unbound before we delete it. if (_glgsg->_current_vbuffer_index == _index) { - if (GLCAT.is_debug() && CLP(debug_buffers)) { + if (GLCAT.is_debug() && gl_debug_buffers) { GLCAT.debug() << "unbinding vertex buffer\n"; } diff --git a/panda/src/glstuff/glmisc_src.cxx b/panda/src/glstuff/glmisc_src.cxx index 8cf477f54b..d01deb3da7 100644 --- a/panda/src/glstuff/glmisc_src.cxx +++ b/panda/src/glstuff/glmisc_src.cxx @@ -14,45 +14,45 @@ #include "pandaSystem.h" -ConfigVariableBool CLP(cheap_textures) +ConfigVariableBool gl_cheap_textures ("gl-cheap-textures", false, - PRC_DESC("Configure this true to GLP(Hint) the textures into the cheapest " + PRC_DESC("Configure this true to glHint the textures into the cheapest " "possible mode.")); -ConfigVariableBool CLP(ignore_clamp) +ConfigVariableBool gl_ignore_clamp ("gl-ignore-clamp", false, PRC_DESC("Configure this true to disable texture clamp mode (all textures " "repeat, a little cheaper for software renderers).")); -ConfigVariableBool CLP(support_clamp_to_border) +ConfigVariableBool gl_support_clamp_to_border ("gl-support-clamp-to-border", true, PRC_DESC("Configure this true to enable the use of the clamp_to_border " "extension if the GL claims to support it, or false not to " "use it even if it appears to be available. (On some OpenGL " "drivers, enabling this mode can force software rendering.)")); -ConfigVariableBool CLP(support_rescale_normal) +ConfigVariableBool gl_support_rescale_normal ("gl-support-rescale-normal", true, PRC_DESC("Configure this true to enable the use of the rescale_normal " "extension if the GL claims to support it, or false not to use " "it even if it appears to be available. (This appears to be " "buggy on some drivers.)")); -ConfigVariableBool CLP(ignore_filters) +ConfigVariableBool gl_ignore_filters ("gl-ignore-filters", false, PRC_DESC("Configure this true to disable any texture filters at all (forcing " "point sampling).")); -ConfigVariableBool CLP(ignore_mipmaps) +ConfigVariableBool gl_ignore_mipmaps ("gl-ignore-mipmaps", false, PRC_DESC("Configure this true to disable mipmapping only.")); -ConfigVariableBool CLP(force_mipmaps) +ConfigVariableBool gl_force_mipmaps ("gl-force-mipmaps", false, PRC_DESC("Configure this true to enable full trilinear mipmapping on every " "texture, whether it asks for it or not.")); -ConfigVariableBool CLP(show_texture_usage) +ConfigVariableBool gl_show_texture_usage ("gl-show-texture-usage", false, PRC_DESC("If you set this true, the screen will flash with textures drawn " "in a special mode that shows the mipmap detail level and texture " @@ -60,27 +60,27 @@ ConfigVariableBool CLP(show_texture_usage) "mipmap level 0, yellow for mipmap level 1, and red for all higher " "mipmap levels. Brighter colors represent larger textures.")); -ConfigVariableInt CLP(show_texture_usage_max_size) +ConfigVariableInt gl_show_texture_usage_max_size ("gl-show-texture-usage-max-size", 1024, PRC_DESC("Specifies the texture size (along one side) of the largest " "texture expected to be loaded. This controls the assignment " "of the texture color in gl-show-texture-usage mode; colors " "will be fully bright for textures of this size or larger.")); -ConfigVariableBool CLP(color_mask) +ConfigVariableBool gl_color_mask ("gl-color-mask", true, PRC_DESC("Configure this false if your GL's implementation of glColorMask() " "is broken (some are). This will force the use of a (presumably) " "more expensive blending operation instead.")); -ConfigVariableBool CLP(support_occlusion_query) +ConfigVariableBool gl_support_occlusion_query ("gl-support-occlusion-query", true, PRC_DESC("Configure this true to enable the use of the occlusion_query " "extension if the GL claims to support it, or false not to " "use it even if it appears to be available. (On some OpenGL " "drivers, enabling this mode can force software rendering.)")); -ConfigVariableBool CLP(compile_and_execute) +ConfigVariableBool gl_compile_and_execute ("gl-compile-and-execute", false, PRC_DESC("Configure this true if you know your GL's implementation of " "glNewList(n, GL_COMPILE_AND_EXECUTE) works. It is " @@ -90,7 +90,7 @@ ConfigVariableBool CLP(compile_and_execute) "for the first time, by allowing the display list to be " "rendered at the same time it is being compiled.")); -ConfigVariableBool CLP(interleaved_arrays) +ConfigVariableBool gl_interleaved_arrays ("gl-interleaved-arrays", false, PRC_DESC("Set this true to convert OpenGL geometry such that the " "primary data columns vertex, normal, color, and texcoord " @@ -98,20 +98,20 @@ ConfigVariableBool CLP(interleaved_arrays) "render geometry as it appears in the GeomVertexData. See " "also gl-parallel-arrays.")); -ConfigVariableBool CLP(parallel_arrays) +ConfigVariableBool gl_parallel_arrays ("gl-parallel-arrays", false, PRC_DESC("Set this true to convert OpenGL geometry such that each " "data column is a separate array, or false to " "render geometry as it appears in the GeomVertexData. See " "also gl-interleaved-arrays.")); -ConfigVariableInt CLP(max_errors) +ConfigVariableInt gl_max_errors ("gl-max-errors", 20, PRC_DESC("This is the limit on the number of OpenGL errors Panda will " "detect and report before it shuts down rendering. Set it to " "-1 for no limit.")); -ConfigVariableEnum CLP(min_buffer_usage_hint) +ConfigVariableEnum gl_min_buffer_usage_hint ("gl-min-buffer-usage-hint", GeomEnums::UH_stream, PRC_DESC("This specifies the first usage hint value that will be " "loaded as a vertex buffer, instead of directly from the " @@ -126,13 +126,38 @@ ConfigVariableEnum CLP(min_buffer_usage_hint) "of reusing the same buffers. Consider increasing " "released-vbuffer-cache-size instead.")); -ConfigVariableBool CLP(debug_buffers) +ConfigVariableBool gl_debug + ("gl-debug", false, + PRC_DESC("Setting this to true will cause OpenGL to emit more useful " + "error and debug messages, at a slight runtime performance cost. " + "notify-level-glgsg controls which severity levels are shown.")); + +ConfigVariableBool gl_debug_synchronous + ("gl-debug-synchronous", false, + PRC_DESC("Set this true to make sure that the errors generated by " + "gl-debug are reported as soon as they happen. This is " + "highly recommended if you want to attach a debugger since " + "the call stack may otherwise not point to the GL call " + "where the error originated.")); + +ConfigVariableEnum gl_debug_abort_level + ("gl-debug-abort-level", NS_fatal, + PRC_DESC("Set this to a setting other than 'fatal' to cause an " + "abort to be triggered when an error of the indicated " + "severity level (or a more severe one) occurs. This is " + "useful if you want to attach a debugger. If you set this, " + "it is highly recommended to also set gl-debug-synchronous, " + "since the call stack will otherwise not point to the GL call " + "that triggered the error message. " + "This feature is not available when NDEBUG has been defined.")); + +ConfigVariableBool gl_debug_buffers ("gl-debug-buffers", false, PRC_DESC("Set this true, in addition to enabling debug notify for " "glgsg, to enable debug messages about the creation and " "destruction of OpenGL vertex buffers.")); -ConfigVariableBool CLP(finish) +ConfigVariableBool gl_finish ("gl-finish", false, PRC_DESC("Set this true to force a call to glFinish() after every major " "graphics operation. This is likely to slow down rendering " @@ -140,31 +165,78 @@ ConfigVariableBool CLP(finish) "more accurately reflect where the graphics bottlenecks are. " "This variable is enabled only if PStats is compiled in.")); -ConfigVariableBool CLP(force_depth_stencil) - ("gl-force-depth-stencil", false, +ConfigVariableBool gl_force_depth_stencil + ("gl-force-depth-stencil", false, PRC_DESC("Temporary hack variable 7x00 vs 8x00 nVidia bug. See glGraphicsStateGuardian_src.cxx.")); -ConfigVariableBool CLP(matrix_palette) - ("gl-matrix-palette", false, +ConfigVariableBool gl_matrix_palette + ("gl-matrix-palette", false, PRC_DESC("Temporary hack variable protecting untested code. See glGraphicsStateGuardian_src.cxx.")); -ConfigVariableBool CLP(force_no_error) - ("gl-force-no-error", false, - PRC_DESC("Avoid reporting OpenGL errors, for a small performance benefit.")); +ConfigVariableBool gl_check_errors + ("gl-check-errors", false, + PRC_DESC("Regularly call glGetError() to check for OpenGL errors. " + "This will slow down rendering significantly. If your " + "video driver supports it, you should use gl-debug instead.")); -ConfigVariableBool CLP(force_no_flush) - ("gl-force-no-flush", false, - PRC_DESC("Avoid calling glFlush(), for a potential performance benefit. This may be a little dangerous.")); +ConfigVariableBool gl_force_flush + ("gl-force-flush", false, + PRC_DESC("Call this to force a call to glFlush() after rendering a " + "frame, even when using a double-buffered framebuffer. " + "This can incur a significant performance penalty.")); -ConfigVariableBool CLP(separate_specular_color) - ("gl-separate-specular-color", true, +ConfigVariableBool gl_separate_specular_color + ("gl-separate-specular-color", true, PRC_DESC("When separate specular mode is on, the specular component " "will be written to the secondary instead of the primary " "color, which is added after the texturing stage. In other " "words, the specular highlight will be unmodulated by the " "color of the texture.")); -extern ConfigVariableBool CLP(parallel_arrays); +ConfigVariableBool gl_cube_map_seamless + ("gl-cube-map-seamless", true, + PRC_DESC("This configures Panda to try and enable seamless cube map " + "sampling when supported. This will help to remove seams " + "that show up at cube map edges, especially at lower " + "resolutions. On by default; disable if you suspect that " + "this is causing problems or if you simply don't need the " + "functionality.")); + +ConfigVariableBool gl_dump_compiled_shaders + ("gl-dump-compiled-shaders", false, + PRC_DESC("This configures Panda to dump the binary content of GLSL " + "programs to disk with a filename like glsl_program0.dump " + "into the current directory.")); + +ConfigVariableBool gl_immutable_texture_storage + ("gl-immutable-texture-storage", false, + PRC_DESC("This configures Panda to pre-allocate immutable storage " + "for each texture. This improves runtime performance, but " + "changing the size or type of a texture will be slower.")); + +ConfigVariableBool gl_use_bindless_texture + ("gl-use-bindless-texture", false, + PRC_DESC("Set this to let Panda use OpenGL's bindless texture " + "extension for all textures passed to shaders, for improved " + "performance. This is an experimental feature and comes " + "with a few caveats; for one, it requires that all sampler " + "uniforms have a layout(bindless_sampler) qualifier, and " + "it also requires that the texture properties are not " + "modified after the texture handle has been initialized.")); + +ConfigVariableBool gl_enable_memory_barriers + ("gl-enable-memory-barriers", true, + PRC_DESC("If this is set, Panda will make sure that every write " + "to an image using an image2D (et al) binding will cause " + "Panda to issue a memory barrier before the next use of " + "said texture, to ensure that all reads and writes are " + "properly synchronized. This may not be strictly necessary " + "when using the 'coherent' qualifier, but Panda has no " + "way to detect whether you are using those. Turning " + "this off may give a slight performance increase, but you " + "have to know what you're doing.")); + +extern ConfigVariableBool gl_parallel_arrays; void CLP(init_classes)() { CLP(GeomContext)::init_type(); @@ -189,4 +261,3 @@ void CLP(init_classes)() { // since we won't know those until we create a graphics context (and // the answer may be different for different contexts). } - diff --git a/panda/src/glstuff/glmisc_src.h b/panda/src/glstuff/glmisc_src.h index f2f71e4772..1d7e330f83 100644 --- a/panda/src/glstuff/glmisc_src.h +++ b/panda/src/glstuff/glmisc_src.h @@ -40,28 +40,36 @@ //#define GSG_VERBOSE 1 -extern ConfigVariableBool CLP(cheap_textures); -extern ConfigVariableBool CLP(ignore_clamp); -extern ConfigVariableBool CLP(support_clamp_to_border); -extern ConfigVariableBool CLP(ignore_filters); -extern ConfigVariableBool CLP(ignore_mipmaps); -extern ConfigVariableBool CLP(force_mipmaps); -extern ConfigVariableBool CLP(show_texture_usage); -extern ConfigVariableInt CLP(show_texture_usage_max_size); -extern ConfigVariableBool CLP(color_mask); -extern ConfigVariableBool CLP(support_occlusion_query); -extern ConfigVariableBool CLP(compile_and_execute); -extern ConfigVariableBool CLP(interleaved_arrays); -extern ConfigVariableBool CLP(parallel_arrays); -extern ConfigVariableInt CLP(max_errors); -extern ConfigVariableEnum CLP(min_buffer_usage_hint); -extern ConfigVariableBool CLP(debug_buffers); -extern ConfigVariableBool CLP(finish); -extern ConfigVariableBool CLP(force_depth_stencil); -extern ConfigVariableBool CLP(matrix_palette); -extern ConfigVariableBool CLP(force_no_error); -extern ConfigVariableBool CLP(force_no_flush); -extern ConfigVariableBool CLP(separate_specular_color); +extern ConfigVariableBool gl_cheap_textures; +extern ConfigVariableBool gl_ignore_clamp; +extern ConfigVariableBool gl_support_clamp_to_border; +extern ConfigVariableBool gl_ignore_filters; +extern ConfigVariableBool gl_ignore_mipmaps; +extern ConfigVariableBool gl_force_mipmaps; +extern ConfigVariableBool gl_show_texture_usage; +extern ConfigVariableInt gl_show_texture_usage_max_size; +extern ConfigVariableBool gl_color_mask; +extern ConfigVariableBool gl_support_occlusion_query; +extern ConfigVariableBool gl_compile_and_execute; +extern ConfigVariableBool gl_interleaved_arrays; +extern ConfigVariableBool gl_parallel_arrays; +extern ConfigVariableInt gl_max_errors; +extern ConfigVariableEnum gl_min_buffer_usage_hint; +extern ConfigVariableBool gl_debug; +extern ConfigVariableBool gl_debug_synchronous; +extern ConfigVariableEnum gl_debug_abort_level; +extern ConfigVariableBool gl_debug_buffers; +extern ConfigVariableBool gl_finish; +extern ConfigVariableBool gl_force_depth_stencil; +extern ConfigVariableBool gl_matrix_palette; +extern ConfigVariableBool gl_check_errors; +extern ConfigVariableBool gl_force_flush; +extern ConfigVariableBool gl_separate_specular_color; +extern ConfigVariableBool gl_cube_map_seamless; +extern ConfigVariableBool gl_dump_compiled_shaders; +extern ConfigVariableBool gl_immutable_texture_storage; +extern ConfigVariableBool gl_use_bindless_texture; +extern ConfigVariableBool gl_enable_memory_barriers; extern EXPCL_GL void CLP(init_classes)(); diff --git a/panda/src/glstuff/glstuff_src.cxx b/panda/src/glstuff/glstuff_src.cxx index 6a46538784..49d54804b8 100644 --- a/panda/src/glstuff/glstuff_src.cxx +++ b/panda/src/glstuff/glstuff_src.cxx @@ -25,8 +25,7 @@ #include "glGeomContext_src.cxx" #include "glGeomMunger_src.cxx" #include "glShaderContext_src.cxx" +#include "glCgShaderContext_src.cxx" #include "glImmediateModeSender_src.cxx" #include "glGraphicsBuffer_src.cxx" #include "glGraphicsStateGuardian_src.cxx" - - diff --git a/panda/src/glstuff/glstuff_src.h b/panda/src/glstuff/glstuff_src.h index f62c4f8c59..0892a8bba3 100644 --- a/panda/src/glstuff/glstuff_src.h +++ b/panda/src/glstuff/glstuff_src.h @@ -18,7 +18,6 @@ // some such), define the following symbols and #include this header // file. -// #define GLP(name): returns name prefixed by the gl prefix, e.g. gl##name // #define CLP(name): returns name prefixed by the class prefix, e.g. GL##name // #define CLASSPREFIX_QUOTED: the quoted prefix of CLP, e.g. "GL" // #define CONFIGOBJ: a Configrc object, e.g. config_glgsg @@ -40,7 +39,7 @@ #include "glGeomContext_src.h" #include "glGeomMunger_src.h" #include "glShaderContext_src.h" +#include "glCgShaderContext_src.h" #include "glImmediateModeSender_src.h" #include "glGraphicsBuffer_src.h" #include "glGraphicsStateGuardian_src.h" - diff --git a/panda/src/glstuff/panda_glext.h b/panda/src/glstuff/panda_glext.h index 6949c1c245..3af15892cd 100644 --- a/panda/src/glstuff/panda_glext.h +++ b/panda/src/glstuff/panda_glext.h @@ -2398,6 +2398,71 @@ extern "C" { #define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F #endif +#ifndef GL_KHR_debug +#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 +#define GL_DEBUG_SOURCE_API 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION 0x824A +#define GL_DEBUG_SOURCE_OTHER 0x824B +#define GL_DEBUG_TYPE_ERROR 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E +#define GL_DEBUG_TYPE_PORTABILITY 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#define GL_DEBUG_TYPE_OTHER 0x8251 +#define GL_DEBUG_TYPE_MARKER 0x8268 +#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 +#define GL_DEBUG_TYPE_POP_GROUP 0x826A +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C +#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D +#define GL_BUFFER 0x82E0 +#define GL_SHADER 0x82E1 +#define GL_PROGRAM 0x82E2 +#define GL_QUERY 0x82E3 +#define GL_PROGRAM_PIPELINE 0x82E4 +#define GL_SAMPLER 0x82E6 +#define GL_DISPLAY_LIST 0x82E7 +/* DISPLAY_LIST used in compatibility profile only */ +#define GL_MAX_LABEL_LENGTH 0x82E8 +#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES 0x9145 +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#define GL_DEBUG_SEVERITY_LOW 0x9148 +#define GL_DEBUG_OUTPUT 0x92E0 +#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 +/* reuse GL_STACK_UNDERFLOW */ +/* reuse GL_STACK_OVERFLOW */ +#endif + +#ifndef GL_ARB_compute_shader +#define GL_COMPUTE_SHADER 0x91B9 +#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB +#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC +#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD +#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262 +#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263 +#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264 +#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265 +#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266 +#define GL_MAX_COMPUTE_LOCAL_INVOCATIONS 0x90EB +#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE +#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF +#define GL_COMPUTE_LOCAL_WORK_SIZE 0x8267 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED +#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE +#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF +#define GL_COMPUTE_SHADER_BIT 0x00000020 +#endif + #ifndef GL_EXT_abgr #define GL_ABGR_EXT 0x8000 #endif @@ -5501,8 +5566,12 @@ typedef ptrdiff_t GLsizeiptrARB; #ifndef GL_ARB_shader_objects /* GL types for program/shader text and shader object handles */ typedef char GLcharARB; +#ifdef __APPLE__ +typedef void *GLhandleARB; +#else typedef unsigned int GLhandleARB; #endif +#endif /* GL type for "half" precision (s10e5) float data in host memory */ #ifndef GL_ARB_half_float_pixel @@ -5576,6 +5645,10 @@ typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLen typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam); #endif +#ifndef GL_KHR_debug +typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam); +#endif + #ifndef GL_NV_vdpau_interop typedef GLintptr GLvdpauSurfaceNV; #endif @@ -7882,6 +7955,42 @@ typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum ta typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); #endif +#ifndef GL_KHR_debug +#define GL_KHR_debug 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +GLAPI void APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +GLAPI void APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam); +GLAPI GLuint APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +GLAPI void APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message); +GLAPI void APIENTRY glPopDebugGroup (void); +GLAPI void APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +GLAPI void APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +GLAPI void APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label); +GLAPI void APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam); +typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +typedef void (APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); +typedef void (APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void); +typedef void (APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +typedef void (APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label); +typedef void (APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +#endif + +#ifndef GL_ARB_compute_shader +#define GL_ARB_compute_shader 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +GLAPI void APIENTRY glDispatchComputeIndirect (GLintptr indirect); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect); +#endif + #ifndef GL_EXT_abgr #define GL_EXT_abgr 1 #endif diff --git a/panda/src/glxdisplay/glxGraphicsPipe.cxx b/panda/src/glxdisplay/glxGraphicsPipe.cxx index b19bcae65f..a4ec5b5409 100644 --- a/panda/src/glxdisplay/glxGraphicsPipe.cxx +++ b/panda/src/glxdisplay/glxGraphicsPipe.cxx @@ -88,14 +88,17 @@ make_output(const string &name, GraphicsOutput *host, int retry, bool &precertify) { - + if (!_is_valid) { return NULL; } - glxGraphicsStateGuardian *glxgsg = 0; - if (gsg != 0) { - DCAST_INTO_R(glxgsg, gsg, NULL); + // This may not be a GLX GSG; it might be a callback GSG. + PosixGraphicsStateGuardian *posixgsg = NULL; + glxGraphicsStateGuardian *glxgsg = NULL; + if (gsg != NULL) { + DCAST_INTO_R(posixgsg, gsg, NULL); + glxgsg = DCAST(glxGraphicsStateGuardian, posixgsg); } bool support_rtt; @@ -103,15 +106,19 @@ make_output(const string &name, /* Currently, no support for glxGraphicsBuffer render-to-texture. if (glxgsg) { - support_rtt = - glxgsg -> get_supports_render_texture() && + support_rtt = + glxgsg -> get_supports_render_texture() && support_render_texture; - } + } */ // First thing to try: a glxGraphicsWindow if (retry == 0) { + if (gsg != NULL && glxgsg == NULL) { + // We can't use a non-GLX GSG. + return NULL; + } if (((flags&BF_require_parasite)!=0)|| ((flags&BF_refuse_window)!=0)|| ((flags&BF_resizeable)!=0)|| @@ -125,7 +132,7 @@ make_output(const string &name, return new glxGraphicsWindow(engine, this, name, fb_prop, win_prop, flags, gsg, host); } - + // Second thing to try: a GLGraphicsBuffer if (retry == 1) { @@ -139,7 +146,7 @@ make_output(const string &name, // meet specs, we can bail out early. int _fbo_multisample = 0; if (!ConfigVariableBool("framebuffer-object-multisample", false, PRC_DESC("Enabled Multisample."))) { - _fbo_multisample = 16; + _fbo_multisample = 16; } if ((flags & BF_fb_props_optional)==0) { if ((fb_prop.get_indexed_color() > 0)|| @@ -151,11 +158,11 @@ make_output(const string &name, } // Early success - if we are sure that this buffer WILL // meet specs, we can precertify it. - if ((glxgsg != 0) && - (glxgsg->is_valid()) && - (!glxgsg->needs_reset()) && - (glxgsg->_supports_framebuffer_object) && - (glxgsg->_glDrawBuffers != 0)&& + if ((posixgsg != 0) && + (posixgsg->is_valid()) && + (!posixgsg->needs_reset()) && + (posixgsg->_supports_framebuffer_object) && + (posixgsg->_glDrawBuffers != 0)&& (fb_prop.is_basic())) { precertify = true; } diff --git a/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx b/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx index 8470fe8d57..96471c1b9d 100644 --- a/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx +++ b/panda/src/glxdisplay/glxGraphicsStateGuardian.cxx @@ -90,7 +90,7 @@ get_properties(FrameBufferProperties &properties, XVisualInfo *visual) { red_size, green_size, blue_size, alpha_size, ared_size, agreen_size, ablue_size, aalpha_size, depth_size, stencil_size; - + glXGetConfig(_display, visual, GLX_USE_GL, &use_gl); glXGetConfig(_display, visual, GLX_RGBA, &render_mode); glXGetConfig(_display, visual, GLX_DOUBLEBUFFER, &double_buffer); @@ -131,7 +131,7 @@ get_properties(FrameBufferProperties &properties, XVisualInfo *visual) { properties.set_depth_bits(depth_size); properties.set_alpha_bits(alpha_size); properties.set_accum_bits(ared_size+agreen_size+ablue_size+aalpha_size); - + // Set both hardware and software bits, indicating not-yet-known. properties.set_force_software(1); properties.set_force_hardware(1); @@ -153,8 +153,8 @@ get_properties_advanced(FrameBufferProperties &properties, // Now update our framebuffer_mode and bit depth appropriately. int render_type, double_buffer, stereo, red_size, green_size, blue_size, alpha_size, ared_size, agreen_size, ablue_size, aalpha_size, - depth_size, stencil_size, samples, drawable_type, caveat; - + depth_size, stencil_size, samples, drawable_type, caveat, srgb_capable; + _glXGetFBConfigAttrib(_display, config, GLX_RENDER_TYPE, &render_type); _glXGetFBConfigAttrib(_display, config, GLX_DOUBLEBUFFER, &double_buffer); _glXGetFBConfigAttrib(_display, config, GLX_STEREO, &stereo); @@ -171,47 +171,54 @@ get_properties_advanced(FrameBufferProperties &properties, _glXGetFBConfigAttrib(_display, config, GLX_SAMPLES, &samples); _glXGetFBConfigAttrib(_display, config, GLX_DRAWABLE_TYPE, &drawable_type); _glXGetFBConfigAttrib(_display, config, GLX_CONFIG_CAVEAT, &caveat); - + _glXGetFBConfigAttrib(_display, config, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb_capable); + context_has_pbuffer = false; if ((drawable_type & GLX_PBUFFER_BIT)!=0) { context_has_pbuffer = true; } - + context_has_pixmap = false; if ((drawable_type & GLX_PIXMAP_BIT)!=0) { context_has_pixmap = true; } - + slow = false; if (caveat == GLX_SLOW_CONFIG) { slow = true; } - + if ((drawable_type & GLX_WINDOW_BIT)==0) { // We insist on having a context that will support an onscreen window. return; } - + if (double_buffer) { properties.set_back_buffers(1); } + if (stereo) { - properties.set_stereo(1); + properties.set_stereo(true); } - + + if (srgb_capable) { + properties.set_srgb_color(true); + } + if ((render_type & GLX_RGBA_BIT)!=0) { - properties.set_rgb_color(1); + properties.set_rgb_color(true); } if ((render_type & GLX_COLOR_INDEX_BIT)!=0) { - properties.set_indexed_color(1); + properties.set_indexed_color(true); } + properties.set_color_bits(red_size+green_size+blue_size); properties.set_stencil_bits(stencil_size); properties.set_depth_bits(depth_size); properties.set_alpha_bits(alpha_size); properties.set_accum_bits(ared_size+agreen_size+ablue_size+aalpha_size); properties.set_multisamples(samples); - + // Set both hardware and software bits, indicating not-yet-known. properties.set_force_software(1); properties.set_force_hardware(1); @@ -288,6 +295,11 @@ choose_pixel_format(const FrameBufferProperties &properties, int best_result = 0; FrameBufferProperties best_props; + int render_type = GLX_RGBA_TYPE; + if (properties.get_indexed_color()) { + render_type = GLX_COLOR_INDEX_TYPE; + } + static const int max_attrib_list = 32; int attrib_list[max_attrib_list]; int n = 0; @@ -298,11 +310,11 @@ choose_pixel_format(const FrameBufferProperties &properties, attrib_list[n++] = GLX_DRAWABLE_TYPE; attrib_list[n++] = GLX_DONT_CARE; attrib_list[n] = (int)None; - + int num_configs = 0; GLXFBConfig *configs = _glXChooseFBConfig(_display, _screen, attrib_list, &num_configs); - + if (configs != 0) { bool context_has_pbuffer, context_has_pixmap, slow; int quality, i; @@ -317,7 +329,8 @@ choose_pixel_format(const FrameBufferProperties &properties, const char *pixmaptext = context_has_pixmap ? " (pixmap)" : ""; const char *slowtext = slow ? " (slow)" : ""; glxdisplay_cat.debug() - << i << ": " << fbprops << " quality=" << quality << pbuffertext << pixmaptext << slowtext << "\n"; + << i << ": " << fbprops << " quality=" << quality << pbuffertext + << pixmaptext << slowtext << "\n"; } if (need_pbuffer && !context_has_pbuffer) { continue; @@ -325,7 +338,7 @@ choose_pixel_format(const FrameBufferProperties &properties, if (need_pixmap && !context_has_pixmap) { continue; } - + if (quality > best_quality) { best_quality = quality; best_result = i; @@ -336,10 +349,29 @@ choose_pixel_format(const FrameBufferProperties &properties, if (best_quality > 0) { _fbconfig = configs[best_result]; - _context = - _glXCreateNewContext(_display, _fbconfig, GLX_RGBA_TYPE, _share_context, - GL_TRUE); + + if (_glXCreateContextAttribs != NULL) { + // NB. This is a wholly different type of attrib list + // than below, the same values are not used! + n = 0; + attrib_list[n++] = GLX_RENDER_TYPE; + attrib_list[n++] = render_type; + if (gl_debug) { + attrib_list[n++] = GLX_CONTEXT_FLAGS_ARB; + attrib_list[n++] = GLX_CONTEXT_DEBUG_BIT_ARB; + } + attrib_list[n] = None; + _context = _glXCreateContextAttribs(_display, _fbconfig, _share_context, + GL_TRUE, attrib_list); + } else { + _context = + _glXCreateNewContext(_display, _fbconfig, render_type, _share_context, + GL_TRUE); + } + if (_context) { + mark_new(); + if (_visuals != (XVisualInfo *)NULL) { XFree(_visuals); _visuals = NULL; @@ -351,6 +383,10 @@ choose_pixel_format(const FrameBufferProperties &properties, get_properties_advanced(_fbprops, _context_has_pbuffer, _context_has_pixmap, _slow, _fbconfig); + if (!properties.get_srgb_color()) { + _fbprops.set_srgb_color(false); + } + if (glxdisplay_cat.is_debug()) { glxdisplay_cat.debug() << "Selected context " << best_result << ": " << _fbprops << "\n"; @@ -387,150 +423,6 @@ choose_pixel_format(const FrameBufferProperties &properties, _context_has_pbuffer = false; } -//////////////////////////////////////////////////////////////////// -// Function: glxGraphicsStateGuardian::reset -// Access: Public, Virtual -// Description: Resets all internal state as if the gsg were newly -// created. -//////////////////////////////////////////////////////////////////// -void glxGraphicsStateGuardian:: -reset() { - PosixGraphicsStateGuardian::reset(); - - _supports_swap_control = has_extension("GLX_SGI_swap_control"); - - if (_supports_swap_control) { - _glXSwapIntervalSGI = - (PFNGLXSWAPINTERVALSGIPROC)get_extension_func("glX", "SwapIntervalSGI"); - if (_glXSwapIntervalSGI == NULL) { - glxdisplay_cat.error() - << "Driver claims to support GLX_SGI_swap_control extension, but does not define all functions.\n"; - _supports_swap_control = false; - } - } - - if (_supports_swap_control) { - // Set the video-sync setting up front, if we have the extension - // that supports it. - _glXSwapIntervalSGI(sync_video ? 1 : 0); - } - - if (glx_support_fbconfig) { - if (glx_is_at_least_version(1, 3)) { - // If we have glx 1.3 or better, we have the FBConfig interface. - _supports_fbconfig = true; - - _glXChooseFBConfig = - (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func("glX", "ChooseFBConfig"); - _glXCreateNewContext = - (PFNGLXCREATENEWCONTEXTPROC)get_extension_func("glX", "CreateNewContext"); - _glXGetVisualFromFBConfig = - (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func("glX", "GetVisualFromFBConfig"); - _glXGetFBConfigAttrib = - (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func("glX", "GetFBConfigAttrib"); - _glXCreatePixmap = - (PFNGLXCREATEPIXMAPPROC)get_extension_func("glX", "CreatePixmap"); - - if (_glXChooseFBConfig == NULL || - _glXCreateNewContext == NULL || - _glXGetVisualFromFBConfig == NULL || - _glXGetFBConfigAttrib == NULL || - _glXCreatePixmap == NULL) { - glxdisplay_cat.error() - << "Driver claims to support GLX_fbconfig extension, but does not define all functions.\n"; - _supports_fbconfig = false; - } - } else if (has_extension("GLX_SGIX_fbconfig")) { - // Or maybe we have the old SGIX extension for FBConfig. This is - // the same, but the function names are different--we just remap - // them to the same function pointers. - _supports_fbconfig = true; - - _glXChooseFBConfig = - (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func("glX", "ChooseFBConfigSGIX"); - _glXCreateNewContext = - (PFNGLXCREATENEWCONTEXTPROC)get_extension_func("glX", "CreateContextWithConfigSGIX"); - _glXGetVisualFromFBConfig = - (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func("glX", "GetVisualFromFBConfigSGIX"); - _glXGetFBConfigAttrib = - (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func("glX", "GetFBConfigAttribSGIX"); - _glXCreatePixmap = - (PFNGLXCREATEPIXMAPPROC)get_extension_func("glX", "CreateGLXPixmapWithConfigSGIX"); - - if (_glXChooseFBConfig == NULL || - _glXCreateNewContext == NULL || - _glXGetVisualFromFBConfig == NULL || - _glXGetFBConfigAttrib == NULL || - _glXCreatePixmap == NULL) { - glxdisplay_cat.error() - << "Driver claims to support GLX_SGIX_fbconfig extension, but does not define all functions.\n"; - _supports_fbconfig = false; - } - } - - if (glx_is_at_least_version(1, 3)) { - // If we have glx 1.3 or better, we have the PBuffer interface. - _supports_pbuffer = true; - _uses_sgix_pbuffer = false; - - _glXCreatePbuffer = - (PFNGLXCREATEPBUFFERPROC)get_extension_func("glX", "CreatePbuffer"); - _glXCreateGLXPbufferSGIX = NULL; - _glXDestroyPbuffer = - (PFNGLXDESTROYPBUFFERPROC)get_extension_func("glX", "DestroyPbuffer"); - if (_glXCreatePbuffer == NULL || - _glXDestroyPbuffer == NULL) { - glxdisplay_cat.error() - << "Driver claims to support GLX_pbuffer extension, but does not define all functions.\n"; - _supports_pbuffer = false; - } - - } else if (has_extension("GLX_SGIX_pbuffer")) { - // Or maybe we have the old SGIX extension for PBuffers. - _uses_sgix_pbuffer = true; - - // CreatePbuffer has a different form between SGIX and 1.3, - // however, so we must treat it specially. But we can use the - // same function pointer for DestroyPbuffer. - _glXCreatePbuffer = NULL; - _glXCreateGLXPbufferSGIX = - (PFNGLXCREATEGLXPBUFFERSGIXPROC)get_extension_func("glX", "CreateGLXPbufferSGIX"); - _glXDestroyPbuffer = - (PFNGLXDESTROYPBUFFERPROC)get_extension_func("glX", "DestroyGLXPbufferSGIX"); - if (_glXCreateGLXPbufferSGIX == NULL || - _glXDestroyPbuffer == NULL) { - glxdisplay_cat.error() - << "Driver claims to support GLX_SGIX_pbuffer extension, but does not define all functions.\n"; - _supports_pbuffer = false; - } - } - } - - - if (glxdisplay_cat.is_debug()) { - glxdisplay_cat.debug() - << "supports_swap_control = " << _supports_swap_control << "\n"; - glxdisplay_cat.debug() - << "supports_fbconfig = " << _supports_fbconfig << "\n"; - glxdisplay_cat.debug() - << "supports_pbuffer = " << _supports_pbuffer - << " sgix = " << _uses_sgix_pbuffer << "\n"; - } - - // If "Mesa" is present, assume software. However, if "Mesa DRI" is - // found, it's actually a Mesa-based OpenGL layer running over a - // hardware driver. - if (_gl_renderer.find("Mesa") != string::npos && - _gl_renderer.find("Mesa DRI") == string::npos) { - // It's Mesa, therefore probably a software context. - _fbprops.set_force_software(1); - _fbprops.set_force_hardware(0); - } else { - _fbprops.set_force_hardware(1); - _fbprops.set_force_software(0); - } -} - //////////////////////////////////////////////////////////////////// // Function: glxGraphicsStateGuardian::glx_is_at_least_version // Access: Public @@ -625,41 +517,39 @@ get_extra_extensions() { // not defined. //////////////////////////////////////////////////////////////////// void *glxGraphicsStateGuardian:: -do_get_extension_func(const char *prefix, const char *name) { - nassertr(prefix != NULL, NULL); +do_get_extension_func(const char *name) { nassertr(name != NULL, NULL); - string fullname = string(prefix) + string(name); if (glx_get_proc_address) { // First, check if we have glXGetProcAddress available. This will // be superior if we can get it. - + #if defined(LINK_IN_GLXGETPROCADDRESS) && defined(HAVE_GLXGETPROCADDRESS) // If we are confident the system headers defined it, we can // call it directly. This is more reliable than trying to // determine its address dynamically, but it may make // libpandagl.so fail to load if the symbol isn't in the runtime // library. - return (void *)glXGetProcAddress((const GLubyte *)fullname.c_str()); - + return (void *)glXGetProcAddress((const GLubyte *)name); + #elif defined(LINK_IN_GLXGETPROCADDRESS) && defined(HAVE_GLXGETPROCADDRESSARB) // The ARB extension version is OK too. Sometimes the prototype // isn't supplied for some reason. - return (void *)glXGetProcAddressARB((const GLubyte *)fullname.c_str()); - + return (void *)glXGetProcAddressARB((const GLubyte *)name); + #else // Otherwise, we have to fiddle around with the dynamic runtime. - + if (!_checked_get_proc_address) { const char *funcName = NULL; - + if (glx_is_at_least_version(1, 4)) { funcName = "glXGetProcAddress"; } else if (has_extension("GLX_ARB_get_proc_address")) { funcName = "glXGetProcAddressARB"; } - + if (funcName != NULL) { _glXGetProcAddress = (PFNGLXGETPROCADDRESSPROC)get_system_func(funcName); if (_glXGetProcAddress == NULL) { @@ -671,16 +561,163 @@ do_get_extension_func(const char *prefix, const char *name) { _checked_get_proc_address = true; } - + // Use glxGetProcAddress() if we've got it; it should be more robust. if (_glXGetProcAddress != NULL) { - return (void *)_glXGetProcAddress((const GLubyte *)fullname.c_str()); + return (void *)_glXGetProcAddress((const GLubyte *)name); } #endif // HAVE_GLXGETPROCADDRESS } // Otherwise, fall back to the OS-provided calls. - return PosixGraphicsStateGuardian::do_get_extension_func(prefix, name); + return PosixGraphicsStateGuardian::do_get_extension_func(name); +} + +//////////////////////////////////////////////////////////////////// +// Function: glxGraphicsStateGuardian::query_glx_extensions +// Access: Private +// Description: Queries the GLX extension pointers. +//////////////////////////////////////////////////////////////////// +void glxGraphicsStateGuardian:: +query_glx_extensions() { + _supports_swap_control = has_extension("GLX_SGI_swap_control"); + + if (_supports_swap_control) { + _glXSwapIntervalSGI = + (PFNGLXSWAPINTERVALSGIPROC)get_extension_func("glXSwapIntervalSGI"); + if (_glXSwapIntervalSGI == NULL) { + glxdisplay_cat.error() + << "Driver claims to support GLX_SGI_swap_control extension, but does not define all functions.\n"; + _supports_swap_control = false; + } + } + + if (_supports_swap_control) { + // Set the video-sync setting up front, if we have the extension + // that supports it. + _glXSwapIntervalSGI(sync_video ? 1 : 0); + } + + if (glx_support_fbconfig) { + if (glx_is_at_least_version(1, 3)) { + // If we have glx 1.3 or better, we have the FBConfig interface. + _supports_fbconfig = true; + + _glXChooseFBConfig = + (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func("glXChooseFBConfig"); + _glXCreateNewContext = + (PFNGLXCREATENEWCONTEXTPROC)get_extension_func("glXCreateNewContext"); + _glXGetVisualFromFBConfig = + (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func("glXGetVisualFromFBConfig"); + _glXGetFBConfigAttrib = + (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func("glXGetFBConfigAttrib"); + _glXCreatePixmap = + (PFNGLXCREATEPIXMAPPROC)get_extension_func("glXCreatePixmap"); + + if (_glXChooseFBConfig == NULL || + _glXCreateNewContext == NULL || + _glXGetVisualFromFBConfig == NULL || + _glXGetFBConfigAttrib == NULL || + _glXCreatePixmap == NULL) { + glxdisplay_cat.error() + << "Driver claims to support GLX_fbconfig extension, but does not define all functions.\n"; + _supports_fbconfig = false; + } + } else if (has_extension("GLX_SGIX_fbconfig")) { + // Or maybe we have the old SGIX extension for FBConfig. This is + // the same, but the function names are different--we just remap + // them to the same function pointers. + _supports_fbconfig = true; + + _glXChooseFBConfig = + (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func("glXChooseFBConfigSGIX"); + _glXCreateNewContext = + (PFNGLXCREATENEWCONTEXTPROC)get_extension_func("glXCreateContextWithConfigSGIX"); + _glXGetVisualFromFBConfig = + (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func("glXGetVisualFromFBConfigSGIX"); + _glXGetFBConfigAttrib = + (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func("glXGetFBConfigAttribSGIX"); + _glXCreatePixmap = + (PFNGLXCREATEPIXMAPPROC)get_extension_func("glXCreateGLXPixmapWithConfigSGIX"); + + if (_glXChooseFBConfig == NULL || + _glXCreateNewContext == NULL || + _glXGetVisualFromFBConfig == NULL || + _glXGetFBConfigAttrib == NULL || + _glXCreatePixmap == NULL) { + glxdisplay_cat.error() + << "Driver claims to support GLX_SGIX_fbconfig extension, but does not define all functions.\n"; + _supports_fbconfig = false; + } + } + + if (glx_is_at_least_version(1, 3)) { + // If we have glx 1.3 or better, we have the PBuffer interface. + _supports_pbuffer = true; + _uses_sgix_pbuffer = false; + + _glXCreatePbuffer = + (PFNGLXCREATEPBUFFERPROC)get_extension_func("glXCreatePbuffer"); + _glXCreateGLXPbufferSGIX = NULL; + _glXDestroyPbuffer = + (PFNGLXDESTROYPBUFFERPROC)get_extension_func("glXDestroyPbuffer"); + if (_glXCreatePbuffer == NULL || + _glXDestroyPbuffer == NULL) { + glxdisplay_cat.error() + << "Driver claims to support GLX_pbuffer extension, but does not define all functions.\n"; + _supports_pbuffer = false; + } + + } else if (has_extension("GLX_SGIX_pbuffer")) { + // Or maybe we have the old SGIX extension for PBuffers. + _uses_sgix_pbuffer = true; + + // CreatePbuffer has a different form between SGIX and 1.3, + // however, so we must treat it specially. But we can use the + // same function pointer for DestroyPbuffer. + _glXCreatePbuffer = NULL; + _glXCreateGLXPbufferSGIX = + (PFNGLXCREATEGLXPBUFFERSGIXPROC)get_extension_func("glXCreateGLXPbufferSGIX"); + _glXDestroyPbuffer = + (PFNGLXDESTROYPBUFFERPROC)get_extension_func("glXDestroyGLXPbufferSGIX"); + if (_glXCreateGLXPbufferSGIX == NULL || + _glXDestroyPbuffer == NULL) { + glxdisplay_cat.error() + << "Driver claims to support GLX_SGIX_pbuffer extension, but does not define all functions.\n"; + _supports_pbuffer = false; + } + } + + if (has_extension("GLX_ARB_create_context")) { + _glXCreateContextAttribs = + (PFNGLXCREATECONTEXTATTRIBSARBPROC)get_extension_func("glXCreateContextAttribsARB"); + } else { + _glXCreateContextAttribs = NULL; + } + } + + if (glxdisplay_cat.is_debug()) { + glxdisplay_cat.debug() + << "supports_swap_control = " << _supports_swap_control << "\n"; + glxdisplay_cat.debug() + << "supports_fbconfig = " << _supports_fbconfig << "\n"; + glxdisplay_cat.debug() + << "supports_pbuffer = " << _supports_pbuffer + << " sgix = " << _uses_sgix_pbuffer << "\n"; + } + + // If "Mesa" is present, assume software. However, if "Mesa DRI" is + // found, it's actually a Mesa-based OpenGL layer running over a + // hardware driver. + if (_gl_renderer.find("Mesa") != string::npos && + _gl_renderer.find("Mesa DRI") == string::npos) { + // It's Mesa, therefore probably a software context. + _fbprops.set_force_software(1); + _fbprops.set_force_hardware(0); + } else { + _fbprops.set_force_hardware(1); + _fbprops.set_force_software(0); + } } //////////////////////////////////////////////////////////////////// @@ -759,17 +796,17 @@ choose_temp_visual(const FrameBufferProperties &properties) { } } } - + if (best_quality > 0) { _visual = _visuals + best_result; - _temp_context = glXCreateContext(_display, _visual, None, GL_TRUE); + _temp_context = glXCreateContext(_display, _visual, None, GL_TRUE); if (_temp_context) { _fbprops = best_props; return; } } - glxdisplay_cat.error() + glxdisplay_cat.error() << "Could not find a usable pixel format.\n"; } @@ -805,8 +842,11 @@ init_temp_context() { return; } + // Now use it to query the available GLX features. glXMakeCurrent(_display, _temp_xwindow, _temp_context); - reset(); + query_gl_version(); + get_extra_extensions(); + query_glx_extensions(); } //////////////////////////////////////////////////////////////////// @@ -828,7 +868,7 @@ destroy_temp_xwindow() { _temp_xwindow = (X11_Window)NULL; } - if (_temp_context != (GLXContext)NULL){ + if (_temp_context != (GLXContext)NULL) { glXDestroyContext(_display, _temp_context); _temp_context = (GLXContext)NULL; } diff --git a/panda/src/glxdisplay/glxGraphicsStateGuardian.h b/panda/src/glxdisplay/glxGraphicsStateGuardian.h index f3f72f5b91..3a6431c865 100644 --- a/panda/src/glxdisplay/glxGraphicsStateGuardian.h +++ b/panda/src/glxdisplay/glxGraphicsStateGuardian.h @@ -67,7 +67,7 @@ typedef int (* PFNGLXGETFBCONFIGATTRIBPROC) (X11_Display *dpy, GLXFBConfig confi typedef GLXPixmap (* PFNGLXCREATEPIXMAPPROC) (X11_Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); typedef GLXPbuffer (* PFNGLXCREATEPBUFFERPROC) (X11_Display *dpy, GLXFBConfig config, const int *attrib_list); typedef void (* PFNGLXDESTROYPBUFFERPROC) (X11_Display *dpy, GLXPbuffer pbuf); - +typedef GLXContext ( *PFNGLXCREATECONTEXTATTRIBSARBPROC) (X11_Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); #endif // __EDG__ //////////////////////////////////////////////////////////////////// @@ -92,8 +92,6 @@ public: virtual ~glxGraphicsStateGuardian(); - virtual void reset(); - bool glx_is_at_least_version(int major_version, int minor_version) const; GLXContext _share_context; @@ -119,6 +117,7 @@ public: PFNGLXGETVISUALFROMFBCONFIGPROC _glXGetVisualFromFBConfig; PFNGLXGETFBCONFIGATTRIBPROC _glXGetFBConfigAttrib; PFNGLXCREATEPIXMAPPROC _glXCreatePixmap; + PFNGLXCREATECONTEXTATTRIBSARBPROC _glXCreateContextAttribs; bool _supports_pbuffer; // true if the interface is available. bool _uses_sgix_pbuffer; @@ -132,9 +131,10 @@ protected: virtual void query_gl_version(); virtual void get_extra_extensions(); - virtual void *do_get_extension_func(const char *prefix, const char *name); + virtual void *do_get_extension_func(const char *name); private: + void query_glx_extensions(); void show_glx_client_string(const string &name, int id); void show_glx_server_string(const string &name, int id); void choose_temp_visual(const FrameBufferProperties &properties); diff --git a/panda/src/glxdisplay/panda_glxext.h b/panda/src/glxdisplay/panda_glxext.h index 71f208f34a..308e166224 100644 --- a/panda/src/glxdisplay/panda_glxext.h +++ b/panda/src/glxdisplay/panda_glxext.h @@ -1,614 +1,867 @@ #ifndef panda__glxext_h_ -#define panda__glxext_h_ +#define panda__glxext_h_ 1 #ifdef __cplusplus extern "C" { #endif /* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 1.1 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2002 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: This software was created using the -** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has -** not been independently verified as being compliant with the OpenGL(R) -** version 1.2.1 Specification. +** Copyright (c) 2013-2014 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ +/* +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** http://www.opengl.org/registry/ +** +** Khronos $Revision$ on $Date$ */ -#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) -#define WIN32_LEAN_AND_MEAN 1 -#include -#endif +#define GLX_GLXEXT_VERSION 20140416 -#ifndef APIENTRY -#define APIENTRY -#endif -#ifndef APIENTRYP -#define APIENTRYP APIENTRY * -#endif -#ifndef GLAPI -#define GLAPI extern -#endif - -/*************************************************************/ - -/* Header file version number, required by OpenGL ABI for Linux */ -/* glxext.h last updated 2002/03/22 */ -/* Current version at http://oss.sgi.com/projects/ogl-sample/registry/ */ -#define GLX_GLXEXT_VERSION 5 - -#ifndef GLX_VERSION_1_3 -#define GLX_WINDOW_BIT 0x00000001 -#define GLX_PIXMAP_BIT 0x00000002 -#define GLX_PBUFFER_BIT 0x00000004 -#define GLX_RGBA_BIT 0x00000001 -#define GLX_COLOR_INDEX_BIT 0x00000002 -#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 -#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 -#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 -#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 -#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 -#define GLX_AUX_BUFFERS_BIT 0x00000010 -#define GLX_DEPTH_BUFFER_BIT 0x00000020 -#define GLX_STENCIL_BUFFER_BIT 0x00000040 -#define GLX_ACCUM_BUFFER_BIT 0x00000080 -#define GLX_CONFIG_CAVEAT 0x20 -#define GLX_X_VISUAL_TYPE 0x22 -#define GLX_TRANSPARENT_TYPE 0x23 -#define GLX_TRANSPARENT_INDEX_VALUE 0x24 -#define GLX_TRANSPARENT_RED_VALUE 0x25 -#define GLX_TRANSPARENT_GREEN_VALUE 0x26 -#define GLX_TRANSPARENT_BLUE_VALUE 0x27 -#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 -#define GLX_DONT_CARE 0xFFFFFFFF -#define GLX_NONE 0x8000 -#define GLX_SLOW_CONFIG 0x8001 -#define GLX_TRUE_COLOR 0x8002 -#define GLX_DIRECT_COLOR 0x8003 -#define GLX_PSEUDO_COLOR 0x8004 -#define GLX_STATIC_COLOR 0x8005 -#define GLX_GRAY_SCALE 0x8006 -#define GLX_STATIC_GRAY 0x8007 -#define GLX_TRANSPARENT_RGB 0x8008 -#define GLX_TRANSPARENT_INDEX 0x8009 -#define GLX_VISUAL_ID 0x800B -#define GLX_SCREEN 0x800C -#define GLX_NON_CONFORMANT_CONFIG 0x800D -#define GLX_DRAWABLE_TYPE 0x8010 -#define GLX_RENDER_TYPE 0x8011 -#define GLX_X_RENDERABLE 0x8012 -#define GLX_FBCONFIG_ID 0x8013 -#define GLX_RGBA_TYPE 0x8014 -#define GLX_COLOR_INDEX_TYPE 0x8015 -#define GLX_MAX_PBUFFER_WIDTH 0x8016 -#define GLX_MAX_PBUFFER_HEIGHT 0x8017 -#define GLX_MAX_PBUFFER_PIXELS 0x8018 -#define GLX_PRESERVED_CONTENTS 0x801B -#define GLX_LARGEST_PBUFFER 0x801C -#define GLX_WIDTH 0x801D -#define GLX_HEIGHT 0x801E -#define GLX_EVENT_MASK 0x801F -#define GLX_DAMAGED 0x8020 -#define GLX_SAVED 0x8021 -#define GLX_WINDOW 0x8022 -#define GLX_PBUFFER 0x8023 -#define GLX_PBUFFER_HEIGHT 0x8040 -#define GLX_PBUFFER_WIDTH 0x8041 -#endif - -#ifndef GLX_VERSION_1_4 -#define GLX_SAMPLE_BUFFERS 100000 -#define GLX_SAMPLES 100001 -#endif - -/* drose: the version of GL/glx.h that ships with Fedora Core 2 seems - to define GLX_VERSION_1_4, but for some reason does not define - GLX_SAMPLE_BUFFERS or GLX_SAMPLES. We work around that here. */ -#ifndef GLX_SAMPLE_BUFFERS -#define GLX_SAMPLE_BUFFERS 100000 -#endif -#ifndef GLX_SAMPLES -#define GLX_SAMPLES 100001 -#endif - -#ifndef GLX_ARB_get_proc_address -#endif - -#ifndef GLX_ARB_multisample -#define GLX_SAMPLE_BUFFERS_ARB 100000 -#define GLX_SAMPLES_ARB 100001 -#endif - -#ifndef GLX_SGIS_multisample -#define GLX_SAMPLE_BUFFERS_SGIS 100000 -#define GLX_SAMPLES_SGIS 100001 -#endif - -#ifndef GLX_EXT_visual_info -#define GLX_X_VISUAL_TYPE_EXT 0x22 -#define GLX_TRANSPARENT_TYPE_EXT 0x23 -#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 -#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 -#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 -#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 -#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 -#define GLX_NONE_EXT 0x8000 -#define GLX_TRUE_COLOR_EXT 0x8002 -#define GLX_DIRECT_COLOR_EXT 0x8003 -#define GLX_PSEUDO_COLOR_EXT 0x8004 -#define GLX_STATIC_COLOR_EXT 0x8005 -#define GLX_GRAY_SCALE_EXT 0x8006 -#define GLX_STATIC_GRAY_EXT 0x8007 -#define GLX_TRANSPARENT_RGB_EXT 0x8008 -#define GLX_TRANSPARENT_INDEX_EXT 0x8009 -#endif - -#ifndef GLX_SGI_swap_control -#endif - -#ifndef GLX_SGI_video_sync -#endif - -#ifndef GLX_SGI_make_current_read -#endif - -#ifndef GLX_SGIX_video_source -#endif - -#ifndef GLX_EXT_visual_rating -#define GLX_VISUAL_CAVEAT_EXT 0x20 -#define GLX_SLOW_VISUAL_EXT 0x8001 -#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D -/* reuse GLX_NONE_EXT */ -#endif - -#ifndef GLX_SGIX_fbconfig -#define GLX_WINDOW_BIT_SGIX 0x00000001 -#define GLX_PIXMAP_BIT_SGIX 0x00000002 -#define GLX_RGBA_BIT_SGIX 0x00000001 -#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 -#define GLX_DRAWABLE_TYPE_SGIX 0x8010 -#define GLX_RENDER_TYPE_SGIX 0x8011 -#define GLX_X_RENDERABLE_SGIX 0x8012 -#define GLX_FBCONFIG_ID_SGIX 0x8013 -#define GLX_RGBA_TYPE_SGIX 0x8014 -#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 -/* reuse GLX_SCREEN_EXT */ -#endif - -#ifndef GLX_SGIX_pbuffer -#define GLX_PBUFFER_BIT_SGIX 0x00000004 -#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 -#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 -#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 -#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 -#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 -#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 -#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 -#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 -#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 -#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 -#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 -#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 -#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 -#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 -#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A -#define GLX_PRESERVED_CONTENTS_SGIX 0x801B -#define GLX_LARGEST_PBUFFER_SGIX 0x801C -#define GLX_WIDTH_SGIX 0x801D -#define GLX_HEIGHT_SGIX 0x801E -#define GLX_EVENT_MASK_SGIX 0x801F -#define GLX_DAMAGED_SGIX 0x8020 -#define GLX_SAVED_SGIX 0x8021 -#define GLX_WINDOW_SGIX 0x8022 -#define GLX_PBUFFER_SGIX 0x8023 -#endif - -#ifndef GLX_SGI_cushion -#endif - -#ifndef GLX_SGIX_video_resize -#define GLX_SYNC_FRAME_SGIX 0x00000000 -#define GLX_SYNC_SWAP_SGIX 0x00000001 -#endif - -#ifndef GLX_SGIX_dmbuffer -#define GLX_DIGITAL_MEDIA_PBUFFER_SGIX 0x8024 -#endif - -#ifndef GLX_SGIX_swap_group -#endif - -#ifndef GLX_SGIX_swap_barrier -#endif - -#ifndef GLX_SGIS_blended_overlay -#define GLX_BLENDED_RGBA_SGIS 0x8025 -#endif - -#ifndef GLX_SGIS_shared_multisample -#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 -#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 -#endif - -#ifndef GLX_SUN_get_transparent_index -#endif - -#ifndef GLX_3DFX_multisample -#define GLX_SAMPLE_BUFFERS_3DFX 0x8050 -#define GLX_SAMPLES_3DFX 0x8051 -#endif - -#ifndef GLX_MESA_copy_sub_buffer -#endif - -#ifndef GLX_MESA_pixmap_colormap -#endif - -#ifndef GLX_MESA_release_buffers -#endif - -#ifndef GLX_MESA_set_3dfx_mode -#define GLX_3DFX_WINDOW_MODE_MESA 0x1 -#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 -#endif - -#ifndef GLX_SGIX_visual_select_group -#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028 -#endif - -#ifndef GLX_OML_swap_method -#define GLX_SWAP_METHOD_OML 0x8060 -#define GLX_SWAP_EXCHANGE_OML 0x8061 -#define GLX_SWAP_COPY_OML 0x8062 -#define GLX_SWAP_UNDEFINED_OML 0x8063 -#endif - -#ifndef GLX_OML_sync_control -#endif - - -/*************************************************************/ - -/* drose: glxext.h seems to have an error in that it assumes - __GLXextFuncPtr will be typedeffed if GLX_ARB_get_proc_address is - defined, which does not seem to be the case (at least it is not so - on my redhat 8.0 box). So we work around this by typedeffing it - explicitly; and we use #define in case it is already typedeffed. */ -#define __GLXextFuncPtr panda__GLXextFuncPtr -typedef void (*__GLXextFuncPtr)(); - - /* -#ifndef GLX_ARB_get_proc_address -typedef void (*__GLXextFuncPtr)(); -#endif - */ - -#ifndef GLX_SGIX_video_source -typedef XID GLXVideoSourceSGIX; -#endif - -#ifndef GLX_SGIX_fbconfig -typedef XID GLXFBConfigIDSGIX; -typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; -#endif - -#ifndef GLX_SGIX_pbuffer -typedef XID GLXPbufferSGIX; -typedef struct { - int type; - unsigned long serial; /* # of last request processed by server */ - Bool send_event; /* true if this came for SendEvent request */ - X11_Display *display; /* display the event was read from */ - GLXDrawable drawable; /* i.d. of Drawable */ - int event_type; /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */ - int draw_type; /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */ - unsigned int mask; /* mask indicating which buffers are affected*/ - int x, y; - int width, height; - int count; /* if nonzero, at least this many more */ -} GLXBufferClobberEventSGIX; -#endif +/* Generated C header for: + * API: glx + * Versions considered: .* + * Versions emitted: 1\.[3-9] + * Default extensions included: glx + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ #ifndef GLX_VERSION_1_3 #define GLX_VERSION_1_3 1 - /* drose: If the system glx.h isn't at least version 1.3, it won't - have defined these types, so we need to do so here in order for - the following to compile. */ -typedef struct __GLXFBConfigRec *GLXFBConfig; -typedef XID GLXPbuffer; +typedef XID GLXContextID; +typedef struct __GLXFBConfigRec *GLXFBConfig; typedef XID GLXWindow; - +typedef XID GLXPbuffer; +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_RGBA_BIT 0x00000001 +#define GLX_COLOR_INDEX_BIT 0x00000002 +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 +#define GLX_CONFIG_CAVEAT 0x20 +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_DONT_CARE 0xFFFFFFFF +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_STATIC_GRAY 0x8007 +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_INDEX 0x8009 +#define GLX_VISUAL_ID 0x800B +#define GLX_SCREEN 0x800C +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_COLOR_INDEX_TYPE 0x8015 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_WIDTH 0x801D +#define GLX_HEIGHT 0x801E +#define GLX_EVENT_MASK 0x801F +#define GLX_DAMAGED 0x8020 +#define GLX_SAVED 0x8021 +#define GLX_WINDOW 0x8022 +#define GLX_PBUFFER 0x8023 +#define GLX_PBUFFER_HEIGHT 0x8040 +#define GLX_PBUFFER_WIDTH 0x8041 +typedef GLXFBConfig *( *PFNGLXGETFBCONFIGSPROC) (X11_Display *dpy, int screen, int *nelements); +typedef GLXFBConfig *( *PFNGLXCHOOSEFBCONFIGPROC) (X11_Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef int ( *PFNGLXGETFBCONFIGATTRIBPROC) (X11_Display *dpy, GLXFBConfig config, int attribute, int *value); +typedef XVisualInfo *( *PFNGLXGETVISUALFROMFBCONFIGPROC) (X11_Display *dpy, GLXFBConfig config); +typedef GLXWindow ( *PFNGLXCREATEWINDOWPROC) (X11_Display *dpy, GLXFBConfig config, X11_Window win, const int *attrib_list); +typedef void ( *PFNGLXDESTROYWINDOWPROC) (X11_Display *dpy, GLXWindow win); +typedef GLXPixmap ( *PFNGLXCREATEPIXMAPPROC) (X11_Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); +typedef void ( *PFNGLXDESTROYPIXMAPPROC) (X11_Display *dpy, GLXPixmap pixmap); +typedef GLXPbuffer ( *PFNGLXCREATEPBUFFERPROC) (X11_Display *dpy, GLXFBConfig config, const int *attrib_list); +typedef void ( *PFNGLXDESTROYPBUFFERPROC) (X11_Display *dpy, GLXPbuffer pbuf); +typedef void ( *PFNGLXQUERYDRAWABLEPROC) (X11_Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); +typedef GLXContext ( *PFNGLXCREATENEWCONTEXTPROC) (X11_Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef Bool ( *PFNGLXMAKECONTEXTCURRENTPROC) (X11_Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef GLXDrawable ( *PFNGLXGETCURRENTREADDRAWABLEPROC) (void); +typedef int ( *PFNGLXQUERYCONTEXTPROC) (X11_Display *dpy, GLXContext ctx, int attribute, int *value); +typedef void ( *PFNGLXSELECTEVENTPROC) (X11_Display *dpy, GLXDrawable draw, unsigned long event_mask); +typedef void ( *PFNGLXGETSELECTEDEVENTPROC) (X11_Display *dpy, GLXDrawable draw, unsigned long *event_mask); #ifdef GLX_GLXEXT_PROTOTYPES -extern GLXFBConfig * glXGetFBConfigs (X11_Display *, int, int *); -extern GLXFBConfig * glXChooseFBConfig (X11_Display *, int, const int *, int *); -extern int glXGetFBConfigAttrib (X11_Display *, GLXFBConfig, int, int *); -extern XVisualInfo * glXGetVisualFromFBConfig (X11_Display *, GLXFBConfig); -extern GLXWindow glXCreateWindow (X11_Display *, GLXFBConfig, X11_Window, const int *); -extern void glXDestroyWindow (X11_Display *, GLXWindow); -extern GLXPixmap glXCreatePixmap (X11_Display *, GLXFBConfig, Pixmap, const int *); -extern void glXDestroyPixmap (X11_Display *, GLXPixmap); -extern GLXPbuffer glXCreatePbuffer (X11_Display *, GLXFBConfig, const int *); -extern void glXDestroyPbuffer (X11_Display *, GLXPbuffer); -extern void glXQueryDrawable (X11_Display *, GLXDrawable, int, unsigned int *); -extern GLXContext glXCreateNewContext (X11_Display *, GLXFBConfig, int, GLXContext, Bool); -extern Bool glXMakeContextCurrent (X11_Display *, GLXDrawable, GLXDrawable, GLXContext); -extern GLXDrawable glXGetCurrentReadDrawable (); -extern X11_Display * glXGetCurrentDisplay (); -extern int glXQueryContext (X11_Display *, GLXContext, int, int *); -extern void glXSelectEvent (X11_Display *, GLXDrawable, unsigned long); -extern void glXGetSelectedEvent (X11_Display *, GLXDrawable, unsigned long *); -#endif /* GLX_GLXEXT_PROTOTYPES */ - /* drose: all of the following PFN... typedefs seemed to be - incorrect. I put a * just inside the leading parenthesis. */ -typedef GLXFBConfig * (* PFNGLXGETFBCONFIGSPROC) (X11_Display *dpy, int screen, int *nelements); -typedef GLXFBConfig * (* PFNGLXCHOOSEFBCONFIGPROC) (X11_Display *dpy, int screen, const int *attrib_list, int *nelements); -typedef int (* PFNGLXGETFBCONFIGATTRIBPROC) (X11_Display *dpy, GLXFBConfig config, int attribute, int *value); -typedef XVisualInfo * (* PFNGLXGETVISUALFROMFBCONFIGPROC) (X11_Display *dpy, GLXFBConfig config); -typedef GLXWindow (* PFNGLXCREATEWINDOWPROC) (X11_Display *dpy, GLXFBConfig config, X11_Window win, const int *attrib_list); -typedef void (* PFNGLXDESTROYWINDOWPROC) (X11_Display *dpy, GLXWindow win); -typedef GLXPixmap (* PFNGLXCREATEPIXMAPPROC) (X11_Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); -typedef void (* PFNGLXDESTROYPIXMAPPROC) (X11_Display *dpy, GLXPixmap pixmap); -typedef GLXPbuffer (* PFNGLXCREATEPBUFFERPROC) (X11_Display *dpy, GLXFBConfig config, const int *attrib_list); -typedef void (* PFNGLXDESTROYPBUFFERPROC) (X11_Display *dpy, GLXPbuffer pbuf); -typedef void (* PFNGLXQUERYDRAWABLEPROC) (X11_Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); -typedef GLXContext (* PFNGLXCREATENEWCONTEXTPROC) (X11_Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); -typedef Bool (* PFNGLXMAKECONTEXTCURRENTPROC) (X11_Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); -typedef GLXDrawable (* PFNGLXGETCURRENTREADDRAWABLEPROC) (); -typedef X11_Display * (* PFNGLXGETCURRENTDISPLAYPROC) (); -typedef int (* PFNGLXQUERYCONTEXTPROC) (X11_Display *dpy, GLXContext ctx, int attribute, int *value); -typedef void (* PFNGLXSELECTEVENTPROC) (X11_Display *dpy, GLXDrawable draw, unsigned long event_mask); -typedef void (* PFNGLXGETSELECTEDEVENTPROC) (X11_Display *dpy, GLXDrawable draw, unsigned long *event_mask); +GLXFBConfig *glXGetFBConfigs (X11_Display *dpy, int screen, int *nelements); +GLXFBConfig *glXChooseFBConfig (X11_Display *dpy, int screen, const int *attrib_list, int *nelements); +int glXGetFBConfigAttrib (X11_Display *dpy, GLXFBConfig config, int attribute, int *value); +XVisualInfo *glXGetVisualFromFBConfig (X11_Display *dpy, GLXFBConfig config); +GLXWindow glXCreateWindow (X11_Display *dpy, GLXFBConfig config, X11_Window win, const int *attrib_list); +void glXDestroyWindow (X11_Display *dpy, GLXWindow win); +GLXPixmap glXCreatePixmap (X11_Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); +void glXDestroyPixmap (X11_Display *dpy, GLXPixmap pixmap); +GLXPbuffer glXCreatePbuffer (X11_Display *dpy, GLXFBConfig config, const int *attrib_list); +void glXDestroyPbuffer (X11_Display *dpy, GLXPbuffer pbuf); +void glXQueryDrawable (X11_Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); +GLXContext glXCreateNewContext (X11_Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +Bool glXMakeContextCurrent (X11_Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +GLXDrawable glXGetCurrentReadDrawable (void); +int glXQueryContext (X11_Display *dpy, GLXContext ctx, int attribute, int *value); +void glXSelectEvent (X11_Display *dpy, GLXDrawable draw, unsigned long event_mask); +void glXGetSelectedEvent (X11_Display *dpy, GLXDrawable draw, unsigned long *event_mask); #endif +#endif /* GLX_VERSION_1_3 */ #ifndef GLX_VERSION_1_4 #define GLX_VERSION_1_4 1 +typedef void ( *__GLXextFuncPtr)(void); +#define GLX_SAMPLE_BUFFERS 100000 +#define GLX_SAMPLES 100001 +typedef __GLXextFuncPtr ( *PFNGLXGETPROCADDRESSPROC) (const GLubyte *procName); #ifdef GLX_GLXEXT_PROTOTYPES -extern __GLXextFuncPtr glXGetProcAddress (const GLubyte *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef __GLXextFuncPtr (* PFNGLXGETPROCADDRESSPROC) (const GLubyte *procName); +__GLXextFuncPtr glXGetProcAddress (const GLubyte *procName); #endif +#endif /* GLX_VERSION_1_4 */ + +#ifndef GLX_ARB_create_context +#define GLX_ARB_create_context 1 +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define GLX_CONTEXT_FLAGS_ARB 0x2094 +typedef GLXContext ( *PFNGLXCREATECONTEXTATTRIBSARBPROC) (X11_Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); +#ifdef GLX_GLXEXT_PROTOTYPES +GLXContext glXCreateContextAttribsARB (X11_Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); +#endif +#endif /* GLX_ARB_create_context */ + +#ifndef GLX_ARB_create_context_profile +#define GLX_ARB_create_context_profile 1 +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 +#endif /* GLX_ARB_create_context_profile */ + +#ifndef GLX_ARB_create_context_robustness +#define GLX_ARB_create_context_robustness 1 +#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261 +#endif /* GLX_ARB_create_context_robustness */ + +#ifndef GLX_ARB_fbconfig_float +#define GLX_ARB_fbconfig_float 1 +#define GLX_RGBA_FLOAT_TYPE_ARB 0x20B9 +#define GLX_RGBA_FLOAT_BIT_ARB 0x00000004 +#endif /* GLX_ARB_fbconfig_float */ + +#ifndef GLX_ARB_framebuffer_sRGB +#define GLX_ARB_framebuffer_sRGB 1 +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2 +#endif /* GLX_ARB_framebuffer_sRGB */ #ifndef GLX_ARB_get_proc_address #define GLX_ARB_get_proc_address 1 +typedef __GLXextFuncPtr ( *PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName); #ifdef GLX_GLXEXT_PROTOTYPES -extern __GLXextFuncPtr glXGetProcAddressARB (const GLubyte *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef __GLXextFuncPtr (* PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName); +__GLXextFuncPtr glXGetProcAddressARB (const GLubyte *procName); #endif +#endif /* GLX_ARB_get_proc_address */ #ifndef GLX_ARB_multisample #define GLX_ARB_multisample 1 -#endif +#define GLX_SAMPLE_BUFFERS_ARB 100000 +#define GLX_SAMPLES_ARB 100001 +#endif /* GLX_ARB_multisample */ -#ifndef GLX_SGIS_multisample -#define GLX_SGIS_multisample 1 +#ifndef GLX_ARB_robustness_application_isolation +#define GLX_ARB_robustness_application_isolation 1 +#define GLX_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008 +#endif /* GLX_ARB_robustness_application_isolation */ + +#ifndef GLX_ARB_robustness_share_group_isolation +#define GLX_ARB_robustness_share_group_isolation 1 +#endif /* GLX_ARB_robustness_share_group_isolation */ + +#ifndef GLX_ARB_vertex_buffer_object +#define GLX_ARB_vertex_buffer_object 1 +#define GLX_CONTEXT_ALLOW_BUFFER_BYTE_ORDER_MISMATCH_ARB 0x2095 +#endif /* GLX_ARB_vertex_buffer_object */ + +#ifndef GLX_3DFX_multisample +#define GLX_3DFX_multisample 1 +#define GLX_SAMPLE_BUFFERS_3DFX 0x8050 +#define GLX_SAMPLES_3DFX 0x8051 +#endif /* GLX_3DFX_multisample */ + +#ifndef GLX_AMD_gpu_association +#define GLX_AMD_gpu_association 1 +#define GLX_GPU_VENDOR_AMD 0x1F00 +#define GLX_GPU_RENDERER_STRING_AMD 0x1F01 +#define GLX_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 +#define GLX_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 +#define GLX_GPU_RAM_AMD 0x21A3 +#define GLX_GPU_CLOCK_AMD 0x21A4 +#define GLX_GPU_NUM_PIPES_AMD 0x21A5 +#define GLX_GPU_NUM_SIMD_AMD 0x21A6 +#define GLX_GPU_NUM_RB_AMD 0x21A7 +#define GLX_GPU_NUM_SPI_AMD 0x21A8 +#endif /* GLX_AMD_gpu_association */ + +#ifndef GLX_EXT_buffer_age +#define GLX_EXT_buffer_age 1 +#define GLX_BACK_BUFFER_AGE_EXT 0x20F4 +#endif /* GLX_EXT_buffer_age */ + +#ifndef GLX_EXT_create_context_es2_profile +#define GLX_EXT_create_context_es2_profile 1 +#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 +#endif /* GLX_EXT_create_context_es2_profile */ + +#ifndef GLX_EXT_create_context_es_profile +#define GLX_EXT_create_context_es_profile 1 +#define GLX_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004 +#endif /* GLX_EXT_create_context_es_profile */ + +#ifndef GLX_EXT_fbconfig_packed_float +#define GLX_EXT_fbconfig_packed_float 1 +#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1 +#define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT 0x00000008 +#endif /* GLX_EXT_fbconfig_packed_float */ + +#ifndef GLX_EXT_framebuffer_sRGB +#define GLX_EXT_framebuffer_sRGB 1 +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2 +#endif /* GLX_EXT_framebuffer_sRGB */ + +#ifndef GLX_EXT_stereo_tree +#define GLX_EXT_stereo_tree 1 +typedef struct { + int type; + unsigned long serial; + Bool send_event; + X11_Display *display; + int extension; + int evtype; + GLXDrawable window; + Bool stereo_tree; +} GLXStereoNotifyEventEXT; +#define GLX_STEREO_TREE_EXT 0x20F5 +#define GLX_STEREO_NOTIFY_MASK_EXT 0x00000001 +#define GLX_STEREO_NOTIFY_EXT 0x00000000 +#endif /* GLX_EXT_stereo_tree */ + +#ifndef GLX_EXT_swap_control +#define GLX_EXT_swap_control 1 +#define GLX_SWAP_INTERVAL_EXT 0x20F1 +#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2 +typedef void ( *PFNGLXSWAPINTERVALEXTPROC) (X11_Display *dpy, GLXDrawable drawable, int interval); +#ifdef GLX_GLXEXT_PROTOTYPES +void glXSwapIntervalEXT (X11_Display *dpy, GLXDrawable drawable, int interval); #endif +#endif /* GLX_EXT_swap_control */ + +#ifndef GLX_EXT_swap_control_tear +#define GLX_EXT_swap_control_tear 1 +#define GLX_LATE_SWAPS_TEAR_EXT 0x20F3 +#endif /* GLX_EXT_swap_control_tear */ + +#ifndef GLX_EXT_texture_from_pixmap +#define GLX_EXT_texture_from_pixmap 1 +#define GLX_TEXTURE_1D_BIT_EXT 0x00000001 +#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 +#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 +#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0 +#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1 +#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2 +#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3 +#define GLX_Y_INVERTED_EXT 0x20D4 +#define GLX_TEXTURE_FORMAT_EXT 0x20D5 +#define GLX_TEXTURE_TARGET_EXT 0x20D6 +#define GLX_MIPMAP_TEXTURE_EXT 0x20D7 +#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8 +#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9 +#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA +#define GLX_TEXTURE_1D_EXT 0x20DB +#define GLX_TEXTURE_2D_EXT 0x20DC +#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD +#define GLX_FRONT_LEFT_EXT 0x20DE +#define GLX_FRONT_RIGHT_EXT 0x20DF +#define GLX_BACK_LEFT_EXT 0x20E0 +#define GLX_BACK_RIGHT_EXT 0x20E1 +#define GLX_FRONT_EXT 0x20DE +#define GLX_BACK_EXT 0x20E0 +#define GLX_AUX0_EXT 0x20E2 +#define GLX_AUX1_EXT 0x20E3 +#define GLX_AUX2_EXT 0x20E4 +#define GLX_AUX3_EXT 0x20E5 +#define GLX_AUX4_EXT 0x20E6 +#define GLX_AUX5_EXT 0x20E7 +#define GLX_AUX6_EXT 0x20E8 +#define GLX_AUX7_EXT 0x20E9 +#define GLX_AUX8_EXT 0x20EA +#define GLX_AUX9_EXT 0x20EB +typedef void ( *PFNGLXBINDTEXIMAGEEXTPROC) (X11_Display *dpy, GLXDrawable drawable, int buffer, const int *attrib_list); +typedef void ( *PFNGLXRELEASETEXIMAGEEXTPROC) (X11_Display *dpy, GLXDrawable drawable, int buffer); +#ifdef GLX_GLXEXT_PROTOTYPES +void glXBindTexImageEXT (X11_Display *dpy, GLXDrawable drawable, int buffer, const int *attrib_list); +void glXReleaseTexImageEXT (X11_Display *dpy, GLXDrawable drawable, int buffer); +#endif +#endif /* GLX_EXT_texture_from_pixmap */ #ifndef GLX_EXT_visual_info #define GLX_EXT_visual_info 1 -#endif +#define GLX_X_VISUAL_TYPE_EXT 0x22 +#define GLX_TRANSPARENT_TYPE_EXT 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 +#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 +#define GLX_NONE_EXT 0x8000 +#define GLX_TRUE_COLOR_EXT 0x8002 +#define GLX_DIRECT_COLOR_EXT 0x8003 +#define GLX_PSEUDO_COLOR_EXT 0x8004 +#define GLX_STATIC_COLOR_EXT 0x8005 +#define GLX_GRAY_SCALE_EXT 0x8006 +#define GLX_STATIC_GRAY_EXT 0x8007 +#define GLX_TRANSPARENT_RGB_EXT 0x8008 +#define GLX_TRANSPARENT_INDEX_EXT 0x8009 +#endif /* GLX_EXT_visual_info */ -#ifndef GLX_SGI_swap_control -#define GLX_SGI_swap_control 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern int glXSwapIntervalSGI (int); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef int (* PFNGLXSWAPINTERVALSGIPROC) (int interval); -#endif - -#ifndef GLX_SGI_video_sync -#define GLX_SGI_video_sync 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern int glXGetVideoSyncSGI (unsigned int *); -extern int glXWaitVideoSyncSGI (int, int, unsigned int *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef int (* PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int *count); -typedef int (* PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int *count); -#endif - -#ifndef GLX_SGI_make_current_read -#define GLX_SGI_make_current_read 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern Bool glXMakeCurrentReadSGI (X11_Display *, GLXDrawable, GLXDrawable, GLXContext); -extern GLXDrawable glXGetCurrentReadDrawableSGI (); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef Bool (* PFNGLXMAKECURRENTREADSGIPROC) (X11_Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); -typedef GLXDrawable (* PFNGLXGETCURRENTREADDRAWABLESGIPROC) (); -#endif - -#ifndef GLX_SGIX_video_source -#define GLX_SGIX_video_source 1 -#ifdef _VL_H -#ifdef GLX_GLXEXT_PROTOTYPES -extern GLXVideoSourceSGIX glXCreateGLXVideoSourceSGIX (X11_Display *, int, VLServer, VLPath, int, VLNode); -extern void glXDestroyGLXVideoSourceSGIX (X11_Display *, GLXVideoSourceSGIX); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef GLXVideoSourceSGIX (* PFNGLXCREATEGLXVIDEOSOURCESGIXPROC) (X11_Display *display, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode); -typedef void (* PFNGLXDESTROYGLXVIDEOSOURCESGIXPROC) (X11_Display *dpy, GLXVideoSourceSGIX glxvideosource); -#endif - -#endif /* _VL_H */ #ifndef GLX_EXT_visual_rating #define GLX_EXT_visual_rating 1 -#endif +#define GLX_VISUAL_CAVEAT_EXT 0x20 +#define GLX_SLOW_VISUAL_EXT 0x8001 +#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D +#endif /* GLX_EXT_visual_rating */ -#ifndef GLX_SGIX_fbconfig -#define GLX_SGIX_fbconfig 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern int glXGetFBConfigAttribSGIX (X11_Display *, GLXFBConfigSGIX, int, int *); -extern GLXFBConfigSGIX * glXChooseFBConfigSGIX (X11_Display *, int, int *, int *); -extern GLXPixmap glXCreateGLXPixmapWithConfigSGIX (X11_Display *, GLXFBConfigSGIX, Pixmap); -extern GLXContext glXCreateContextWithConfigSGIX (X11_Display *, GLXFBConfigSGIX, int, GLXContext, Bool); -extern XVisualInfo * glXGetVisualFromFBConfigSGIX (X11_Display *, GLXFBConfigSGIX); -extern GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX (X11_Display *, XVisualInfo *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef int (* PFNGLXGETFBCONFIGATTRIBSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, int attribute, int *value); -typedef GLXFBConfigSGIX * (* PFNGLXCHOOSEFBCONFIGSGIXPROC) (X11_Display *dpy, int screen, int *attrib_list, int *nelements); -typedef GLXPixmap (* PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap); -typedef GLXContext (* PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct); -typedef XVisualInfo * (* PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config); -typedef GLXFBConfigSGIX (* PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (X11_Display *dpy, XVisualInfo *vis); -#endif +#ifndef GLX_INTEL_swap_event +#define GLX_INTEL_swap_event 1 +#define GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK 0x04000000 +#define GLX_EXCHANGE_COMPLETE_INTEL 0x8180 +#define GLX_COPY_COMPLETE_INTEL 0x8181 +#define GLX_FLIP_COMPLETE_INTEL 0x8182 +#endif /* GLX_INTEL_swap_event */ -#ifndef GLX_SGIX_pbuffer -#define GLX_SGIX_pbuffer 1 +#ifndef GLX_MESA_agp_offset +#define GLX_MESA_agp_offset 1 +typedef unsigned int ( *PFNGLXGETAGPOFFSETMESAPROC) (const void *pointer); #ifdef GLX_GLXEXT_PROTOTYPES -extern GLXPbufferSGIX glXCreateGLXPbufferSGIX (X11_Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *); -extern void glXDestroyGLXPbufferSGIX (X11_Display *, GLXPbufferSGIX); -extern int glXQueryGLXPbufferSGIX (X11_Display *, GLXPbufferSGIX, int, unsigned int *); -extern void glXSelectEventSGIX (X11_Display *, GLXDrawable, unsigned long); -extern void glXGetSelectedEventSGIX (X11_Display *, GLXDrawable, unsigned long *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef GLXPbufferSGIX (* PFNGLXCREATEGLXPBUFFERSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list); -typedef void (* PFNGLXDESTROYGLXPBUFFERSGIXPROC) (X11_Display *dpy, GLXPbufferSGIX pbuf); -typedef int (* PFNGLXQUERYGLXPBUFFERSGIXPROC) (X11_Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value); -typedef void (* PFNGLXSELECTEVENTSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, unsigned long mask); -typedef void (* PFNGLXGETSELECTEDEVENTSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, unsigned long *mask); -#endif - -#ifndef GLX_SGI_cushion -#define GLX_SGI_cushion 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern void glXCushionSGI (X11_Display *, X11_Window, float); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef void (* PFNGLXCUSHIONSGIPROC) (X11_Display *dpy, X11_Window window, float cushion); -#endif - -#ifndef GLX_SGIX_video_resize -#define GLX_SGIX_video_resize 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern int glXBindChannelToWindowSGIX (X11_Display *, int, int, X11_Window); -extern int glXChannelRectSGIX (X11_Display *, int, int, int, int, int, int); -extern int glXQueryChannelRectSGIX (X11_Display *, int, int, int *, int *, int *, int *); -extern int glXQueryChannelDeltasSGIX (X11_Display *, int, int, int *, int *, int *, int *); -extern int glXChannelRectSyncSGIX (X11_Display *, int, int, GLenum); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef int (* PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (X11_Display *display, int screen, int channel, X11_Window window); -typedef int (* PFNGLXCHANNELRECTSGIXPROC) (X11_Display *display, int screen, int channel, int x, int y, int w, int h); -typedef int (* PFNGLXQUERYCHANNELRECTSGIXPROC) (X11_Display *display, int screen, int channel, int *dx, int *dy, int *dw, int *dh); -typedef int (* PFNGLXQUERYCHANNELDELTASSGIXPROC) (X11_Display *display, int screen, int channel, int *x, int *y, int *w, int *h); -typedef int (* PFNGLXCHANNELRECTSYNCSGIXPROC) (X11_Display *display, int screen, int channel, GLenum synctype); -#endif - -#ifndef GLX_SGIX_dmbuffer -#define GLX_SGIX_dmbuffer 1 -#ifdef _DM_BUFFER_H_ -#ifdef GLX_GLXEXT_PROTOTYPES -extern Bool glXAssociateDMPbufferSGIX (X11_Display *, GLXPbufferSGIX, DMparams *, DMbuffer); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef Bool (* PFNGLXASSOCIATEDMPBUFFERSGIXPROC) (X11_Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer); -#endif - -#endif /* _DM_BUFFER_H_ */ -#ifndef GLX_SGIX_swap_group -#define GLX_SGIX_swap_group 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern void glXJoinSwapGroupSGIX (X11_Display *, GLXDrawable, GLXDrawable); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef void (* PFNGLXJOINSWAPGROUPSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, GLXDrawable member); -#endif - -#ifndef GLX_SGIX_swap_barrier -#define GLX_SGIX_swap_barrier 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern void glXBindSwapBarrierSGIX (X11_Display *, GLXDrawable, int); -extern Bool glXQueryMaxSwapBarriersSGIX (X11_Display *, int, int *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef void (* PFNGLXBINDSWAPBARRIERSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, int barrier); -typedef Bool (* PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (X11_Display *dpy, int screen, int *max); -#endif - -#ifndef GLX_SUN_get_transparent_index -#define GLX_SUN_get_transparent_index 1 -#ifdef GLX_GLXEXT_PROTOTYPES -extern Status glXGetTransparentIndexSUN (X11_Display *, X11_Window, X11_Window, long *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef Status (* PFNGLXGETTRANSPARENTINDEXSUNPROC) (X11_Display *dpy, X11_Window overlay, X11_Window underlay, long *pTransparentIndex); +unsigned int glXGetAGPOffsetMESA (const void *pointer); #endif +#endif /* GLX_MESA_agp_offset */ #ifndef GLX_MESA_copy_sub_buffer #define GLX_MESA_copy_sub_buffer 1 +typedef void ( *PFNGLXCOPYSUBBUFFERMESAPROC) (X11_Display *dpy, GLXDrawable drawable, int x, int y, int width, int height); #ifdef GLX_GLXEXT_PROTOTYPES -extern void glXCopySubBufferMESA (X11_Display *, GLXDrawable, int, int, int, int); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef void (* PFNGLXCOPYSUBBUFFERMESAPROC) (X11_Display *dpy, GLXDrawable drawable, int x, int y, int width, int height); +void glXCopySubBufferMESA (X11_Display *dpy, GLXDrawable drawable, int x, int y, int width, int height); #endif +#endif /* GLX_MESA_copy_sub_buffer */ #ifndef GLX_MESA_pixmap_colormap #define GLX_MESA_pixmap_colormap 1 +typedef GLXPixmap ( *PFNGLXCREATEGLXPIXMAPMESAPROC) (X11_Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); #ifdef GLX_GLXEXT_PROTOTYPES -extern GLXPixmap glXCreateGLXPixmapMESA (X11_Display *, XVisualInfo *, Pixmap, Colormap); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef GLXPixmap (* PFNGLXCREATEGLXPIXMAPMESAPROC) (X11_Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); +GLXPixmap glXCreateGLXPixmapMESA (X11_Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); #endif +#endif /* GLX_MESA_pixmap_colormap */ + +#ifndef GLX_MESA_query_renderer +#define GLX_MESA_query_renderer 1 +#define GLX_RENDERER_VENDOR_ID_MESA 0x8183 +#define GLX_RENDERER_DEVICE_ID_MESA 0x8184 +#define GLX_RENDERER_VERSION_MESA 0x8185 +#define GLX_RENDERER_ACCELERATED_MESA 0x8186 +#define GLX_RENDERER_VIDEO_MEMORY_MESA 0x8187 +#define GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA 0x8188 +#define GLX_RENDERER_PREFERRED_PROFILE_MESA 0x8189 +#define GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA 0x818A +#define GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA 0x818B +#define GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA 0x818C +#define GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA 0x818D +#define GLX_RENDERER_ID_MESA 0x818E +typedef Bool ( *PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC) (int attribute, unsigned int *value); +typedef const char *( *PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC) (int attribute); +typedef Bool ( *PFNGLXQUERYRENDERERINTEGERMESAPROC) (X11_Display *dpy, int screen, int renderer, int attribute, unsigned int *value); +typedef const char *( *PFNGLXQUERYRENDERERSTRINGMESAPROC) (X11_Display *dpy, int screen, int renderer, int attribute); +#ifdef GLX_GLXEXT_PROTOTYPES +Bool glXQueryCurrentRendererIntegerMESA (int attribute, unsigned int *value); +const char *glXQueryCurrentRendererStringMESA (int attribute); +Bool glXQueryRendererIntegerMESA (X11_Display *dpy, int screen, int renderer, int attribute, unsigned int *value); +const char *glXQueryRendererStringMESA (X11_Display *dpy, int screen, int renderer, int attribute); +#endif +#endif /* GLX_MESA_query_renderer */ #ifndef GLX_MESA_release_buffers #define GLX_MESA_release_buffers 1 +typedef Bool ( *PFNGLXRELEASEBUFFERSMESAPROC) (X11_Display *dpy, GLXDrawable drawable); #ifdef GLX_GLXEXT_PROTOTYPES -extern Bool glXReleaseBuffersMESA (X11_Display *, GLXDrawable); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef Bool (* PFNGLXRELEASEBUFFERSMESAPROC) (X11_Display *dpy, GLXDrawable drawable); +Bool glXReleaseBuffersMESA (X11_Display *dpy, GLXDrawable drawable); #endif +#endif /* GLX_MESA_release_buffers */ #ifndef GLX_MESA_set_3dfx_mode #define GLX_MESA_set_3dfx_mode 1 +#define GLX_3DFX_WINDOW_MODE_MESA 0x1 +#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 +typedef Bool ( *PFNGLXSET3DFXMODEMESAPROC) (int mode); #ifdef GLX_GLXEXT_PROTOTYPES -extern Bool glXSet3DfxModeMESA (int); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef Bool (* PFNGLXSET3DFXMODEMESAPROC) (int mode); +Bool glXSet3DfxModeMESA (int mode); #endif +#endif /* GLX_MESA_set_3dfx_mode */ -#ifndef GLX_SGIX_visual_select_group -#define GLX_SGIX_visual_select_group 1 +#ifndef GLX_NV_copy_image +#define GLX_NV_copy_image 1 +typedef void ( *PFNGLXCOPYIMAGESUBDATANVPROC) (X11_Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); +#ifdef GLX_GLXEXT_PROTOTYPES +void glXCopyImageSubDataNV (X11_Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); #endif +#endif /* GLX_NV_copy_image */ + +#ifndef GLX_NV_delay_before_swap +#define GLX_NV_delay_before_swap 1 +typedef Bool ( *PFNGLXDELAYBEFORESWAPNVPROC) (X11_Display *dpy, GLXDrawable drawable, GLfloat seconds); +#ifdef GLX_GLXEXT_PROTOTYPES +Bool glXDelayBeforeSwapNV (X11_Display *dpy, GLXDrawable drawable, GLfloat seconds); +#endif +#endif /* GLX_NV_delay_before_swap */ + +#ifndef GLX_NV_float_buffer +#define GLX_NV_float_buffer 1 +#define GLX_FLOAT_COMPONENTS_NV 0x20B0 +#endif /* GLX_NV_float_buffer */ + +#ifndef GLX_NV_multisample_coverage +#define GLX_NV_multisample_coverage 1 +#define GLX_COVERAGE_SAMPLES_NV 100001 +#define GLX_COLOR_SAMPLES_NV 0x20B3 +#endif /* GLX_NV_multisample_coverage */ + +#ifndef GLX_NV_present_video +#define GLX_NV_present_video 1 +#define GLX_NUM_VIDEO_SLOTS_NV 0x20F0 +typedef unsigned int *( *PFNGLXENUMERATEVIDEODEVICESNVPROC) (X11_Display *dpy, int screen, int *nelements); +typedef int ( *PFNGLXBINDVIDEODEVICENVPROC) (X11_Display *dpy, unsigned int video_slot, unsigned int video_device, const int *attrib_list); +#ifdef GLX_GLXEXT_PROTOTYPES +unsigned int *glXEnumerateVideoDevicesNV (X11_Display *dpy, int screen, int *nelements); +int glXBindVideoDeviceNV (X11_Display *dpy, unsigned int video_slot, unsigned int video_device, const int *attrib_list); +#endif +#endif /* GLX_NV_present_video */ + +#ifndef GLX_NV_swap_group +#define GLX_NV_swap_group 1 +typedef Bool ( *PFNGLXJOINSWAPGROUPNVPROC) (X11_Display *dpy, GLXDrawable drawable, GLuint group); +typedef Bool ( *PFNGLXBINDSWAPBARRIERNVPROC) (X11_Display *dpy, GLuint group, GLuint barrier); +typedef Bool ( *PFNGLXQUERYSWAPGROUPNVPROC) (X11_Display *dpy, GLXDrawable drawable, GLuint *group, GLuint *barrier); +typedef Bool ( *PFNGLXQUERYMAXSWAPGROUPSNVPROC) (X11_Display *dpy, int screen, GLuint *maxGroups, GLuint *maxBarriers); +typedef Bool ( *PFNGLXQUERYFRAMECOUNTNVPROC) (X11_Display *dpy, int screen, GLuint *count); +typedef Bool ( *PFNGLXRESETFRAMECOUNTNVPROC) (X11_Display *dpy, int screen); +#ifdef GLX_GLXEXT_PROTOTYPES +Bool glXJoinSwapGroupNV (X11_Display *dpy, GLXDrawable drawable, GLuint group); +Bool glXBindSwapBarrierNV (X11_Display *dpy, GLuint group, GLuint barrier); +Bool glXQuerySwapGroupNV (X11_Display *dpy, GLXDrawable drawable, GLuint *group, GLuint *barrier); +Bool glXQueryMaxSwapGroupsNV (X11_Display *dpy, int screen, GLuint *maxGroups, GLuint *maxBarriers); +Bool glXQueryFrameCountNV (X11_Display *dpy, int screen, GLuint *count); +Bool glXResetFrameCountNV (X11_Display *dpy, int screen); +#endif +#endif /* GLX_NV_swap_group */ + +#ifndef GLX_NV_video_capture +#define GLX_NV_video_capture 1 +typedef XID GLXVideoCaptureDeviceNV; +#define GLX_DEVICE_ID_NV 0x20CD +#define GLX_UNIQUE_ID_NV 0x20CE +#define GLX_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF +typedef int ( *PFNGLXBINDVIDEOCAPTUREDEVICENVPROC) (X11_Display *dpy, unsigned int video_capture_slot, GLXVideoCaptureDeviceNV device); +typedef GLXVideoCaptureDeviceNV *( *PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC) (X11_Display *dpy, int screen, int *nelements); +typedef void ( *PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC) (X11_Display *dpy, GLXVideoCaptureDeviceNV device); +typedef int ( *PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC) (X11_Display *dpy, GLXVideoCaptureDeviceNV device, int attribute, int *value); +typedef void ( *PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC) (X11_Display *dpy, GLXVideoCaptureDeviceNV device); +#ifdef GLX_GLXEXT_PROTOTYPES +int glXBindVideoCaptureDeviceNV (X11_Display *dpy, unsigned int video_capture_slot, GLXVideoCaptureDeviceNV device); +GLXVideoCaptureDeviceNV *glXEnumerateVideoCaptureDevicesNV (X11_Display *dpy, int screen, int *nelements); +void glXLockVideoCaptureDeviceNV (X11_Display *dpy, GLXVideoCaptureDeviceNV device); +int glXQueryVideoCaptureDeviceNV (X11_Display *dpy, GLXVideoCaptureDeviceNV device, int attribute, int *value); +void glXReleaseVideoCaptureDeviceNV (X11_Display *dpy, GLXVideoCaptureDeviceNV device); +#endif +#endif /* GLX_NV_video_capture */ + +#ifndef GLX_NV_video_output +#define GLX_NV_video_output 1 +typedef unsigned int GLXVideoDeviceNV; +#define GLX_VIDEO_OUT_COLOR_NV 0x20C3 +#define GLX_VIDEO_OUT_ALPHA_NV 0x20C4 +#define GLX_VIDEO_OUT_DEPTH_NV 0x20C5 +#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define GLX_VIDEO_OUT_FRAME_NV 0x20C8 +#define GLX_VIDEO_OUT_FIELD_1_NV 0x20C9 +#define GLX_VIDEO_OUT_FIELD_2_NV 0x20CA +#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB +#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC +typedef int ( *PFNGLXGETVIDEODEVICENVPROC) (X11_Display *dpy, int screen, int numVideoDevices, GLXVideoDeviceNV *pVideoDevice); +typedef int ( *PFNGLXRELEASEVIDEODEVICENVPROC) (X11_Display *dpy, int screen, GLXVideoDeviceNV VideoDevice); +typedef int ( *PFNGLXBINDVIDEOIMAGENVPROC) (X11_Display *dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer); +typedef int ( *PFNGLXRELEASEVIDEOIMAGENVPROC) (X11_Display *dpy, GLXPbuffer pbuf); +typedef int ( *PFNGLXSENDPBUFFERTOVIDEONVPROC) (X11_Display *dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock); +typedef int ( *PFNGLXGETVIDEOINFONVPROC) (X11_Display *dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +#ifdef GLX_GLXEXT_PROTOTYPES +int glXGetVideoDeviceNV (X11_Display *dpy, int screen, int numVideoDevices, GLXVideoDeviceNV *pVideoDevice); +int glXReleaseVideoDeviceNV (X11_Display *dpy, int screen, GLXVideoDeviceNV VideoDevice); +int glXBindVideoImageNV (X11_Display *dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer); +int glXReleaseVideoImageNV (X11_Display *dpy, GLXPbuffer pbuf); +int glXSendPbufferToVideoNV (X11_Display *dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock); +int glXGetVideoInfoNV (X11_Display *dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +#endif +#endif /* GLX_NV_video_output */ #ifndef GLX_OML_swap_method #define GLX_OML_swap_method 1 -#endif +#define GLX_SWAP_METHOD_OML 0x8060 +#define GLX_SWAP_EXCHANGE_OML 0x8061 +#define GLX_SWAP_COPY_OML 0x8062 +#define GLX_SWAP_UNDEFINED_OML 0x8063 +#endif /* GLX_OML_swap_method */ #ifndef GLX_OML_sync_control #define GLX_OML_sync_control 1 -#if defined(__STDC_VERSION__) -#if __STDC_VERSION__ >= 199901L -/* Include ISO C99 integer types for OML_sync_control; need a better test */ +#ifndef GLEXT_64_TYPES_DEFINED +/* This code block is duplicated in glext.h, so must be protected */ +#define GLEXT_64_TYPES_DEFINED +/* Define int32_t, int64_t, and uint64_t types for UST/MSC */ +/* (as used in the GLX_OML_sync_control extension). */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +#elif defined(__sun__) || defined(__digital__) +#include +#if defined(__STDC__) +#if defined(__arch64__) || defined(_LP64) +typedef long int int64_t; +typedef unsigned long int uint64_t; +#else +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#endif /* __arch64__ */ +#endif /* __STDC__ */ +#elif defined( __VMS ) || defined(__sgi) +#include +#elif defined(__SCO__) || defined(__USLC__) +#include +#elif defined(__UNIXOS2__) || defined(__SOL64__) +typedef long int int32_t; +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#elif defined(_WIN32) && defined(__GNUC__) +#include +#elif defined(_WIN32) +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +/* Fallback if nothing above works */ #include - -#ifdef GLX_GLXEXT_PROTOTYPES -extern Bool glXGetSyncValuesOML (X11_Display *, GLXDrawable, int64_t *, int64_t *, int64_t *); -extern Bool glXGetMscRateOML (X11_Display *, GLXDrawable, int32_t *, int32_t *); -extern int64_t glXSwapBuffersMscOML (X11_Display *, GLXDrawable, int64_t, int64_t, int64_t); -extern Bool glXWaitForMscOML (X11_Display *, GLXDrawable, int64_t, int64_t, int64_t, int64_t *, int64_t *, int64_t *); -extern Bool glXWaitForSbcOML (X11_Display *, GLXDrawable, int64_t, int64_t *, int64_t *, int64_t *); -#endif /* GLX_GLXEXT_PROTOTYPES */ -typedef Bool (* PFNGLXGETSYNCVALUESOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t *ust, int64_t *msc, int64_t *sbc); -typedef Bool (* PFNGLXGETMSCRATEOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator); -typedef int64_t (* PFNGLXSWAPBUFFERSMSCOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder); -typedef Bool (* PFNGLXWAITFORMSCOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc); -typedef Bool (* PFNGLXWAITFORSBCOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t target_sbc, int64_t *ust, int64_t *msc, int64_t *sbc); #endif +#endif +typedef Bool ( *PFNGLXGETSYNCVALUESOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t *ust, int64_t *msc, int64_t *sbc); +typedef Bool ( *PFNGLXGETMSCRATEOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator); +typedef int64_t ( *PFNGLXSWAPBUFFERSMSCOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder); +typedef Bool ( *PFNGLXWAITFORMSCOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc); +typedef Bool ( *PFNGLXWAITFORSBCOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t target_sbc, int64_t *ust, int64_t *msc, int64_t *sbc); +#ifdef GLX_GLXEXT_PROTOTYPES +Bool glXGetSyncValuesOML (X11_Display *dpy, GLXDrawable drawable, int64_t *ust, int64_t *msc, int64_t *sbc); +Bool glXGetMscRateOML (X11_Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator); +int64_t glXSwapBuffersMscOML (X11_Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder); +Bool glXWaitForMscOML (X11_Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc); +Bool glXWaitForSbcOML (X11_Display *dpy, GLXDrawable drawable, int64_t target_sbc, int64_t *ust, int64_t *msc, int64_t *sbc); +#endif +#endif /* GLX_OML_sync_control */ -#endif /* C99 version test */ -#endif /* STDC test */ +#ifndef GLX_SGIS_blended_overlay +#define GLX_SGIS_blended_overlay 1 +#define GLX_BLENDED_RGBA_SGIS 0x8025 +#endif /* GLX_SGIS_blended_overlay */ + +#ifndef GLX_SGIS_multisample +#define GLX_SGIS_multisample 1 +#define GLX_SAMPLE_BUFFERS_SGIS 100000 +#define GLX_SAMPLES_SGIS 100001 +#endif /* GLX_SGIS_multisample */ + +#ifndef GLX_SGIS_shared_multisample +#define GLX_SGIS_shared_multisample 1 +#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 +#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 +#endif /* GLX_SGIS_shared_multisample */ + +#ifndef GLX_SGIX_dmbuffer +#define GLX_SGIX_dmbuffer 1 +typedef XID GLXPbufferSGIX; +#ifdef _DM_BUFFER_H_ +#define GLX_DIGITAL_MEDIA_PBUFFER_SGIX 0x8024 +typedef Bool ( *PFNGLXASSOCIATEDMPBUFFERSGIXPROC) (X11_Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer); +#ifdef GLX_GLXEXT_PROTOTYPES +Bool glXAssociateDMPbufferSGIX (X11_Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer); +#endif +#endif /* _DM_BUFFER_H_ */ +#endif /* GLX_SGIX_dmbuffer */ + +#ifndef GLX_SGIX_fbconfig +#define GLX_SGIX_fbconfig 1 +typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; +#define GLX_WINDOW_BIT_SGIX 0x00000001 +#define GLX_PIXMAP_BIT_SGIX 0x00000002 +#define GLX_RGBA_BIT_SGIX 0x00000001 +#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 +#define GLX_DRAWABLE_TYPE_SGIX 0x8010 +#define GLX_RENDER_TYPE_SGIX 0x8011 +#define GLX_X_RENDERABLE_SGIX 0x8012 +#define GLX_FBCONFIG_ID_SGIX 0x8013 +#define GLX_RGBA_TYPE_SGIX 0x8014 +#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 +typedef int ( *PFNGLXGETFBCONFIGATTRIBSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, int attribute, int *value); +typedef GLXFBConfigSGIX *( *PFNGLXCHOOSEFBCONFIGSGIXPROC) (X11_Display *dpy, int screen, int *attrib_list, int *nelements); +typedef GLXPixmap ( *PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap); +typedef GLXContext ( *PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct); +typedef XVisualInfo *( *PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config); +typedef GLXFBConfigSGIX ( *PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (X11_Display *dpy, XVisualInfo *vis); +#ifdef GLX_GLXEXT_PROTOTYPES +int glXGetFBConfigAttribSGIX (X11_Display *dpy, GLXFBConfigSGIX config, int attribute, int *value); +GLXFBConfigSGIX *glXChooseFBConfigSGIX (X11_Display *dpy, int screen, int *attrib_list, int *nelements); +GLXPixmap glXCreateGLXPixmapWithConfigSGIX (X11_Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap); +GLXContext glXCreateContextWithConfigSGIX (X11_Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct); +XVisualInfo *glXGetVisualFromFBConfigSGIX (X11_Display *dpy, GLXFBConfigSGIX config); +GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX (X11_Display *dpy, XVisualInfo *vis); +#endif +#endif /* GLX_SGIX_fbconfig */ + +#ifndef GLX_SGIX_hyperpipe +#define GLX_SGIX_hyperpipe 1 +typedef struct { + char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */ + int networkId; +} GLXHyperpipeNetworkSGIX; +typedef struct { + char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */ + int channel; + unsigned int participationType; + int timeSlice; +} GLXHyperpipeConfigSGIX; +typedef struct { + char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */ + int srcXOrigin, srcYOrigin, srcWidth, srcHeight; + int destXOrigin, destYOrigin, destWidth, destHeight; +} GLXPipeRect; +typedef struct { + char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */ + int XOrigin, YOrigin, maxHeight, maxWidth; +} GLXPipeRectLimits; +#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80 +#define GLX_BAD_HYPERPIPE_CONFIG_SGIX 91 +#define GLX_BAD_HYPERPIPE_SGIX 92 +#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001 +#define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002 +#define GLX_PIPE_RECT_SGIX 0x00000001 +#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002 +#define GLX_HYPERPIPE_STEREO_SGIX 0x00000003 +#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004 +#define GLX_HYPERPIPE_ID_SGIX 0x8030 +typedef GLXHyperpipeNetworkSGIX *( *PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (X11_Display *dpy, int *npipes); +typedef int ( *PFNGLXHYPERPIPECONFIGSGIXPROC) (X11_Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId); +typedef GLXHyperpipeConfigSGIX *( *PFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (X11_Display *dpy, int hpId, int *npipes); +typedef int ( *PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (X11_Display *dpy, int hpId); +typedef int ( *PFNGLXBINDHYPERPIPESGIXPROC) (X11_Display *dpy, int hpId); +typedef int ( *PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (X11_Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList); +typedef int ( *PFNGLXHYPERPIPEATTRIBSGIXPROC) (X11_Display *dpy, int timeSlice, int attrib, int size, void *attribList); +typedef int ( *PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (X11_Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList); +#ifdef GLX_GLXEXT_PROTOTYPES +GLXHyperpipeNetworkSGIX *glXQueryHyperpipeNetworkSGIX (X11_Display *dpy, int *npipes); +int glXHyperpipeConfigSGIX (X11_Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId); +GLXHyperpipeConfigSGIX *glXQueryHyperpipeConfigSGIX (X11_Display *dpy, int hpId, int *npipes); +int glXDestroyHyperpipeConfigSGIX (X11_Display *dpy, int hpId); +int glXBindHyperpipeSGIX (X11_Display *dpy, int hpId); +int glXQueryHyperpipeBestAttribSGIX (X11_Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList); +int glXHyperpipeAttribSGIX (X11_Display *dpy, int timeSlice, int attrib, int size, void *attribList); +int glXQueryHyperpipeAttribSGIX (X11_Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList); +#endif +#endif /* GLX_SGIX_hyperpipe */ + +#ifndef GLX_SGIX_pbuffer +#define GLX_SGIX_pbuffer 1 +#define GLX_PBUFFER_BIT_SGIX 0x00000004 +#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 +#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 +#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 +#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 +#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 +#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 +#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 +#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 +#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 +#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 +#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A +#define GLX_PRESERVED_CONTENTS_SGIX 0x801B +#define GLX_LARGEST_PBUFFER_SGIX 0x801C +#define GLX_WIDTH_SGIX 0x801D +#define GLX_HEIGHT_SGIX 0x801E +#define GLX_EVENT_MASK_SGIX 0x801F +#define GLX_DAMAGED_SGIX 0x8020 +#define GLX_SAVED_SGIX 0x8021 +#define GLX_WINDOW_SGIX 0x8022 +#define GLX_PBUFFER_SGIX 0x8023 +typedef GLXPbufferSGIX ( *PFNGLXCREATEGLXPBUFFERSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list); +typedef void ( *PFNGLXDESTROYGLXPBUFFERSGIXPROC) (X11_Display *dpy, GLXPbufferSGIX pbuf); +typedef int ( *PFNGLXQUERYGLXPBUFFERSGIXPROC) (X11_Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value); +typedef void ( *PFNGLXSELECTEVENTSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, unsigned long mask); +typedef void ( *PFNGLXGETSELECTEDEVENTSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, unsigned long *mask); +#ifdef GLX_GLXEXT_PROTOTYPES +GLXPbufferSGIX glXCreateGLXPbufferSGIX (X11_Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list); +void glXDestroyGLXPbufferSGIX (X11_Display *dpy, GLXPbufferSGIX pbuf); +int glXQueryGLXPbufferSGIX (X11_Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value); +void glXSelectEventSGIX (X11_Display *dpy, GLXDrawable drawable, unsigned long mask); +void glXGetSelectedEventSGIX (X11_Display *dpy, GLXDrawable drawable, unsigned long *mask); +#endif +#endif /* GLX_SGIX_pbuffer */ + +#ifndef GLX_SGIX_swap_barrier +#define GLX_SGIX_swap_barrier 1 +typedef void ( *PFNGLXBINDSWAPBARRIERSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, int barrier); +typedef Bool ( *PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (X11_Display *dpy, int screen, int *max); +#ifdef GLX_GLXEXT_PROTOTYPES +void glXBindSwapBarrierSGIX (X11_Display *dpy, GLXDrawable drawable, int barrier); +Bool glXQueryMaxSwapBarriersSGIX (X11_Display *dpy, int screen, int *max); +#endif +#endif /* GLX_SGIX_swap_barrier */ + +#ifndef GLX_SGIX_swap_group +#define GLX_SGIX_swap_group 1 +typedef void ( *PFNGLXJOINSWAPGROUPSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, GLXDrawable member); +#ifdef GLX_GLXEXT_PROTOTYPES +void glXJoinSwapGroupSGIX (X11_Display *dpy, GLXDrawable drawable, GLXDrawable member); +#endif +#endif /* GLX_SGIX_swap_group */ + +#ifndef GLX_SGIX_video_resize +#define GLX_SGIX_video_resize 1 +#define GLX_SYNC_FRAME_SGIX 0x00000000 +#define GLX_SYNC_SWAP_SGIX 0x00000001 +typedef int ( *PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (X11_Display *display, int screen, int channel, X11_Window window); +typedef int ( *PFNGLXCHANNELRECTSGIXPROC) (X11_Display *display, int screen, int channel, int x, int y, int w, int h); +typedef int ( *PFNGLXQUERYCHANNELRECTSGIXPROC) (X11_Display *display, int screen, int channel, int *dx, int *dy, int *dw, int *dh); +typedef int ( *PFNGLXQUERYCHANNELDELTASSGIXPROC) (X11_Display *display, int screen, int channel, int *x, int *y, int *w, int *h); +typedef int ( *PFNGLXCHANNELRECTSYNCSGIXPROC) (X11_Display *display, int screen, int channel, GLenum synctype); +#ifdef GLX_GLXEXT_PROTOTYPES +int glXBindChannelToWindowSGIX (X11_Display *display, int screen, int channel, X11_Window window); +int glXChannelRectSGIX (X11_Display *display, int screen, int channel, int x, int y, int w, int h); +int glXQueryChannelRectSGIX (X11_Display *display, int screen, int channel, int *dx, int *dy, int *dw, int *dh); +int glXQueryChannelDeltasSGIX (X11_Display *display, int screen, int channel, int *x, int *y, int *w, int *h); +int glXChannelRectSyncSGIX (X11_Display *display, int screen, int channel, GLenum synctype); +#endif +#endif /* GLX_SGIX_video_resize */ + +#ifndef GLX_SGIX_video_source +#define GLX_SGIX_video_source 1 +typedef XID GLXVideoSourceSGIX; +#ifdef _VL_H +typedef GLXVideoSourceSGIX ( *PFNGLXCREATEGLXVIDEOSOURCESGIXPROC) (X11_Display *display, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode); +typedef void ( *PFNGLXDESTROYGLXVIDEOSOURCESGIXPROC) (X11_Display *dpy, GLXVideoSourceSGIX glxvideosource); +#ifdef GLX_GLXEXT_PROTOTYPES +GLXVideoSourceSGIX glXCreateGLXVideoSourceSGIX (X11_Display *display, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode); +void glXDestroyGLXVideoSourceSGIX (X11_Display *dpy, GLXVideoSourceSGIX glxvideosource); +#endif +#endif /* _VL_H */ +#endif /* GLX_SGIX_video_source */ + +#ifndef GLX_SGIX_visual_select_group +#define GLX_SGIX_visual_select_group 1 +#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028 +#endif /* GLX_SGIX_visual_select_group */ + +#ifndef GLX_SGI_cushion +#define GLX_SGI_cushion 1 +typedef void ( *PFNGLXCUSHIONSGIPROC) (X11_Display *dpy, X11_Window window, float cushion); +#ifdef GLX_GLXEXT_PROTOTYPES +void glXCushionSGI (X11_Display *dpy, X11_Window window, float cushion); +#endif +#endif /* GLX_SGI_cushion */ + +#ifndef GLX_SGI_make_current_read +#define GLX_SGI_make_current_read 1 +typedef Bool ( *PFNGLXMAKECURRENTREADSGIPROC) (X11_Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef GLXDrawable ( *PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void); +#ifdef GLX_GLXEXT_PROTOTYPES +Bool glXMakeCurrentReadSGI (X11_Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +GLXDrawable glXGetCurrentReadDrawableSGI (void); +#endif +#endif /* GLX_SGI_make_current_read */ + +#ifndef GLX_SGI_swap_control +#define GLX_SGI_swap_control 1 +typedef int ( *PFNGLXSWAPINTERVALSGIPROC) (int interval); +#ifdef GLX_GLXEXT_PROTOTYPES +int glXSwapIntervalSGI (int interval); +#endif +#endif /* GLX_SGI_swap_control */ + +#ifndef GLX_SGI_video_sync +#define GLX_SGI_video_sync 1 +typedef int ( *PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int *count); +typedef int ( *PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int *count); +#ifdef GLX_GLXEXT_PROTOTYPES +int glXGetVideoSyncSGI (unsigned int *count); +int glXWaitVideoSyncSGI (int divisor, int remainder, unsigned int *count); +#endif +#endif /* GLX_SGI_video_sync */ + +#ifndef GLX_SUN_get_transparent_index +#define GLX_SUN_get_transparent_index 1 +typedef Status ( *PFNGLXGETTRANSPARENTINDEXSUNPROC) (X11_Display *dpy, X11_Window overlay, X11_Window underlay, long *pTransparentIndex); +#ifdef GLX_GLXEXT_PROTOTYPES +Status glXGetTransparentIndexSUN (X11_Display *dpy, X11_Window overlay, X11_Window underlay, long *pTransparentIndex); +#endif +#endif /* GLX_SUN_get_transparent_index */ #ifdef __cplusplus } diff --git a/panda/src/glxdisplay/posixGraphicsStateGuardian.cxx b/panda/src/glxdisplay/posixGraphicsStateGuardian.cxx index cdba89853d..25ec38afac 100644 --- a/panda/src/glxdisplay/posixGraphicsStateGuardian.cxx +++ b/panda/src/glxdisplay/posixGraphicsStateGuardian.cxx @@ -53,13 +53,11 @@ PosixGraphicsStateGuardian:: // not defined. //////////////////////////////////////////////////////////////////// void *PosixGraphicsStateGuardian:: -do_get_extension_func(const char *prefix, const char *name) { - nassertr(prefix != NULL, NULL); +do_get_extension_func(const char *name) { nassertr(name != NULL, NULL); - string fullname = string(prefix) + string(name); if (glx_get_os_address) { - return get_system_func(fullname.c_str()); + return get_system_func(name); } return NULL; diff --git a/panda/src/glxdisplay/posixGraphicsStateGuardian.h b/panda/src/glxdisplay/posixGraphicsStateGuardian.h index 950844951c..04e4850ea2 100644 --- a/panda/src/glxdisplay/posixGraphicsStateGuardian.h +++ b/panda/src/glxdisplay/posixGraphicsStateGuardian.h @@ -32,7 +32,7 @@ public: ~PosixGraphicsStateGuardian(); protected: - virtual void *do_get_extension_func(const char *prefix, const char *name); + virtual void *do_get_extension_func(const char *name); void *get_system_func(const char *name); private: diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 9295d6475a..c60c75fb95 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -510,6 +510,13 @@ ConfigVariableInt lens_geom_segments "lens; for a normal perspective or orthographic lens, the " "wireframe is not subdivided.")); +ConfigVariableString cg_glsl_version +("cg-glsl-version", "", + PRC_DESC("If this is set, it forces the Cg compiler to generate GLSL " + "code conforming to the given GLSL version when using the " + "glslv, glslf or glslg profiles. Use this when you are having " + "problems with these profiles. Example values are 120 or 150.")); + ConfigureFn(config_gobj) { AnimateVerticesRequest::init_type(); BufferContext::init_type(); diff --git a/panda/src/gobj/config_gobj.h b/panda/src/gobj/config_gobj.h index 3e1192ef48..8c33fa004f 100644 --- a/panda/src/gobj/config_gobj.h +++ b/panda/src/gobj/config_gobj.h @@ -101,6 +101,6 @@ extern EXPCL_PANDA_GOBJ ConfigVariableInt adaptive_lru_max_updates_per_frame; extern EXPCL_PANDA_GOBJ ConfigVariableDouble async_load_delay; extern EXPCL_PANDA_GOBJ ConfigVariableInt lens_geom_segments; +extern EXPCL_PANDA_GOBJ ConfigVariableString cg_glsl_version; + #endif - - diff --git a/panda/src/gobj/geom.I b/panda/src/gobj/geom.I index f34df85a75..acf7b61745 100644 --- a/panda/src/gobj/geom.I +++ b/panda/src/gobj/geom.I @@ -242,6 +242,19 @@ make_points() const { return new_geom; } +//////////////////////////////////////////////////////////////////// +// Function: Geom::make_patches +// Access: Published +// Description: Returns a new Geom with each primitive converted +// into a patch. Calls decompose() first. +//////////////////////////////////////////////////////////////////// +INLINE PT(Geom) Geom:: +make_patches() const { + PT(Geom) new_geom = make_copy(); + new_geom->make_patches_in_place(); + return new_geom; +} + //////////////////////////////////////////////////////////////////// // Function: Geom::get_modified // Access: Published diff --git a/panda/src/gobj/geom.cxx b/panda/src/gobj/geom.cxx index 1a4251e5f6..da20e629b4 100644 --- a/panda/src/gobj/geom.cxx +++ b/panda/src/gobj/geom.cxx @@ -788,6 +788,43 @@ make_points_in_place() { nassertv(all_is_valid); } +//////////////////////////////////////////////////////////////////// +// Function: Geom::make_patches_in_place +// Access: Published +// Description: Replaces the GeomPrimitives within this Geom with +// corresponding GeomPatches. See +// GeomPrimitive::make_patches(). +// +// Don't call this in a downstream thread unless you +// don't mind it blowing away other changes you might +// have recently made in an upstream thread. +//////////////////////////////////////////////////////////////////// +void Geom:: +make_patches_in_place() { + Thread *current_thread = Thread::get_current_thread(); + CDWriter cdata(_cycler, true, current_thread); + +#ifndef NDEBUG + bool all_is_valid = true; +#endif + Primitives::iterator pi; + for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) { + CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->make_patches(); + (*pi) = (GeomPrimitive *)new_prim.p(); + +#ifndef NDEBUG + if (!new_prim->check_valid(cdata->_data.get_read_pointer())) { + all_is_valid = false; + } +#endif + } + + cdata->_modified = Geom::get_next_modified(); + reset_geom_rendering(cdata); + clear_cache_stage(current_thread); + + nassertv(all_is_valid); +} //////////////////////////////////////////////////////////////////// // Function: Geom::copy_primitives_from diff --git a/panda/src/gobj/geom.h b/panda/src/gobj/geom.h index 075c92c765..af0eca41a0 100644 --- a/panda/src/gobj/geom.h +++ b/panda/src/gobj/geom.h @@ -102,6 +102,7 @@ PUBLISHED: INLINE PT(Geom) rotate() const; INLINE PT(Geom) unify(int max_indices, bool preserve_order) const; INLINE PT(Geom) make_points() const; + INLINE PT(Geom) make_patches() const; void decompose_in_place(); void doubleside_in_place(); @@ -109,6 +110,7 @@ PUBLISHED: void rotate_in_place(); void unify_in_place(int max_indices, bool preserve_order); void make_points_in_place(); + void make_patches_in_place(); virtual bool copy_primitives_from(const Geom *other); diff --git a/panda/src/gobj/geomPrimitive.cxx b/panda/src/gobj/geomPrimitive.cxx index 99271ffe4c..86d07499d0 100644 --- a/panda/src/gobj/geomPrimitive.cxx +++ b/panda/src/gobj/geomPrimitive.cxx @@ -991,6 +991,41 @@ make_points() const { return points; } +//////////////////////////////////////////////////////////////////// +// Function: GeomPrimitive::make_patches +// Access: Published +// Description: Decomposes a complex primitive type into a simpler +// primitive type, for instance triangle strips to +// triangles, puts these in a new GeomPatches objectand returns a pointer to the new primitive +// definition. If the decomposition cannot be +// performed, this might return the original object. +// +// This method is useful for application code that wants +// to iterate through the set of triangles on the +// primitive without having to write handlers for each +// possible kind of primitive type. +//////////////////////////////////////////////////////////////////// +CPT(GeomPrimitive) GeomPrimitive:: +make_patches() const { + if (is_exact_type(GeomPatches::get_class_type())) { + return this; + } + + CPT(GeomPrimitive) prim = decompose_impl(); + int num_vertices_per_patch = prim->get_num_vertices_per_primitive(); + + PT(GeomPrimitive) patches = new GeomPatches(num_vertices_per_patch, get_usage_hint()); + + if (prim->is_indexed()) { + patches->set_vertices(prim->get_vertices()); + } else { + patches->set_nonindexed_vertices(prim->get_first_vertex(), + prim->get_num_vertices()); + } + + return patches; +} + //////////////////////////////////////////////////////////////////// // Function: GeomPrimitive::get_num_bytes // Access: Published diff --git a/panda/src/gobj/geomPrimitive.h b/panda/src/gobj/geomPrimitive.h index 655ec5867e..18213be302 100644 --- a/panda/src/gobj/geomPrimitive.h +++ b/panda/src/gobj/geomPrimitive.h @@ -133,6 +133,7 @@ PUBLISHED: CPT(GeomPrimitive) reverse() const; CPT(GeomPrimitive) match_shade_model(ShadeModel shade_model) const; CPT(GeomPrimitive) make_points() const; + CPT(GeomPrimitive) make_patches() const; int get_num_bytes() const; INLINE int get_data_size_bytes() const; @@ -232,14 +233,14 @@ private: // itself from the other's list. typedef pmap Contexts; Contexts _contexts; - + // This is the data that must be cycled between pipeline stages. class EXPCL_PANDA_GOBJ CData : public CycleData { public: INLINE CData(); INLINE CData(const CData ©); ALLOC_DELETED_CHAIN(CData); - + virtual CycleData *make_copy() const; virtual void write_datagram(BamWriter *manager, Datagram &dg) const; virtual int complete_pointers(TypedWritable **plist, BamReader *manager); @@ -247,7 +248,7 @@ private: virtual TypeHandle get_parent_type() const { return GeomPrimitive::get_class_type(); } - + ShadeModel _shade_model; int _first_vertex; int _num_vertices; @@ -258,11 +259,11 @@ private: COWPT(GeomVertexArrayData) _mins; COWPT(GeomVertexArrayData) _maxs; UpdateSeq _modified; - + bool _got_minmax; unsigned int _min_vertex; unsigned int _max_vertex; - + public: static TypeHandle get_class_type() { return _type_handle; @@ -270,7 +271,7 @@ private: static void init_type() { register_type(_type_handle, "GeomPrimitive::CData"); } - + private: static TypeHandle _type_handle; @@ -282,7 +283,7 @@ private: typedef CycleDataWriter CDWriter; typedef CycleDataStageReader CDStageReader; typedef CycleDataStageWriter CDStageWriter; - + private: static PStatCollector _decompose_pcollector; static PStatCollector _doubleside_pcollector; @@ -360,7 +361,7 @@ public: INLINE CPTA_int get_ends() const; INLINE CPT(GeomVertexArrayData) get_mins() const; INLINE CPT(GeomVertexArrayData) get_maxs() const; - + private: CPT(GeomPrimitive) _object; Thread *_current_thread; diff --git a/panda/src/gobj/geomVertexColumn.cxx b/panda/src/gobj/geomVertexColumn.cxx index 0c272ad477..d629121ffc 100644 --- a/panda/src/gobj/geomVertexColumn.cxx +++ b/panda/src/gobj/geomVertexColumn.cxx @@ -1043,75 +1043,69 @@ get_data1i(const unsigned char *pointer) { // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -const int *GeomVertexColumn::Packer:: +const LVecBase2i &GeomVertexColumn::Packer:: get_data2i(const unsigned char *pointer) { switch (_column->get_num_values()) { case 1: - _i[0] = get_data1i(pointer); - _i[1] = 0; - return _i; + _v2i.set(get_data1i(pointer), 0); + return _v2i; default: switch (_column->get_numeric_type()) { case NT_uint8: - _i[0] = pointer[0]; - _i[1] = pointer[1]; - return _i; + _v2i.set(pointer[0], pointer[1]); + return _v2i; case NT_uint16: { const PN_uint16 *pi = (const PN_uint16 *)pointer; - _i[0] = pi[0]; - _i[1] = pi[1]; + _v2i.set(pi[0], pi[1]); } - return _i; + return _v2i; case NT_uint32: { const PN_uint32 *pi = (const PN_uint32 *)pointer; - _i[0] = pi[0]; - _i[1] = pi[1]; + _v2i.set(pi[0], pi[1]); } - return _i; + return _v2i; case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; - _i[0] = GeomVertexData::unpack_abcd_d(dword); - _i[1] = GeomVertexData::unpack_abcd_c(dword); + _v2i.set(GeomVertexData::unpack_abcd_d(dword), + GeomVertexData::unpack_abcd_c(dword)); } - return _i; + return _v2i; case NT_packed_dabc: { PN_uint32 dword = *(const PN_uint32 *)pointer; - _i[0] = GeomVertexData::unpack_abcd_b(dword); - _i[1] = GeomVertexData::unpack_abcd_c(dword); + _v2i.set(GeomVertexData::unpack_abcd_b(dword), + GeomVertexData::unpack_abcd_c(dword)); } - return _i; + return _v2i; case NT_float32: { const PN_float32 *pi = (const PN_float32 *)pointer; - _i[0] = (int)pi[0]; - _i[1] = (int)pi[1]; + _v2i.set((int)pi[0], (int)pi[1]); } - return _i; + return _v2i; case NT_float64: { const PN_float64 *pi = (const PN_float64 *)pointer; - _i[0] = (int)pi[0]; - _i[1] = (int)pi[1]; + _v2i.set((int)pi[0], (int)pi[1]); } - return _i; + return _v2i; case NT_stdfloat: - nassertr(false, _i); + nassertr(false, _v2i); } } - return _i; + return _v2i; } //////////////////////////////////////////////////////////////////// @@ -1119,92 +1113,78 @@ get_data2i(const unsigned char *pointer) { // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -const int *GeomVertexColumn::Packer:: +const LVecBase3i &GeomVertexColumn::Packer:: get_data3i(const unsigned char *pointer) { switch (_column->get_num_values()) { case 1: - _i[0] = get_data1i(pointer); - _i[1] = 0; - _i[2] = 0; - return _i; + _v3i.set(get_data1i(pointer), 0, 0); + return _v3i; case 2: { - const int *i = get_data2i(pointer); - _i[0] = i[0]; - _i[1] = i[1]; - _i[2] = 0; + const LVecBase2i &v2 = get_data2i(pointer); + _v3i.set(v2[0], v2[1], 0); } - return _i; + return _v3i; default: switch (_column->get_numeric_type()) { case NT_uint8: - _i[0] = pointer[0]; - _i[1] = pointer[1]; - _i[2] = pointer[2]; - return _i; - + _v3i.set(pointer[0], pointer[1], 0); + return _v3i; + case NT_uint16: { const PN_uint16 *pi = (const PN_uint16 *)pointer; - _i[0] = pi[0]; - _i[1] = pi[1]; - _i[2] = pi[2]; + _v3i.set(pi[0], pi[1], pi[2]); } - return _i; - + return _v3i; + case NT_uint32: { const PN_uint32 *pi = (const PN_uint32 *)pointer; - _i[0] = pi[0]; - _i[1] = pi[1]; - _i[2] = pi[2]; + _v3i.set(pi[0], pi[1], pi[2]); } - return _i; - + return _v3i; + case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; - _i[0] = GeomVertexData::unpack_abcd_d(dword); - _i[1] = GeomVertexData::unpack_abcd_c(dword); - _i[2] = GeomVertexData::unpack_abcd_b(dword); + _v3i.set(GeomVertexData::unpack_abcd_d(dword), + GeomVertexData::unpack_abcd_c(dword), + GeomVertexData::unpack_abcd_b(dword)); } - return _i; - + return _v3i; + case NT_packed_dabc: { PN_uint32 dword = *(const PN_uint32 *)pointer; - _i[0] = GeomVertexData::unpack_abcd_b(dword); - _i[1] = GeomVertexData::unpack_abcd_c(dword); - _i[2] = GeomVertexData::unpack_abcd_d(dword); + _v3i.set(GeomVertexData::unpack_abcd_b(dword), + GeomVertexData::unpack_abcd_c(dword), + GeomVertexData::unpack_abcd_d(dword)); } - return _i; - + return _v3i; + case NT_float32: { const PN_float32 *pi = (const PN_float32 *)pointer; - _i[0] = (int)pi[0]; - _i[1] = (int)pi[1]; - _i[2] = (int)pi[2]; + _v3i.set((int)pi[0], (int)pi[1], (int)pi[2]); } - return _i; - + return _v3i; + case NT_float64: { const PN_float64 *pi = (const PN_float64 *)pointer; - _i[0] = (int)pi[0]; - _i[1] = (int)pi[1]; - _i[2] = (int)pi[2]; + _v3i.set((int)pi[0], (int)pi[1], (int)pi[2]); } - return _i; + return _v3i; case NT_stdfloat: - nassertr(false, _i); + nassertr(false, _v3i); } } - return _i; + return _v3i; } //////////////////////////////////////////////////////////////////// @@ -1212,111 +1192,87 @@ get_data3i(const unsigned char *pointer) { // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -const int *GeomVertexColumn::Packer:: +const LVecBase4i &GeomVertexColumn::Packer:: get_data4i(const unsigned char *pointer) { switch (_column->get_num_values()) { case 1: - _i[0] = get_data1i(pointer); - _i[1] = 0; - _i[2] = 0; - _i[3] = 0; - return _i; + _v4i.set(get_data1i(pointer), 0, 0, 0); + return _v4i; case 2: { - const int *i = get_data2i(pointer); - _i[0] = i[0]; - _i[1] = i[1]; - _i[2] = 0; - _i[3] = 0; + const LVecBase2i &v2 = get_data2i(pointer); + _v4i.set(v2[0], v2[1], 0, 0); } - return _i; + return _v4i; case 3: { - const int *i = get_data3i(pointer); - _i[0] = i[0]; - _i[1] = i[1]; - _i[2] = i[2]; - _i[3] = 0; + const LVecBase3i &v3 = get_data3i(pointer); + _v4i.set(v3[0], v3[1], v3[2], 0); } - return _i; + return _v4i; default: switch (_column->get_numeric_type()) { case NT_uint8: - _i[0] = pointer[0]; - _i[1] = pointer[1]; - _i[2] = pointer[2]; - _i[3] = pointer[3]; - return _i; + _v4i.set(pointer[0], pointer[1], pointer[2], pointer[3]); + return _v4i; case NT_uint16: { const PN_uint16 *pi = (const PN_uint16 *)pointer; - _i[0] = pi[0]; - _i[1] = pi[1]; - _i[2] = pi[2]; - _i[3] = pi[3]; + _v4i.set(pi[0], pi[1], pi[2], pi[3]); } - return _i; + return _v4i; case NT_uint32: { const PN_uint32 *pi = (const PN_uint32 *)pointer; - _i[0] = pi[0]; - _i[1] = pi[1]; - _i[2] = pi[2]; - _i[3] = pi[3]; + _v4i.set(pi[0], pi[1], pi[2], pi[3]); } - return _i; + return _v4i; case NT_packed_dcba: { PN_uint32 dword = *(const PN_uint32 *)pointer; - _i[0] = GeomVertexData::unpack_abcd_d(dword); - _i[1] = GeomVertexData::unpack_abcd_c(dword); - _i[2] = GeomVertexData::unpack_abcd_b(dword); - _i[3] = GeomVertexData::unpack_abcd_a(dword); + _v4i.set(GeomVertexData::unpack_abcd_d(dword), + GeomVertexData::unpack_abcd_c(dword), + GeomVertexData::unpack_abcd_b(dword), + GeomVertexData::unpack_abcd_a(dword)); } - return _i; + return _v4i; case NT_packed_dabc: { PN_uint32 dword = *(const PN_uint32 *)pointer; - _i[0] = GeomVertexData::unpack_abcd_b(dword); - _i[1] = GeomVertexData::unpack_abcd_c(dword); - _i[2] = GeomVertexData::unpack_abcd_d(dword); - _i[3] = GeomVertexData::unpack_abcd_a(dword); + _v4i.set(GeomVertexData::unpack_abcd_b(dword), + GeomVertexData::unpack_abcd_c(dword), + GeomVertexData::unpack_abcd_d(dword), + GeomVertexData::unpack_abcd_a(dword)); } - return _i; + return _v4i; case NT_float32: { const PN_float32 *pi = (const PN_float32 *)pointer; - _i[0] = (int)pi[0]; - _i[1] = (int)pi[1]; - _i[2] = (int)pi[2]; - _i[3] = (int)pi[3]; + _v4i.set((int)pi[0], (int)pi[1], (int)pi[2], (int)pi[3]); } - return _i; + return _v4i; case NT_float64: { const PN_float64 *pi = (const PN_float64 *)pointer; - _i[0] = (int)pi[0]; - _i[1] = (int)pi[1]; - _i[2] = (int)pi[2]; - _i[3] = (int)pi[3]; + _v4i.set((int)pi[0], (int)pi[1], (int)pi[2], (int)pi[3]); } - return _i; + return _v4i; case NT_stdfloat: - nassertr(false, _i); + nassertr(false, _v4i); } } - return _i; + return _v4i; } //////////////////////////////////////////////////////////////////// @@ -1903,22 +1859,22 @@ set_data4d(unsigned char *pointer, const LVecBase4d &data) { // Description: //////////////////////////////////////////////////////////////////// void GeomVertexColumn::Packer:: -set_data1i(unsigned char *pointer, int a) { +set_data1i(unsigned char *pointer, int data) { switch (_column->get_num_values()) { case 1: switch (_column->get_numeric_type()) { case NT_uint8: - *pointer = a; - nassertv((*pointer) == a); + *pointer = data; + nassertv((*pointer) == data); break; case NT_uint16: - *(PN_uint16 *)pointer = a; - nassertv(*(PN_uint16 *)pointer == a); + *(PN_uint16 *)pointer = data; + nassertv(*(PN_uint16 *)pointer == data); break; case NT_uint32: - *(PN_uint32 *)pointer = a; + *(PN_uint32 *)pointer = data; break; case NT_packed_dcba: @@ -1927,11 +1883,11 @@ set_data1i(unsigned char *pointer, int a) { break; case NT_float32: - *(PN_float32 *)pointer = (float)a; + *(PN_float32 *)pointer = (float)data; break; case NT_float64: - *(PN_float64 *)pointer = (double)a; + *(PN_float64 *)pointer = (double)data; break; case NT_stdfloat: @@ -1940,15 +1896,15 @@ set_data1i(unsigned char *pointer, int a) { break; case 2: - set_data2i(pointer, a, 0); + set_data2i(pointer, LVecBase2i(data, 0)); break; case 3: - set_data3i(pointer, a, 0, 0); + set_data3i(pointer, LVecBase3i(data, 0, 0)); break; default: - set_data4i(pointer, a, 0, 0, 0); + set_data4i(pointer, LVecBase4i(data, 0, 0, 0)); break; } } @@ -1959,32 +1915,32 @@ set_data1i(unsigned char *pointer, int a) { // Description: //////////////////////////////////////////////////////////////////// void GeomVertexColumn::Packer:: -set_data2i(unsigned char *pointer, int a, int b) { +set_data2i(unsigned char *pointer, const LVecBase2i &data) { switch (_column->get_num_values()) { case 1: - set_data1i(pointer, a); + set_data1i(pointer, data[0]); break; case 2: switch (_column->get_numeric_type()) { case NT_uint8: - pointer[0] = a; - pointer[1] = b; + pointer[0] = data[0]; + pointer[1] = data[1]; break; case NT_uint16: { PN_uint16 *pi = (PN_uint16 *)pointer; - pi[0] = a; - pi[1] = b; + pi[0] = data[0]; + pi[1] = data[1]; } break; case NT_uint32: { PN_uint32 *pi = (PN_uint32 *)pointer; - pi[0] = a; - pi[1] = b; + pi[0] = data[0]; + pi[1] = data[1]; } break; @@ -1996,16 +1952,16 @@ set_data2i(unsigned char *pointer, int a, int b) { case NT_float32: { PN_float32 *pi = (PN_float32 *)pointer; - pi[0] = a; - pi[1] = b; + pi[0] = data[0]; + pi[1] = data[1]; } break; case NT_float64: { PN_float64 *pi = (PN_float64 *)pointer; - pi[0] = a; - pi[1] = b; + pi[0] = data[0]; + pi[1] = data[1]; } break; @@ -2015,11 +1971,11 @@ set_data2i(unsigned char *pointer, int a, int b) { break; case 3: - set_data3i(pointer, a, b, 0); + set_data3i(pointer, LVecBase3i(data[0], data[1], 0)); break; default: - set_data4i(pointer, a, b, 0, 0); + set_data4i(pointer, LVecBase4i(data[0], data[1], 0, 0)); break; } } @@ -2030,39 +1986,39 @@ set_data2i(unsigned char *pointer, int a, int b) { // Description: //////////////////////////////////////////////////////////////////// void GeomVertexColumn::Packer:: -set_data3i(unsigned char *pointer, int a, int b, int c) { +set_data3i(unsigned char *pointer, const LVecBase3i &data) { switch (_column->get_num_values()) { case 1: - set_data1i(pointer, a); + set_data1i(pointer, data[0]); break; case 2: - set_data2i(pointer, a, b); + set_data2i(pointer, LVecBase2i(data[0], data[1])); break; case 3: switch (_column->get_numeric_type()) { case NT_uint8: - pointer[0] = a; - pointer[1] = b; - pointer[2] = c; + pointer[0] = data[0]; + pointer[1] = data[1]; + pointer[2] = data[2]; break; case NT_uint16: { PN_uint16 *pi = (PN_uint16 *)pointer; - pi[0] = a; - pi[1] = b; - pi[2] = c; + pi[0] = data[0]; + pi[1] = data[1]; + pi[2] = data[2]; } break; case NT_uint32: { PN_uint32 *pi = (PN_uint32 *)pointer; - pi[0] = a; - pi[1] = b; - pi[2] = c; + pi[0] = data[0]; + pi[1] = data[1]; + pi[2] = data[2]; } break; @@ -2074,18 +2030,18 @@ set_data3i(unsigned char *pointer, int a, int b, int c) { case NT_float32: { PN_float32 *pi = (PN_float32 *)pointer; - pi[0] = a; - pi[1] = b; - pi[2] = c; + pi[0] = data[0]; + pi[1] = data[1]; + pi[2] = data[2]; } break; case NT_float64: { PN_float64 *pi = (PN_float64 *)pointer; - pi[0] = a; - pi[1] = b; - pi[2] = c; + pi[0] = data[0]; + pi[1] = data[1]; + pi[2] = data[2]; } break; @@ -2095,7 +2051,7 @@ set_data3i(unsigned char *pointer, int a, int b, int c) { break; default: - set_data4i(pointer, a, b, c, 0); + set_data4i(pointer, LVecBase4i(data[0], data[1], data[2], 0)); break; } } @@ -2106,74 +2062,74 @@ set_data3i(unsigned char *pointer, int a, int b, int c) { // Description: //////////////////////////////////////////////////////////////////// void GeomVertexColumn::Packer:: -set_data4i(unsigned char *pointer, int a, int b, int c, int d) { +set_data4i(unsigned char *pointer, const LVecBase4i &data) { switch (_column->get_num_values()) { case 1: - set_data1i(pointer, a); + set_data1i(pointer, data[0]); break; case 2: - set_data2i(pointer, a, b); + set_data2i(pointer, LVecBase2i(data[0], data[1])); break; case 3: - set_data3i(pointer, a, b, c); + set_data3i(pointer, LVecBase3i(data[0], data[1], data[2])); break; default: switch (_column->get_numeric_type()) { case NT_uint8: - pointer[0] = a; - pointer[1] = b; - pointer[2] = c; - pointer[3] = d; + pointer[0] = data[0]; + pointer[1] = data[1]; + pointer[2] = data[2]; + pointer[3] = data[3]; break; case NT_uint16: { PN_uint16 *pi = (PN_uint16 *)pointer; - pi[0] = a; - pi[1] = b; - pi[2] = c; - pi[3] = d; + pi[0] = data[0]; + pi[1] = data[1]; + pi[2] = data[2]; + pi[3] = data[3]; } break; case NT_uint32: { PN_uint32 *pi = (PN_uint32 *)pointer; - pi[0] = a; - pi[1] = b; - pi[2] = c; - pi[3] = d; + pi[0] = data[0]; + pi[1] = data[1]; + pi[2] = data[2]; + pi[3] = data[3]; } break; case NT_packed_dcba: - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(d, c, b, a); + *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[2], data[1], data[0]); break; case NT_packed_dabc: - *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(d, a, b, c); + *(PN_uint32 *)pointer = GeomVertexData::pack_abcd(data[3], data[0], data[1], data[2]); break; case NT_float32: { PN_float32 *pi = (PN_float32 *)pointer; - pi[0] = a; - pi[1] = b; - pi[2] = c; - pi[3] = d; + pi[0] = data[0]; + pi[1] = data[1]; + pi[2] = data[2]; + pi[3] = data[3]; } break; case NT_float64: { PN_float64 *pi = (PN_float64 *)pointer; - pi[0] = a; - pi[1] = b; - pi[2] = c; - pi[3] = d; + pi[0] = data[0]; + pi[1] = data[1]; + pi[2] = data[2]; + pi[3] = data[3]; } break; diff --git a/panda/src/gobj/geomVertexColumn.h b/panda/src/gobj/geomVertexColumn.h index 09510a3e89..88384c4909 100644 --- a/panda/src/gobj/geomVertexColumn.h +++ b/panda/src/gobj/geomVertexColumn.h @@ -124,9 +124,9 @@ private: virtual const LVecBase4d &get_data4d(const unsigned char *pointer); virtual int get_data1i(const unsigned char *pointer); - virtual const int *get_data2i(const unsigned char *pointer); - virtual const int *get_data3i(const unsigned char *pointer); - virtual const int *get_data4i(const unsigned char *pointer); + virtual const LVecBase2i &get_data2i(const unsigned char *pointer); + virtual const LVecBase3i &get_data3i(const unsigned char *pointer); + virtual const LVecBase4i &get_data4i(const unsigned char *pointer); virtual void set_data1f(unsigned char *pointer, float data); virtual void set_data2f(unsigned char *pointer, const LVecBase2f &data); @@ -138,10 +138,10 @@ private: virtual void set_data3d(unsigned char *pointer, const LVecBase3d &data); virtual void set_data4d(unsigned char *pointer, const LVecBase4d &data); - virtual void set_data1i(unsigned char *pointer, int a); - virtual void set_data2i(unsigned char *pointer, int a, int b); - virtual void set_data3i(unsigned char *pointer, int a, int b, int c); - virtual void set_data4i(unsigned char *pointer, int a, int b, int c, int d); + virtual void set_data1i(unsigned char *pointer, int data); + virtual void set_data2i(unsigned char *pointer, const LVecBase2i &data); + virtual void set_data3i(unsigned char *pointer, const LVecBase3i &data); + virtual void set_data4i(unsigned char *pointer, const LVecBase4i &data); virtual const char *get_name() const { return "Packer"; @@ -178,7 +178,9 @@ private: LVecBase2d _v2d; LVecBase3d _v3d; LVecBase4d _v4d; - int _i[4]; + LVecBase2i _v2i; + LVecBase3i _v3i; + LVecBase4i _v4i; unsigned int _a, _b, _c, _d; }; diff --git a/panda/src/gobj/geomVertexData.cxx b/panda/src/gobj/geomVertexData.cxx index 69ef264418..08e6fdc200 100644 --- a/panda/src/gobj/geomVertexData.cxx +++ b/panda/src/gobj/geomVertexData.cxx @@ -699,7 +699,7 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, while (!from.is_at_end()) { const TransformBlend &blend = blend_table->get_blend(from.get_data1i()); LVecBase4 weights = LVecBase4::zero(); - int indices[4] = {0, 0, 0, 0}; + LVecBase4i indices(0, 0, 0, 0); nassertv(blend.get_num_transforms() <= 4); for (int i = 0; i < blend.get_num_transforms(); i++) { diff --git a/panda/src/gobj/geomVertexReader.I b/panda/src/gobj/geomVertexReader.I index 4e757a0d2a..1c19429d51 100644 --- a/panda/src/gobj/geomVertexReader.I +++ b/panda/src/gobj/geomVertexReader.I @@ -660,9 +660,9 @@ get_data1i() { // expressed as a 2-component value, and advances the // read row. //////////////////////////////////////////////////////////////////// -INLINE const int *GeomVertexReader:: +INLINE const LVecBase2i &GeomVertexReader:: get_data2i() { - nassertr(has_column(), 0); + nassertr(has_column(), LVecBase2i::zero()); return _packer->get_data2i(inc_pointer()); } @@ -673,9 +673,9 @@ get_data2i() { // expressed as a 3-component value, and advances the // read row. //////////////////////////////////////////////////////////////////// -INLINE const int *GeomVertexReader:: +INLINE const LVecBase3i &GeomVertexReader:: get_data3i() { - nassertr(has_column(), 0); + nassertr(has_column(), LVecBase3i::zero()); return _packer->get_data3i(inc_pointer()); } @@ -686,9 +686,9 @@ get_data3i() { // expressed as a 4-component value, and advances the // read row. //////////////////////////////////////////////////////////////////// -INLINE const int *GeomVertexReader:: +INLINE const LVecBase4i &GeomVertexReader:: get_data4i() { - nassertr(has_column(), 0); + nassertr(has_column(), LVecBase4i::zero()); return _packer->get_data4i(inc_pointer()); } diff --git a/panda/src/gobj/geomVertexReader.h b/panda/src/gobj/geomVertexReader.h index 74d3071cf4..d2f8611dfb 100644 --- a/panda/src/gobj/geomVertexReader.h +++ b/panda/src/gobj/geomVertexReader.h @@ -122,9 +122,9 @@ PUBLISHED: INLINE const LVecBase4 &get_data4(); INLINE int get_data1i(); - INLINE const int *get_data2i(); - INLINE const int *get_data3i(); - INLINE const int *get_data4i(); + INLINE const LVecBase2i &get_data2i(); + INLINE const LVecBase3i &get_data3i(); + INLINE const LVecBase4i &get_data4i(); void output(ostream &out) const; diff --git a/panda/src/gobj/geomVertexWriter.I b/panda/src/gobj/geomVertexWriter.I index 27fdf40206..5c63dc46a9 100644 --- a/panda/src/gobj/geomVertexWriter.I +++ b/panda/src/gobj/geomVertexWriter.I @@ -792,8 +792,7 @@ set_data1i(int data) { //////////////////////////////////////////////////////////////////// INLINE void GeomVertexWriter:: set_data2i(int a, int b) { - nassertv(has_column()); - _packer->set_data2i(inc_pointer(), a, b); + set_data2i(LVecBase2i(a, b)); } //////////////////////////////////////////////////////////////////// @@ -807,7 +806,22 @@ set_data2i(int a, int b) { //////////////////////////////////////////////////////////////////// INLINE void GeomVertexWriter:: set_data2i(const int data[2]) { - set_data2i(data[0], data[1]); + set_data2i(LVecBase2i(data[0], data[1])); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexWriter::set_data2i +// Access: Published +// Description: Sets the write row to a particular 2-component +// value, and advances the write row. +// +// It is an error for the write row to advance past +// the end of data. +//////////////////////////////////////////////////////////////////// +INLINE void GeomVertexWriter:: +set_data2i(const LVecBase2i &data) { + nassertv(has_column()); + _packer->set_data2i(inc_pointer(), data); } //////////////////////////////////////////////////////////////////// @@ -821,8 +835,7 @@ set_data2i(const int data[2]) { //////////////////////////////////////////////////////////////////// INLINE void GeomVertexWriter:: set_data3i(int a, int b, int c) { - nassertv(has_column()); - _packer->set_data3i(inc_pointer(), a, b, c); + set_data3i(LVecBase3i(a, b, c)); } //////////////////////////////////////////////////////////////////// @@ -836,7 +849,22 @@ set_data3i(int a, int b, int c) { //////////////////////////////////////////////////////////////////// INLINE void GeomVertexWriter:: set_data3i(const int data[3]) { - set_data3i(data[0], data[1], data[2]); + set_data3i(LVecBase3i(data[0], data[1], data[2])); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexWriter::set_data3i +// Access: Published +// Description: Sets the write row to a particular 3-component +// value, and advances the write row. +// +// It is an error for the write row to advance past +// the end of data. +//////////////////////////////////////////////////////////////////// +INLINE void GeomVertexWriter:: +set_data3i(const LVecBase3i &data) { + nassertv(has_column()); + _packer->set_data3i(inc_pointer(), data); } //////////////////////////////////////////////////////////////////// @@ -850,8 +878,7 @@ set_data3i(const int data[3]) { //////////////////////////////////////////////////////////////////// INLINE void GeomVertexWriter:: set_data4i(int a, int b, int c, int d) { - nassertv(has_column()); - _packer->set_data4i(inc_pointer(), a, b, c, d); + set_data4i(LVecBase4i(a, b, c, d)); } //////////////////////////////////////////////////////////////////// @@ -865,7 +892,22 @@ set_data4i(int a, int b, int c, int d) { //////////////////////////////////////////////////////////////////// INLINE void GeomVertexWriter:: set_data4i(const int data[4]) { - set_data4i(data[0], data[1], data[2], data[3]); + set_data4i(LVecBase4i(data[0], data[1], data[2], data[3])); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexWriter::set_data4i +// Access: Published +// Description: Sets the write row to a particular 4-component +// value, and advances the write row. +// +// It is an error for the write row to advance past +// the end of data. +//////////////////////////////////////////////////////////////////// +INLINE void GeomVertexWriter:: +set_data4i(const LVecBase4i &data) { + nassertv(has_column()); + _packer->set_data4i(inc_pointer(), data); } //////////////////////////////////////////////////////////////////// @@ -1224,8 +1266,7 @@ add_data1i(int data) { //////////////////////////////////////////////////////////////////// INLINE void GeomVertexWriter:: add_data2i(int a, int b) { - nassertv(has_column()); - _packer->set_data2i(inc_add_pointer(), a, b); + add_data2i(LVecBase2i(a, b)); } //////////////////////////////////////////////////////////////////// @@ -1239,7 +1280,22 @@ add_data2i(int a, int b) { //////////////////////////////////////////////////////////////////// INLINE void GeomVertexWriter:: add_data2i(const int data[2]) { - add_data2i(data[0], data[1]); + add_data2i(LVecBase2i(data[0], data[1])); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexWriter::add_data2i +// Access: Published +// Description: Sets the write row to a particular 2-component +// value, and advances the write row. +// +// If the write row advances past the end of data, +// implicitly adds a new row to the data. +//////////////////////////////////////////////////////////////////// +INLINE void GeomVertexWriter:: +add_data2i(const LVecBase2i &data) { + nassertv(has_column()); + _packer->set_data2i(inc_add_pointer(), data); } //////////////////////////////////////////////////////////////////// @@ -1253,8 +1309,7 @@ add_data2i(const int data[2]) { //////////////////////////////////////////////////////////////////// INLINE void GeomVertexWriter:: add_data3i(int a, int b, int c) { - nassertv(has_column()); - _packer->set_data3i(inc_add_pointer(), a, b, c); + add_data3i(LVecBase3i(a, b, c)); } //////////////////////////////////////////////////////////////////// @@ -1268,7 +1323,22 @@ add_data3i(int a, int b, int c) { //////////////////////////////////////////////////////////////////// INLINE void GeomVertexWriter:: add_data3i(const int data[3]) { - add_data3i(data[0], data[1], data[2]); + add_data3i(LVecBase3i(data[0], data[1], data[2])); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexWriter::add_data3i +// Access: Published +// Description: Sets the write row to a particular 3-component +// value, and advances the write row. +// +// If the write row advances past the end of data, +// implicitly adds a new row to the data. +//////////////////////////////////////////////////////////////////// +INLINE void GeomVertexWriter:: +add_data3i(const LVecBase3i &data) { + nassertv(has_column()); + _packer->set_data3i(inc_add_pointer(), data); } //////////////////////////////////////////////////////////////////// @@ -1282,8 +1352,7 @@ add_data3i(const int data[3]) { //////////////////////////////////////////////////////////////////// INLINE void GeomVertexWriter:: add_data4i(int a, int b, int c, int d) { - nassertv(has_column()); - _packer->set_data4i(inc_add_pointer(), a, b, c, d); + add_data4i(LVecBase4i(a, b, c, d)); } //////////////////////////////////////////////////////////////////// @@ -1297,7 +1366,22 @@ add_data4i(int a, int b, int c, int d) { //////////////////////////////////////////////////////////////////// INLINE void GeomVertexWriter:: add_data4i(const int data[4]) { - add_data4i(data[0], data[1], data[2], data[3]); + add_data4i(LVecBase4i(data[0], data[1], data[2], data[3])); +} + +//////////////////////////////////////////////////////////////////// +// Function: GeomVertexWriter::add_data4i +// Access: Published +// Description: Sets the write row to a particular 4-component +// value, and advances the write row. +// +// If the write row advances past the end of data, +// implicitly adds a new row to the data. +//////////////////////////////////////////////////////////////////// +INLINE void GeomVertexWriter:: +add_data4i(const LVecBase4i &data) { + nassertv(has_column()); + _packer->set_data4i(inc_add_pointer(), data); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/geomVertexWriter.h b/panda/src/gobj/geomVertexWriter.h index 34978847b3..2109353757 100644 --- a/panda/src/gobj/geomVertexWriter.h +++ b/panda/src/gobj/geomVertexWriter.h @@ -143,10 +143,13 @@ PUBLISHED: INLINE void set_data1i(int data); INLINE void set_data2i(int a, int b); INLINE void set_data2i(const int data[2]); + INLINE void set_data2i(const LVecBase2i &data); INLINE void set_data3i(int a, int b, int c); INLINE void set_data3i(const int data[3]); + INLINE void set_data3i(const LVecBase3i &data); INLINE void set_data4i(int a, int b, int c, int d); INLINE void set_data4i(const int data[4]); + INLINE void set_data4i(const LVecBase4i &data); INLINE void add_data1f(float data); INLINE void add_data2f(float x, float y); @@ -175,10 +178,13 @@ PUBLISHED: INLINE void add_data1i(int data); INLINE void add_data2i(int a, int b); INLINE void add_data2i(const int data[2]); + INLINE void add_data2i(const LVecBase2i &data); INLINE void add_data3i(int a, int b, int c); INLINE void add_data3i(const int data[3]); + INLINE void add_data3i(const LVecBase3i &data); INLINE void add_data4i(int a, int b, int c, int d); INLINE void add_data4i(const int data[4]); + INLINE void add_data4i(const LVecBase4i &data); void output(ostream &out) const; diff --git a/panda/src/gobj/shader.I b/panda/src/gobj/shader.I index 9ea0869884..9a84d9b6ef 100755 --- a/panda/src/gobj/shader.I +++ b/panda/src/gobj/shader.I @@ -32,6 +32,15 @@ get_filename(const ShaderType &type) const { case ST_geometry: return _filename->_geometry; break; + case ST_tess_control: + return _text->_tess_control; + break; + case ST_tess_evaluation: + return _text->_tess_evaluation; + break; + case ST_compute: + return _text->_compute; + break; default: return _filename->_shared; } @@ -65,6 +74,9 @@ get_text(const ShaderType &type) const { case ST_tess_evaluation: return _text->_tess_evaluation; break; + case ST_compute: + return _text->_compute; + break; default: return _text->_shared; } @@ -543,6 +555,120 @@ ShaderPtrData(const LMatrix3d &mat) : memcpy(_ptr, mat.get_data(), sizeof(mat(0, 0)) * mat.get_num_components()); } +//////////////////////////////////////////////////////////////////// +// Function: Shader::ShaderPtrData Constructor +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Shader::ShaderPtrData:: +ShaderPtrData(const PTA_int &ptr): + _pta(ptr.v0()), + _ptr(ptr.p()), + _type(SPT_int), + _updated(true), + _size(ptr.size()) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: Shader::ShaderPtrData Constructor +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Shader::ShaderPtrData:: +ShaderPtrData(const PTA_LVecBase4i &ptr): + _pta(ptr.v0()), + _ptr(ptr.p()), + _type(SPT_int), + _updated(true), + _size(ptr.size() * 4) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: Shader::ShaderPtrData Constructor +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Shader::ShaderPtrData:: +ShaderPtrData(const PTA_LVecBase3i &ptr): + _pta(ptr.v0()), + _ptr(ptr.p()), + _type(SPT_int), + _updated(true), + _size(ptr.size() * 3) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: Shader::ShaderPtrData Constructor +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Shader::ShaderPtrData:: +ShaderPtrData(const PTA_LVecBase2i &ptr): + _pta(ptr.v0()), + _ptr(ptr.p()), + _type(SPT_int), + _updated(true), + _size(ptr.size() * 2) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: Shader::ShaderPtrData Constructor +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Shader::ShaderPtrData:: +ShaderPtrData(const LVecBase4i &vec) : + _type(SPT_int), + _updated(true), + _size(4) +{ + PTA_int pta = PTA_int::empty_array(4); + _pta = pta.v0(); + _ptr = pta.p(); + nassertv(sizeof(vec[0]) * vec.get_num_components() == pta.size() * sizeof(pta[0])); + memcpy(_ptr, vec.get_data(), sizeof(vec[0]) * vec.get_num_components()); +} + +//////////////////////////////////////////////////////////////////// +// Function: Shader::ShaderPtrData Constructor +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Shader::ShaderPtrData:: +ShaderPtrData(const LVecBase3i &vec) : + _type(SPT_int), + _updated(true), + _size(3) +{ + PTA_int pta = PTA_int::empty_array(3); + _pta = pta.v0(); + _ptr = pta.p(); + nassertv(sizeof(vec[0]) * vec.get_num_components() == pta.size() * sizeof(pta[0])); + memcpy(_ptr, vec.get_data(), sizeof(vec[0]) * vec.get_num_components()); +} + +//////////////////////////////////////////////////////////////////// +// Function: Shader::ShaderPtrData Constructor +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Shader::ShaderPtrData:: +ShaderPtrData(const LVecBase2i &vec) : + _type(SPT_int), + _updated(true), + _size(2) +{ + PTA_int pta = PTA_int::empty_array(2); + _pta = pta.v0(); + _ptr = pta.p(); + nassertv(sizeof(vec[0]) * vec.get_num_components() == pta.size() * sizeof(pta[0])); + memcpy(_ptr, vec.get_data(), sizeof(vec[0]) * vec.get_num_components()); +} + //////////////////////////////////////////////////////////////////// // Function: Shader::ShaderPtrData::write_datagram // Access: Public @@ -565,6 +691,11 @@ write_datagram(Datagram &dg) const { for (size_t i = 0; i < _size; ++i) { dg.add_float32(data[i]); } + } else if (_type == SPT_int) { + const int *data = (const int *) _ptr; + for (size_t i = 0; i < _size; ++i) { + dg.add_int32(data[i]); + } } } @@ -593,6 +724,14 @@ read_datagram(DatagramIterator &scan) { } _pta = pta.v0(); _ptr = pta.p(); + + } else if (_type == SPT_int) { + PTA_int pta = PTA_int::empty_array(_size); + for (size_t i = 0; i < _size; ++i) { + pta[i] = scan.get_int32(); + } + _pta = pta.v0(); + _ptr = pta.p(); } } @@ -636,14 +775,16 @@ ShaderFile(const string &vertex, //////////////////////////////////////////////////////////////////// INLINE void Shader::ShaderFile:: write_datagram(Datagram &dg) const { - dg.add_bool(_separate); if (_separate) { + dg.add_uint8(6); dg.add_string(_vertex); dg.add_string(_fragment); dg.add_string(_geometry); dg.add_string(_tess_control); dg.add_string(_tess_evaluation); + dg.add_string(_compute); } else { + dg.add_uint8(0); dg.add_string(_shared); } } @@ -655,13 +796,17 @@ write_datagram(Datagram &dg) const { //////////////////////////////////////////////////////////////////// INLINE void Shader::ShaderFile:: read_datagram(DatagramIterator &scan) { - _separate = scan.get_bool(); - if (_separate) { - _vertex = scan.get_string(); - _fragment = scan.get_string(); - _geometry = scan.get_string(); - _tess_control = scan.get_string(); - _tess_evaluation = scan.get_string(); + short count = scan.get_uint8(); + if (count > 0) { + if (count-- > 0) _vertex = scan.get_string(); + if (count-- > 0) _fragment = scan.get_string(); + if (count-- > 0) _geometry = scan.get_string(); + if (count-- > 0) _tess_control = scan.get_string(); + if (count-- > 0) _tess_evaluation = scan.get_string(); + if (count-- > 0) _compute = scan.get_string(); + while (count-- > 0) { + scan.get_string(); + } } else { _shared = scan.get_string(); } diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 675fbca876..1482613b4f 100755 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -20,8 +20,6 @@ #ifdef HAVE_CG #include -#define JCG_PROFILE_GLSLV ((CGprofile)7007) -#define JCG_PROFILE_GLSLF ((CGprofile)7008) #endif TypeHandle Shader::_type_handle; @@ -589,6 +587,7 @@ compile_parameter(const ShaderArgId &arg_id, ShaderVarSpec bind; bind._id = arg_id; bind._append_uv = -1; + bind._integer = false; if (pieces.size() == 2) { if (pieces[1] == "position") { @@ -1428,6 +1427,14 @@ cg_compile_entry_point(const char *entry, const ShaderCaps &caps, ShaderType typ compiler_args[nargs++] = "-po"; compiler_args[nargs++] = "ATI_draw_buffers"; } + + char version_arg[16]; + if (!cg_glsl_version.empty() && cgGetProfileProperty((CGprofile) active, CG_IS_GLSL_PROFILE)) { + snprintf(version_arg, 16, "version=%s", cg_glsl_version.c_str()); + compiler_args[nargs++] = "-po"; + compiler_args[nargs++] = version_arg; + } + compiler_args[nargs] = 0; if ((active != (int)CG_PROFILE_UNKNOWN) && (active != ultimate)) { @@ -2243,6 +2250,34 @@ load(const ShaderLanguage &lang, const Filename &vertex, return result; } +//////////////////////////////////////////////////////////////////// +// Function: Shader::load_compute +// Access: Published, Static +// Description: Loads a compute shader. +//////////////////////////////////////////////////////////////////// +PT(Shader) Shader:: +load_compute(const ShaderLanguage &lang, const Filename &fn) { + PT(ShaderFile) sfile = new ShaderFile(fn); + ShaderTable::const_iterator i = _load_table.find(sfile); + if (i != _load_table.end() && (lang == SL_none || lang == i->second->_language)) { + return i->second; + } + + PT(ShaderFile) sbody = new ShaderFile; + sbody->_separate = true; + VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); + if (!vfs->read_file(fn, sbody->_compute, true)) { + gobj_cat.error() + << "Could not read compute shader file: " << fn << "\n"; + return NULL; + } + + PT(Shader) result = new Shader(sfile, sbody, lang); + result->_loaded = true; + _load_table[sfile] = result; + return result; +} + ////////////////////////////////////////////////////////////////////// // Function: Shader::make // Access: Published, Static @@ -2255,17 +2290,20 @@ make(const string &body, const ShaderLanguage &lang) { if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) { return i->second; } + PT(ShaderFile) sfile = new ShaderFile("created-shader"); PT(Shader) result = new Shader(sfile, sbody, lang); _make_table[sbody] = result; + if (dump_generated_shaders) { ostringstream fns; int index = _shaders_generated ++; fns << "genshader" << index; string fn = fns.str(); gobj_cat.warning() << "Dumping shader: " << fn << "\n"; + pofstream s; - s.open(fn.c_str()); + s.open(fn.c_str(), ios::out | ios::trunc); s << body; s.close(); } @@ -2294,6 +2332,28 @@ make(const ShaderLanguage &lang, const string &vertex, const string &fragment, return result; } +////////////////////////////////////////////////////////////////////// +// Function: Shader::make_compute +// Access: Published, Static +// Description: Loads the compute shader from the given string. +////////////////////////////////////////////////////////////////////// +PT(Shader) Shader:: +make_compute(const ShaderLanguage &lang, const string &body) { + PT(ShaderFile) sbody = new ShaderFile; + sbody->_separate = true; + sbody->_compute = body; + + ShaderTable::const_iterator i = _make_table.find(sbody); + if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) { + return i->second; + } + + PT(ShaderFile) sfile = new ShaderFile("created-shader"); + PT(Shader) result = new Shader(sfile, sbody, lang); + _make_table[sbody] = result; + return result; +} + //////////////////////////////////////////////////////////////////// // Function: Shader::parse_init // Access: Public diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index 365ee0df74..04ae46ffc2 100755 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -60,6 +60,7 @@ PUBLISHED: ST_geometry, ST_tess_control, ST_tess_evaluation, + ST_compute, }; enum AutoShaderSwitch { @@ -85,11 +86,13 @@ PUBLISHED: const Filename &geometry = "", const Filename &tess_control = "", const Filename &tess_evaluation = ""); + static PT(Shader) load_compute(const ShaderLanguage &lang, const Filename &fn); static PT(Shader) make(const ShaderLanguage &lang, const string &vertex, const string &fragment, const string &geometry = "", const string &tess_control = "", const string &tess_evaluation = ""); + static PT(Shader) make_compute(const ShaderLanguage &lang, const string &body); INLINE const Filename get_filename(const ShaderType &type = ST_none) const; INLINE const string &get_text(const ShaderType &type = ST_none) const; @@ -232,6 +235,7 @@ public: SMP_row3x3, SMP_upper3x3, SMP_transpose3x3, + SMP_cell15, }; enum ShaderStateDep { @@ -276,6 +280,7 @@ public: enum ShaderPtrType { SPT_float, SPT_double, + SPT_int, SPT_unknown }; @@ -316,6 +321,14 @@ public: INLINE ShaderPtrData(const LMatrix4d &mat); INLINE ShaderPtrData(const LMatrix3d &mat); + INLINE ShaderPtrData(const PTA_int &ptr); + INLINE ShaderPtrData(const PTA_LVecBase4i &ptr); + INLINE ShaderPtrData(const PTA_LVecBase3i &ptr); + INLINE ShaderPtrData(const PTA_LVecBase2i &ptr); + INLINE ShaderPtrData(const LVecBase4i &vec); + INLINE ShaderPtrData(const LVecBase3i &vec); + INLINE ShaderPtrData(const LVecBase2i &vec); + INLINE void write_datagram(Datagram &dg) const; INLINE void read_datagram(DatagramIterator &source); }; @@ -343,6 +356,7 @@ public: ShaderArgId _id; PT(InternalName) _name; int _append_uv; + bool _integer; }; struct ShaderPtrSpec { @@ -351,6 +365,7 @@ public: int _dep[2]; PT(InternalName) _arg; ShaderArgInfo _info; + ShaderPtrType _type; }; class ShaderCaps { @@ -398,6 +413,7 @@ public: string _geometry; string _tess_control; string _tess_evaluation; + string _compute; }; public: diff --git a/panda/src/gobj/shaderContext.h b/panda/src/gobj/shaderContext.h index 18b4a3ed2a..5785b155c9 100755 --- a/panda/src/gobj/shaderContext.h +++ b/panda/src/gobj/shaderContext.h @@ -36,10 +36,23 @@ class EXPCL_PANDA_GOBJ ShaderContext: public SavedContext { public: INLINE ShaderContext(Shader *se); + INLINE virtual bool valid() { return false; } + INLINE virtual void bind(bool reissue_parameters = true) {}; + INLINE virtual void unbind() {}; + INLINE virtual void issue_parameters(int altered) {}; + INLINE virtual void disable_shader_vertex_arrays() {}; + INLINE virtual bool update_shader_vertex_arrays(ShaderContext *prev, bool force) { return false; }; + INLINE virtual void disable_shader_texture_bindings() {}; + INLINE virtual void update_shader_texture_bindings(ShaderContext *prev) {}; + + INLINE virtual bool uses_standard_vertex_arrays(void) { return true; }; + INLINE virtual bool uses_custom_vertex_arrays(void) { return false; }; + INLINE virtual bool uses_custom_texture_bindings(void) { return false; }; + PUBLISHED: INLINE Shader *get_shader() const; -public: +public: Shader *_shader; public: diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index b4b96217f9..6f973c2c65 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -161,6 +161,46 @@ struct DDSHeader { DDSCaps2 caps; }; +// This table is used for converting unsigned char texture values in an sRGB +// texture to linear RGB values, for use in mipmap generation. +static float srgb_to_lrgbf[256] = {0.000000f, 0.000304f, 0.000607f, 0.000911f, + 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f, + 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, + 0.006049f, 0.006512f, 0.006995f, 0.007499f, 0.008023f, 0.008568f, 0.009134f, + 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, + 0.014444f, 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, + 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, 0.025187f, 0.026241f, + 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, + 0.035601f, 0.036889f, 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, + 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, 0.054480f, + 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, + 0.068478f, 0.070360f, 0.072272f, 0.074214f, 0.076185f, 0.078187f, 0.080220f, + 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, + 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, + 0.114435f, 0.116971f, 0.119538f, 0.122139f, 0.124772f, 0.127438f, 0.130136f, + 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, + 0.152926f, 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, + 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, 0.191202f, 0.194618f, + 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, + 0.223228f, 0.226966f, 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, + 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, 0.274677f, + 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, + 0.309469f, 0.313989f, 0.318547f, 0.323143f, 0.327778f, 0.332452f, 0.337164f, + 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f, + 0.376262f, 0.381326f, 0.386429f, 0.391572f, 0.396755f, 0.401978f, 0.407240f, + 0.412543f, 0.417885f, 0.423268f, 0.428690f, 0.434154f, 0.439657f, 0.445201f, + 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473531f, 0.479320f, 0.485150f, + 0.491021f, 0.496933f, 0.502886f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, + 0.533276f, 0.539479f, 0.545724f, 0.552011f, 0.558340f, 0.564712f, 0.571125f, + 0.577580f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, + 0.623960f, 0.630757f, 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, + 0.672443f, 0.679542f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, 0.715694f, + 0.723055f, 0.730461f, 0.737910f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, + 0.775822f, 0.783538f, 0.791298f, 0.799103f, 0.806952f, 0.814847f, 0.822786f, + 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, + 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, + 0.947307f, 0.955973f, 0.964686f, 0.973445f, 0.982251f, 0.991102f, 1.000000f}; + //////////////////////////////////////////////////////////////////// // Function: Texture::Constructor // Access: Published @@ -532,6 +572,8 @@ estimate_texture_memory() const { case Texture::F_luminance: case Texture::F_luminance_alpha: case Texture::F_luminance_alphamask: + case Texture::F_sluminance: + case Texture::F_sluminance_alpha: bpp = 4; break; @@ -541,12 +583,14 @@ estimate_texture_memory() const { case Texture::F_rgb: case Texture::F_rgb5: case Texture::F_rgba5: + case Texture::F_srgb: bpp = 4; break; case Texture::F_color_index: case Texture::F_rgb8: case Texture::F_rgba8: + case Texture::F_srgb_alpha: bpp = 4; break; @@ -577,6 +621,20 @@ estimate_texture_memory() const { bpp = 6; break; + case Texture::F_r32i: + bpp = 4; + break; + + case Texture::F_r32: + bpp = 4; + break; + case Texture::F_rg32: + bpp = 8; + break; + case Texture::F_rgb32: + bpp = 12; + break; + default: break; } @@ -1593,6 +1651,11 @@ write(ostream &out, int indent_level) const { out << " floats"; break; + case T_unsigned_int_24_8: + case T_int: + out << " ints"; + break; + default: break; } @@ -1690,6 +1753,33 @@ write(ostream &out, int indent_level) const { case F_rgb16: out << "rgb16"; break; + + case F_srgb: + out << "srgb"; + break; + case F_srgb_alpha: + out << "srgb_alpha"; + break; + case F_sluminance: + out << "sluminance"; + break; + case F_sluminance_alpha: + out << "sluminance_alpha"; + break; + + case F_r32i: + out << "r32i"; + break; + + case F_r32: + out << "r32"; + break; + case F_rg32: + out << "rg32"; + break; + case F_rgb32: + out << "rgb32"; + break; } if (cdata->_compression != CM_default) { @@ -2017,6 +2107,8 @@ format_component_type(ComponentType ct) { return "float"; case T_unsigned_int_24_8: return "unsigned_int_24_8"; + case T_int: + return "int"; } return "**invalid**"; @@ -2038,6 +2130,8 @@ string_component_type(const string &str) { return T_float; } else if (cmp_nocase(str, "unsigned_int_24_8") == 0) { return T_unsigned_int_24_8; + } else if (cmp_nocase(str, "int") == 0) { + return T_int; } gobj_cat->error() @@ -2112,6 +2206,22 @@ format_format(Format format) { return "rg16"; case F_rgb16: return "rgb16"; + case F_srgb: + return "srgb"; + case F_srgb_alpha: + return "srgb_alpha"; + case F_sluminance: + return "sluminance"; + case F_sluminance_alpha: + return "sluminance_alpha"; + case F_r32i: + return "r32i"; + case F_r32: + return "r32"; + case F_rg32: + return "rg32"; + case F_rgb32: + return "rgb32"; } return "**invalid**"; } @@ -2182,6 +2292,22 @@ string_format(const string &str) { return F_rg16; } else if (cmp_nocase(str, "rgb16") == 0 || cmp_nocase(str, "r16g16b16") == 0) { return F_rgb16; + } else if (cmp_nocase(str, "srgb") == 0) { + return F_srgb; + } else if (cmp_nocase(str, "srgb_alpha") == 0) { + return F_srgb_alpha; + } else if (cmp_nocase(str, "sluminance") == 0) { + return F_sluminance; + } else if (cmp_nocase(str, "sluminance_alpha") == 0) { + return F_sluminance_alpha; + } else if (cmp_nocase(str, "r32i") == 0) { + return F_r32i; + } else if (cmp_nocase(str, "r32") == 0 || cmp_nocase(str, "red32") == 0) { + return F_r32; + } else if (cmp_nocase(str, "rg32") == 0 || cmp_nocase(str, "r32g32") == 0) { + return F_rg32; + } else if (cmp_nocase(str, "rgb32") == 0 || cmp_nocase(str, "r32g32b32") == 0) { + return F_rgb32; } gobj_cat->error() @@ -2541,6 +2667,8 @@ has_alpha(Format format) { case F_rgba32: case F_luminance_alpha: case F_luminance_alphamask: + case F_srgb_alpha: + case F_sluminance_alpha: return true; default: @@ -2565,6 +2693,26 @@ has_binary_alpha(Format format) { } } +//////////////////////////////////////////////////////////////////// +// Function: Texture::is_srgb +// Access: Public, Static +// Description: Returns true if the indicated format is in the +// sRGB color space, false otherwise. +//////////////////////////////////////////////////////////////////// +bool Texture:: +is_srgb(Format format) { + switch (format) { + case F_srgb: + case F_srgb_alpha: + case F_sluminance: + case F_sluminance_alpha: + return true; + + default: + return false; + } +} + //////////////////////////////////////////////////////////////////// // Function: Texture::adjust_size // Access: Public, Static @@ -4487,6 +4635,8 @@ do_compress_ram_image(CData *cdata, Texture::CompressionMode compression, case Texture::F_rgb8: case Texture::F_rgb12: case Texture::F_rgb332: + case Texture::F_rgb16: + case Texture::F_rgb32: if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt1)) { compression = CM_dxt1; } else if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt3)) { @@ -4743,27 +4893,24 @@ do_reconsider_image_properties(CData *cdata, int x_size, int y_size, int num_com // But only do this the first time the file is loaded, or if the // number of channels in the image changes on subsequent loads. + //TODO: handle sRGB properly switch (num_components) { case 1: - if (component_type == T_float) { - cdata->_format = F_depth_component; - } else { - cdata->_format = F_luminance; - } + cdata->_format = F_luminance; break; - + case 2: cdata->_format = F_luminance_alpha; break; - + case 3: cdata->_format = F_rgb; break; - + case 4: cdata->_format = F_rgba; break; - + default: // Eh? nassertr(false, false); @@ -5023,12 +5170,17 @@ do_set_format(CData *cdata, Texture::Format format) { case F_alpha: case F_luminance: case F_r16: + case F_sluminance: + case F_r32i: + case F_r32: cdata->_num_components = 1; break; case F_luminance_alpha: case F_luminance_alphamask: case F_rg16: + case F_sluminance_alpha: + case F_rg32: cdata->_num_components = 2; break; @@ -5038,6 +5190,8 @@ do_set_format(CData *cdata, Texture::Format format) { case F_rgb12: case F_rgb332: case F_rgb16: + case F_srgb: + case F_rgb32: cdata->_num_components = 3; break; @@ -5049,6 +5203,7 @@ do_set_format(CData *cdata, Texture::Format format) { case F_rgba12: case F_rgba16: case F_rgba32: + case F_srgb_alpha: cdata->_num_components = 4; break; } @@ -5079,6 +5234,10 @@ do_set_component_type(CData *cdata, Texture::ComponentType component_type) { case T_unsigned_int_24_8: cdata->_component_width = 4; break; + + case T_int: + cdata->_component_width = 4; + break; } } @@ -5671,7 +5830,7 @@ do_clear_ram_mipmap_images(CData *cdata) { void Texture:: do_generate_ram_mipmap_images(CData *cdata) { nassertv(do_has_ram_image(cdata)); - nassertv(cdata->_component_type != T_float); + if (do_get_expected_num_mipmap_levels(cdata) == 1) { // Don't bother. return; @@ -6835,6 +6994,40 @@ void Texture:: do_filter_2d_mipmap_pages(const CData *cdata, Texture::RamImage &to, const Texture::RamImage &from, int x_size, int y_size) const { + Filter2DComponent *filter_component; + Filter2DComponent *filter_alpha; + + if (is_srgb(cdata->_format)) { + // We currently only support sRGB mipmap generation for + // unsigned byte textures, due to our use of a lookup table. + nassertv(cdata->_component_type == T_unsigned_byte); + filter_component = &filter_2d_unsigned_byte_srgb; + // Alpha is always linear. + filter_alpha = &filter_2d_unsigned_byte; + + } else { + switch (cdata->_component_type) { + case T_unsigned_byte: + filter_component = &filter_2d_unsigned_byte; + break; + + case T_unsigned_short: + filter_component = &filter_2d_unsigned_short; + break; + + case T_float: + filter_component = &filter_2d_float; + break; + + default: + gobj_cat.error() + << "Unable to generate mipmaps for 2D texture with component type " + << cdata->_component_type << "!"; + return; + } + filter_alpha = filter_component; + } + size_t pixel_size = cdata->_num_components * cdata->_component_width; size_t row_size = (size_t)x_size * pixel_size; @@ -6845,7 +7038,11 @@ do_filter_2d_mipmap_pages(const CData *cdata, to._page_size = (size_t)to_y_size * to_row_size; to._image = PTA_uchar::empty_array(to._page_size * cdata->_z_size * cdata->_num_views, get_class_type()); - Filter2DComponent *filter_component = (cdata->_component_type == T_unsigned_byte ? &filter_2d_unsigned_byte : filter_2d_unsigned_short); + bool alpha = has_alpha(cdata->_format); + int num_color_components = cdata->_num_components; + if (alpha) { + --num_color_components; + } int num_pages = cdata->_z_size * cdata->_num_views; for (int z = 0; z < num_pages; ++z) { @@ -6864,10 +7061,13 @@ do_filter_2d_mipmap_pages(const CData *cdata, int x; for (x = 0; x < x_size - 1; x += 2) { // For each pixel. - for (int c = 0; c < cdata->_num_components; ++c) { + for (int c = 0; c < num_color_components; ++c) { // For each component. filter_component(p, q, pixel_size, row_size); } + if (alpha) { + filter_alpha(p, q, pixel_size, row_size); + } q += pixel_size; } if (x < x_size) { @@ -6876,10 +7076,13 @@ do_filter_2d_mipmap_pages(const CData *cdata, } } else { // Just one pixel. - for (int c = 0; c < cdata->_num_components; ++c) { + for (int c = 0; c < num_color_components; ++c) { // For each component. filter_component(p, q, 0, row_size); } + if (alpha) { + filter_alpha(p, q, 0, row_size); + } } q += row_size; Thread::consider_yield(); @@ -6894,10 +7097,13 @@ do_filter_2d_mipmap_pages(const CData *cdata, int x; for (x = 0; x < x_size - 1; x += 2) { // For each pixel. - for (int c = 0; c < cdata->_num_components; ++c) { + for (int c = 0; c < num_color_components; ++c) { // For each component. filter_component(p, q, pixel_size, 0); } + if (alpha) { + filter_alpha(p, q, pixel_size, 0); + } q += pixel_size; } if (x < x_size) { @@ -6906,10 +7112,13 @@ do_filter_2d_mipmap_pages(const CData *cdata, } } else { // Just one pixel. - for (int c = 0; c < cdata->_num_components; ++c) { + for (int c = 0; c < num_color_components; ++c) { // For each component. filter_component(p, q, 0, 0); } + if (alpha) { + filter_alpha(p, q, pixel_size, 0); + } } } @@ -6935,6 +7144,40 @@ void Texture:: do_filter_3d_mipmap_level(const CData *cdata, Texture::RamImage &to, const Texture::RamImage &from, int x_size, int y_size, int z_size) const { + Filter3DComponent *filter_component; + Filter3DComponent *filter_alpha; + + if (is_srgb(cdata->_format)) { + // We currently only support sRGB mipmap generation for + // unsigned byte textures, due to our use of a lookup table. + nassertv(cdata->_component_type == T_unsigned_byte); + filter_component = &filter_3d_unsigned_byte_srgb; + // Alpha is always linear. + filter_alpha = &filter_3d_unsigned_byte; + + } else { + switch (cdata->_component_type) { + case T_unsigned_byte: + filter_component = &filter_3d_unsigned_byte; + break; + + case T_unsigned_short: + filter_component = &filter_3d_unsigned_short; + break; + + case T_float: + filter_component = &filter_3d_float; + break; + + default: + gobj_cat.error() + << "Unable to generate mipmaps for 3D texture with component type " + << cdata->_component_type << "!"; + return; + } + filter_alpha = filter_component; + } + size_t pixel_size = cdata->_num_components * cdata->_component_width; size_t row_size = (size_t)x_size * pixel_size; size_t page_size = (size_t)y_size * row_size; @@ -6950,7 +7193,11 @@ do_filter_3d_mipmap_level(const CData *cdata, to._page_size = to_page_size; to._image = PTA_uchar::empty_array(to_page_size * to_z_size * cdata->_num_views, get_class_type()); - Filter3DComponent *filter_component = (cdata->_component_type == T_unsigned_byte ? &filter_3d_unsigned_byte : filter_3d_unsigned_short); + bool alpha = has_alpha(cdata->_format); + int num_color_components = cdata->_num_components; + if (alpha) { + --num_color_components; + } for (int view = 0; view < cdata->_num_views; ++view) { unsigned char *start_to = to._image.p() + view * to_view_size; @@ -6975,10 +7222,13 @@ do_filter_3d_mipmap_level(const CData *cdata, int x; for (x = 0; x < x_size - 1; x += 2) { // For each pixel. - for (int c = 0; c < cdata->_num_components; ++c) { + for (int c = 0; c < num_color_components; ++c) { // For each component. filter_component(p, q, pixel_size, row_size, page_size); } + if (alpha) { + filter_alpha(p, q, pixel_size, row_size, page_size); + } q += pixel_size; } if (x < x_size) { @@ -6987,10 +7237,13 @@ do_filter_3d_mipmap_level(const CData *cdata, } } else { // Just one pixel. - for (int c = 0; c < cdata->_num_components; ++c) { + for (int c = 0; c < num_color_components; ++c) { // For each component. filter_component(p, q, 0, row_size, page_size); } + if (alpha) { + filter_alpha(p, q, 0, row_size, page_size); + } } q += row_size; Thread::consider_yield(); @@ -7005,10 +7258,13 @@ do_filter_3d_mipmap_level(const CData *cdata, int x; for (x = 0; x < x_size - 1; x += 2) { // For each pixel. - for (int c = 0; c < cdata->_num_components; ++c) { + for (int c = 0; c < num_color_components; ++c) { // For each component. filter_component(p, q, pixel_size, 0, page_size); } + if (alpha) { + filter_alpha(p, q, pixel_size, 0, page_size); + } q += pixel_size; } if (x < x_size) { @@ -7017,10 +7273,13 @@ do_filter_3d_mipmap_level(const CData *cdata, } } else { // Just one pixel. - for (int c = 0; c < cdata->_num_components; ++c) { + for (int c = 0; c < num_color_components; ++c) { // For each component. filter_component(p, q, 0, 0, page_size); } + if (alpha) { + filter_alpha(p, q, 0, 0, page_size); + } } } q += page_size; @@ -7041,10 +7300,13 @@ do_filter_3d_mipmap_level(const CData *cdata, int x; for (x = 0; x < x_size - 1; x += 2) { // For each pixel. - for (int c = 0; c < cdata->_num_components; ++c) { + for (int c = 0; c < num_color_components; ++c) { // For each component. filter_component(p, q, pixel_size, row_size, 0); } + if (alpha) { + filter_alpha(p, q, pixel_size, row_size, 0); + } q += pixel_size; } if (x < x_size) { @@ -7053,10 +7315,13 @@ do_filter_3d_mipmap_level(const CData *cdata, } } else { // Just one pixel. - for (int c = 0; c < cdata->_num_components; ++c) { + for (int c = 0; c < num_color_components; ++c) { // For each component. filter_component(p, q, 0, row_size, 0); } + if (alpha) { + filter_alpha(p, q, 0, row_size, 0); + } } q += row_size; Thread::consider_yield(); @@ -7071,10 +7336,13 @@ do_filter_3d_mipmap_level(const CData *cdata, int x; for (x = 0; x < x_size - 1; x += 2) { // For each pixel. - for (int c = 0; c < cdata->_num_components; ++c) { + for (int c = 0; c < num_color_components; ++c) { // For each component. filter_component(p, q, pixel_size, 0, 0); } + if (alpha) { + filter_alpha(p, q, pixel_size, 0, 0); + } q += pixel_size; } if (x < x_size) { @@ -7083,10 +7351,13 @@ do_filter_3d_mipmap_level(const CData *cdata, } } else { // Just one pixel. - for (int c = 0; c < cdata->_num_components; ++c) { + for (int c = 0; c < num_color_components; ++c) { // For each component. filter_component(p, q, 0, 0, 0); } + if (alpha) { + filter_alpha(p, q, 0, 0, 0); + } } } } @@ -7115,6 +7386,32 @@ filter_2d_unsigned_byte(unsigned char *&p, const unsigned char *&q, ++q; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::filter_2d_unsigned_byte_srgb +// Access: Public, Static +// Description: Averages a 2x2 block of pixel components into a +// single pixel component, for producing the next mipmap +// level. Increments p and q to the next component. +//////////////////////////////////////////////////////////////////// +void Texture:: +filter_2d_unsigned_byte_srgb(unsigned char *&p, const unsigned char *&q, + size_t pixel_size, size_t row_size) { + float result = (srgb_to_lrgbf[q[0]] + + srgb_to_lrgbf[q[pixel_size]] + + srgb_to_lrgbf[q[row_size]] + + srgb_to_lrgbf[q[pixel_size + row_size]]) / 4.0f; + + // This is based on the formula out of the EXT_texture_sRGB + // specification, except the factors are multiplied with 255.0f. + if (result < 0.0031308f) { + *p = (unsigned char)(result * 3294.6f); + } else { + *p = (unsigned char)(269.025f * powf(result, 0.41666f) - 14.025f); + } + ++p; + ++q; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::filter_2d_unsigned_short // Access: Public, Static @@ -7133,6 +7430,24 @@ filter_2d_unsigned_short(unsigned char *&p, const unsigned char *&q, q += 2; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::filter_2d_float +// Access: Public, Static +// Description: Averages a 2x2 block of pixel components into a +// single pixel component, for producing the next mipmap +// level. Increments p and q to the next component. +//////////////////////////////////////////////////////////////////// +void Texture:: +filter_2d_float(unsigned char *&p, const unsigned char *&q, + size_t pixel_size, size_t row_size) { + *(float *)p = (*(float *)&q[0] + + *(float *)&q[pixel_size] + + *(float *)&q[row_size] + + *(float *)&q[pixel_size + row_size]) / 4.0f; + p += 4; + q += 4; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::filter_3d_unsigned_byte // Access: Public, Static @@ -7156,6 +7471,36 @@ filter_3d_unsigned_byte(unsigned char *&p, const unsigned char *&q, ++q; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::filter_3d_unsigned_byte_srgb +// Access: Public, Static +// Description: Averages a 2x2x2 block of pixel components into a +// single pixel component, for producing the next mipmap +// level. Increments p and q to the next component. +//////////////////////////////////////////////////////////////////// +void Texture:: +filter_3d_unsigned_byte_srgb(unsigned char *&p, const unsigned char *&q, + size_t pixel_size, size_t row_size, size_t page_size) { + float result = (srgb_to_lrgbf[q[0]] + + srgb_to_lrgbf[q[pixel_size]] + + srgb_to_lrgbf[q[row_size]] + + srgb_to_lrgbf[q[pixel_size + row_size]] + + srgb_to_lrgbf[q[page_size]] + + srgb_to_lrgbf[q[pixel_size + page_size]] + + srgb_to_lrgbf[q[row_size + page_size]] + + srgb_to_lrgbf[q[pixel_size + row_size + page_size]]) / 8.0f; + + // This is based on the formula out of the EXT_texture_sRGB + // specification, except the factors are multiplied with 255.0f. + if (result < 0.0031308f) { + *p = (unsigned char)(result * 3294.6f); + } else { + *p = (unsigned char)(269.025f * powf(result, 0.41666f) - 14.025f); + } + ++p; + ++q; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::filter_3d_unsigned_short // Access: Public, Static @@ -7179,6 +7524,28 @@ filter_3d_unsigned_short(unsigned char *&p, const unsigned char *&q, q += 2; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::filter_3d_float +// Access: Public, Static +// Description: Averages a 2x2x2 block of pixel components into a +// single pixel component, for producing the next mipmap +// level. Increments p and q to the next component. +//////////////////////////////////////////////////////////////////// +void Texture:: +filter_3d_float(unsigned char *&p, const unsigned char *&q, + size_t pixel_size, size_t row_size, size_t page_size) { + *(float *)p = (*(float *)&q[0] + + *(float *)&q[pixel_size] + + *(float *)&q[row_size] + + *(float *)&q[pixel_size + row_size] + + *(float *)&q[page_size] + + *(float *)&q[pixel_size + page_size] + + *(float *)&q[row_size + page_size] + + *(float *)&q[pixel_size + row_size + page_size]) / 8.0f; + p += 4; + q += 4; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::do_squish // Access: Private diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 638bbc4120..d0d0d47462 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -85,7 +85,8 @@ PUBLISHED: T_unsigned_byte, T_unsigned_short, T_float, - T_unsigned_int_24_8, + T_unsigned_int_24_8, // Packed + T_int, }; enum Format { @@ -132,6 +133,18 @@ PUBLISHED: F_r16, F_rg16, F_rgb16, + + // These formats are in the sRGB color space. + // RGB is 2.2 gamma corrected, alpha is always linear. + F_srgb, + F_srgb_alpha, + F_sluminance, + F_sluminance_alpha, + + F_r32i, // 32-bit integer, used for atomic access + F_r32, + F_rg32, + F_rgb32, }; enum FilterType { @@ -160,7 +173,7 @@ PUBLISHED: // The OpenGL ARB_shadow extension can be thought of as a kind of filtering. FT_shadow, - + // Default is usually linear, but it depends on format. // This was added at the end of the list to avoid bumping TXO version #. FT_default, @@ -514,6 +527,7 @@ public: static bool is_specific(CompressionMode compression); static bool has_alpha(Format format); static bool has_binary_alpha(Format format); + static bool is_srgb(Format format); static bool adjust_size(int &x_size, int &y_size, const string &name, bool for_padding, AutoTextureScale auto_texture_scale = ATS_unspecified); @@ -742,19 +756,30 @@ private: static void filter_2d_unsigned_byte(unsigned char *&p, const unsigned char *&q, size_t pixel_size, size_t row_size); + static void filter_2d_unsigned_byte_srgb(unsigned char *&p, + const unsigned char *&q, + size_t pixel_size, size_t row_size); static void filter_2d_unsigned_short(unsigned char *&p, const unsigned char *&q, size_t pixel_size, size_t row_size); + static void filter_2d_float(unsigned char *&p, const unsigned char *&q, + size_t pixel_size, size_t row_size); static void filter_3d_unsigned_byte(unsigned char *&p, const unsigned char *&q, size_t pixel_size, size_t row_size, size_t page_size); + static void filter_3d_unsigned_byte_srgb(unsigned char *&p, + const unsigned char *&q, + size_t pixel_size, size_t row_size, + size_t page_size); static void filter_3d_unsigned_short(unsigned char *&p, const unsigned char *&q, size_t pixel_size, size_t row_size, size_t page_size); - + static void filter_3d_float(unsigned char *&p, const unsigned char *&q, + size_t pixel_size, size_t row_size, size_t page_size); + bool do_squish(CData *cdata, CompressionMode compression, int squish_flags); bool do_unsquish(CData *cdata, int squish_flags); diff --git a/panda/src/grutil/config_grutil.cxx b/panda/src/grutil/config_grutil.cxx index 98ff1e0012..2c8cc825c9 100644 --- a/panda/src/grutil/config_grutil.cxx +++ b/panda/src/grutil/config_grutil.cxx @@ -34,12 +34,18 @@ ConfigureFn(config_grutil) { init_libgrutil(); } +ConfigVariableBool frame_rate_meter_milliseconds +("frame-rate-meter-milliseconds", false); + ConfigVariableDouble frame_rate_meter_update_interval ("frame-rate-meter-update-interval", 1.5); ConfigVariableString frame_rate_meter_text_pattern ("frame-rate-meter-text-pattern", "%0.1f fps"); +ConfigVariableString frame_rate_meter_ms_text_pattern +("frame-rate-meter-ms-text-pattern", "%0.1f ms"); + ConfigVariableInt frame_rate_meter_layer_sort ("frame-rate-meter-layer-sort", 1000); @@ -84,10 +90,16 @@ ConfigVariableInt pfm_vis_max_indices "a single generated mesh. If the mesh would require more than that, " "the mesh is subdivided into smaller pieces.")); -ConfigVariableDouble ae_undershift_factor -("ae-undershift-factor", 1.004, +ConfigVariableDouble ae_undershift_factor_16 +("ae-undershift-factor-16", 1.004, PRC_DESC("Specifies the factor by which After Effects under-applies the specified " - "maximum pixel shift when applying a displacement map. This is used " + "maximum pixel shift when applying a displacement map, in a 16-bit project file. This is used " + "to control PfmVizzer::make_displacement().")); + +ConfigVariableDouble ae_undershift_factor_32 +("ae-undershift-factor-32", 1.0, + PRC_DESC("Specifies the factor by which After Effects under-applies the specified " + "maximum pixel shift when applying a displacement map, in a 32-bit project file. This is used " "to control PfmVizzer::make_displacement().")); //////////////////////////////////////////////////////////////////// diff --git a/panda/src/grutil/config_grutil.h b/panda/src/grutil/config_grutil.h index eb84add0d3..e20f4117f3 100644 --- a/panda/src/grutil/config_grutil.h +++ b/panda/src/grutil/config_grutil.h @@ -24,8 +24,10 @@ NotifyCategoryDecl(grutil, EXPCL_PANDA_GRUTIL, EXPTP_PANDA_GRUTIL); +extern ConfigVariableBool frame_rate_meter_milliseconds; extern ConfigVariableDouble frame_rate_meter_update_interval; extern ConfigVariableString frame_rate_meter_text_pattern; +extern ConfigVariableString frame_rate_meter_ms_text_pattern; extern ConfigVariableInt frame_rate_meter_layer_sort; extern ConfigVariableDouble frame_rate_meter_scale; extern ConfigVariableDouble frame_rate_meter_side_margins; @@ -40,7 +42,8 @@ extern ConfigVariableBool movies_sync_pages; extern ConfigVariableInt pfm_vis_max_vertices; extern ConfigVariableInt pfm_vis_max_indices; -extern ConfigVariableDouble ae_undershift_factor; +extern ConfigVariableDouble ae_undershift_factor_16; +extern ConfigVariableDouble ae_undershift_factor_32; extern EXPCL_PANDA_GRUTIL void init_libgrutil(); diff --git a/panda/src/grutil/frameRateMeter.cxx b/panda/src/grutil/frameRateMeter.cxx index fb5b82f0e1..7e4f779a8b 100644 --- a/panda/src/grutil/frameRateMeter.cxx +++ b/panda/src/grutil/frameRateMeter.cxx @@ -38,9 +38,15 @@ FrameRateMeter(const string &name) : TextNode(name) { Thread *current_thread = Thread::get_current_thread(); + _show_milliseconds = frame_rate_meter_milliseconds; + if (_show_milliseconds) { + _text_pattern = frame_rate_meter_ms_text_pattern; + } else { + _text_pattern = frame_rate_meter_text_pattern; + } + _update_interval = frame_rate_meter_update_interval; _last_update = 0.0f; - _text_pattern = frame_rate_meter_text_pattern; _clock_object = ClockObject::get_global_clock(); // The top of the visible frame is 80% of the line height, based on @@ -184,16 +190,21 @@ void FrameRateMeter:: do_update(Thread *current_thread) { _last_update = _clock_object->get_frame_time(current_thread); - double frame_rate = _clock_object->get_average_frame_rate(current_thread); + double value = _clock_object->get_average_frame_rate(current_thread); double deviation = _clock_object->calc_frame_rate_deviation(current_thread); + if (_show_milliseconds) { + value = 1000.0 / value; + deviation = 1000.0 / deviation; + } + static const size_t buffer_size = 1024; char buffer[buffer_size]; #if defined(WIN32_VC) || defined(WIN64_VC) // Windows doesn't define snprintf(). Hope we don't overflow. - sprintf(buffer, _text_pattern.c_str(), frame_rate, deviation); + sprintf(buffer, _text_pattern.c_str(), value, deviation); #else - snprintf(buffer, buffer_size, _text_pattern.c_str(), frame_rate, deviation); + snprintf(buffer, buffer_size, _text_pattern.c_str(), value, deviation); #endif nassertv(strlen(buffer) < buffer_size); diff --git a/panda/src/grutil/frameRateMeter.h b/panda/src/grutil/frameRateMeter.h index acc2a312e5..2f95bbaf72 100644 --- a/panda/src/grutil/frameRateMeter.h +++ b/panda/src/grutil/frameRateMeter.h @@ -71,6 +71,7 @@ private: PT(DisplayRegion) _display_region; NodePath _root; + bool _show_milliseconds; double _update_interval; double _last_update; string _text_pattern; diff --git a/panda/src/grutil/pfmVizzer.cxx b/panda/src/grutil/pfmVizzer.cxx index d9bdff2413..563f1b4714 100644 --- a/panda/src/grutil/pfmVizzer.cxx +++ b/panda/src/grutil/pfmVizzer.cxx @@ -451,9 +451,17 @@ calc_max_v_displacement() const { // Use calc_max_u_displacement() and // calc_max_v_displacement() to compute suitable values // for max_u and max_v. +// +// This generates an integer 16-bit displacement image. +// It is a good idea, though not necessarily essential, +// to check "Preserve RGB" in the interpret footage +// section for each displacement image. Set +// for_32bit true if this is meant to be used in a +// 32-bit project file, and false if it is meant to be +// used in a 16-bit project file. //////////////////////////////////////////////////////////////////// void PfmVizzer:: -make_displacement(PNMImage &result, double max_u, double max_v) const { +make_displacement(PNMImage &result, double max_u, double max_v, bool for_32bit) const { int x_size = _pfm.get_x_size(); int y_size = _pfm.get_y_size(); result.clear(x_size, y_size, 3, PNM_MAXMAXVAL); @@ -463,10 +471,19 @@ make_displacement(PNMImage &result, double max_u, double max_v) const { // not exactly 0.5, because they round up. static const int midval = (PNM_MAXMAXVAL + 1) / 2; - // Empirically, After Effects seems to undershift by precisely this - // amount. Curiously, this value is very close to, but not exactly, - // 256 / 255. - const double scale_factor = ae_undershift_factor; + double scale_factor; + if (for_32bit) { + // There doesn't appear to be an undershift needed on 32-bit + // projects, but we have the factor here anyway in case it + // develops. + scale_factor = ae_undershift_factor_32; + } else { + // Empirically, After Effects seems to undershift by precisely + // this amount (but only in a 16-bit project, not in a 32-bit + // project). Curiously, this value is very close to, but not + // exactly, 256 / 255. + scale_factor = ae_undershift_factor_16; + } double u_scale = scale_factor * 0.5 * PNM_MAXMAXVAL / max_u; double v_scale = scale_factor * 0.5 * PNM_MAXMAXVAL / max_v; @@ -522,6 +539,102 @@ make_displacement(PNMImage &result, double max_u, double max_v) const { } } +//////////////////////////////////////////////////////////////////// +// Function: PfmVizzer::make_displacement +// Access: Published +// Description: Assuming the underlying PfmFile is a 2-d distortion +// mesh, with the U and V in the first two components +// and the third component unused, this computes an +// AfterEffects-style displacement map that represents +// the same distortion. The indicated PNMImage will be +// filled in with a displacement map image, with +// horizontal shift in the red channel and vertical +// shift in the green channel, where a fully bright (or +// fully black) pixel indicates a shift of max_u or +// max_v pixels. +// +// Use calc_max_u_displacement() and +// calc_max_v_displacement() to compute suitable values +// for max_u and max_v. +// +// This generates a 32-bit floating-point displacement +// image. It is essential to check "Preserve RGB" in +// the interpret footage section for each displacement +// image. Set for_32bit true if this is meant to +// be used in a 32-bit project file, and false if it is +// meant to be used in a 16-bit project file. +//////////////////////////////////////////////////////////////////// +void PfmVizzer:: +make_displacement(PfmFile &result, double max_u, double max_v, bool for_32bit) const { + int x_size = _pfm.get_x_size(); + int y_size = _pfm.get_y_size(); + result.clear(x_size, y_size, 3); + + double scale_factor; + if (for_32bit) { + // There doesn't appear to be an undershift needed on 32-bit + // projects, but we have the factor here anyway in case it + // develops. + scale_factor = ae_undershift_factor_32; + } else { + // Empirically, After Effects seems to undershift by precisely + // this amount (but only in a 16-bit project, not in a 32-bit + // project). Curiously, this value is very close to, but not + // exactly, 256 / 255. + scale_factor = ae_undershift_factor_16; + } + + double u_scale = scale_factor * 0.5 / max_u; + double v_scale = scale_factor * 0.5 / max_v; + + for (int yi = 0; yi < y_size; ++yi) { + for (int xi = 0; xi < x_size; ++xi) { + if (!_pfm.has_point(xi, yi)) { + continue; + } + + const LPoint3f &point = _pfm.get_point(xi, yi); + double nxi = point[0] * (double)x_size - 0.5; + double nyi = point[1] * (double)y_size - 0.5; + + double x_shift = (nxi - (double)xi); + double y_shift = (nyi - (double)yi); + + float u_val = 0.5 + (float)(x_shift * u_scale); + float v_val = 0.5 + (float)(y_shift * v_scale); + + // We use the blue channel to mark holes, so we can fill them in + // later. + result.set_point3(xi, yi, LVecBase3f(u_val, v_val, 0)); + } + } + + // Now fill in holes. + for (int yi = 0; yi < y_size; ++yi) { + for (int xi = 0; xi < x_size; ++xi) { + if (!_pfm.has_point(xi, yi)) { + continue; + } + + const LPoint3f &point = _pfm.get_point(xi, yi); + double nxi = point[0] * (double)x_size - 0.5; + double nyi = point[1] * (double)y_size - 0.5; + + r_fill_displacement(result, xi - 1, yi, nxi, nyi, u_scale, v_scale, 1); + r_fill_displacement(result, xi + 1, yi, nxi, nyi, u_scale, v_scale, 1); + r_fill_displacement(result, xi, yi - 1, nxi, nyi, u_scale, v_scale, 1); + r_fill_displacement(result, xi, yi + 1, nxi, nyi, u_scale, v_scale, 1); + } + } + + // Finally, reset the blue channel for cleanliness. + for (int yi = 0; yi < y_size; ++yi) { + for (int xi = 0; xi < x_size; ++xi) { + result.set_channel(xi, yi, 2, 0.5); + } + } +} + //////////////////////////////////////////////////////////////////// // Function: PfmVizzer::uses_aux_pfm // Access: Private @@ -591,6 +704,45 @@ r_fill_displacement(PNMImage &result, int xi, int yi, } } +//////////////////////////////////////////////////////////////////// +// Function: PfmVizzer::r_fill_displacement +// Access: Private +// Description: Recursively fills in holes with the color of their +// nearest neighbor after processing the image. This +// avoids sudden discontinuities in the displacement map +// at the edge of the screen geometry. +//////////////////////////////////////////////////////////////////// +void PfmVizzer:: +r_fill_displacement(PfmFile &result, int xi, int yi, + double nxi, double nyi, double u_scale, double v_scale, + int distance) const { + if (xi < 0 || yi < 0 || + xi >= result.get_x_size() || yi >= result.get_y_size()) { + // Stop at the edge. + return; + } + + if (distance > 1000) { + // Avoid runaway recursion. + return; + } + + float val = result.get_channel(xi, yi, 2); + if (val > (float)distance) { + // We've found a point that's closer. + double x_shift = (nxi - (double)xi); + double y_shift = (nyi - (double)yi); + float u_val = 0.5 + (float)(x_shift * u_scale); + float v_val = 0.5 + (float)(y_shift * v_scale); + result.set_point3(xi, yi, LVecBase3f(u_val, v_val, distance)); + + r_fill_displacement(result, xi - 1, yi, nxi, nyi, u_scale, v_scale, distance + 1); + r_fill_displacement(result, xi + 1, yi, nxi, nyi, u_scale, v_scale, distance + 1); + r_fill_displacement(result, xi, yi - 1, nxi, nyi, u_scale, v_scale, distance + 1); + r_fill_displacement(result, xi, yi + 1, nxi, nyi, u_scale, v_scale, distance + 1); + } +} + //////////////////////////////////////////////////////////////////// // Function: PfmVizzer::make_vis_mesh_geom // Access: Private diff --git a/panda/src/grutil/pfmVizzer.h b/panda/src/grutil/pfmVizzer.h index 2d20b4d1d6..df2f00eac2 100644 --- a/panda/src/grutil/pfmVizzer.h +++ b/panda/src/grutil/pfmVizzer.h @@ -86,13 +86,17 @@ PUBLISHED: BLOCKING double calc_max_u_displacement() const; BLOCKING double calc_max_v_displacement() const; - BLOCKING void make_displacement(PNMImage &result, double max_u, double max_v) const; + BLOCKING void make_displacement(PNMImage &result, double max_u, double max_v, bool for_32bit) const; + BLOCKING void make_displacement(PfmFile &result, double max_u, double max_v, bool for_32bit) const; private: bool uses_aux_pfm() const; void r_fill_displacement(PNMImage &result, int xi, int yi, double nxi, double nyi, double u_scale, double v_scale, int distance) const; + void r_fill_displacement(PfmFile &result, int xi, int yi, + double nxi, double nyi, double u_scale, double v_scale, + int distance) const; void make_vis_mesh_geom(GeomNode *gnode, bool inverted) const; diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 4de1ffca8f..33e3793edd 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -163,6 +163,8 @@ public: virtual void begin_occlusion_query()=0; virtual PT(OcclusionQueryContext) end_occlusion_query()=0; + virtual void dispatch_compute(int size_x, int size_y, int size_z)=0; + virtual PT(GeomMunger) get_geom_munger(const RenderState *state, Thread *current_thread)=0; diff --git a/panda/src/linmath/Sources.pp b/panda/src/linmath/Sources.pp index 9c5a1c9548..0e84fb271e 100644 --- a/panda/src/linmath/Sources.pp +++ b/panda/src/linmath/Sources.pp @@ -14,7 +14,7 @@ compose_matrix_src.cxx compose_matrix_src.h config_linmath.h \ coordinateSystem.h dbl2fltnames.h dblnames.h \ deg_2_rad.h deg_2_rad.I \ - flt2dblnames.h fltnames.h lcast_to.h lcast_to_src.h \ + flt2dblnames.h fltnames.h intnames.h lcast_to.h lcast_to_src.h \ lcast_to_src.I lmatrix.h lmatrix_ext.h lmatrix3_src.I \ lmatrix3_src.cxx lmatrix3_src.h lmatrix4_src.I \ lmatrix4_src.cxx lmatrix4_src.h lorientation.h \ @@ -56,7 +56,7 @@ compose_matrix_src.h config_linmath.h coordinateSystem.h \ dbl2fltnames.h dblnames.h \ deg_2_rad.h deg_2_rad.I \ - flt2dblnames.h fltnames.h lcast_to.h lcast_to_src.I lcast_to_src.h \ + flt2dblnames.h fltnames.h intnames.h lcast_to.h lcast_to_src.I lcast_to_src.h \ lmat_ops.h lmat_ops_src.I lmat_ops_src.h lmatrix.h \ lmatrix3_src.I lmatrix3_src.h lmatrix4_src.I \ lmatrix4_src.h lorientation.h lorientation_src.I \ diff --git a/panda/src/linmath/config_linmath.cxx b/panda/src/linmath/config_linmath.cxx index ca15d71f91..8aab5f0568 100644 --- a/panda/src/linmath/config_linmath.cxx +++ b/panda/src/linmath/config_linmath.cxx @@ -88,6 +88,17 @@ init_liblinmath() { UnalignedLVecBase4d::init_type(); UnalignedLMatrix4d::init_type(); + LVecBase2i::init_type(); + LVecBase3i::init_type(); + LVecBase4i::init_type(); + LVector2i::init_type(); + LVector3i::init_type(); + LVector4i::init_type(); + LPoint2i::init_type(); + LPoint3i::init_type(); + LPoint4i::init_type(); + UnalignedLVecBase4i::init_type(); + LQuaternionf::init_type(); LRotationf::init_type(); LOrientationf::init_type(); diff --git a/panda/src/linmath/dblnames.h b/panda/src/linmath/dblnames.h index 9d089bd5a5..cb841dd977 100644 --- a/panda/src/linmath/dblnames.h +++ b/panda/src/linmath/dblnames.h @@ -37,9 +37,9 @@ #undef FLOATNAME #undef FLOATTOKEN #undef FLOATCONST +#undef FLOATTYPE_IS_INT #define FLOATTYPE double #define FLOATNAME(ARG) ARG##d #define FLOATTOKEN 'd' #define FLOATCONST(ARG) ARG - diff --git a/panda/src/linmath/fltnames.h b/panda/src/linmath/fltnames.h index 98946f7977..b6aae8bd3e 100644 --- a/panda/src/linmath/fltnames.h +++ b/panda/src/linmath/fltnames.h @@ -37,6 +37,7 @@ #undef FLOATNAME #undef FLOATTOKEN #undef FLOATCONST +#undef FLOATTYPE_IS_INT #define FLOATTYPE float #define FLOATNAME(ARG) ARG##f diff --git a/panda/src/linmath/intnames.h b/panda/src/linmath/intnames.h new file mode 100644 index 0000000000..1ae59f275a --- /dev/null +++ b/panda/src/linmath/intnames.h @@ -0,0 +1,46 @@ +// Filename: intnames.h +// Created by: rdb (07Jun14) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// +// This file is used throughout this directory, in conjunction with +// dblnames.h, to implement a poor man's template of the linmath +// objects on numeric type. The idea is to #include either fltnames.h +// or dblnames.h (or, in theory, intnames.h or any other numeric type +// we wanted to implement) and then to include the various *_src.h +// and/or *_src.cxx files that actually define the linmath objects. +// +// We do this instead of using actual templates to avoid some of the +// inherent problems with templates: compiler complexity and +// distributed code bloat, for instance; plus it allows us to +// implement #if-based specialization on numeric type for compilers +// (like VC++) that don't completely support template specialization. +// That and the fact that VC++ seems to have a particularly bad time +// with templates in general. +// +//////////////////////////////////////////////////////////////////// + + +#undef FLOATTYPE +#undef FLOATNAME +#undef FLOATTOKEN +#undef FLOATCONST +#undef FLOATTYPE_IS_INT + +#define FLOATTYPE int +#define FLOATNAME(ARG) ARG##i +#define FLOATTOKEN 'i' +#define FLOATCONST(ARG) ARG +#define FLOATTYPE_IS_INT diff --git a/panda/src/linmath/lcast_to_src.h b/panda/src/linmath/lcast_to_src.h index 55d2a3446f..9fa5b9e0cd 100644 --- a/panda/src/linmath/lcast_to_src.h +++ b/panda/src/linmath/lcast_to_src.h @@ -12,6 +12,8 @@ // //////////////////////////////////////////////////////////////////// +#ifndef CPPPARSER + INLINE_LINMATH const FLOATNAME(LVecBase2) & lcast_to(FLOATTYPE *, const FLOATNAME(LVecBase2) &source); @@ -85,3 +87,5 @@ INLINE_LINMATH FLOATNAME2(LMatrix4) lcast_to(FLOATTYPE2 *, const FLOATNAME(LMatrix4) &source); #include "lcast_to_src.I" + +#endif // CPPPARSER diff --git a/panda/src/linmath/lpoint2.cxx b/panda/src/linmath/lpoint2.cxx index 64f3df5a5f..f28a903549 100644 --- a/panda/src/linmath/lpoint2.cxx +++ b/panda/src/linmath/lpoint2.cxx @@ -20,3 +20,5 @@ #include "dblnames.h" #include "lpoint2_src.cxx" +#include "intnames.h" +#include "lpoint2_src.cxx" diff --git a/panda/src/linmath/lpoint2.h b/panda/src/linmath/lpoint2.h index 500bc858fe..9384bc99de 100644 --- a/panda/src/linmath/lpoint2.h +++ b/panda/src/linmath/lpoint2.h @@ -26,5 +26,7 @@ #include "dblnames.h" #include "lpoint2_src.h" +#include "intnames.h" +#include "lpoint2_src.h" #endif diff --git a/panda/src/linmath/lpoint2_ext.h b/panda/src/linmath/lpoint2_ext.h index 006697f0c0..c4a1a068e5 100644 --- a/panda/src/linmath/lpoint2_ext.h +++ b/panda/src/linmath/lpoint2_ext.h @@ -26,4 +26,7 @@ #include "dblnames.h" #include "lpoint2_ext_src.h" +#include "intnames.h" +#include "lpoint2_ext_src.h" + #endif diff --git a/panda/src/linmath/lpoint2_ext_src.I b/panda/src/linmath/lpoint2_ext_src.I index 195c1b38d9..d6deaa3a8b 100644 --- a/panda/src/linmath/lpoint2_ext_src.I +++ b/panda/src/linmath/lpoint2_ext_src.I @@ -18,6 +18,16 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint3); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint4); #endif +#ifdef FLOATTYPE_IS_INT +#if PY_MAJOR_VERSION >= 3 +#define PY_FROM_FLOATTYPE PyLong_FromLong +#else +#define PY_FROM_FLOATTYPE PyInt_FromLong +#endif +#else +#define PY_FROM_FLOATTYPE PyFloat_FromDouble +#endif + //////////////////////////////////////////////////////////////////// // Function: LPoint2::python_repr // Access: Published @@ -46,7 +56,7 @@ __getattr__(const string &attr_name) const { switch (attr_name.size()) { case 1: - return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); + return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); case 2: { FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2); @@ -84,3 +94,5 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase2. return invoke_extension(_this).__setattr__(self, attr_name, assign); } + +#undef PY_FROM_FLOATTYPE diff --git a/panda/src/linmath/lpoint2_src.I b/panda/src/linmath/lpoint2_src.I index 9184b5adab..a3f27084f6 100644 --- a/panda/src/linmath/lpoint2_src.I +++ b/panda/src/linmath/lpoint2_src.I @@ -185,6 +185,7 @@ operator / (FLOATTYPE scalar) const { return FLOATNAME(LPoint2)(FLOATNAME(LVecBase2)::operator / (scalar)); } +#ifndef FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LPoint2::project // Access: Published @@ -196,3 +197,4 @@ INLINE_LINMATH FLOATNAME(LPoint2) FLOATNAME(LPoint2):: project(const FLOATNAME(LVecBase2) &onto) const { return FLOATNAME(LVecBase2)::project(onto); } +#endif // FLOATTYPE_IS_INT diff --git a/panda/src/linmath/lpoint2_src.h b/panda/src/linmath/lpoint2_src.h index 7d726e4f33..5218cfc483 100644 --- a/panda/src/linmath/lpoint2_src.h +++ b/panda/src/linmath/lpoint2_src.h @@ -49,7 +49,10 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LPoint2) operator * (FLOATTYPE scalar) const; INLINE_LINMATH FLOATNAME(LPoint2) operator / (FLOATTYPE scalar) const; + +#ifndef FLOATTYPE_IS_INT INLINE_LINMATH FLOATNAME(LPoint2) project(const FLOATNAME(LVecBase2) &onto) const; +#endif EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); diff --git a/panda/src/linmath/lpoint3.cxx b/panda/src/linmath/lpoint3.cxx index f6e59d4857..8caa5a8b0f 100644 --- a/panda/src/linmath/lpoint3.cxx +++ b/panda/src/linmath/lpoint3.cxx @@ -20,3 +20,5 @@ #include "dblnames.h" #include "lpoint3_src.cxx" +#include "intnames.h" +#include "lpoint3_src.cxx" diff --git a/panda/src/linmath/lpoint3.h b/panda/src/linmath/lpoint3.h index 06d90128c4..a458777bd8 100644 --- a/panda/src/linmath/lpoint3.h +++ b/panda/src/linmath/lpoint3.h @@ -28,5 +28,7 @@ #include "dblnames.h" #include "lpoint3_src.h" +#include "intnames.h" +#include "lpoint3_src.h" #endif diff --git a/panda/src/linmath/lpoint3_ext.h b/panda/src/linmath/lpoint3_ext.h index 0f4c860b9e..5ba6d499c1 100644 --- a/panda/src/linmath/lpoint3_ext.h +++ b/panda/src/linmath/lpoint3_ext.h @@ -26,4 +26,7 @@ #include "dblnames.h" #include "lpoint3_ext_src.h" +#include "intnames.h" +#include "lpoint3_ext_src.h" + #endif diff --git a/panda/src/linmath/lpoint3_ext_src.I b/panda/src/linmath/lpoint3_ext_src.I index 19f32de4e7..583c4ff55a 100644 --- a/panda/src/linmath/lpoint3_ext_src.I +++ b/panda/src/linmath/lpoint3_ext_src.I @@ -18,6 +18,16 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint3); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint4); #endif +#ifdef FLOATTYPE_IS_INT +#if PY_MAJOR_VERSION >= 3 +#define PY_FROM_FLOATTYPE PyLong_FromLong +#else +#define PY_FROM_FLOATTYPE PyInt_FromLong +#endif +#else +#define PY_FROM_FLOATTYPE PyFloat_FromDouble +#endif + //////////////////////////////////////////////////////////////////// // Function: LPoint3::python_repr // Access: Published @@ -47,7 +57,7 @@ __getattr__(const string &attr_name) const { switch (attr_name.size()) { case 1: - return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); + return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); case 2: { FLOATNAME(LPoint2) *vec = new FLOATNAME(LPoint2); @@ -85,3 +95,5 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase2. return invoke_extension(_this).__setattr__(self, attr_name, assign); } + +#undef PY_FROM_FLOATTYPE diff --git a/panda/src/linmath/lpoint3_src.I b/panda/src/linmath/lpoint3_src.I index d8fdec75a9..9f8143c7d7 100644 --- a/panda/src/linmath/lpoint3_src.I +++ b/panda/src/linmath/lpoint3_src.I @@ -75,6 +75,17 @@ FLOATNAME(LPoint3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) : { } +//////////////////////////////////////////////////////////////////// +// Function: LPoint3::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LPoint3):: +FLOATNAME(LPoint3)(const FLOATNAME(LVecBase2) ©, FLOATTYPE z) : + FLOATNAME(LVecBase3)(copy, z) +{ +} + //////////////////////////////////////////////////////////////////// // Function: LPoint3::zero Named Constructor // Access: Public @@ -218,6 +229,7 @@ cross(const FLOATNAME(LVecBase3) &other) const { return FLOATNAME(LVecBase3)::cross(other); } +#ifndef FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LPoint3::project // Access: Published @@ -229,6 +241,7 @@ INLINE_LINMATH FLOATNAME(LPoint3) FLOATNAME(LPoint3):: project(const FLOATNAME(LVecBase3) &onto) const { return FLOATNAME(LVecBase3)::project(onto); } +#endif // FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LPoint3::operator * scalar @@ -258,9 +271,9 @@ operator / (FLOATTYPE scalar) const { // existing coordinate systems; it's hard to imagine it // ever being different. //////////////////////////////////////////////////////////////////// -INLINE_LINMATH FLOATNAME(LPoint3) FLOATNAME(LPoint3):: +INLINE_LINMATH const FLOATNAME(LPoint3) &FLOATNAME(LPoint3):: origin(CoordinateSystem) { - return FLOATNAME(LPoint3)(0.0f, 0.0f, 0.0f); + return FLOATNAME(LPoint3)::zero(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lpoint3_src.h b/panda/src/linmath/lpoint3_src.h index ce1852bda5..11c1ccc29d 100644 --- a/panda/src/linmath/lpoint3_src.h +++ b/panda/src/linmath/lpoint3_src.h @@ -30,6 +30,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LPoint3) &operator = (FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LPoint3)(FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LPoint3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z); + INLINE_LINMATH FLOATNAME(LPoint3)(const FLOATNAME(LVecBase2) ©, FLOATTYPE z); EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); @@ -58,13 +59,17 @@ PUBLISHED: operator - (const FLOATNAME(LVector3) &other) const; INLINE_LINMATH FLOATNAME(LPoint3) cross(const FLOATNAME(LVecBase3) &other) const; + +#ifndef FLOATTYPE_IS_INT INLINE_LINMATH FLOATNAME(LPoint3) project(const FLOATNAME(LVecBase3) &onto) const; +#endif + INLINE_LINMATH FLOATNAME(LPoint3) operator * (FLOATTYPE scalar) const; INLINE_LINMATH FLOATNAME(LPoint3) operator / (FLOATTYPE scalar) const; // Some special named constructors for LPoint3. - INLINE_LINMATH static FLOATNAME(LPoint3) origin(CoordinateSystem cs = CS_default); + INLINE_LINMATH static const FLOATNAME(LPoint3) &origin(CoordinateSystem cs = CS_default); INLINE_LINMATH static FLOATNAME(LPoint3) rfu(FLOATTYPE right, FLOATTYPE fwd, FLOATTYPE up, diff --git a/panda/src/linmath/lpoint4.cxx b/panda/src/linmath/lpoint4.cxx index 242c365715..373cf273d3 100644 --- a/panda/src/linmath/lpoint4.cxx +++ b/panda/src/linmath/lpoint4.cxx @@ -20,3 +20,5 @@ #include "dblnames.h" #include "lpoint4_src.cxx" +#include "intnames.h" +#include "lpoint4_src.cxx" diff --git a/panda/src/linmath/lpoint4.h b/panda/src/linmath/lpoint4.h index 097712a6e5..f7b69f02ec 100644 --- a/panda/src/linmath/lpoint4.h +++ b/panda/src/linmath/lpoint4.h @@ -26,4 +26,7 @@ #include "dblnames.h" #include "lpoint4_src.h" +#include "intnames.h" +#include "lpoint4_src.h" + #endif diff --git a/panda/src/linmath/lpoint4_ext.h b/panda/src/linmath/lpoint4_ext.h index ac51d90156..31704152a4 100644 --- a/panda/src/linmath/lpoint4_ext.h +++ b/panda/src/linmath/lpoint4_ext.h @@ -26,4 +26,7 @@ #include "dblnames.h" #include "lpoint4_ext_src.h" +#include "intnames.h" +#include "lpoint4_ext_src.h" + #endif diff --git a/panda/src/linmath/lpoint4_ext_src.I b/panda/src/linmath/lpoint4_ext_src.I index 841e1271b2..c34af5986e 100644 --- a/panda/src/linmath/lpoint4_ext_src.I +++ b/panda/src/linmath/lpoint4_ext_src.I @@ -18,6 +18,16 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint3); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LPoint4); #endif +#ifdef FLOATTYPE_IS_INT +#if PY_MAJOR_VERSION >= 3 +#define PY_FROM_FLOATTYPE PyLong_FromLong +#else +#define PY_FROM_FLOATTYPE PyInt_FromLong +#endif +#else +#define PY_FROM_FLOATTYPE PyFloat_FromDouble +#endif + //////////////////////////////////////////////////////////////////// // Function: LPoint4::python_repr // Access: Published @@ -49,9 +59,9 @@ __getattr__(const string &attr_name) const { switch (attr_name.size()) { case 1: if (attr_name[0] == 'w') { - return PyFloat_FromDouble(_this->_v(3)); + return PY_FROM_FLOATTYPE(_this->_v(3)); } else { - return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); + return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); } case 2: { @@ -90,3 +100,5 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase4. return invoke_extension(_this).__setattr__(self, attr_name, assign); } + +#undef PY_FROM_FLOATTYPE diff --git a/panda/src/linmath/lpoint4_src.I b/panda/src/linmath/lpoint4_src.I index f9e2819a13..d1a7e7b3ab 100644 --- a/panda/src/linmath/lpoint4_src.I +++ b/panda/src/linmath/lpoint4_src.I @@ -75,6 +75,17 @@ FLOATNAME(LPoint4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) : { } +//////////////////////////////////////////////////////////////////// +// Function: LPoint4::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LPoint4):: +FLOATNAME(LPoint4)(const FLOATNAME(LVecBase3) ©, FLOATTYPE w) : + FLOATNAME(LVecBase4)(copy, w) +{ +} + //////////////////////////////////////////////////////////////////// // Function: LPoint4::zero Named Constructor // Access: Public @@ -205,6 +216,7 @@ operator / (FLOATTYPE scalar) const { return FLOATNAME(LPoint4)(FLOATNAME(LVecBase4)::operator / (scalar)); } +#ifndef FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LPoint4::project // Access: Published @@ -216,4 +228,4 @@ INLINE_LINMATH FLOATNAME(LPoint4) FLOATNAME(LPoint4):: project(const FLOATNAME(LVecBase4) &onto) const { return FLOATNAME(LVecBase4)::project(onto); } - +#endif // FLOATTYPE_IS_INT diff --git a/panda/src/linmath/lpoint4_src.h b/panda/src/linmath/lpoint4_src.h index 04404b8713..877c3fe766 100644 --- a/panda/src/linmath/lpoint4_src.h +++ b/panda/src/linmath/lpoint4_src.h @@ -24,6 +24,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LPoint4) &operator = (FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LPoint4)(FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LPoint4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w); + INLINE_LINMATH FLOATNAME(LPoint4)(const FLOATNAME(LVecBase3) ©, FLOATTYPE w); EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); @@ -50,7 +51,10 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LPoint4) operator * (FLOATTYPE scalar) const; INLINE_LINMATH FLOATNAME(LPoint4) operator / (FLOATTYPE scalar) const; + +#ifndef FLOATTYPE_IS_INT INLINE_LINMATH FLOATNAME(LPoint4) project(const FLOATNAME(LVecBase4) &onto) const; +#endif EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); diff --git a/panda/src/linmath/lquaternion.h b/panda/src/linmath/lquaternion.h index f0da179aa9..fcb123c257 100644 --- a/panda/src/linmath/lquaternion.h +++ b/panda/src/linmath/lquaternion.h @@ -31,5 +31,4 @@ #include "dblnames.h" #include "lquaternion_src.h" - #endif /* __LQUATERNION_H__ */ diff --git a/panda/src/linmath/luse.N b/panda/src/linmath/luse.N index 7b82e0ac27..20da19f1c8 100644 --- a/panda/src/linmath/luse.N +++ b/panda/src/linmath/luse.N @@ -2,23 +2,32 @@ defconstruct LPoint2f new LPoint2f(0.0f) defconstruct LPoint3f new LPoint3f(0.0f) defconstruct LPoint4f new LPoint4f(0.0f) -defconstruct LPoint2d new LPoint2d(0.0f) -defconstruct LPoint3d new LPoint3d(0.0f) -defconstruct LPoint4d new LPoint4d(0.0f) +defconstruct LPoint2d new LPoint2d(0.0) +defconstruct LPoint3d new LPoint3d(0.0) +defconstruct LPoint4d new LPoint4d(0.0) +defconstruct LPoint2i new LPoint2i(0) +defconstruct LPoint3i new LPoint3i(0) +defconstruct LPoint4i new LPoint4i(0) defconstruct LVecBase2f new LVecBase2f(0.0f) defconstruct LVecBase3f new LVecBase3f(0.0f) defconstruct LVecBase4f new LVecBase4f(0.0f) -defconstruct LVecBase2d new LVecBase2d(0.0f) -defconstruct LVecBase3d new LVecBase3d(0.0f) -defconstruct LVecBase4d new LVecBase4d(0.0f) +defconstruct LVecBase2d new LVecBase2d(0.0) +defconstruct LVecBase3d new LVecBase3d(0.0) +defconstruct LVecBase4d new LVecBase4d(0.0) +defconstruct LVecBase2i new LVecBase2i(0) +defconstruct LVecBase3i new LVecBase3i(0) +defconstruct LVecBase4i new LVecBase4i(0) defconstruct LVector2f new LVector2f(0.0f) defconstruct LVector3f new LVector3f(0.0f) defconstruct LVector4f new LVector4f(0.0f) -defconstruct LVector2d new LVector2d(0.0f) -defconstruct LVector3d new LVector3d(0.0f) -defconstruct LVector4d new LVector4d(0.0f) +defconstruct LVector2d new LVector2d(0.0) +defconstruct LVector3d new LVector3d(0.0) +defconstruct LVector4d new LVector4d(0.0) +defconstruct LVector2i new LVector2i(0) +defconstruct LVector3i new LVector3i(0) +defconstruct LVector4i new LVector4i(0) defconstruct LMatrix3f new LMatrix3f(LMatrix3f::ident_mat()) defconstruct LMatrix4f new LMatrix4f(LMatrix4f::ident_mat()) diff --git a/panda/src/linmath/lvec2_ops.h b/panda/src/linmath/lvec2_ops.h index 89b31baba4..819bc7bf59 100644 --- a/panda/src/linmath/lvec2_ops.h +++ b/panda/src/linmath/lvec2_ops.h @@ -27,4 +27,7 @@ #include "dblnames.h" #include "lvec2_ops_src.h" +#include "intnames.h" +#include "lvec2_ops_src.h" + #endif diff --git a/panda/src/linmath/lvec2_ops_src.I b/panda/src/linmath/lvec2_ops_src.I index 3ca435033c..de3e19cab3 100644 --- a/panda/src/linmath/lvec2_ops_src.I +++ b/panda/src/linmath/lvec2_ops_src.I @@ -48,6 +48,7 @@ dot(const FLOATNAME(LVecBase2) &a, const FLOATNAME(LVecBase2) &b) { return a.dot(b); } +#ifndef FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: length of a vector // Description: @@ -67,7 +68,7 @@ normalize(const FLOATNAME(LVector2) &v) { v1.normalize(); return v1; } - +#endif // FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: generic_write_datagram diff --git a/panda/src/linmath/lvec2_ops_src.h b/panda/src/linmath/lvec2_ops_src.h index 150345c47f..fe65dd8862 100644 --- a/panda/src/linmath/lvec2_ops_src.h +++ b/panda/src/linmath/lvec2_ops_src.h @@ -33,14 +33,15 @@ operator * (FLOATTYPE scalar, const FLOATNAME(LVector2) &a); INLINE_LINMATH FLOATTYPE dot(const FLOATNAME(LVecBase2) &a, const FLOATNAME(LVecBase2) &b); +#ifndef FLOATTYPE_IS_INT // Length of a vector. INLINE_LINMATH FLOATTYPE length(const FLOATNAME(LVector2) &a); - // A normalized vector. INLINE_LINMATH FLOATNAME(LVector2) normalize(const FLOATNAME(LVector2) &v); +#endif // FLOATTYPE_IS_INT INLINE_LINMATH void generic_write_datagram(Datagram &dest, const FLOATNAME(LVecBase2) &value); diff --git a/panda/src/linmath/lvec3_ops.h b/panda/src/linmath/lvec3_ops.h index 24f34ed842..e6b394e297 100644 --- a/panda/src/linmath/lvec3_ops.h +++ b/panda/src/linmath/lvec3_ops.h @@ -27,5 +27,7 @@ #include "dblnames.h" #include "lvec3_ops_src.h" +#include "intnames.h" +#include "lvec3_ops_src.h" #endif diff --git a/panda/src/linmath/lvec3_ops_src.I b/panda/src/linmath/lvec3_ops_src.I index 8e978679d1..b68b8064d4 100644 --- a/panda/src/linmath/lvec3_ops_src.I +++ b/panda/src/linmath/lvec3_ops_src.I @@ -70,7 +70,7 @@ cross(const FLOATNAME(LVector3) &a, const FLOATNAME(LVector3) &b) { return FLOATNAME(LVector3)(a.cross(b)); } - +#ifndef FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: length of a vector // Description: @@ -81,7 +81,6 @@ length(const FLOATNAME(LVecBase3) &a) { return a.length(); } - //////////////////////////////////////////////////////////////////// // Function: normalize // Description: Returns a normalized vector from the given vector. @@ -93,6 +92,7 @@ normalize(const FLOATNAME(LVecBase3) &v) { v1.normalize(); return v1; } +#endif // FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: generic_write_datagram diff --git a/panda/src/linmath/lvec3_ops_src.h b/panda/src/linmath/lvec3_ops_src.h index 797d0bb17a..e3cdb4b0b7 100644 --- a/panda/src/linmath/lvec3_ops_src.h +++ b/panda/src/linmath/lvec3_ops_src.h @@ -41,7 +41,7 @@ cross(const FLOATNAME(LVecBase3) &a, const FLOATNAME(LVecBase3) &b); INLINE_LINMATH FLOATNAME(LVector3) cross(const FLOATNAME(LVector3) &a, const FLOATNAME(LVector3) &b); - +#ifndef FLOATTYPE_IS_INT // Length of a vector. INLINE_LINMATH FLOATTYPE length(const FLOATNAME(LVecBase3) &a); @@ -49,6 +49,7 @@ length(const FLOATNAME(LVecBase3) &a); // A normalized vector. INLINE_LINMATH FLOATNAME(LVector3) normalize(const FLOATNAME(LVecBase3) &v); +#endif // FLOATTYPE_IS_INT INLINE_LINMATH void generic_write_datagram(Datagram &dest, const FLOATNAME(LVecBase3) &value); diff --git a/panda/src/linmath/lvec4_ops.h b/panda/src/linmath/lvec4_ops.h index 88ed60e6b0..b020bd5df9 100644 --- a/panda/src/linmath/lvec4_ops.h +++ b/panda/src/linmath/lvec4_ops.h @@ -27,5 +27,7 @@ #include "dblnames.h" #include "lvec4_ops_src.h" +#include "intnames.h" +#include "lvec4_ops_src.h" #endif diff --git a/panda/src/linmath/lvec4_ops_src.I b/panda/src/linmath/lvec4_ops_src.I index 6f97a1f26a..2e4c72da51 100644 --- a/panda/src/linmath/lvec4_ops_src.I +++ b/panda/src/linmath/lvec4_ops_src.I @@ -49,6 +49,7 @@ dot(const FLOATNAME(LVecBase4) &a, const FLOATNAME(LVecBase4) &b) { return a.dot(b); } +#ifndef FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: length of a vector // Description: @@ -59,7 +60,6 @@ length(const FLOATNAME(LVector4) &a) { return a.length(); } - //////////////////////////////////////////////////////////////////// // Function: normalize // Description: Returns a normalized vector from the given vector. @@ -71,6 +71,7 @@ normalize(const FLOATNAME(LVector4) &v) { v1.normalize(); return v1; } +#endif // FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: generic_write_datagram diff --git a/panda/src/linmath/lvec4_ops_src.h b/panda/src/linmath/lvec4_ops_src.h index 425f5f3194..86ef7350aa 100644 --- a/panda/src/linmath/lvec4_ops_src.h +++ b/panda/src/linmath/lvec4_ops_src.h @@ -33,15 +33,15 @@ operator * (FLOATTYPE scalar, const FLOATNAME(LVector4) &a); INLINE_LINMATH FLOATTYPE dot(const FLOATNAME(LVecBase4) &a, const FLOATNAME(LVecBase4) &b); - +#ifndef FLOATTYPE_IS_INT // Length of a vector. INLINE_LINMATH FLOATTYPE length(const FLOATNAME(LVector4) &a); - // A normalized vector. INLINE_LINMATH FLOATNAME(LVector4) normalize(const FLOATNAME(LVector4) &v); +#endif // FLOATTYPE_IS_INT INLINE_LINMATH void generic_write_datagram(Datagram &dest, const FLOATNAME(LVecBase4) &value); diff --git a/panda/src/linmath/lvecBase2.cxx b/panda/src/linmath/lvecBase2.cxx index 77be67d08e..ad14be3a47 100644 --- a/panda/src/linmath/lvecBase2.cxx +++ b/panda/src/linmath/lvecBase2.cxx @@ -20,3 +20,5 @@ #include "dblnames.h" #include "lvecBase2_src.cxx" +#include "intnames.h" +#include "lvecBase2_src.cxx" diff --git a/panda/src/linmath/lvecBase2.h b/panda/src/linmath/lvecBase2.h index 42e87b40a8..e5c150ceaf 100644 --- a/panda/src/linmath/lvecBase2.h +++ b/panda/src/linmath/lvecBase2.h @@ -16,6 +16,7 @@ #define LVECBASE2_H #include "pandabase.h" +#include "config_linmath.h" #include "typedObject.h" #include "pnotify.h" #include "datagram.h" @@ -37,4 +38,7 @@ class DatagramIterator; #include "dblnames.h" #include "lvecBase2_src.h" +#include "intnames.h" +#include "lvecBase2_src.h" + #endif diff --git a/panda/src/linmath/lvecBase2_ext.h b/panda/src/linmath/lvecBase2_ext.h index 59f06da699..9e2e262596 100644 --- a/panda/src/linmath/lvecBase2_ext.h +++ b/panda/src/linmath/lvecBase2_ext.h @@ -24,4 +24,7 @@ #include "dblnames.h" #include "lvecBase2_ext_src.h" +#include "intnames.h" +#include "lvecBase2_ext_src.h" + #endif diff --git a/panda/src/linmath/lvecBase2_ext_src.I b/panda/src/linmath/lvecBase2_ext_src.I index 6f8bef7585..7910b6aec3 100644 --- a/panda/src/linmath/lvecBase2_ext_src.I +++ b/panda/src/linmath/lvecBase2_ext_src.I @@ -19,6 +19,22 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); #endif +#ifdef FLOATTYPE_IS_INT +#if PY_MAJOR_VERSION >= 3 +#define PYNUMBER_FLOATTYPE PyNumber_Long +#define PY_FROM_FLOATTYPE PyLong_FromLong +#define PY_AS_FLOATTYPE PyLong_AS_LONG +#else +#define PYNUMBER_FLOATTYPE PyNumber_Int +#define PY_FROM_FLOATTYPE PyInt_FromLong +#define PY_AS_FLOATTYPE PyInt_AS_LONG +#endif +#else +#define PYNUMBER_FLOATTYPE PyNumber_Float +#define PY_FROM_FLOATTYPE PyFloat_FromDouble +#define PY_AS_FLOATTYPE PyFloat_AsDouble +#endif + //////////////////////////////////////////////////////////////////// // Function: LVecBase2::__setitem__ // Access: Public @@ -59,8 +75,17 @@ __reduce__(PyObject *self) const { return NULL; } +#if FLOATTOKEN == 'i' + PyObject *result = Py_BuildValue("(O(ii))", this_class, + (*_this)[0], (*_this)[1]); +#elif FLOATTOKEN == 'f' PyObject *result = Py_BuildValue("(O(ff))", this_class, (*_this)[0], (*_this)[1]); +#else + PyObject *result = Py_BuildValue("(O(dd))", this_class, + (*_this)[0], (*_this)[1]); +#endif + Py_DECREF(this_class); return result; } @@ -81,7 +106,7 @@ __getattr__(const string &attr_name) const { switch (attr_name.size()) { case 1: - return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); + return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); case 2: { FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2); @@ -148,14 +173,18 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { PyObject** items = PySequence_Fast_ITEMS(fast); for (size_t i = 0; i < attr_name.size(); ++i) { - PyObject* fl = PyNumber_Float(items[i]); + PyObject* fl = PYNUMBER_FLOATTYPE(items[i]); if (fl == NULL) { // Oh darn. Not when we've come this far. +#ifdef FLOATTYPE_IS_INT + PyErr_SetString(PyExc_ValueError, "a sequence of integers is required"); +#else PyErr_SetString(PyExc_ValueError, "a sequence of floats is required"); +#endif Py_DECREF(fast); return -1; } - double value = PyFloat_AS_DOUBLE(fl); + FLOATTYPE value = PY_AS_FLOATTYPE(fl); Py_DECREF(fl); _this->_v(attr_name[i] - 'x') = value; @@ -165,19 +194,23 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { } else { // Maybe it's a single floating-point value. - PyObject* fl = PyNumber_Float(assign); + PyObject* fl = PYNUMBER_FLOATTYPE(assign); if (fl == NULL) { // It's not a floating-point value either? // Sheesh, I don't know what to do with it then. if (attr_name.size() == 1) { +#ifdef FLOATTYPE_IS_INT + PyErr_SetString(PyExc_ValueError, "an integer is required"); +#else PyErr_SetString(PyExc_ValueError, "a float is required"); +#endif } else { PyErr_Format(PyExc_ValueError, "'%.200s' object is not iterable", assign->ob_type->tp_name); } return -1; } - double value = PyFloat_AS_DOUBLE(fl); + FLOATTYPE value = PY_AS_FLOATTYPE(fl); Py_DECREF(fl); // Loop through the components in the attribute name, @@ -189,3 +222,32 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { return 0; } + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase2::__pow__ +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVecBase2) Extension:: +__pow__(FLOATTYPE exponent) const { + return FLOATNAME(LVecBase2)( + cpow(_this->_v(0), exponent), + cpow(_this->_v(1), exponent)); +} + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase2::__ipow__ +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH PyObject *Extension:: +__ipow__(PyObject *self, FLOATTYPE exponent) { + _this->_v(0) = cpow(_this->_v(0), exponent); + _this->_v(1) = cpow(_this->_v(1), exponent); + Py_INCREF(self); + return self; +} + +#undef PYNUMBER_FLOATTYPE +#undef PY_FROM_FLOATTYPE +#undef PY_AS_FLOATTYPE diff --git a/panda/src/linmath/lvecBase2_ext_src.h b/panda/src/linmath/lvecBase2_ext_src.h index 65b815e04a..0e7cba9a4f 100644 --- a/panda/src/linmath/lvecBase2_ext_src.h +++ b/panda/src/linmath/lvecBase2_ext_src.h @@ -27,6 +27,9 @@ public: INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); INLINE_LINMATH void __setitem__(int i, FLOATTYPE v); INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + + INLINE_LINMATH FLOATNAME(LVecBase2) __pow__(FLOATTYPE exponent) const; + INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent); }; #include "lvecBase2_ext_src.I" diff --git a/panda/src/linmath/lvecBase2_src.I b/panda/src/linmath/lvecBase2_src.I index 37ad3f0f20..d4869daa13 100644 --- a/panda/src/linmath/lvecBase2_src.I +++ b/panda/src/linmath/lvecBase2_src.I @@ -123,7 +123,7 @@ INLINE_LINMATH FLOATNAME(LVecBase2):: //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase2):: operator [](int i) const { - nassertr(i >= 0 && i < 2, 0.0); + nassertr(i >= 0 && i < 2, 0); return _v(i); } @@ -156,8 +156,12 @@ size() { //////////////////////////////////////////////////////////////////// INLINE_LINMATH bool FLOATNAME(LVecBase2):: is_nan() const { +#ifdef FLOATTYPE_IS_INT + return false; +#else TAU_PROFILE("bool LVecBase2::is_nan()", " ", TAU_USER); return cnan(_v(0)) || cnan(_v(1)); +#endif } //////////////////////////////////////////////////////////////////// @@ -167,7 +171,7 @@ is_nan() const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase2):: get_cell(int i) const { - nassertr(i >= 0 && i < 2, 0.0); + nassertr(i >= 0 && i < 2, 0); return _v(i); } @@ -346,18 +350,17 @@ set(FLOATTYPE x, FLOATTYPE y) { } //////////////////////////////////////////////////////////////////// -// Function: LVecBase2::length +// Function: LVecBase2::dot // Access: Published -// Description: Returns the length of the vector, by the Pythagorean -// theorem. +// Description: //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase2):: -length() const { - TAU_PROFILE("FLOATTYPE LVecBase2::length()", " ", TAU_USER); +dot(const FLOATNAME(LVecBase2) &other) const { + TAU_PROFILE("FLOATTYPE LVecBase2::dot()", " ", TAU_USER); #ifdef HAVE_EIGEN - return _v.norm(); + return _v.dot(other._v); #else - return csqrt((*this).dot(*this)); + return _v(0) * other._v(0) + _v(1) * other._v(1); #endif // HAVE_EIGEN } @@ -377,6 +380,23 @@ length_squared() const { #endif // HAVE_EIGEN } +#ifndef FLOATTYPE_IS_INT +//////////////////////////////////////////////////////////////////// +// Function: LVecBase2::length +// Access: Published +// Description: Returns the length of the vector, by the Pythagorean +// theorem. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase2):: +length() const { + TAU_PROFILE("FLOATTYPE LVecBase2::length()", " ", TAU_USER); +#ifdef HAVE_EIGEN + return _v.norm(); +#else + return csqrt((*this).dot(*this)); +#endif // HAVE_EIGEN +} + //////////////////////////////////////////////////////////////////// // Function: LVecBase2::normalize // Access: Published @@ -398,21 +418,6 @@ normalize() { return true; } -//////////////////////////////////////////////////////////////////// -// Function: LVecBase2::dot -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase2):: -dot(const FLOATNAME(LVecBase2) &other) const { - TAU_PROFILE("FLOATTYPE LVecBase2::dot()", " ", TAU_USER); -#ifdef HAVE_EIGEN - return _v.dot(other._v); -#else - return _v(0) * other._v(0) + _v(1) * other._v(1); -#endif // HAVE_EIGEN -} - //////////////////////////////////////////////////////////////////// // Function: LVecBase2::project // Access: Published @@ -424,6 +429,7 @@ INLINE_LINMATH FLOATNAME(LVecBase2) FLOATNAME(LVecBase2):: project(const FLOATNAME(LVecBase2) &onto) const { return onto * (dot(onto) / onto.length_squared()); } +#endif // FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LVecBase2::operator < @@ -475,9 +481,64 @@ operator != (const FLOATNAME(LVecBase2) &other) const { INLINE_LINMATH int FLOATNAME(LVecBase2):: compare_to(const FLOATNAME(LVecBase2) &other) const { TAU_PROFILE("int LVecBase2::compare_to(const LVecBase2 &)", " ", TAU_USER); +#ifdef FLOATTYPE_IS_INT + if (_v(0) != other._v(0)) { + return (_v(0) < other._v(0)) ? -1 : 1; + } + if (_v(1) != other._v(1)) { + return (_v(1) < other._v(1)) ? -1 : 1; + } + return 0; +#else return compare_to(other, NEARLY_ZERO(FLOATTYPE)); +#endif } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase2::get_hash +// Access: Published +// Description: Returns a suitable hash for phash_map. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH size_t FLOATNAME(LVecBase2):: +get_hash() const { + TAU_PROFILE("size_t LVecBase2::get_hash()", " ", TAU_USER); + return add_hash(0); +} + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase2::add_hash +// Access: Published +// Description: Adds the vector into the running hash. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH size_t FLOATNAME(LVecBase2):: +add_hash(size_t hash) const { + TAU_PROFILE("size_t LVecBase2::add_hash(size_t)", " ", TAU_USER); +#ifdef FLOATTYPE_IS_INT + int_hash ihasher; + hash = ihasher.add_hash(hash, _v(0)); + hash = ihasher.add_hash(hash, _v(1)); + return hash; +#else + return add_hash(hash, NEARLY_ZERO(FLOATTYPE)); +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase2::generate_hash +// Access: Published +// Description: Adds the vector to the indicated hash generator. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH void FLOATNAME(LVecBase2):: +generate_hash(ChecksumHashGenerator &hashgen) const { +#ifdef FLOATTYPE_IS_INT + hashgen.add_int(_v(0)); + hashgen.add_int(_v(1)); +#else + generate_hash(hashgen, NEARLY_ZERO(FLOATTYPE)); +#endif +} + +#ifndef FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LVecBase2::compare_to // Access: Published @@ -499,17 +560,6 @@ compare_to(const FLOATNAME(LVecBase2) &other, FLOATTYPE threshold) const { return 0; } -//////////////////////////////////////////////////////////////////// -// Function: LVecBase2::get_hash -// Access: Published -// Description: Returns a suitable hash for phash_map. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH size_t FLOATNAME(LVecBase2):: -get_hash() const { - TAU_PROFILE("size_t LVecBase2::get_hash()", " ", TAU_USER); - return add_hash(0); -} - //////////////////////////////////////////////////////////////////// // Function: LVecBase2::get_hash // Access: Published @@ -521,17 +571,6 @@ get_hash(FLOATTYPE threshold) const { return add_hash(0, threshold); } -//////////////////////////////////////////////////////////////////// -// Function: LVecBase2::add_hash -// Access: Published -// Description: Adds the vector into the running hash. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH size_t FLOATNAME(LVecBase2):: -add_hash(size_t hash) const { - TAU_PROFILE("size_t LVecBase2::add_hash(size_t)", " ", TAU_USER); - return add_hash(hash, NEARLY_ZERO(FLOATTYPE)); -} - //////////////////////////////////////////////////////////////////// // Function: LVecBase2::add_hash // Access: Published @@ -546,6 +585,18 @@ add_hash(size_t hash, FLOATTYPE threshold) const { return hash; } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase2::generate_hash +// Access: Published +// Description: Adds the vector to the indicated hash generator. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH void FLOATNAME(LVecBase2):: +generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const { + hashgen.add_fp(_v(0), threshold); + hashgen.add_fp(_v(1), threshold); +} +#endif // FLOATTYPE_IS_INT + //////////////////////////////////////////////////////////////////// // Function: LVecBase2::unary - // Access: Published @@ -612,8 +663,13 @@ operator * (FLOATTYPE scalar) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATNAME(LVecBase2) FLOATNAME(LVecBase2):: operator / (FLOATTYPE scalar) const { +#ifdef FLOATTYPE_IS_INT + return FLOATNAME(LVecBase2)(_v(0) / scalar, + _v(1) / scalar); +#else FLOATTYPE recip_scalar = 1.0f/scalar; return operator * (recip_scalar); +#endif } //////////////////////////////////////////////////////////////////// @@ -668,8 +724,13 @@ operator *= (FLOATTYPE scalar) { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase2):: operator /= (FLOATTYPE scalar) { +#ifdef FLOATTYPE_IS_INT + _v(0) /= scalar; + _v(1) /= scalar; +#else FLOATTYPE recip_scalar = 1.0f/scalar; operator *= (recip_scalar); +#endif } //////////////////////////////////////////////////////////////////// @@ -732,27 +793,6 @@ output(ostream &out) const { << MAYBE_ZERO(_v(1)); } -//////////////////////////////////////////////////////////////////// -// Function: LVecBase2::generate_hash -// Access: Published -// Description: Adds the vector to the indicated hash generator. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH void FLOATNAME(LVecBase2):: -generate_hash(ChecksumHashGenerator &hashgen) const { - generate_hash(hashgen, NEARLY_ZERO(FLOATTYPE)); -} - -//////////////////////////////////////////////////////////////////// -// Function: LVecBase2::generate_hash -// Access: Published -// Description: Adds the vector to the indicated hash generator. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH void FLOATNAME(LVecBase2):: -generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const { - hashgen.add_fp(_v(0), threshold); - hashgen.add_fp(_v(1), threshold); -} - //////////////////////////////////////////////////////////////////// // Function: LVecBase2::write_datagram_fixed // Access: Published @@ -766,7 +806,10 @@ generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase2):: write_datagram_fixed(Datagram &destination) const { -#if FLOATTOKEN == 'f' +#if FLOATTOKEN == 'i' + destination.add_int32(_v(0)); + destination.add_int32(_v(1)); +#elif FLOATTOKEN == 'f' destination.add_float32(_v(0)); destination.add_float32(_v(1)); #else @@ -783,7 +826,10 @@ write_datagram_fixed(Datagram &destination) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase2):: read_datagram_fixed(DatagramIterator &source) { -#if FLOATTOKEN == 'f' +#if FLOATTOKEN == 'i' + _v(0) = source.get_int32(); + _v(1) = source.get_int32(); +#elif FLOATTOKEN == 'f' _v(0) = source.get_float32(); _v(1) = source.get_float32(); #else @@ -802,8 +848,13 @@ read_datagram_fixed(DatagramIterator &source) { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase2):: write_datagram(Datagram &destination) const { +#if FLOATTOKEN == 'i' + destination.add_int32(_v(0)); + destination.add_int32(_v(1)); +#else destination.add_stdfloat(_v(0)); destination.add_stdfloat(_v(1)); +#endif } //////////////////////////////////////////////////////////////////// @@ -813,6 +864,11 @@ write_datagram(Datagram &destination) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase2):: read_datagram(DatagramIterator &source) { +#if FLOATTOKEN == 'i' + _v(0) = source.get_int32(); + _v(1) = source.get_int32(); +#else _v(0) = source.get_stdfloat(); _v(1) = source.get_stdfloat(); +#endif } diff --git a/panda/src/linmath/lvecBase2_src.cxx b/panda/src/linmath/lvecBase2_src.cxx index a4b591564d..02a5507069 100644 --- a/panda/src/linmath/lvecBase2_src.cxx +++ b/panda/src/linmath/lvecBase2_src.cxx @@ -15,11 +15,11 @@ TypeHandle FLOATNAME(LVecBase2)::_type_handle; const FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::_zero = - FLOATNAME(LVecBase2)(0.0f, 0.0f); + FLOATNAME(LVecBase2)(0, 0); const FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::_unit_x = - FLOATNAME(LVecBase2)(1.0f, 0.0f); + FLOATNAME(LVecBase2)(1, 0); const FLOATNAME(LVecBase2) FLOATNAME(LVecBase2)::_unit_y = - FLOATNAME(LVecBase2)(0.0f, 1.0f); + FLOATNAME(LVecBase2)(0, 1); //////////////////////////////////////////////////////////////////// // Function: LVecBase2::init_type diff --git a/panda/src/linmath/lvecBase2_src.h b/panda/src/linmath/lvecBase2_src.h index f2daaae505..979165fa4d 100644 --- a/panda/src/linmath/lvecBase2_src.h +++ b/panda/src/linmath/lvecBase2_src.h @@ -78,24 +78,32 @@ PUBLISHED: INLINE_LINMATH void fill(FLOATTYPE fill_value); INLINE_LINMATH void set(FLOATTYPE x, FLOATTYPE y); - INLINE_LINMATH FLOATTYPE length() const; - INLINE_LINMATH FLOATTYPE length_squared() const; - INLINE_LINMATH bool normalize(); - INLINE_LINMATH FLOATTYPE dot(const FLOATNAME(LVecBase2) &other) const; + INLINE_LINMATH FLOATTYPE length_squared() const; + +#ifndef FLOATTYPE_IS_INT + INLINE_LINMATH FLOATTYPE length() const; + INLINE_LINMATH bool normalize(); INLINE_LINMATH FLOATNAME(LVecBase2) project(const FLOATNAME(LVecBase2) &onto) const; +#endif INLINE_LINMATH bool operator < (const FLOATNAME(LVecBase2) &other) const; INLINE_LINMATH bool operator == (const FLOATNAME(LVecBase2) &other) const; INLINE_LINMATH bool operator != (const FLOATNAME(LVecBase2) &other) const; INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase2) &other) const; + INLINE_LINMATH size_t get_hash() const; + INLINE_LINMATH size_t add_hash(size_t hash) const; + INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const; + +#ifndef FLOATTYPE_IS_INT INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase2) &other, FLOATTYPE threshold) const; - INLINE_LINMATH size_t get_hash() const; INLINE_LINMATH size_t get_hash(FLOATTYPE threshold) const; - INLINE_LINMATH size_t add_hash(size_t hash) const; INLINE_LINMATH size_t add_hash(size_t hash, FLOATTYPE threshold) const; + INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen, + FLOATTYPE threshold) const; +#endif INLINE_LINMATH FLOATNAME(LVecBase2) operator - () const; @@ -113,6 +121,9 @@ PUBLISHED: INLINE_LINMATH void operator *= (FLOATTYPE scalar); INLINE_LINMATH void operator /= (FLOATTYPE scalar); + EXTENSION(INLINE_LINMATH FLOATNAME(LVecBase2) __pow__(FLOATTYPE exponent) const); + EXTENSION(INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent)); + INLINE_LINMATH FLOATNAME(LVecBase2) fmax(const FLOATNAME(LVecBase2) &other); INLINE_LINMATH FLOATNAME(LVecBase2) fmin(const FLOATNAME(LVecBase2) &other); @@ -123,10 +134,6 @@ PUBLISHED: INLINE_LINMATH void output(ostream &out) const; EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); - INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const; - INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen, - FLOATTYPE threshold) const; - INLINE_LINMATH void write_datagram_fixed(Datagram &destination) const; INLINE_LINMATH void read_datagram_fixed(DatagramIterator &source); INLINE_LINMATH void write_datagram(Datagram &destination) const; diff --git a/panda/src/linmath/lvecBase3.cxx b/panda/src/linmath/lvecBase3.cxx index 030e90ac38..79e0405525 100644 --- a/panda/src/linmath/lvecBase3.cxx +++ b/panda/src/linmath/lvecBase3.cxx @@ -20,3 +20,5 @@ #include "dblnames.h" #include "lvecBase3_src.cxx" +#include "intnames.h" +#include "lvecBase3_src.cxx" diff --git a/panda/src/linmath/lvecBase3.h b/panda/src/linmath/lvecBase3.h index 85d2b081c8..3152b72e8f 100644 --- a/panda/src/linmath/lvecBase3.h +++ b/panda/src/linmath/lvecBase3.h @@ -16,6 +16,7 @@ #define LVECBASE3_H #include "pandabase.h" +#include "config_linmath.h" #include "typedObject.h" #include "pnotify.h" #include "datagram.h" @@ -37,4 +38,7 @@ class DatagramIterator; #include "dblnames.h" #include "lvecBase3_src.h" +#include "intnames.h" +#include "lvecBase3_src.h" + #endif diff --git a/panda/src/linmath/lvecBase3_ext.h b/panda/src/linmath/lvecBase3_ext.h index f68fd8d782..26180bfb42 100644 --- a/panda/src/linmath/lvecBase3_ext.h +++ b/panda/src/linmath/lvecBase3_ext.h @@ -24,4 +24,7 @@ #include "dblnames.h" #include "lvecBase3_ext_src.h" +#include "intnames.h" +#include "lvecBase3_ext_src.h" + #endif diff --git a/panda/src/linmath/lvecBase3_ext_src.I b/panda/src/linmath/lvecBase3_ext_src.I index 9dc8fd4dab..3e99e9e3e7 100644 --- a/panda/src/linmath/lvecBase3_ext_src.I +++ b/panda/src/linmath/lvecBase3_ext_src.I @@ -19,6 +19,22 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); #endif +#ifdef FLOATTYPE_IS_INT +#if PY_MAJOR_VERSION >= 3 +#define PYNUMBER_FLOATTYPE PyNumber_Long +#define PY_FROM_FLOATTYPE PyLong_FromLong +#define PY_AS_FLOATTYPE PyLong_AS_LONG +#else +#define PYNUMBER_FLOATTYPE PyNumber_Int +#define PY_FROM_FLOATTYPE PyInt_FromLong +#define PY_AS_FLOATTYPE PyInt_AS_LONG +#endif +#else +#define PYNUMBER_FLOATTYPE PyNumber_Float +#define PY_FROM_FLOATTYPE PyFloat_FromDouble +#define PY_AS_FLOATTYPE PyFloat_AsDouble +#endif + //////////////////////////////////////////////////////////////////// // Function: LVecBase3::__setitem__ // Access: Public @@ -60,8 +76,17 @@ __reduce__(PyObject *self) const { return NULL; } +#if FLOATTOKEN == 'i' + PyObject *result = Py_BuildValue("(O(iii))", this_class, + (*_this)[0], (*_this)[1], (*_this)[2]); +#elif FLOATTOKEN == 'f' PyObject *result = Py_BuildValue("(O(fff))", this_class, (*_this)[0], (*_this)[1], (*_this)[2]); +#else + PyObject *result = Py_BuildValue("(O(ddd))", this_class, + (*_this)[0], (*_this)[1], (*_this)[2]); +#endif + Py_DECREF(this_class); return result; } @@ -82,7 +107,7 @@ __getattr__(const string &attr_name) const { switch (attr_name.size()) { case 1: - return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); + return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); case 2: { FLOATNAME(LVecBase2) *vec = new FLOATNAME(LVecBase2); @@ -149,14 +174,18 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { PyObject** items = PySequence_Fast_ITEMS(fast); for (size_t i = 0; i < attr_name.size(); ++i) { - PyObject* fl = PyNumber_Float(items[i]); + PyObject* fl = PYNUMBER_FLOATTYPE(items[i]); if (fl == NULL) { // Oh darn. Not when we've come this far. +#ifdef FLOATTYPE_IS_INT + PyErr_SetString(PyExc_ValueError, "a sequence of integers is required"); +#else PyErr_SetString(PyExc_ValueError, "a sequence of floats is required"); +#endif Py_DECREF(fast); return -1; } - double value = PyFloat_AS_DOUBLE(fl); + FLOATTYPE value = PY_AS_FLOATTYPE(fl); Py_DECREF(fl); _this->_v(attr_name[i] - 'x') = value; @@ -166,19 +195,23 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { } else { // Maybe it's a single floating-point value. - PyObject* fl = PyNumber_Float(assign); + PyObject* fl = PYNUMBER_FLOATTYPE(assign); if (fl == NULL) { // It's not a floating-point value either? // Sheesh, I don't know what to do with it then. if (attr_name.size() == 1) { +#ifdef FLOATTYPE_IS_INT + PyErr_SetString(PyExc_ValueError, "an integer is required"); +#else PyErr_SetString(PyExc_ValueError, "a float is required"); +#endif } else { PyErr_Format(PyExc_ValueError, "'%.200s' object is not iterable", assign->ob_type->tp_name); } return -1; } - double value = PyFloat_AS_DOUBLE(fl); + FLOATTYPE value = PY_AS_FLOATTYPE(fl); Py_DECREF(fl); // Loop through the components in the attribute name, @@ -191,3 +224,33 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { return 0; } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase3::__pow__ +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVecBase3) Extension:: +__pow__(FLOATTYPE exponent) const { + return FLOATNAME(LVecBase3)( + cpow(_this->_v(0), exponent), + cpow(_this->_v(1), exponent), + cpow(_this->_v(2), exponent)); +} + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase3::__ipow__ +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH PyObject *Extension:: +__ipow__(PyObject *self, FLOATTYPE exponent) { + _this->_v(0) = cpow(_this->_v(0), exponent); + _this->_v(1) = cpow(_this->_v(1), exponent); + _this->_v(2) = cpow(_this->_v(2), exponent); + Py_INCREF(self); + return self; +} + +#undef PYNUMBER_FLOATTYPE +#undef PY_FROM_FLOATTYPE +#undef PY_AS_FLOATTYPE diff --git a/panda/src/linmath/lvecBase3_ext_src.h b/panda/src/linmath/lvecBase3_ext_src.h index 3c78131aed..cc86087833 100644 --- a/panda/src/linmath/lvecBase3_ext_src.h +++ b/panda/src/linmath/lvecBase3_ext_src.h @@ -27,6 +27,9 @@ public: INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); INLINE_LINMATH void __setitem__(int i, FLOATTYPE v); INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + + INLINE_LINMATH FLOATNAME(LVecBase3) __pow__(FLOATTYPE exponent) const; + INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent); }; #include "lvecBase3_ext_src.I" diff --git a/panda/src/linmath/lvecBase3_src.I b/panda/src/linmath/lvecBase3_src.I index f5848dfa3c..ce243aa893 100644 --- a/panda/src/linmath/lvecBase3_src.I +++ b/panda/src/linmath/lvecBase3_src.I @@ -77,6 +77,16 @@ FLOATNAME(LVecBase3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) { // set(x, y, z); } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase3::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVecBase3):: +FLOATNAME(LVecBase3)(const FLOATNAME(LVecBase2) ©, FLOATTYPE z) { + set(copy[0], copy[1], z); +} + //////////////////////////////////////////////////////////////////// // Function: LVecBase3::zero Named Constructor // Access: Public @@ -133,7 +143,7 @@ INLINE_LINMATH FLOATNAME(LVecBase3):: //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase3):: operator [](int i) const { - nassertr(i >= 0 && i < 3, 0.0); + nassertr(i >= 0 && i < 3, 0); return _v(i); } @@ -166,8 +176,12 @@ size() { //////////////////////////////////////////////////////////////////// INLINE_LINMATH bool FLOATNAME(LVecBase3):: is_nan() const { +#ifdef FLOATTYPE_IS_INT + return false; +#else TAU_PROFILE("bool LVecBase3::is_nan()", " ", TAU_USER); return cnan(_v(0)) || cnan(_v(1)) || cnan(_v(2)); +#endif } //////////////////////////////////////////////////////////////////// @@ -425,18 +439,17 @@ set(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) { } //////////////////////////////////////////////////////////////////// -// Function: LVecBase3::length +// Function: LVecBase3::dot // Access: Published -// Description: Returns the length of the vector, by the Pythagorean -// theorem. +// Description: //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase3):: -length() const { - TAU_PROFILE("FLOATTYPE LVecBase3::length()", " ", TAU_USER); +dot(const FLOATNAME(LVecBase3) &other) const { + TAU_PROFILE("FLOATTYPE LVecBase3::dot()", " ", TAU_USER); #ifdef HAVE_EIGEN - return _v.norm(); + return _v.dot(other._v); #else - return csqrt((*this).dot(*this)); + return _v(0) * other._v(0) + _v(1) * other._v(1) + _v(2) * other._v(2); #endif // HAVE_EIGEN } @@ -456,6 +469,23 @@ length_squared() const { #endif // HAVE_EIGEN } +#ifndef FLOATTYPE_IS_INT +//////////////////////////////////////////////////////////////////// +// Function: LVecBase3::length +// Access: Published +// Description: Returns the length of the vector, by the Pythagorean +// theorem. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase3):: +length() const { + TAU_PROFILE("FLOATTYPE LVecBase3::length()", " ", TAU_USER); +#ifdef HAVE_EIGEN + return _v.norm(); +#else + return csqrt((*this).dot(*this)); +#endif // HAVE_EIGEN +} + //////////////////////////////////////////////////////////////////// // Function: LVecBase3::normalize // Access: Published @@ -479,19 +509,17 @@ normalize() { } //////////////////////////////////////////////////////////////////// -// Function: LVecBase3::dot +// Function: LVecBase3::project // Access: Published -// Description: +// Description: Returns a new vector representing the projection of +// this vector onto another one. The resulting vector +// will be a scalar multiple of onto. //////////////////////////////////////////////////////////////////// -INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase3):: -dot(const FLOATNAME(LVecBase3) &other) const { - TAU_PROFILE("FLOATTYPE LVecBase3::dot()", " ", TAU_USER); -#ifdef HAVE_EIGEN - return _v.dot(other._v); -#else - return _v(0) * other._v(0) + _v(1) * other._v(1) + _v(2) * other._v(2); -#endif // HAVE_EIGEN +INLINE_LINMATH FLOATNAME(LVecBase3) FLOATNAME(LVecBase3):: +project(const FLOATNAME(LVecBase3) &onto) const { + return onto * (dot(onto) / onto.length_squared()); } +#endif // FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LVecBase3::cross @@ -510,18 +538,6 @@ cross(const FLOATNAME(LVecBase3) &other) const { #endif // HAVE_EIGEN } -//////////////////////////////////////////////////////////////////// -// Function: LVecBase3::project -// Access: Published -// Description: Returns a new vector representing the projection of -// this vector onto another one. The resulting vector -// will be a scalar multiple of onto. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH FLOATNAME(LVecBase3) FLOATNAME(LVecBase3):: -project(const FLOATNAME(LVecBase3) &onto) const { - return onto * (dot(onto) / onto.length_squared()); -} - //////////////////////////////////////////////////////////////////// // Function: LVecBase3::operator < // Access: Published @@ -621,9 +637,70 @@ get_standardized_hpr() const { INLINE_LINMATH int FLOATNAME(LVecBase3):: compare_to(const FLOATNAME(LVecBase3) &other) const { TAU_PROFILE("int LVecBase3::compare_to(const LVecBase3 &)", " ", TAU_USER); +#ifdef FLOATTYPE_IS_INT + if (_v(0) != other._v(0)) { + return (_v(0) < other._v(0)) ? -1 : 1; + } + if (_v(1) != other._v(1)) { + return (_v(1) < other._v(1)) ? -1 : 1; + } + if (_v(2) != other._v(2)) { + return (_v(2) < other._v(2)) ? -1 : 1; + } + return 0; +#else return compare_to(other, NEARLY_ZERO(FLOATTYPE)); +#endif } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase3::get_hash +// Access: Published +// Description: Returns a suitable hash for phash_map. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH size_t FLOATNAME(LVecBase3):: +get_hash() const { + TAU_PROFILE("size_t LVecBase3::get_hash()", " ", TAU_USER); + return add_hash(0); +} + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase3::add_hash +// Access: Published +// Description: Adds the vector into the running hash. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH size_t FLOATNAME(LVecBase3):: +add_hash(size_t hash) const { + TAU_PROFILE("size_t LVecBase3::add_hash(size_t)", " ", TAU_USER); +#ifdef FLOATTYPE_IS_INT + int_hash ihasher; + hash = ihasher.add_hash(hash, _v(0)); + hash = ihasher.add_hash(hash, _v(1)); + hash = ihasher.add_hash(hash, _v(2)); + return hash; +#else + return add_hash(hash, NEARLY_ZERO(FLOATTYPE)); +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase3::generate_hash +// Access: Published +// Description: Adds the vector to the indicated hash generator. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH void FLOATNAME(LVecBase3):: +generate_hash(ChecksumHashGenerator &hashgen) const { + TAU_PROFILE("LVecBase3::generate_hash(ChecksumHashGenerator &)", " ", TAU_USER); +#ifdef FLOATTYPE_IS_INT + hashgen.add_int(_v(0)); + hashgen.add_int(_v(1)); + hashgen.add_int(_v(2)); +#else + generate_hash(hashgen, NEARLY_ZERO(FLOATTYPE)); +#endif +} + +#ifndef FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LVecBase3::compare_to // Access: Published @@ -648,17 +725,6 @@ compare_to(const FLOATNAME(LVecBase3) &other, FLOATTYPE threshold) const { return 0; } -//////////////////////////////////////////////////////////////////// -// Function: LVecBase3::get_hash -// Access: Published -// Description: Returns a suitable hash for phash_map. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH size_t FLOATNAME(LVecBase3):: -get_hash() const { - TAU_PROFILE("size_t LVecBase3::get_hash()", " ", TAU_USER); - return add_hash(0); -} - //////////////////////////////////////////////////////////////////// // Function: LVecBase3::get_hash // Access: Published @@ -670,17 +736,6 @@ get_hash(FLOATTYPE threshold) const { return add_hash(0, threshold); } -//////////////////////////////////////////////////////////////////// -// Function: LVecBase3::add_hash -// Access: Published -// Description: Adds the vector into the running hash. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH size_t FLOATNAME(LVecBase3):: -add_hash(size_t hash) const { - TAU_PROFILE("size_t LVecBase3::add_hash(size_t)", " ", TAU_USER); - return add_hash(hash, NEARLY_ZERO(FLOATTYPE)); -} - //////////////////////////////////////////////////////////////////// // Function: LVecBase3::add_hash // Access: Published @@ -696,6 +751,20 @@ add_hash(size_t hash, FLOATTYPE threshold) const { return hash; } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase3::generate_hash +// Access: Published +// Description: Adds the vector to the indicated hash generator. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH void FLOATNAME(LVecBase3):: +generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const { + TAU_PROFILE("LVecBase3::generate_hash(ChecksumHashGenerator &, FLOATTYPE)", " ", TAU_USER); + hashgen.add_fp(_v(0), threshold); + hashgen.add_fp(_v(1), threshold); + hashgen.add_fp(_v(2), threshold); +} +#endif // FLOATTYPE_IS_INT + //////////////////////////////////////////////////////////////////// // Function: LVecBase3::unary - // Access: Published @@ -765,8 +834,14 @@ operator * (FLOATTYPE scalar) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATNAME(LVecBase3) FLOATNAME(LVecBase3):: operator / (FLOATTYPE scalar) const { +#ifdef FLOATTYPE_IS_INT + return FLOATNAME(LVecBase3)(_v(0) / scalar, + _v(1) / scalar, + _v(2) / scalar); +#else FLOATTYPE recip_scalar = 1.0f/scalar; return operator * (recip_scalar); +#endif } //////////////////////////////////////////////////////////////////// @@ -824,8 +899,14 @@ operator *= (FLOATTYPE scalar) { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase3):: operator /= (FLOATTYPE scalar) { +#ifdef FLOATTYPE_IS_INT + _v(0) /= scalar; + _v(1) /= scalar; + _v(2) /= scalar; +#else FLOATTYPE recip_scalar = 1.0f/scalar; operator *= (recip_scalar); +#endif } //////////////////////////////////////////////////////////////////// @@ -902,30 +983,6 @@ output(ostream &out) const { << MAYBE_ZERO(_v(2)); } -//////////////////////////////////////////////////////////////////// -// Function: LVecBase3::generate_hash -// Access: Published -// Description: Adds the vector to the indicated hash generator. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH void FLOATNAME(LVecBase3):: -generate_hash(ChecksumHashGenerator &hashgen) const { - TAU_PROFILE("LVecBase3::generate_hash(ChecksumHashGenerator &)", " ", TAU_USER); - generate_hash(hashgen, NEARLY_ZERO(FLOATTYPE)); -} - -//////////////////////////////////////////////////////////////////// -// Function: LVecBase3::generate_hash -// Access: Published -// Description: Adds the vector to the indicated hash generator. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH void FLOATNAME(LVecBase3):: -generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const { - TAU_PROFILE("LVecBase3::generate_hash(ChecksumHashGenerator &, FLOATTYPE)", " ", TAU_USER); - hashgen.add_fp(_v(0), threshold); - hashgen.add_fp(_v(1), threshold); - hashgen.add_fp(_v(2), threshold); -} - //////////////////////////////////////////////////////////////////// // Function: LVecBase3::write_datagram_fixed // Access: Published @@ -939,7 +996,11 @@ generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase3):: write_datagram_fixed(Datagram &destination) const { -#if FLOATTOKEN == 'f' +#if FLOATTOKEN == 'i' + destination.add_int32(_v(0)); + destination.add_int32(_v(1)); + destination.add_int32(_v(2)); +#elif FLOATTOKEN == 'f' destination.add_float32(_v(0)); destination.add_float32(_v(1)); destination.add_float32(_v(2)); @@ -958,7 +1019,11 @@ write_datagram_fixed(Datagram &destination) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase3):: read_datagram_fixed(DatagramIterator &source) { -#if FLOATTOKEN == 'f' +#if FLOATTOKEN == 'i' + _v(0) = source.get_int32(); + _v(1) = source.get_int32(); + _v(2) = source.get_int32(); +#elif FLOATTOKEN == 'f' _v(0) = source.get_float32(); _v(1) = source.get_float32(); _v(2) = source.get_float32(); @@ -979,9 +1044,15 @@ read_datagram_fixed(DatagramIterator &source) { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase3):: write_datagram(Datagram &destination) const { +#if FLOATTOKEN == 'i' + destination.add_int32(_v(0)); + destination.add_int32(_v(1)); + destination.add_int32(_v(2)); +#else destination.add_stdfloat(_v(0)); destination.add_stdfloat(_v(1)); destination.add_stdfloat(_v(2)); +#endif } //////////////////////////////////////////////////////////////////// @@ -991,7 +1062,13 @@ write_datagram(Datagram &destination) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase3):: read_datagram(DatagramIterator &source) { +#if FLOATTOKEN == 'i' + _v(0) = source.get_int32(); + _v(1) = source.get_int32(); + _v(2) = source.get_int32(); +#else _v(0) = source.get_stdfloat(); _v(1) = source.get_stdfloat(); _v(2) = source.get_stdfloat(); +#endif } diff --git a/panda/src/linmath/lvecBase3_src.cxx b/panda/src/linmath/lvecBase3_src.cxx index cfa0d6505e..f2d243fb3c 100644 --- a/panda/src/linmath/lvecBase3_src.cxx +++ b/panda/src/linmath/lvecBase3_src.cxx @@ -16,13 +16,13 @@ TypeHandle FLOATNAME(LVecBase3)::_type_handle; const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_zero = - FLOATNAME(LVecBase3)(0.0f, 0.0f, 0.0f); + FLOATNAME(LVecBase3)(0, 0, 0); const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_unit_x = - FLOATNAME(LVecBase3)(1.0f, 0.0f, 0.0f); + FLOATNAME(LVecBase3)(1, 0, 0); const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_unit_y = - FLOATNAME(LVecBase3)(0.0f, 1.0f, 0.0f); + FLOATNAME(LVecBase3)(0, 1, 0); const FLOATNAME(LVecBase3) FLOATNAME(LVecBase3)::_unit_z = - FLOATNAME(LVecBase3)(0.0f, 0.0f, 1.0f); + FLOATNAME(LVecBase3)(0, 0, 1); //////////////////////////////////////////////////////////////////// // Function: LVecBase3::init_type diff --git a/panda/src/linmath/lvecBase3_src.h b/panda/src/linmath/lvecBase3_src.h index c3635ea73c..99e9dbe38a 100644 --- a/panda/src/linmath/lvecBase3_src.h +++ b/panda/src/linmath/lvecBase3_src.h @@ -29,6 +29,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVecBase3) &operator = (FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LVecBase3)(FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LVecBase3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z); + INLINE_LINMATH FLOATNAME(LVecBase3)(const FLOATNAME(LVecBase2) ©, FLOATTYPE z); ALLOC_DELETED_CHAIN(FLOATNAME(LVecBase3)); INLINE_LINMATH static const FLOATNAME(LVecBase3) &zero(); @@ -86,13 +87,16 @@ PUBLISHED: INLINE_LINMATH void fill(FLOATTYPE fill_value); INLINE_LINMATH void set(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z); - INLINE_LINMATH FLOATTYPE length() const; - INLINE_LINMATH FLOATTYPE length_squared() const; - INLINE_LINMATH bool normalize(); - INLINE_LINMATH FLOATTYPE dot(const FLOATNAME(LVecBase3) &other) const; - INLINE_LINMATH FLOATNAME(LVecBase3) cross(const FLOATNAME(LVecBase3) &other) const; + INLINE_LINMATH FLOATTYPE length_squared() const; + +#ifndef FLOATTYPE_IS_INT + INLINE_LINMATH FLOATTYPE length() const; + INLINE_LINMATH bool normalize(); INLINE_LINMATH FLOATNAME(LVecBase3) project(const FLOATNAME(LVecBase3) &onto) const; +#endif + + INLINE_LINMATH FLOATNAME(LVecBase3) cross(const FLOATNAME(LVecBase3) &other) const; INLINE_LINMATH bool operator < (const FLOATNAME(LVecBase3) &other) const; INLINE_LINMATH bool operator == (const FLOATNAME(LVecBase3) &other) const; @@ -101,12 +105,18 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVecBase3) get_standardized_hpr() const; INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase3) &other) const; + INLINE_LINMATH size_t get_hash() const; + INLINE_LINMATH size_t add_hash(size_t hash) const; + INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const; + +#ifndef FLOATTYPE_IS_INT INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase3) &other, FLOATTYPE threshold) const; - INLINE_LINMATH size_t get_hash() const; INLINE_LINMATH size_t get_hash(FLOATTYPE threshold) const; - INLINE_LINMATH size_t add_hash(size_t hash) const; INLINE_LINMATH size_t add_hash(size_t hash, FLOATTYPE threshold) const; + INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen, + FLOATTYPE threshold) const; +#endif INLINE_LINMATH FLOATNAME(LVecBase3) operator - () const; @@ -124,6 +134,9 @@ PUBLISHED: INLINE_LINMATH void operator *= (FLOATTYPE scalar); INLINE_LINMATH void operator /= (FLOATTYPE scalar); + EXTENSION(INLINE_LINMATH FLOATNAME(LVecBase3) __pow__(FLOATTYPE exponent) const); + EXTENSION(INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent)); + INLINE_LINMATH FLOATNAME(LVecBase3) fmax(const FLOATNAME(LVecBase3) &other); INLINE_LINMATH FLOATNAME(LVecBase3) fmin(const FLOATNAME(LVecBase3) &other); @@ -136,10 +149,6 @@ PUBLISHED: INLINE_LINMATH void output(ostream &out) const; EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); - INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const; - INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen, - FLOATTYPE threshold) const; - INLINE_LINMATH void write_datagram_fixed(Datagram &destination) const; INLINE_LINMATH void read_datagram_fixed(DatagramIterator &source); INLINE_LINMATH void write_datagram(Datagram &destination) const; diff --git a/panda/src/linmath/lvecBase4.cxx b/panda/src/linmath/lvecBase4.cxx index e94eeb4436..5c316c7716 100644 --- a/panda/src/linmath/lvecBase4.cxx +++ b/panda/src/linmath/lvecBase4.cxx @@ -20,3 +20,5 @@ #include "dblnames.h" #include "lvecBase4_src.cxx" +#include "intnames.h" +#include "lvecBase4_src.cxx" diff --git a/panda/src/linmath/lvecBase4.h b/panda/src/linmath/lvecBase4.h index cad78f0a93..0e144630e4 100644 --- a/panda/src/linmath/lvecBase4.h +++ b/panda/src/linmath/lvecBase4.h @@ -16,12 +16,14 @@ #define LVECBASE4_H #include "pandabase.h" +#include "config_linmath.h" #include "typedObject.h" #include "pnotify.h" #include "datagram.h" #include "datagramIterator.h" #include "checksumHashGenerator.h" -#include "lsimpleMatrix.h" +#include "lvecBase2.h" +#include "lvecBase3.h" #include "cmath.h" #include "nearly_zero.h" @@ -35,5 +37,7 @@ class DatagramIterator; #include "dblnames.h" #include "lvecBase4_src.h" +#include "intnames.h" +#include "lvecBase4_src.h" #endif diff --git a/panda/src/linmath/lvecBase4_ext.h b/panda/src/linmath/lvecBase4_ext.h index 1cccf511e6..5ece57435e 100644 --- a/panda/src/linmath/lvecBase4_ext.h +++ b/panda/src/linmath/lvecBase4_ext.h @@ -24,4 +24,7 @@ #include "dblnames.h" #include "lvecBase4_ext_src.h" +#include "intnames.h" +#include "lvecBase4_ext_src.h" + #endif diff --git a/panda/src/linmath/lvecBase4_ext_src.I b/panda/src/linmath/lvecBase4_ext_src.I index c76a00e1ac..ddb1f71e1d 100644 --- a/panda/src/linmath/lvecBase4_ext_src.I +++ b/panda/src/linmath/lvecBase4_ext_src.I @@ -19,6 +19,22 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); #endif +#ifdef FLOATTYPE_IS_INT +#if PY_MAJOR_VERSION >= 3 +#define PYNUMBER_FLOATTYPE PyNumber_Long +#define PY_FROM_FLOATTYPE PyLong_FromLong +#define PY_AS_FLOATTYPE PyLong_AS_LONG +#else +#define PYNUMBER_FLOATTYPE PyNumber_Int +#define PY_FROM_FLOATTYPE PyInt_FromLong +#define PY_AS_FLOATTYPE PyInt_AS_LONG +#endif +#else +#define PYNUMBER_FLOATTYPE PyNumber_Float +#define PY_FROM_FLOATTYPE PyFloat_FromDouble +#define PY_AS_FLOATTYPE PyFloat_AsDouble +#endif + //////////////////////////////////////////////////////////////////// // Function: LVecBase4::__setitem__ // Access: Public @@ -61,8 +77,17 @@ __reduce__(PyObject *self) const { return NULL; } +#if FLOATTOKEN == 'i' + PyObject *result = Py_BuildValue("(O(iiii))", this_class, + (*_this)[0], (*_this)[1], (*_this)[2], (*_this)[3]); +#elif FLOATTOKEN == 'f' PyObject *result = Py_BuildValue("(O(ffff))", this_class, (*_this)[0], (*_this)[1], (*_this)[2], (*_this)[3]); +#else + PyObject *result = Py_BuildValue("(O(dddd))", this_class, + (*_this)[0], (*_this)[1], (*_this)[2], (*_this)[3]); +#endif + Py_DECREF(this_class); return result; } @@ -84,9 +109,9 @@ __getattr__(const string &attr_name) const { switch (attr_name.size()) { case 1: if (attr_name[0] == 'w') { - return PyFloat_FromDouble(_this->_v(3)); + return PY_FROM_FLOATTYPE(_this->_v(3)); } else { - return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); + return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); } case 2: { @@ -154,14 +179,18 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { PyObject** items = PySequence_Fast_ITEMS(fast); for (size_t i = 0; i < attr_name.size(); ++i) { - PyObject* fl = PyNumber_Float(items[i]); + PyObject* fl = PYNUMBER_FLOATTYPE(items[i]); if (fl == NULL) { // Oh darn. Not when we've come this far. +#ifdef FLOATTYPE_IS_INT + PyErr_SetString(PyExc_ValueError, "a sequence of integers is required"); +#else PyErr_SetString(PyExc_ValueError, "a sequence of floats is required"); +#endif Py_DECREF(fast); return -1; } - double value = PyFloat_AS_DOUBLE(fl); + FLOATTYPE value = PY_AS_FLOATTYPE(fl); Py_DECREF(fl); _this->_v((attr_name[i] == 'w') ? 3 : attr_name[i] - 'x') = value; @@ -171,19 +200,24 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { } else { // Maybe it's a single floating-point value. - PyObject* fl = PyNumber_Float(assign); + PyObject* fl = PYNUMBER_FLOATTYPE(assign); + if (fl == NULL) { // It's not a floating-point value either? // Sheesh, I don't know what to do with it then. if (attr_name.size() == 1) { +#ifdef FLOATTYPE_IS_INT + PyErr_SetString(PyExc_ValueError, "an integer is required"); +#else PyErr_SetString(PyExc_ValueError, "a float is required"); +#endif } else { PyErr_Format(PyExc_ValueError, "'%.200s' object is not iterable", assign->ob_type->tp_name); } return -1; } - double value = PyFloat_AS_DOUBLE(fl); + FLOATTYPE value = PY_AS_FLOATTYPE(fl); Py_DECREF(fl); // Loop through the components in the attribute name, @@ -196,6 +230,35 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { return 0; } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase4::__pow__ +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVecBase4) Extension:: +__pow__(FLOATTYPE exponent) const { + return FLOATNAME(LVecBase4)( + cpow(_this->_v(0), exponent), + cpow(_this->_v(1), exponent), + cpow(_this->_v(2), exponent), + cpow(_this->_v(3), exponent)); +} + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase4::__ipow__ +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH PyObject *Extension:: +__ipow__(PyObject *self, FLOATTYPE exponent) { + _this->_v(0) = cpow(_this->_v(0), exponent); + _this->_v(1) = cpow(_this->_v(1), exponent); + _this->_v(2) = cpow(_this->_v(2), exponent); + _this->_v(3) = cpow(_this->_v(3), exponent); + Py_INCREF(self); + return self; +} + //////////////////////////////////////////////////////////////////// // Function: UnalignedLVecBase4::__setitem__ // Access: Public @@ -206,3 +269,7 @@ __setitem__(int i, FLOATTYPE v) { nassertv(i >= 0 && i < 4); _this->_v(i) = v; } + +#undef PYNUMBER_FLOATTYPE +#undef PY_FROM_FLOATTYPE +#undef PY_AS_FLOATTYPE diff --git a/panda/src/linmath/lvecBase4_ext_src.h b/panda/src/linmath/lvecBase4_ext_src.h index 61ff4e907c..edcecb4dbf 100644 --- a/panda/src/linmath/lvecBase4_ext_src.h +++ b/panda/src/linmath/lvecBase4_ext_src.h @@ -27,6 +27,9 @@ public: INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); INLINE_LINMATH void __setitem__(int i, FLOATTYPE v); INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + + INLINE_LINMATH FLOATNAME(LVecBase4) __pow__(FLOATTYPE exponent) const; + INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent); }; //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lvecBase4_src.I b/panda/src/linmath/lvecBase4_src.I index 1ffd3da3ee..207788d92e 100644 --- a/panda/src/linmath/lvecBase4_src.I +++ b/panda/src/linmath/lvecBase4_src.I @@ -96,6 +96,16 @@ FLOATNAME(LVecBase4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) { set(x, y, z, w); } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase4::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVecBase4):: +FLOATNAME(LVecBase4)(const FLOATNAME(LVecBase3) ©, FLOATTYPE w) { + set(copy[0], copy[1], copy[2], w); +} + //////////////////////////////////////////////////////////////////// // Function: LVecBase4::Destructor // Access: Published @@ -162,7 +172,7 @@ unit_w() { //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase4):: operator [](int i) const { - nassertr(i >= 0 && i < 4, 0.0); + nassertr(i >= 0 && i < 4, 0); return _v(i); } @@ -195,8 +205,12 @@ size() { //////////////////////////////////////////////////////////////////// INLINE_LINMATH bool FLOATNAME(LVecBase4):: is_nan() const { +#ifdef FLOATTYPE_IS_INT + return false; +#else TAU_PROFILE("bool LVecBase4::is_nan()", " ", TAU_USER); return cnan(_v(0)) || cnan(_v(1)) || cnan(_v(2)) || cnan(_v(3)); +#endif } //////////////////////////////////////////////////////////////////// @@ -206,7 +220,7 @@ is_nan() const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase4):: get_cell(int i) const { - nassertr(i >= 0 && i < 4, 0.0); + nassertr(i >= 0 && i < 4, 0); return _v(i); } @@ -453,18 +467,19 @@ set(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) { } //////////////////////////////////////////////////////////////////// -// Function: LVecBase4::length +// Function: LVecBase4::dot // Access: Published -// Description: Returns the length of the vector, by the Pythagorean -// theorem. +// Description: //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase4):: -length() const { - TAU_PROFILE("FLOATTYPE LVecBase4::length()", " ", TAU_USER); +dot(const FLOATNAME(LVecBase4) &other) const { + TAU_PROFILE("FLOATTYPE LVecBase4::dot()", " ", TAU_USER); #ifdef HAVE_EIGEN - return _v.norm(); + return _v.dot(other._v); #else - return csqrt((*this).dot(*this)); + return + _v(0) * other._v(0) + _v(1) * other._v(1) + + _v(2) * other._v(2) + _v(3) * other._v(3); #endif // HAVE_EIGEN } @@ -484,6 +499,23 @@ length_squared() const { #endif // HAVE_EIGEN } +#ifndef FLOATTYPE_IS_INT +//////////////////////////////////////////////////////////////////// +// Function: LVecBase4::length +// Access: Published +// Description: Returns the length of the vector, by the Pythagorean +// theorem. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase4):: +length() const { + TAU_PROFILE("FLOATTYPE LVecBase4::length()", " ", TAU_USER); +#ifdef HAVE_EIGEN + return _v.norm(); +#else + return csqrt((*this).dot(*this)); +#endif // HAVE_EIGEN +} + //////////////////////////////////////////////////////////////////// // Function: LVecBase4::normalize // Access: Published @@ -505,23 +537,6 @@ normalize() { return true; } -//////////////////////////////////////////////////////////////////// -// Function: LVecBase4::dot -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH FLOATTYPE FLOATNAME(LVecBase4):: -dot(const FLOATNAME(LVecBase4) &other) const { - TAU_PROFILE("FLOATTYPE LVecBase4::dot()", " ", TAU_USER); -#ifdef HAVE_EIGEN - return _v.dot(other._v); -#else - return - _v(0) * other._v(0) + _v(1) * other._v(1) + - _v(2) * other._v(2) + _v(3) * other._v(3); -#endif // HAVE_EIGEN -} - //////////////////////////////////////////////////////////////////// // Function: LVecBase4::project // Access: Published @@ -533,6 +548,7 @@ INLINE_LINMATH FLOATNAME(LVecBase4) FLOATNAME(LVecBase4):: project(const FLOATNAME(LVecBase4) &onto) const { return onto * (dot(onto) / onto.length_squared()); } +#endif // FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LVecBase4::operator < @@ -586,9 +602,75 @@ operator != (const FLOATNAME(LVecBase4) &other) const { INLINE_LINMATH int FLOATNAME(LVecBase4):: compare_to(const FLOATNAME(LVecBase4) &other) const { TAU_PROFILE("int LVecBase4::compare_to(const LVecBase4 &)", " ", TAU_USER); +#ifdef FLOATTYPE_IS_INT + if (_v(0) != other._v(0)) { + return (_v(0) < other._v(0)) ? -1 : 1; + } + if (_v(1) != other._v(1)) { + return (_v(1) < other._v(1)) ? -1 : 1; + } + if (_v(2) != other._v(2)) { + return (_v(2) < other._v(2)) ? -1 : 1; + } + if (_v(3) != other._v(3)) { + return (_v(3) < other._v(3)) ? -1 : 1; + } + return 0; +#else return compare_to(other, NEARLY_ZERO(FLOATTYPE)); +#endif } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase4::get_hash +// Access: Published +// Description: Returns a suitable hash for phash_map. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH size_t FLOATNAME(LVecBase4):: +get_hash() const { + TAU_PROFILE("size_t LVecBase4::get_hash()", " ", TAU_USER); + return add_hash(0); +} + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase4::add_hash +// Access: Published +// Description: Adds the vector into the running hash. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH size_t FLOATNAME(LVecBase4):: +add_hash(size_t hash) const { + TAU_PROFILE("size_t LVecBase4::add_hash(size_t)", " ", TAU_USER); +#ifdef FLOATTYPE_IS_INT + int_hash ihasher; + hash = ihasher.add_hash(hash, _v(0)); + hash = ihasher.add_hash(hash, _v(1)); + hash = ihasher.add_hash(hash, _v(2)); + hash = ihasher.add_hash(hash, _v(3)); + return hash; +#else + return add_hash(hash, NEARLY_ZERO(FLOATTYPE)); +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: LVecBase4::generate_hash +// Access: Published +// Description: Adds the vector to the indicated hash generator. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH void FLOATNAME(LVecBase4):: +generate_hash(ChecksumHashGenerator &hashgen) const { + TAU_PROFILE("LVecBase4::generate_hash(ChecksumHashGenerator &)", " ", TAU_USER); +#ifdef FLOATTYPE_IS_INT + hashgen.add_int(_v(0)); + hashgen.add_int(_v(1)); + hashgen.add_int(_v(2)); + hashgen.add_int(_v(3)); +#else + generate_hash(hashgen, NEARLY_ZERO(FLOATTYPE)); +#endif +} + +#ifndef FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LVecBase4::compare_to // Access: Published @@ -616,17 +698,6 @@ compare_to(const FLOATNAME(LVecBase4) &other, FLOATTYPE threshold) const { return 0; } -//////////////////////////////////////////////////////////////////// -// Function: LVecBase4::get_hash -// Access: Published -// Description: Returns a suitable hash for phash_map. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH size_t FLOATNAME(LVecBase4):: -get_hash() const { - TAU_PROFILE("size_t LVecBase4::get_hash()", " ", TAU_USER); - return add_hash(0); -} - //////////////////////////////////////////////////////////////////// // Function: LVecBase4::get_hash // Access: Published @@ -638,17 +709,6 @@ get_hash(FLOATTYPE threshold) const { return add_hash(0, threshold); } -//////////////////////////////////////////////////////////////////// -// Function: LVecBase4::add_hash -// Access: Published -// Description: Adds the vector into the running hash. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH size_t FLOATNAME(LVecBase4):: -add_hash(size_t hash) const { - TAU_PROFILE("size_t LVecBase4::add_hash(size_t)", " ", TAU_USER); - return add_hash(hash, NEARLY_ZERO(FLOATTYPE)); -} - //////////////////////////////////////////////////////////////////// // Function: LVecBase4::add_hash // Access: Published @@ -665,6 +725,21 @@ add_hash(size_t hash, FLOATTYPE threshold) const { return hash; } +//////////////////////////////////////////////////////////////////// +// Function: LVecBase4::generate_hash +// Access: Published +// Description: Adds the vector to the indicated hash generator. +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH void FLOATNAME(LVecBase4):: +generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const { + TAU_PROFILE("LVecBase4::generate_hash(ChecksumHashGenerator &, FLOATTYPE)", " ", TAU_USER); + hashgen.add_fp(_v(0), threshold); + hashgen.add_fp(_v(1), threshold); + hashgen.add_fp(_v(2), threshold); + hashgen.add_fp(_v(3), threshold); +} +#endif // FLOATTYPE_IS_INT + //////////////////////////////////////////////////////////////////// // Function: LVecBase4::unary - // Access: Published @@ -737,8 +812,15 @@ operator * (FLOATTYPE scalar) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATNAME(LVecBase4) FLOATNAME(LVecBase4):: operator / (FLOATTYPE scalar) const { +#ifdef FLOATTYPE_IS_INT + return FLOATNAME(LVecBase4)(_v(0) / scalar, + _v(1) / scalar, + _v(2) / scalar, + _v(3) / scalar); +#else FLOATTYPE recip_scalar = 1.0f/scalar; return operator * (recip_scalar); +#endif } //////////////////////////////////////////////////////////////////// @@ -799,8 +881,15 @@ operator *= (FLOATTYPE scalar) { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase4):: operator /= (FLOATTYPE scalar) { +#ifdef FLOATTYPE_IS_INT + _v(0) /= scalar; + _v(1) /= scalar; + _v(2) /= scalar; + _v(3) /= scalar; +#else FLOATTYPE recip_scalar = 1.0f/scalar; operator *= (recip_scalar); +#endif } //////////////////////////////////////////////////////////////////// @@ -871,31 +960,6 @@ output(ostream &out) const { << MAYBE_ZERO(_v(3)); } -//////////////////////////////////////////////////////////////////// -// Function: LVecBase4::generate_hash -// Access: Published -// Description: Adds the vector to the indicated hash generator. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH void FLOATNAME(LVecBase4):: -generate_hash(ChecksumHashGenerator &hashgen) const { - TAU_PROFILE("LVecBase4::generate_hash(ChecksumHashGenerator &)", " ", TAU_USER); - generate_hash(hashgen, NEARLY_ZERO(FLOATTYPE)); -} - -//////////////////////////////////////////////////////////////////// -// Function: LVecBase4::generate_hash -// Access: Published -// Description: Adds the vector to the indicated hash generator. -//////////////////////////////////////////////////////////////////// -INLINE_LINMATH void FLOATNAME(LVecBase4):: -generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const { - TAU_PROFILE("LVecBase4::generate_hash(ChecksumHashGenerator &, FLOATTYPE)", " ", TAU_USER); - hashgen.add_fp(_v(0), threshold); - hashgen.add_fp(_v(1), threshold); - hashgen.add_fp(_v(2), threshold); - hashgen.add_fp(_v(3), threshold); -} - //////////////////////////////////////////////////////////////////// // Function: LVecBase4::write_datagram_fixed // Access: Published @@ -909,7 +973,12 @@ generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE threshold) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase4):: write_datagram_fixed(Datagram &destination) const { -#if FLOATTOKEN == 'f' +#if FLOATTOKEN == 'i' + destination.add_int32(_v(0)); + destination.add_int32(_v(1)); + destination.add_int32(_v(2)); + destination.add_int32(_v(3)); +#elif FLOATTOKEN == 'f' destination.add_float32(_v(0)); destination.add_float32(_v(1)); destination.add_float32(_v(2)); @@ -930,7 +999,12 @@ write_datagram_fixed(Datagram &destination) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase4):: read_datagram_fixed(DatagramIterator &source) { -#if FLOATTOKEN == 'f' +#if FLOATTOKEN == 'i' + _v(0) = source.get_int32(); + _v(1) = source.get_int32(); + _v(2) = source.get_int32(); + _v(3) = source.get_int32(); +#elif FLOATTOKEN == 'f' _v(0) = source.get_float32(); _v(1) = source.get_float32(); _v(2) = source.get_float32(); @@ -953,10 +1027,17 @@ read_datagram_fixed(DatagramIterator &source) { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase4):: write_datagram(Datagram &destination) const { +#if FLOATTOKEN == 'i' + destination.add_int32(_v(0)); + destination.add_int32(_v(1)); + destination.add_int32(_v(2)); + destination.add_int32(_v(3)); +#else destination.add_stdfloat(_v(0)); destination.add_stdfloat(_v(1)); destination.add_stdfloat(_v(2)); destination.add_stdfloat(_v(3)); +#endif } //////////////////////////////////////////////////////////////////// @@ -966,10 +1047,17 @@ write_datagram(Datagram &destination) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH void FLOATNAME(LVecBase4):: read_datagram(DatagramIterator &source) { +#if FLOATTOKEN == 'i' + _v(0) = source.get_int32(); + _v(1) = source.get_int32(); + _v(2) = source.get_int32(); + _v(3) = source.get_int32(); +#else _v(0) = source.get_stdfloat(); _v(1) = source.get_stdfloat(); _v(2) = source.get_stdfloat(); _v(3) = source.get_stdfloat(); +#endif } //////////////////////////////////////////////////////////////////// @@ -1055,7 +1143,7 @@ set(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) { //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATTYPE FLOATNAME(UnalignedLVecBase4):: operator [](int i) const { - nassertr(i >= 0 && i < 4, 0.0); + nassertr(i >= 0 && i < 4, 0); return _v(i); } diff --git a/panda/src/linmath/lvecBase4_src.cxx b/panda/src/linmath/lvecBase4_src.cxx index 23afd7b395..49debed5a7 100644 --- a/panda/src/linmath/lvecBase4_src.cxx +++ b/panda/src/linmath/lvecBase4_src.cxx @@ -16,15 +16,15 @@ TypeHandle FLOATNAME(LVecBase4)::_type_handle; TypeHandle FLOATNAME(UnalignedLVecBase4)::_type_handle; const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_zero = - FLOATNAME(LVecBase4)(0.0f, 0.0f, 0.0f, 0.0f); + FLOATNAME(LVecBase4)(0, 0, 0, 0); const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_unit_x = - FLOATNAME(LVecBase4)(1.0f, 0.0f, 0.0f, 0.0f); + FLOATNAME(LVecBase4)(1, 0, 0, 0); const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_unit_y = - FLOATNAME(LVecBase4)(0.0f, 1.0f, 0.0f, 0.0f); + FLOATNAME(LVecBase4)(0, 1, 0, 0); const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_unit_z = - FLOATNAME(LVecBase4)(0.0f, 0.0f, 1.0f, 0.0f); + FLOATNAME(LVecBase4)(0, 0, 1, 0); const FLOATNAME(LVecBase4) FLOATNAME(LVecBase4)::_unit_w = - FLOATNAME(LVecBase4)(0.0f, 0.0f, 0.0f, 1.0f); + FLOATNAME(LVecBase4)(0, 0, 0, 1); //////////////////////////////////////////////////////////////////// // Function: LVecBase4::init_type diff --git a/panda/src/linmath/lvecBase4_src.h b/panda/src/linmath/lvecBase4_src.h index 312c31a222..395505046a 100644 --- a/panda/src/linmath/lvecBase4_src.h +++ b/panda/src/linmath/lvecBase4_src.h @@ -34,6 +34,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVecBase4) &operator = (FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LVecBase4)(FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LVecBase4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w); + INLINE_LINMATH FLOATNAME(LVecBase4)(const FLOATNAME(LVecBase3) ©, FLOATTYPE w); ALLOC_DELETED_CHAIN(FLOATNAME(LVecBase4)); INLINE_LINMATH static const FLOATNAME(LVecBase4) &zero(); @@ -91,24 +92,32 @@ PUBLISHED: INLINE_LINMATH void fill(FLOATTYPE fill_value); INLINE_LINMATH void set(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w); - INLINE_LINMATH FLOATTYPE length() const; - INLINE_LINMATH FLOATTYPE length_squared() const; - INLINE_LINMATH bool normalize(); - INLINE_LINMATH FLOATTYPE dot(const FLOATNAME(LVecBase4) &other) const; + INLINE_LINMATH FLOATTYPE length_squared() const; + +#ifndef FLOATTYPE_IS_INT + INLINE_LINMATH FLOATTYPE length() const; + INLINE_LINMATH bool normalize(); INLINE_LINMATH FLOATNAME(LVecBase4) project(const FLOATNAME(LVecBase4) &onto) const; +#endif INLINE_LINMATH bool operator < (const FLOATNAME(LVecBase4) &other) const; INLINE_LINMATH bool operator == (const FLOATNAME(LVecBase4) &other) const; INLINE_LINMATH bool operator != (const FLOATNAME(LVecBase4) &other) const; INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase4) &other) const; + INLINE_LINMATH size_t get_hash() const; + INLINE_LINMATH size_t add_hash(size_t hash) const; + INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const; + +#ifndef FLOATTYPE_IS_INT INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase4) &other, FLOATTYPE threshold) const; - INLINE_LINMATH size_t get_hash() const; INLINE_LINMATH size_t get_hash(FLOATTYPE threshold) const; - INLINE_LINMATH size_t add_hash(size_t hash) const; INLINE_LINMATH size_t add_hash(size_t hash, FLOATTYPE threshold) const; + INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen, + FLOATTYPE threshold) const; +#endif INLINE_LINMATH FLOATNAME(LVecBase4) operator - () const; @@ -126,6 +135,9 @@ PUBLISHED: INLINE_LINMATH void operator *= (FLOATTYPE scalar); INLINE_LINMATH void operator /= (FLOATTYPE scalar); + EXTENSION(INLINE_LINMATH FLOATNAME(LVecBase4) __pow__(FLOATTYPE exponent) const); + EXTENSION(INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent)); + INLINE_LINMATH FLOATNAME(LVecBase4) fmax(const FLOATNAME(LVecBase4) &other); INLINE_LINMATH FLOATNAME(LVecBase4) fmin(const FLOATNAME(LVecBase4) &other); @@ -136,10 +148,6 @@ PUBLISHED: INLINE_LINMATH void output(ostream &out) const; EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); - INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const; - INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen, - FLOATTYPE threshold) const; - INLINE_LINMATH void write_datagram_fixed(Datagram &destination) const; INLINE_LINMATH void read_datagram_fixed(DatagramIterator &source); INLINE_LINMATH void write_datagram(Datagram &destination) const; diff --git a/panda/src/linmath/lvector2.cxx b/panda/src/linmath/lvector2.cxx index cef623c5db..ac3193eebd 100644 --- a/panda/src/linmath/lvector2.cxx +++ b/panda/src/linmath/lvector2.cxx @@ -20,3 +20,5 @@ #include "dblnames.h" #include "lvector2_src.cxx" +#include "intnames.h" +#include "lvector2_src.cxx" diff --git a/panda/src/linmath/lvector2.h b/panda/src/linmath/lvector2.h index dba3fdc99f..61cc423310 100644 --- a/panda/src/linmath/lvector2.h +++ b/panda/src/linmath/lvector2.h @@ -26,4 +26,7 @@ #include "dblnames.h" #include "lvector2_src.h" +#include "intnames.h" +#include "lvector2_src.h" + #endif diff --git a/panda/src/linmath/lvector2_ext.h b/panda/src/linmath/lvector2_ext.h index 08ca44d07a..824b60a908 100644 --- a/panda/src/linmath/lvector2_ext.h +++ b/panda/src/linmath/lvector2_ext.h @@ -26,4 +26,7 @@ #include "dblnames.h" #include "lvector2_ext_src.h" +#include "intnames.h" +#include "lvector2_ext_src.h" + #endif diff --git a/panda/src/linmath/lvector2_ext_src.I b/panda/src/linmath/lvector2_ext_src.I index 091c68760a..3fb1284ddd 100644 --- a/panda/src/linmath/lvector2_ext_src.I +++ b/panda/src/linmath/lvector2_ext_src.I @@ -18,6 +18,16 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector3); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector4); #endif +#ifdef FLOATTYPE_IS_INT +#if PY_MAJOR_VERSION >= 3 +#define PY_FROM_FLOATTYPE PyLong_FromLong +#else +#define PY_FROM_FLOATTYPE PyInt_FromLong +#endif +#else +#define PY_FROM_FLOATTYPE PyFloat_FromDouble +#endif + //////////////////////////////////////////////////////////////////// // Function: LVector2::python_repr // Access: Published @@ -46,7 +56,7 @@ __getattr__(const string &attr_name) const { switch (attr_name.size()) { case 1: - return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); + return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); case 2: { FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2); @@ -84,3 +94,5 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase2. return invoke_extension(_this).__setattr__(self, attr_name, assign); } + +#undef PY_FROM_FLOATTYPE diff --git a/panda/src/linmath/lvector2_src.I b/panda/src/linmath/lvector2_src.I index ba419811fa..45c7975fea 100644 --- a/panda/src/linmath/lvector2_src.I +++ b/panda/src/linmath/lvector2_src.I @@ -171,10 +171,10 @@ operator * (FLOATTYPE scalar) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATNAME(LVector2) FLOATNAME(LVector2):: operator / (FLOATTYPE scalar) const { - FLOATTYPE recip_scalar = 1.0f/scalar; - return FLOATNAME(LVector2)(FLOATNAME(LVecBase2)::operator * (recip_scalar)); + return FLOATNAME(LVector2)(FLOATNAME(LVecBase2)::operator / (scalar)); } +#ifndef FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LVector2::project // Access: Published @@ -208,4 +208,4 @@ INLINE_LINMATH FLOATTYPE FLOATNAME(LVector2):: signed_angle_deg(const FLOATNAME(LVector2) &other) const { return rad_2_deg(signed_angle_rad(other)); } - +#endif // FLOATTYPE_IS_INT diff --git a/panda/src/linmath/lvector2_src.h b/panda/src/linmath/lvector2_src.h index 8a0459737a..417379b37f 100644 --- a/panda/src/linmath/lvector2_src.h +++ b/panda/src/linmath/lvector2_src.h @@ -43,9 +43,11 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVector2) operator * (FLOATTYPE scalar) const; INLINE_LINMATH FLOATNAME(LVector2) operator / (FLOATTYPE scalar) const; +#ifndef FLOATTYPE_IS_INT INLINE_LINMATH FLOATNAME(LVector2) project(const FLOATNAME(LVecBase2) &onto) const; INLINE_LINMATH FLOATTYPE signed_angle_rad(const FLOATNAME(LVector2) &other) const; INLINE_LINMATH FLOATTYPE signed_angle_deg(const FLOATNAME(LVector2) &other) const; +#endif EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); diff --git a/panda/src/linmath/lvector3.cxx b/panda/src/linmath/lvector3.cxx index 91902e7d59..ad4857ebff 100644 --- a/panda/src/linmath/lvector3.cxx +++ b/panda/src/linmath/lvector3.cxx @@ -20,3 +20,5 @@ #include "dblnames.h" #include "lvector3_src.cxx" +#include "intnames.h" +#include "lvector3_src.cxx" diff --git a/panda/src/linmath/lvector3.h b/panda/src/linmath/lvector3.h index 7750cd159f..bf6e7659b2 100644 --- a/panda/src/linmath/lvector3.h +++ b/panda/src/linmath/lvector3.h @@ -29,4 +29,7 @@ #include "dblnames.h" #include "lvector3_src.h" +#include "intnames.h" +#include "lvector3_src.h" + #endif diff --git a/panda/src/linmath/lvector3_ext.h b/panda/src/linmath/lvector3_ext.h index 4deae20e6d..3423fc351e 100644 --- a/panda/src/linmath/lvector3_ext.h +++ b/panda/src/linmath/lvector3_ext.h @@ -26,4 +26,7 @@ #include "dblnames.h" #include "lvector3_ext_src.h" +#include "intnames.h" +#include "lvector3_ext_src.h" + #endif diff --git a/panda/src/linmath/lvector3_ext_src.I b/panda/src/linmath/lvector3_ext_src.I index a0046c513a..183e633a76 100644 --- a/panda/src/linmath/lvector3_ext_src.I +++ b/panda/src/linmath/lvector3_ext_src.I @@ -18,6 +18,16 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector3); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector4); #endif +#ifdef FLOATTYPE_IS_INT +#if PY_MAJOR_VERSION >= 3 +#define PY_FROM_FLOATTYPE PyLong_FromLong +#else +#define PY_FROM_FLOATTYPE PyInt_FromLong +#endif +#else +#define PY_FROM_FLOATTYPE PyFloat_FromDouble +#endif + //////////////////////////////////////////////////////////////////// // Function: LVector3::python_repr // Access: Published @@ -47,7 +57,7 @@ __getattr__(const string &attr_name) const { switch (attr_name.size()) { case 1: - return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); + return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); case 2: { FLOATNAME(LVector2) *vec = new FLOATNAME(LVector2); @@ -85,3 +95,5 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase3. return invoke_extension(_this).__setattr__(self, attr_name, assign); } + +#undef PY_FROM_FLOATTYPE diff --git a/panda/src/linmath/lvector3_src.I b/panda/src/linmath/lvector3_src.I index bf4dbcc067..5a23e12c43 100644 --- a/panda/src/linmath/lvector3_src.I +++ b/panda/src/linmath/lvector3_src.I @@ -75,6 +75,17 @@ FLOATNAME(LVector3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z) : { } +//////////////////////////////////////////////////////////////////// +// Function: LVector3::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVector3):: +FLOATNAME(LVector3)(const FLOATNAME(LVecBase2) ©, FLOATTYPE z) : + FLOATNAME(LVecBase3)(copy, z) +{ +} + //////////////////////////////////////////////////////////////////// // Function: LVector3::zero Named Constructor // Access: Published @@ -208,6 +219,7 @@ cross(const FLOATNAME(LVecBase3) &other) const { return FLOATNAME(LVecBase3)::cross(other); } +#ifndef FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LVector3::project // Access: Published @@ -309,6 +321,7 @@ INLINE_LINMATH FLOATTYPE FLOATNAME(LVector3):: relative_angle_deg(const FLOATNAME(LVector3) &other) const { return relative_angle_rad(other)*180/3.1415926535; } +#endif // FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LVector3::operator * scalar @@ -327,8 +340,7 @@ operator * (FLOATTYPE scalar) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATNAME(LVector3) FLOATNAME(LVector3):: operator / (FLOATTYPE scalar) const { - FLOATTYPE recip_scalar = 1.0f/scalar; - return FLOATNAME(LVector3)(FLOATNAME(LVecBase3)::operator * (recip_scalar)); + return FLOATNAME(LVector3)(FLOATNAME(LVecBase3)::operator / (scalar)); } //////////////////////////////////////////////////////////////////// @@ -345,16 +357,16 @@ up(CoordinateSystem cs) { switch (cs) { case CS_zup_right: case CS_zup_left: - return FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f); + return FLOATNAME(LVector3)(0, 0, 1); case CS_yup_right: case CS_yup_left: - return FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f); + return FLOATNAME(LVector3)(0, 1, 0); default: linmath_cat.error() << "Invalid coordinate system!\n"; - return FLOATNAME(LVector3)(0.0f, 0.0f, 0.0f); + return FLOATNAME(LVector3)(0, 0, 0); } } @@ -366,7 +378,7 @@ up(CoordinateSystem cs) { //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATNAME(LVector3) FLOATNAME(LVector3):: right(CoordinateSystem) { - return FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f); + return FLOATNAME(LVector3)(1, 0, 0); } //////////////////////////////////////////////////////////////////// @@ -382,21 +394,21 @@ forward(CoordinateSystem cs) { } switch (cs) { case CS_zup_right: - return FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f); + return FLOATNAME(LVector3)(0, 1, 0); case CS_zup_left: - return FLOATNAME(LVector3)(0.0f, -1.0f, 0.0f); + return FLOATNAME(LVector3)(0, -1, 0); case CS_yup_right: - return FLOATNAME(LVector3)(0.0f, 0.0f, -1.0f); + return FLOATNAME(LVector3)(0, 0, -1); case CS_yup_left: - return FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f); + return FLOATNAME(LVector3)(0, 0, 1); default: linmath_cat.error() << "Invalid coordinate system!\n"; - return FLOATNAME(LVector3)(0.0f, 0.0f, 0.0f); + return FLOATNAME(LVector3)(0, 0, 0); } } @@ -440,8 +452,7 @@ back(CoordinateSystem cs) { // forward, and up components, in whatever way the // coordinate system represents that vector. //////////////////////////////////////////////////////////////////// - -//INLINE_LINMATH FLOATNAME(LVector3) & FLOATNAME(LVector3):: +//INLINE_LINMATH FLOATNAME(LVector3) &FLOATNAME(LVector3):: INLINE_LINMATH FLOATNAME(LVector3) FLOATNAME(LVector3):: rfu(FLOATTYPE right_v, FLOATTYPE fwd_v, FLOATTYPE up_v, CoordinateSystem cs) { @@ -449,12 +460,11 @@ rfu(FLOATTYPE right_v, FLOATTYPE fwd_v, FLOATTYPE up_v, /* return forward(cs) * fwd_v + up(cs) * up_v + right(cs) * right_v; */ // fast implementation of above for axis-aligned coordinate systems - - if (cs == CS_default) { cs = get_default_coordinate_system(); } - FLOATTYPE vy,vz; + + FLOATTYPE vy, vz; switch(cs) { case CS_yup_right: vz = -fwd_v; @@ -479,9 +489,8 @@ rfu(FLOATTYPE right_v, FLOATTYPE fwd_v, FLOATTYPE up_v, default: linmath_cat.error() << "Invalid coordinate system!\n"; - return FLOATNAME(LVector3)(0.0f, 0.0f, 0.0f); + return FLOATNAME(LVector3)(0); } - return FLOATNAME(LVector3)(right_v,vy,vz); + return FLOATNAME(LVector3)(right_v, vy, vz); } - diff --git a/panda/src/linmath/lvector3_src.h b/panda/src/linmath/lvector3_src.h index 282a41bcd5..bac80207a4 100644 --- a/panda/src/linmath/lvector3_src.h +++ b/panda/src/linmath/lvector3_src.h @@ -30,6 +30,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVector3) &operator = (FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LVector3)(FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LVector3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z); + INLINE_LINMATH FLOATNAME(LVector3)(const FLOATNAME(LVecBase2) ©, FLOATTYPE z); EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); @@ -52,6 +53,8 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVector3) operator - (const FLOATNAME(LVector3) &other) const; INLINE_LINMATH FLOATNAME(LVector3) cross(const FLOATNAME(LVecBase3) &other) const; + +#ifndef FLOATTYPE_IS_INT INLINE_LINMATH FLOATNAME(LVector3) project(const FLOATNAME(LVecBase3) &onto) const; INLINE_LINMATH FLOATTYPE angle_rad(const FLOATNAME(LVector3) &other) const; INLINE_LINMATH FLOATTYPE angle_deg(const FLOATNAME(LVector3) &other) const; @@ -63,7 +66,7 @@ PUBLISHED: INLINE_LINMATH FLOATTYPE relative_angle_rad(const FLOATNAME(LVector3) &other) const; INLINE_LINMATH FLOATTYPE relative_angle_deg(const FLOATNAME(LVector3) &other) const; - +#endif INLINE_LINMATH FLOATNAME(LVector3) operator * (FLOATTYPE scalar) const; INLINE_LINMATH FLOATNAME(LVector3) operator / (FLOATTYPE scalar) const; diff --git a/panda/src/linmath/lvector4.cxx b/panda/src/linmath/lvector4.cxx index 18f4c156e3..68f8940dc1 100644 --- a/panda/src/linmath/lvector4.cxx +++ b/panda/src/linmath/lvector4.cxx @@ -20,3 +20,5 @@ #include "dblnames.h" #include "lvector4_src.cxx" +#include "intnames.h" +#include "lvector4_src.cxx" diff --git a/panda/src/linmath/lvector4.h b/panda/src/linmath/lvector4.h index 566fc9b702..3e36792309 100644 --- a/panda/src/linmath/lvector4.h +++ b/panda/src/linmath/lvector4.h @@ -26,4 +26,7 @@ #include "dblnames.h" #include "lvector4_src.h" +#include "intnames.h" +#include "lvector4_src.h" + #endif diff --git a/panda/src/linmath/lvector4_ext.h b/panda/src/linmath/lvector4_ext.h index 8bd174885e..a7805a2ab5 100644 --- a/panda/src/linmath/lvector4_ext.h +++ b/panda/src/linmath/lvector4_ext.h @@ -26,4 +26,7 @@ #include "dblnames.h" #include "lvector4_ext_src.h" +#include "intnames.h" +#include "lvector4_ext_src.h" + #endif diff --git a/panda/src/linmath/lvector4_ext_src.I b/panda/src/linmath/lvector4_ext_src.I index 8b84439228..f22510fc49 100644 --- a/panda/src/linmath/lvector4_ext_src.I +++ b/panda/src/linmath/lvector4_ext_src.I @@ -18,6 +18,16 @@ IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector3); IMPORT_THIS struct Dtool_PyTypedObject FLOATNAME(Dtool_LVector4); #endif +#ifdef FLOATTYPE_IS_INT +#if PY_MAJOR_VERSION >= 3 +#define PY_FROM_FLOATTYPE PyLong_FromLong +#else +#define PY_FROM_FLOATTYPE PyInt_FromLong +#endif +#else +#define PY_FROM_FLOATTYPE PyFloat_FromDouble +#endif + //////////////////////////////////////////////////////////////////// // Function: LVector4::python_repr // Access: Published @@ -49,9 +59,9 @@ __getattr__(const string &attr_name) const { switch (attr_name.size()) { case 1: if (attr_name[0] == 'w') { - return PyFloat_FromDouble(_this->_v(3)); + return PY_FROM_FLOATTYPE(_this->_v(3)); } else { - return PyFloat_FromDouble(_this->_v(attr_name[0] - 'x')); + return PY_FROM_FLOATTYPE(_this->_v(attr_name[0] - 'x')); } case 2: { @@ -90,3 +100,5 @@ __setattr__(PyObject *self, const string &attr_name, PyObject *assign) { // Upcall to LVecBase4. return invoke_extension(_this).__setattr__(self, attr_name, assign); } + +#undef PY_FROM_FLOATTYPE diff --git a/panda/src/linmath/lvector4_src.I b/panda/src/linmath/lvector4_src.I index 59e7213b53..78333268f4 100644 --- a/panda/src/linmath/lvector4_src.I +++ b/panda/src/linmath/lvector4_src.I @@ -75,6 +75,17 @@ FLOATNAME(LVector4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w) : { } +//////////////////////////////////////////////////////////////////// +// Function: LVector4::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE_LINMATH FLOATNAME(LVector4):: +FLOATNAME(LVector4)(const FLOATNAME(LVecBase3) ©, FLOATTYPE w) : + FLOATNAME(LVecBase4)(copy, w) +{ +} + //////////////////////////////////////////////////////////////////// // Function: LVector4::zero Named Constructor // Access: Public @@ -192,10 +203,10 @@ operator * (FLOATTYPE scalar) const { //////////////////////////////////////////////////////////////////// INLINE_LINMATH FLOATNAME(LVector4) FLOATNAME(LVector4):: operator / (FLOATTYPE scalar) const { - FLOATTYPE recip_scalar = 1.0f/scalar; - return FLOATNAME(LVector4)(FLOATNAME(LVecBase4)::operator * (recip_scalar)); + return FLOATNAME(LVector4)(FLOATNAME(LVecBase4)::operator / (scalar)); } +#ifndef FLOATTYPE_IS_INT //////////////////////////////////////////////////////////////////// // Function: LVector4::project // Access: Published @@ -207,4 +218,4 @@ INLINE_LINMATH FLOATNAME(LVector4) FLOATNAME(LVector4):: project(const FLOATNAME(LVecBase4) &onto) const { return FLOATNAME(LVecBase4)::project(onto); } - +#endif // FLOATTYPE_IS_INT diff --git a/panda/src/linmath/lvector4_src.h b/panda/src/linmath/lvector4_src.h index d9c639fcf1..179ccfdbfd 100644 --- a/panda/src/linmath/lvector4_src.h +++ b/panda/src/linmath/lvector4_src.h @@ -24,6 +24,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVector4) &operator = (FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LVector4)(FLOATTYPE fill_value); INLINE_LINMATH FLOATNAME(LVector4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w); + INLINE_LINMATH FLOATNAME(LVector4)(const FLOATNAME(LVecBase3) ©, FLOATTYPE w); EXTENSION(INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const); EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign)); @@ -45,7 +46,9 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVector4) operator * (FLOATTYPE scalar) const; INLINE_LINMATH FLOATNAME(LVector4) operator / (FLOATTYPE scalar) const; +#ifndef FLOATTYPE_IS_INT INLINE_LINMATH FLOATNAME(LVector4) project(const FLOATNAME(LVecBase4) &onto) const; +#endif EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); diff --git a/panda/src/mathutil/config_mathutil.N b/panda/src/mathutil/config_mathutil.N index 2462341234..491a404161 100644 --- a/panda/src/mathutil/config_mathutil.N +++ b/panda/src/mathutil/config_mathutil.N @@ -51,3 +51,18 @@ forcetype PointerToBase > forcetype PointerToArrayBase forcetype PTA_LVecBase2d forcetype CPTA_LVecBase2d + +forcetype PointerToBase > +forcetype PointerToArrayBase +forcetype PTA_LVecBase4i +forcetype CPTA_LVecBase4i + +forcetype PointerToBase > +forcetype PointerToArrayBase +forcetype PTA_LVecBase3i +forcetype CPTA_LVecBase3i + +forcetype PointerToBase > +forcetype PointerToArrayBase +forcetype PTA_LVecBase2i +forcetype CPTA_LVecBase2i diff --git a/panda/src/mathutil/pta_LVecBase2.h b/panda/src/mathutil/pta_LVecBase2.h index c1dba12a10..8a89d075b6 100644 --- a/panda/src/mathutil/pta_LVecBase2.h +++ b/panda/src/mathutil/pta_LVecBase2.h @@ -53,6 +53,23 @@ EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, ConstPointerTo typedef PointerToArray PTA_LVecBase2d; typedef ConstPointerToArray CPTA_LVecBase2d; +//////////////////////////////////////////////////////////////////// +// Class : PTA_LVecBase2i +// Description : A pta of LVecBase2is. This class is defined once here, +// and exported to PANDA.DLL; other packages that want +// to use a pta of this type (whether they need to +// export it or not) should include this header file, +// rather than defining the pta again. +//////////////////////////////////////////////////////////////////// + +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, PointerToBase >) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, PointerToArrayBase) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, PointerToArray) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, ConstPointerToArray) + +typedef PointerToArray PTA_LVecBase2i; +typedef ConstPointerToArray CPTA_LVecBase2i; + #ifndef STDFLOAT_DOUBLE typedef PTA_LVecBase2f PTA_LVecBase2; typedef CPTA_LVecBase2f CPTA_LVecBase2; diff --git a/panda/src/mathutil/pta_LVecBase3.h b/panda/src/mathutil/pta_LVecBase3.h index 5a9531aca6..f2805a938e 100644 --- a/panda/src/mathutil/pta_LVecBase3.h +++ b/panda/src/mathutil/pta_LVecBase3.h @@ -53,6 +53,23 @@ EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, ConstPointerTo typedef PointerToArray PTA_LVecBase3d; typedef ConstPointerToArray CPTA_LVecBase3d; +//////////////////////////////////////////////////////////////////// +// Class : PTA_LVecBase3i +// Description : A pta of LVecBase3is. This class is defined once here, +// and exported to PANDA.DLL; other packages that want +// to use a pta of this type (whether they need to +// export it or not) should include this header file, +// rather than defining the pta again. +//////////////////////////////////////////////////////////////////// + +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, PointerToBase >) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, PointerToArrayBase) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, PointerToArray) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, ConstPointerToArray) + +typedef PointerToArray PTA_LVecBase3i; +typedef ConstPointerToArray CPTA_LVecBase3i; + #ifndef STDFLOAT_DOUBLE typedef PTA_LVecBase3f PTA_LVecBase3; typedef CPTA_LVecBase3f CPTA_LVecBase3; diff --git a/panda/src/mathutil/pta_LVecBase4.h b/panda/src/mathutil/pta_LVecBase4.h index e1012a45c7..555d4252b1 100644 --- a/panda/src/mathutil/pta_LVecBase4.h +++ b/panda/src/mathutil/pta_LVecBase4.h @@ -61,6 +61,27 @@ EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, ConstPointerTo typedef PointerToArray PTA_LVecBase4d; typedef ConstPointerToArray CPTA_LVecBase4d; +//////////////////////////////////////////////////////////////////// +// Class : PTA_LVecBase4i +// Description : A pta of LVecBase4is. This class is defined once here, +// and exported to PANDA.DLL; other packages that want +// to use a pta of this type (whether they need to +// export it or not) should include this header file, +// rather than defining the pta again. +// +// We actually wrap UnalignedLVecBase4i, in case we are +// building with SSE2 and LVecBase4i requires strict +// alignment. +//////////////////////////////////////////////////////////////////// + +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, PointerToBase >) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, PointerToArrayBase) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, PointerToArray) +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_MATHUTIL, EXPTP_PANDA_MATHUTIL, ConstPointerToArray) + +typedef PointerToArray PTA_LVecBase4i; +typedef ConstPointerToArray CPTA_LVecBase4i; + #ifndef STDFLOAT_DOUBLE typedef PTA_LVecBase4f PTA_LVecBase4; typedef CPTA_LVecBase4f CPTA_LVecBase4; diff --git a/panda/src/mesadisplay/Sources.pp b/panda/src/mesadisplay/Sources.pp deleted file mode 100644 index ad3017e39d..0000000000 --- a/panda/src/mesadisplay/Sources.pp +++ /dev/null @@ -1,23 +0,0 @@ -#define BUILD_DIRECTORY $[HAVE_MESA] -#define BUILDING_DLL BUILDING_PANDAMESA - -#define OTHER_LIBS p3interrogatedb:c p3dconfig:c p3dtoolconfig:m \ - p3dtoolutil:c p3dtoolbase:c p3dtool:m -#define USE_PACKAGES mesa cg cggl - -#begin lib_target - #define TARGET p3mesadisplay - #define LOCAL_LIBS \ - p3glstuff p3gsgbase p3gobj p3display \ - p3putil p3linmath p3mathutil p3pnmimage - - #define SOURCES \ - config_mesadisplay.cxx config_mesadisplay.h \ - mesagsg.h mesagsg.cxx \ - osMesaGraphicsBuffer.I osMesaGraphicsBuffer.cxx osMesaGraphicsBuffer.h \ - osMesaGraphicsPipe.I osMesaGraphicsPipe.cxx osMesaGraphicsPipe.h \ - osMesaGraphicsStateGuardian.h osMesaGraphicsStateGuardian.cxx \ - osMesaGraphicsStateGuardian.I - -#end lib_target - diff --git a/panda/src/mesadisplay/config_mesadisplay.cxx b/panda/src/mesadisplay/config_mesadisplay.cxx deleted file mode 100644 index 6a4f0f8d49..0000000000 --- a/panda/src/mesadisplay/config_mesadisplay.cxx +++ /dev/null @@ -1,65 +0,0 @@ -// Filename: config_mesadisplay.cxx -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "config_mesadisplay.h" -#include "osMesaGraphicsBuffer.h" -#include "osMesaGraphicsPipe.h" -#include "osMesaGraphicsStateGuardian.h" -#include "graphicsPipeSelection.h" -#include "dconfig.h" -#include "mesagsg.h" - -ConfigureDef(config_mesadisplay); -NotifyCategoryDef(mesadisplay, "display"); - -ConfigureFn(config_mesadisplay) { - init_libmesadisplay(); -} - -//////////////////////////////////////////////////////////////////// -// Function: init_libmesadisplay -// Description: Initializes the library. This must be called at -// least once before any of the functions or classes in -// this library can be used. Normally it will be -// called by the static initializers and need not be -// called explicitly, but special cases exist. -//////////////////////////////////////////////////////////////////// -void -init_libmesadisplay() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - - OsMesaGraphicsBuffer::init_type(); - OsMesaGraphicsPipe::init_type(); - OSMesaGraphicsStateGuardian::init_type(); - - GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr(); - selection->add_pipe_type(OsMesaGraphicsPipe::get_class_type(), - OsMesaGraphicsPipe::pipe_constructor); - - Mesainit_classes(); -} - -//////////////////////////////////////////////////////////////////// -// Function: get_pipe_type_mesadisplay -// Description: Returns the TypeHandle index of the recommended -// graphics pipe type defined by this module. -//////////////////////////////////////////////////////////////////// -int -get_pipe_type_mesadisplay() { - return OsMesaGraphicsPipe::get_class_type().get_index(); -} diff --git a/panda/src/mesadisplay/config_mesadisplay.h b/panda/src/mesadisplay/config_mesadisplay.h deleted file mode 100644 index 43009ac83e..0000000000 --- a/panda/src/mesadisplay/config_mesadisplay.h +++ /dev/null @@ -1,28 +0,0 @@ -// Filename: config_mesadisplay.h -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef CONFIG_MESADISPLAY_H -#define CONFIG_MESADISPLAY_H - -#include "pandabase.h" -#include "notifyCategoryProxy.h" -#include "dconfig.h" - -ConfigureDecl(config_mesadisplay, EXPCL_PANDAMESA, EXPTP_PANDAMESA); -NotifyCategoryDecl(mesadisplay, EXPCL_PANDAMESA, EXPTP_PANDAMESA); - -extern EXPCL_PANDAMESA void init_libmesadisplay(); -extern "C" EXPCL_PANDAMESA int get_pipe_type_mesadisplay(); - -#endif diff --git a/panda/src/mesadisplay/mesagsg.cxx b/panda/src/mesadisplay/mesagsg.cxx deleted file mode 100644 index 561e212e32..0000000000 --- a/panda/src/mesadisplay/mesagsg.cxx +++ /dev/null @@ -1,20 +0,0 @@ -// Filename: mesagsg.cxx -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -// This is the actual .cxx file to include if you want to pick up -// any or all of the header files in this directory as compiled to use -// the Mesa library. - -#include "mesagsg.h" -#include "glstuff_src.cxx" diff --git a/panda/src/mesadisplay/mesagsg.h b/panda/src/mesadisplay/mesagsg.h deleted file mode 100644 index dcdb6205c4..0000000000 --- a/panda/src/mesadisplay/mesagsg.h +++ /dev/null @@ -1,103 +0,0 @@ -// Filename: mesagsg.h -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef MESAGSG_H -#define MESAGSG_H - -// This is the actual header file to include if you want to pick up -// any or all of the header files in this directory as compiled to use -// the Mesa library. - -#include "pandabase.h" -#include "config_mesadisplay.h" - -// This stuff seems to crash with Mesa. -#undef HAVE_CG -#undef HAVE_CGGL - -#ifdef MESA_MGL - #define GLP(name) mgl##name - -#ifndef STDFLOAT_DOUBLE -#define GLPf(name) mgl ## name ## f -#define GLPfv(name) mgl ## name ## fv -#else // STDFLOAT_DOUBLE -#define GLPf(name) mgl ## name ## d -#define GLPfv(name) mgl ## name ## dv -#endif // STDFLOAT_DOUBLE - - #define GLPREFIX_QUOTED "mgl" - #define USE_MGL_NAMESPACE 1 - -#else // MESA_MGL - -#ifndef STDFLOAT_DOUBLE -#define GLPf(name) gl ## name ## f -#define GLPfv(name) gl ## name ## fv -#else // STDFLOAT_DOUBLE -#define GLPf(name) gl ## name ## d -#define GLPfv(name) gl ## name ## dv -#endif // STDFLOAT_DOUBLE - - #define GLP(name) gl##name - #define GLPREFIX_QUOTED "gl" - -#endif // MESA_MGL - -#define CLP(name) Mesa##name -#define CLASSPREFIX_QUOTED "Mesa" -#define GLSYSTEM_NAME "Mesa" -#define CONFIGOBJ config_mesadisplay -#define GLCAT mesadisplay_cat -#define EXPCL_GL EXPCL_PANDAMESA -#define EXPTP_GL EXPTP_PANDAMESA - -#if MIN_MESA_VERSION_MAJOR > 1 || (MIN_MESA_VERSION_MAJOR == 1 && MIN_MESA_VERSION_MINOR >= 2) -#define EXPECT_GL_VERSION_1_2 -#endif - -#if MIN_MESA_VERSION_MAJOR > 1 || (MIN_MESA_VERSION_MAJOR == 1 && MIN_MESA_VERSION_MINOR >= 3) -#define EXPECT_GL_VERSION_1_3 -#endif - -#if MIN_MESA_VERSION_MAJOR > 1 || (MIN_MESA_VERSION_MAJOR == 1 && MIN_MESA_VERSION_MINOR >= 4) -#define EXPECT_GL_VERSION_1_4 -#endif - -#if MIN_MESA_VERSION_MAJOR > 1 || (MIN_MESA_VERSION_MAJOR == 1 && MIN_MESA_VERSION_MINOR >= 5) -#define EXPECT_GL_VERSION_1_5 -#endif - -#if MIN_MESA_VERSION_MAJOR > 2 || (MIN_MESA_VERSION_MAJOR == 2 && MIN_MESA_VERSION_MINOR >= 0) -#define EXPECT_GL_VERSION_2_0 -#endif - -#if MIN_MESA_VERSION_MAJOR > 2 || (MIN_MESA_VERSION_MAJOR == 2 && MIN_MESA_VERSION_MINOR >= 1) -#define EXPECT_GL_VERSION_2_1 -#endif - -// This prevents glext.h from getting included by gl.h -// That way, we can provide our own, better version. -#define __glext_h_ -#define GL_GLEXT_VERSION 0 - -#include -#include - -#undef GL_GLEXT_VERSION -#include "panda_glext.h" - -#include "glstuff_src.h" - -#endif // MESAGSG_H diff --git a/panda/src/mesadisplay/osMesaGraphicsBuffer.I b/panda/src/mesadisplay/osMesaGraphicsBuffer.I deleted file mode 100644 index 6907bab451..0000000000 --- a/panda/src/mesadisplay/osMesaGraphicsBuffer.I +++ /dev/null @@ -1,14 +0,0 @@ -// Filename: osMesaGraphicsBuffer.I -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - diff --git a/panda/src/mesadisplay/osMesaGraphicsBuffer.cxx b/panda/src/mesadisplay/osMesaGraphicsBuffer.cxx deleted file mode 100644 index fc292af3c6..0000000000 --- a/panda/src/mesadisplay/osMesaGraphicsBuffer.cxx +++ /dev/null @@ -1,153 +0,0 @@ -// Filename: osMesaGraphicsBuffer.cxx -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "osMesaGraphicsBuffer.h" -#include "config_mesadisplay.h" -#include "osMesaGraphicsPipe.h" -#include "osMesaGraphicsStateGuardian.h" - -TypeHandle OsMesaGraphicsBuffer::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: OsMesaGraphicsBuffer::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -OsMesaGraphicsBuffer:: -OsMesaGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe, - const string &name, - const FrameBufferProperties &fb_prop, - const WindowProperties &win_prop, - int flags, - GraphicsStateGuardian *gsg, - GraphicsOutput *host) : - GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host) -{ - _type = GL_UNSIGNED_BYTE; - _screenshot_buffer_type = _draw_buffer_type; -} - -//////////////////////////////////////////////////////////////////// -// Function: OsMesaGraphicsBuffer::Destructor -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -OsMesaGraphicsBuffer:: -~OsMesaGraphicsBuffer() { -} - -//////////////////////////////////////////////////////////////////// -// Function: OsMesaGraphicsBuffer::begin_frame -// Access: Public, Virtual -// Description: This function will be called within the draw thread -// before beginning rendering for a given frame. It -// should do whatever setup is required, and return true -// if the frame should be rendered, or false if it -// should be skipped. -//////////////////////////////////////////////////////////////////// -bool OsMesaGraphicsBuffer:: -begin_frame(FrameMode mode, Thread *current_thread) { - begin_frame_spam(mode); - if (_gsg == (GraphicsStateGuardian *)NULL) { - return false; - } - - OSMesaGraphicsStateGuardian *mesagsg; - DCAST_INTO_R(mesagsg, _gsg, false); - OSMesaMakeCurrent(mesagsg->_context, _image.p(), _type, - _x_size, _y_size); - - mesagsg->reset_if_new(); - - if (mode == FM_render) { - CDLockedReader cdata(_cycler); - for (size_t i = 0; i != cdata->_textures.size(); ++i) { - const RenderTexture &rt = cdata->_textures[i]; - RenderTextureMode rtm_mode = rt._rtm_mode; - if (rtm_mode == RTM_bind_or_copy) { - CDWriter cdataw(_cycler, cdata, false); - nassertr(cdata->_textures.size() == cdataw->_textures.size(), false); - cdataw->_textures[i]._rtm_mode = RTM_copy_texture; - } - } - clear_cube_map_selection(); - } - _gsg->set_current_properties(&get_fb_properties()); - return _gsg->begin_frame(current_thread); -} - -//////////////////////////////////////////////////////////////////// -// Function: OsMesaGraphicsBuffer::end_frame -// Access: Public, Virtual -// Description: This function will be called within the draw thread -// after rendering is completed for a given frame. It -// should do whatever finalization is required. -//////////////////////////////////////////////////////////////////// -void OsMesaGraphicsBuffer:: -end_frame(FrameMode mode, Thread *current_thread) { - end_frame_spam(mode); - nassertv(_gsg != (GraphicsStateGuardian *)NULL); - - if (mode == FM_render) { - copy_to_textures(); - } - - _gsg->end_frame(current_thread); - - if (mode == FM_render) { - trigger_flip(); - clear_cube_map_selection(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: OsMesaGraphicsBuffer::close_buffer -// Access: Protected, Virtual -// Description: Closes the buffer right now. Called from the window -// thread. -//////////////////////////////////////////////////////////////////// -void OsMesaGraphicsBuffer:: -close_buffer() { - _image.clear(); - _is_valid = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: OsMesaGraphicsBuffer::open_buffer -// Access: Protected, Virtual -// Description: Opens the buffer right now. Called from the window -// thread. Returns true if the buffer is successfully -// opened, or false if there was a problem. -//////////////////////////////////////////////////////////////////// -bool OsMesaGraphicsBuffer:: -open_buffer() { - if (_gsg == 0) { - _gsg = new OSMesaGraphicsStateGuardian(_engine, _pipe, NULL); - } - - _image = PTA_uchar::empty_array(_x_size * _y_size * 4); - _is_valid = true; - - // All OSMesa buffers (that we create) always have the same format. - _fb_properties.clear(); - _fb_properties.set_rgb_color(1); - _fb_properties.set_color_bits(24); - _fb_properties.set_alpha_bits(8); - _fb_properties.set_stencil_bits(8); - _fb_properties.set_depth_bits(16); - _fb_properties.set_accum_bits(8); - _fb_properties.set_force_software(1); - - return true; -} diff --git a/panda/src/mesadisplay/osMesaGraphicsBuffer.h b/panda/src/mesadisplay/osMesaGraphicsBuffer.h deleted file mode 100644 index cf513b2559..0000000000 --- a/panda/src/mesadisplay/osMesaGraphicsBuffer.h +++ /dev/null @@ -1,71 +0,0 @@ -// Filename: osMesaGraphicsBuffer.h -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef OSMESAGRAPHICSBUFFER_H -#define OSMESAGRAPHICSBUFFER_H - -#include "pandabase.h" - -#include "osMesaGraphicsPipe.h" -#include "graphicsBuffer.h" - -//////////////////////////////////////////////////////////////////// -// Class : OsMesaGraphicsBuffer -// Description : An offscreen buffer using direct calls to Mesa. This -// is the only kind of graphics output supported by -// osmesa.h. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDAMESA OsMesaGraphicsBuffer : public GraphicsBuffer { -public: - OsMesaGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe, - const string &name, - const FrameBufferProperties &fb_prop, - const WindowProperties &win_prop, - int flags, - GraphicsStateGuardian *gsg, - GraphicsOutput *host); - virtual ~OsMesaGraphicsBuffer(); - - virtual bool begin_frame(FrameMode mode, Thread *current_thread); - virtual void end_frame(FrameMode mode, Thread *current_thread); - -protected: - virtual void close_buffer(); - virtual bool open_buffer(); - -private: - GLenum _type; - PTA_uchar _image; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - GraphicsBuffer::init_type(); - register_type(_type_handle, "OsMesaGraphicsBuffer", - GraphicsBuffer::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; -}; - -#include "osMesaGraphicsBuffer.I" - -#endif diff --git a/panda/src/mesadisplay/osMesaGraphicsPipe.I b/panda/src/mesadisplay/osMesaGraphicsPipe.I deleted file mode 100644 index 384dab37aa..0000000000 --- a/panda/src/mesadisplay/osMesaGraphicsPipe.I +++ /dev/null @@ -1,14 +0,0 @@ -// Filename: osMesaGraphicsPipe.I -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - diff --git a/panda/src/mesadisplay/osMesaGraphicsPipe.cxx b/panda/src/mesadisplay/osMesaGraphicsPipe.cxx deleted file mode 100644 index 7705645e64..0000000000 --- a/panda/src/mesadisplay/osMesaGraphicsPipe.cxx +++ /dev/null @@ -1,113 +0,0 @@ -// Filename: osMesaGraphicsPipe.cxx -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "osMesaGraphicsPipe.h" -#include "osMesaGraphicsBuffer.h" -#include "osMesaGraphicsStateGuardian.h" -#include "config_mesadisplay.h" -#include "frameBufferProperties.h" -#include "mutexHolder.h" - -TypeHandle OsMesaGraphicsPipe::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: OsMesaGraphicsPipe::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -OsMesaGraphicsPipe:: -OsMesaGraphicsPipe() { - _supported_types = OT_buffer | OT_texture_buffer; - _is_valid = true; -} - -//////////////////////////////////////////////////////////////////// -// Function: OsMesaGraphicsPipe::Destructor -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -OsMesaGraphicsPipe:: -~OsMesaGraphicsPipe() { -} - -//////////////////////////////////////////////////////////////////// -// Function: OsMesaGraphicsPipe::get_interface_name -// Access: Published, Virtual -// Description: Returns the name of the rendering interface -// associated with this GraphicsPipe. This is used to -// present to the user to allow him/her to choose -// between several possible GraphicsPipes available on a -// particular platform, so the name should be meaningful -// and unique for a given platform. -//////////////////////////////////////////////////////////////////// -string OsMesaGraphicsPipe:: -get_interface_name() const { - return "Offscreen Mesa"; -} - -//////////////////////////////////////////////////////////////////// -// Function: OsMesaGraphicsPipe::pipe_constructor -// Access: Public, Static -// Description: This function is passed to the GraphicsPipeSelection -// object to allow the user to make a default -// OsMesaGraphicsPipe. -//////////////////////////////////////////////////////////////////// -PT(GraphicsPipe) OsMesaGraphicsPipe:: -pipe_constructor() { - return new OsMesaGraphicsPipe; -} - -//////////////////////////////////////////////////////////////////// -// Function: OsMesaGraphicsPipe::make_output -// Access: Protected, Virtual -// Description: Creates a new window on the pipe, if possible. -//////////////////////////////////////////////////////////////////// -PT(GraphicsOutput) OsMesaGraphicsPipe:: -make_output(const string &name, - const FrameBufferProperties &fb_prop, - const WindowProperties &win_prop, - int flags, - GraphicsEngine *engine, - GraphicsStateGuardian *gsg, - GraphicsOutput *host, - int retry, - bool &precertify) { - - if (!_is_valid) { - return NULL; - } - - if (retry == 0) { - if ((!support_render_texture)|| - ((flags&BF_require_parasite)!=0)|| - ((flags&BF_require_window)!=0)|| - ((flags&BF_resizeable)!=0)|| - ((flags&BF_size_track_host)!=0)|| - ((flags&BF_can_bind_every)!=0)|| - ((flags&BF_rtt_cumulative)!=0)) { - return NULL; - } - - // We know that OsMesa windows only support single buffering. So - // don't bother asking for more than that. - FrameBufferProperties fb_prop2 = fb_prop; - fb_prop2.set_back_buffers(0); - - return new OsMesaGraphicsBuffer(engine, this, name, fb_prop2, win_prop, - flags, gsg, host); - } - - // Nothing else left to try. - return NULL; -} diff --git a/panda/src/mesadisplay/osMesaGraphicsPipe.h b/panda/src/mesadisplay/osMesaGraphicsPipe.h deleted file mode 100644 index 4d8d388f59..0000000000 --- a/panda/src/mesadisplay/osMesaGraphicsPipe.h +++ /dev/null @@ -1,77 +0,0 @@ -// Filename: osMesaGraphicsPipe.h -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef OSMESAGRAPHICSPIPE_H -#define OSMESAGRAPHICSPIPE_H - -#include "pandabase.h" -#include "graphicsWindow.h" -#include "graphicsPipe.h" -#include "mesagsg.h" - -class FrameBufferProperties; - -//////////////////////////////////////////////////////////////////// -// Class : OsMesaGraphicsPipe -// Description : This graphics pipe represents the interface for -// rendering with direct calls to the Mesa open-source -// software-only implementation of OpenGL. -// -// Raw Mesa supports only offscreen buffers, but it's -// possible to create and render into these offscreen -// buffers without having any X server or other -// operating system infrastructure in place. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDAMESA OsMesaGraphicsPipe : public GraphicsPipe { -public: - OsMesaGraphicsPipe(); - virtual ~OsMesaGraphicsPipe(); - - virtual string get_interface_name() const; - static PT(GraphicsPipe) pipe_constructor(); - -protected: - virtual PT(GraphicsOutput) make_output(const string &name, - const FrameBufferProperties &fb_prop, - const WindowProperties &win_prop, - int flags, - GraphicsEngine *engine, - GraphicsStateGuardian *gsg, - GraphicsOutput *host, - int retry, - bool &precertify); - -private: - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - GraphicsPipe::init_type(); - register_type(_type_handle, "OsMesaGraphicsPipe", - GraphicsPipe::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; -}; - -#include "osMesaGraphicsPipe.I" - -#endif diff --git a/panda/src/mesadisplay/osMesaGraphicsStateGuardian.I b/panda/src/mesadisplay/osMesaGraphicsStateGuardian.I deleted file mode 100644 index ac66c72fbf..0000000000 --- a/panda/src/mesadisplay/osMesaGraphicsStateGuardian.I +++ /dev/null @@ -1,13 +0,0 @@ -// Filename: osMesaGraphicsStateGuardian.I -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// diff --git a/panda/src/mesadisplay/osMesaGraphicsStateGuardian.cxx b/panda/src/mesadisplay/osMesaGraphicsStateGuardian.cxx deleted file mode 100644 index ef256636d7..0000000000 --- a/panda/src/mesadisplay/osMesaGraphicsStateGuardian.cxx +++ /dev/null @@ -1,106 +0,0 @@ -// Filename: osMesaGraphicsStateGuardian.cxx -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#include "osMesaGraphicsStateGuardian.h" - -TypeHandle OSMesaGraphicsStateGuardian::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: OSMesaGraphicsStateGuardian::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -OSMesaGraphicsStateGuardian:: -OSMesaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe, - OSMesaGraphicsStateGuardian *share_with) : - MesaGraphicsStateGuardian(engine, pipe) -{ - OSMesaContext share_context = NULL; - if (share_with != (OSMesaGraphicsStateGuardian *)NULL) { - share_context = share_with->_context; - _prepared_objects = share_with->get_prepared_objects(); - } - - _context = OSMesaCreateContext(OSMESA_RGBA, share_context); - - // OSMesa is never hardware-accelerated. - _is_hardware = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: OSMesaGraphicsStateGuardian::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -OSMesaGraphicsStateGuardian:: -~OSMesaGraphicsStateGuardian() { - if (_context != (OSMesaContext)NULL) { - OSMesaDestroyContext(_context); - _context = (OSMesaContext)NULL; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: OSMesaGraphicsStateGuardian::do_get_extension_func -// Access: Public, Virtual -// Description: Returns the pointer to the GL extension function with -// the indicated name. It is the responsibility of the -// caller to ensure that the required extension is -// defined in the OpenGL runtime prior to calling this; -// it is an error to call this for a function that is -// not defined. -//////////////////////////////////////////////////////////////////// -void *OSMesaGraphicsStateGuardian:: -do_get_extension_func(const char *prefix, const char *name) { -#if (OSMESA_MAJOR_VERSION == 4 && OSMESA_MINOR_VERSION >= 1) || OSMESA_MAJOR_VERSION > 4 - // If we've got at least OSMesa version 4.1, then we can use - // OSMesaGetProcAddress. - - // We ignore the prefix and always use "gl", since that's what Mesa - // does (even if we compile with name mangling enabled to rename the - // Mesa functions to "mgl", they're still stored as "gl" in the - // OSMesaGetProcAddress() lookup table. - string fullname = string("gl") + string(name); - void *ptr = (void *)OSMesaGetProcAddress(fullname.c_str()); - if (mesadisplay_cat.is_debug()) { - mesadisplay_cat.debug() - << "Looking for function " << fullname << ": " << ptr << "\n"; - } - if (ptr == (void *)NULL) { - // Well, try for the more accurate name. - fullname = string(prefix) + string(name); - ptr = (void *)OSMesaGetProcAddress(fullname.c_str()); - if (mesadisplay_cat.is_debug()) { - mesadisplay_cat.debug() - << "Looking for function " << fullname << ": " << ptr << "\n"; - } - } - - return ptr; - -#else - if (mesadisplay_cat.is_debug()) { - mesadisplay_cat.debug() - << "Couldn't look up extension function: compiled with Mesa version " - << OSMESA_MAJOR_VERSION << "." << OSMESA_MINOR_VERSION << "\n"; - } - - // Otherwise, too bad. No extension functions for you. We could - // try to write code that would dig around in the system interface - // (using dlopen(), for instance) to find the extension functions, - // but why should we have to do that? Just go get the latest Mesa, - // for goodness sakes! - return NULL; -#endif -} diff --git a/panda/src/mesadisplay/osMesaGraphicsStateGuardian.h b/panda/src/mesadisplay/osMesaGraphicsStateGuardian.h deleted file mode 100644 index 5dd58402ed..0000000000 --- a/panda/src/mesadisplay/osMesaGraphicsStateGuardian.h +++ /dev/null @@ -1,57 +0,0 @@ -// Filename: osMesaGraphicsStateGuardian.h -// Created by: drose (09Feb04) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// - -#ifndef OSMESAGRAPHICSSTATEGUARDIAN_H -#define OSMESAGRAPHICSSTATEGUARDIAN_H - -#include "pandabase.h" -#include "mesagsg.h" - -//////////////////////////////////////////////////////////////////// -// Class : OSMesaGraphicsStateGuardian -// Description : A tiny specialization on MesaGraphicsStateGuardian to -// add a reference to the OSMesaContext. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDAMESA OSMesaGraphicsStateGuardian : public MesaGraphicsStateGuardian { -public: - OSMesaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe, - OSMesaGraphicsStateGuardian *share_with); - virtual ~OSMesaGraphicsStateGuardian(); - - OSMesaContext _context; - -protected: - virtual void *do_get_extension_func(const char *prefix, const char *name); - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - MesaGraphicsStateGuardian::init_type(); - register_type(_type_handle, "OSMesaGraphicsStateGuardian", - MesaGraphicsStateGuardian::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; -}; - -#include "osMesaGraphicsStateGuardian.I" - -#endif diff --git a/panda/src/mesadisplay/p3mesadisplay_composite1.cxx b/panda/src/mesadisplay/p3mesadisplay_composite1.cxx deleted file mode 100644 index e12afcd1ae..0000000000 --- a/panda/src/mesadisplay/p3mesadisplay_composite1.cxx +++ /dev/null @@ -1,5 +0,0 @@ -#include "config_mesadisplay.cxx" -#include "osMesaGraphicsBuffer.cxx" -#include "osMesaGraphicsPipe.cxx" -#include "osMesaGraphicsStateGuardian.cxx" -#include "mesagsg.cxx" diff --git a/panda/src/osxdisplay/osxGraphicsStateGuardian.cxx b/panda/src/osxdisplay/osxGraphicsStateGuardian.cxx index 1b693800f4..6d4ad703aa 100644 --- a/panda/src/osxdisplay/osxGraphicsStateGuardian.cxx +++ b/panda/src/osxdisplay/osxGraphicsStateGuardian.cxx @@ -38,14 +38,14 @@ TypeHandle osxGraphicsStateGuardian::_type_handle; // not defined. //////////////////////////////////////////////////////////////////// void *osxGraphicsStateGuardian:: -do_get_extension_func(const char *prefix, const char *name) { - string fullname = "_" + string(prefix) + string(name); +do_get_extension_func(const char *name) { + string fullname = "_" + string(name); NSSymbol symbol = NULL; - - if (NSIsSymbolNameDefined (fullname.c_str())) { - symbol = NSLookupAndBindSymbol (fullname.c_str()); + + if (NSIsSymbolNameDefined(fullname.c_str())) { + symbol = NSLookupAndBindSymbol(fullname.c_str()); } - + return symbol ? NSAddressOfSymbol(symbol) : NULL; } diff --git a/panda/src/osxdisplay/osxGraphicsStateGuardian.h b/panda/src/osxdisplay/osxGraphicsStateGuardian.h index cb901fa1bc..855965c6ed 100644 --- a/panda/src/osxdisplay/osxGraphicsStateGuardian.h +++ b/panda/src/osxdisplay/osxGraphicsStateGuardian.h @@ -17,7 +17,7 @@ #define __glext_h_ #include #include - + #include "pandabase.h" #include "glgsg.h" @@ -38,20 +38,20 @@ public: virtual void reset(); void draw_resize_box(); - + bool get_gamma_table(); bool static_set_gamma(bool restore, PN_stdfloat gamma); bool set_gamma(PN_stdfloat gamma); void atexit_function(); void restore_gamma(); - + protected: - virtual void *do_get_extension_func(const char *prefix, const char *name); - + virtual void *do_get_extension_func(const char *name); + public: OSStatus build_gl(bool full_screen, bool pbuffer, FrameBufferProperties &fb_props); AGLContext get_context() { return _aglcontext; }; - + const AGLPixelFormat get_agl_pixel_format() const { return _aglPixFmt; }; private: diff --git a/panda/src/pandabase/pandasymbols.h b/panda/src/pandabase/pandasymbols.h index 1f75ec5a86..670ae662df 100644 --- a/panda/src/pandabase/pandasymbols.h +++ b/panda/src/pandabase/pandasymbols.h @@ -184,14 +184,6 @@ #define EXPTP_PANDAGLES2 extern #endif -#ifdef BUILDING_PANDAMESA - #define EXPCL_PANDAMESA __declspec(dllexport) - #define EXPTP_PANDAMESA -#else - #define EXPCL_PANDAMESA __declspec(dllimport) - #define EXPTP_PANDAMESA extern -#endif - #ifdef BUILDING_PANDAODE #define EXPCL_PANDAODE __declspec(dllexport) #define EXPTP_PANDAODE @@ -350,9 +342,6 @@ #define EXPCL_PANDAGLES2 #define EXPTP_PANDAGLES2 -#define EXPCL_PANDAMESA -#define EXPTP_PANDAMESA - #define EXPCL_PANDAODE #define EXPTP_PANDAODE diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index 5908e7b551..b03f0386aa 100644 --- a/panda/src/pgraph/Sources.pp +++ b/panda/src/pgraph/Sources.pp @@ -72,10 +72,9 @@ modelPool.I modelPool.h \ modelRoot.I modelRoot.h \ nodePath.I nodePath.h nodePath.cxx \ - nodePath_ext.I nodePath_ext.h nodePath_ext.cxx \ + nodePath_ext.I nodePath_ext.h \ nodePathCollection.I nodePathCollection.h \ nodePathCollection_ext.I nodePathCollection_ext.h \ - nodePathCollection_ext.cxx \ nodePathComponent.I nodePathComponent.h \ occluderEffect.I occluderEffect.h \ occluderNode.I occluderNode.h \ @@ -112,7 +111,12 @@ transformState.I transformState.h \ transparencyAttrib.I transparencyAttrib.h \ weakNodePath.I weakNodePath.h \ - workingNodePath.I workingNodePath.h + workingNodePath.I workingNodePath.h \ + nodePath_ext.h nodePath_ext.I \ + nodePathCollection_ext.h nodePathCollection_ext.I \ + pandaNode_ext.h \ + renderState_ext.h \ + transformState_ext.h #define COMBINED_SOURCES \ $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx \ @@ -213,7 +217,12 @@ transformState.cxx \ transparencyAttrib.cxx \ weakNodePath.cxx \ - workingNodePath.cxx + workingNodePath.cxx \ + nodePath_ext.cxx \ + nodePathCollection_ext.cxx \ + pandaNode_ext.cxx \ + renderState_ext.cxx \ + transformState_ext.cxx #define INSTALL_HEADERS \ accumulatedAttribs.I accumulatedAttribs.h \ diff --git a/panda/src/pgraph/geomTransformer.cxx b/panda/src/pgraph/geomTransformer.cxx index bc988fffa0..410f9b22cb 100644 --- a/panda/src/pgraph/geomTransformer.cxx +++ b/panda/src/pgraph/geomTransformer.cxx @@ -1439,16 +1439,15 @@ append_vdata(const GeomVertexData *vdata, int vertex_offset) { if (index.has_column()) { int num_values = index.get_column()->get_num_values(); int num_rows = vdata->get_num_rows(); - int new_index[4]; - + index.set_row_unsafe(vertex_offset); for (int ci = 0; ci < num_rows; ++ci) { - const int *orig_index = index.get_data4i(); + LVecBase4i indices = index.get_data4i(); for (int i = 0; i < num_values; i++) { - nassertv(orig_index[i] >= 0 && orig_index[i] < (int)transform_map.size()); - new_index[i] = transform_map[orig_index[i]]; + nassertv(indices[i] >= 0 && indices[i] < (int)transform_map.size()); + indices[i] = transform_map[indices[i]]; } - index.set_data4i(new_index); + index.set_data4i(indices); } } } diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 216c7deb4b..2e88f06184 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -3813,6 +3813,16 @@ set_shader_input(const InternalName *id, const PTA_double &v, int priority) { set_shader_input(new ShaderInput(id,v,priority)); } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const InternalName *id, const PTA_int &v, int priority) { + set_shader_input(new ShaderInput(id,v,priority)); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::set_shader_input // Access: Published @@ -3874,6 +3884,67 @@ set_shader_input(const InternalName *id, const LVecBase2 &v, int priority) { set_shader_input(new ShaderInput(id,v,priority)); } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const InternalName *id, const PTA_LVecBase4i &v, int priority) { + set_shader_input(new ShaderInput(id,v,priority)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const InternalName *id, const PTA_LVecBase3i &v, int priority) { + set_shader_input(new ShaderInput(id,v,priority)); +} + + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const InternalName *id, const PTA_LVecBase2i &v, int priority) { + set_shader_input(new ShaderInput(id,v,priority)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const InternalName *id, const LVecBase4i &v, int priority) { + set_shader_input(new ShaderInput(id,v,priority)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const InternalName *id, const LVecBase3i &v, int priority) { + set_shader_input(new ShaderInput(id,v,priority)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const InternalName *id, const LVecBase2i &v, int priority) { + set_shader_input(new ShaderInput(id,v,priority)); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::set_shader_input // Access: Published @@ -3934,13 +4005,23 @@ set_shader_input(const InternalName *id, const NodePath &np, int priority) { set_shader_input(new ShaderInput(id,np,priority)); } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const InternalName *id, int n1, int n2, int n3, int n4, int priority) { + set_shader_input(new ShaderInput(id, LVecBase4i(n1, n2, n3, n4), priority)); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::set_shader_input // Access: Published // Description: //////////////////////////////////////////////////////////////////// void NodePath:: -set_shader_input(const InternalName *id, double n1, double n2, double n3, double n4, int priority) { +set_shader_input(const InternalName *id, PN_stdfloat n1, PN_stdfloat n2, PN_stdfloat n3, PN_stdfloat n4, int priority) { set_shader_input(new ShaderInput(id, LVecBase4(n1, n2, n3, n4), priority)); } @@ -3964,6 +4045,16 @@ set_shader_input(const string &id, const PTA_double &v, int priority) { set_shader_input(new ShaderInput(InternalName::make(id),v,priority)); } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const string &id, const PTA_int &v, int priority) { + set_shader_input(new ShaderInput(InternalName::make(id),v,priority)); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::set_shader_input // Access: Published @@ -4015,6 +4106,68 @@ set_shader_input(const string &id, const LVecBase3 &v, int priority) { set_shader_input(new ShaderInput(InternalName::make(id),v,priority)); } + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const string &id, const PTA_LVecBase4i &v, int priority) { + set_shader_input(new ShaderInput(InternalName::make(id),v,priority)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const string &id, const PTA_LVecBase3i &v, int priority) { + set_shader_input(new ShaderInput(InternalName::make(id),v,priority)); +} + + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const string &id, const PTA_LVecBase2i &v, int priority) { + set_shader_input(new ShaderInput(InternalName::make(id),v,priority)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const string &id, const LVecBase4i &v, int priority) { + set_shader_input(new ShaderInput(InternalName::make(id),v,priority)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const string &id, const LVecBase3i &v, int priority) { + set_shader_input(new ShaderInput(InternalName::make(id),v,priority)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const string &id, const LVecBase2i &v, int priority) { + set_shader_input(new ShaderInput(InternalName::make(id),v,priority)); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::set_shader_input // Access: Published @@ -4090,7 +4243,17 @@ set_shader_input(const string &id, const NodePath &np, int priority) { // Description: //////////////////////////////////////////////////////////////////// void NodePath:: -set_shader_input(const string &id, double n1, double n2, double n3, double n4, int priority) { +set_shader_input(const string &id, int n1, int n2, int n3, int n4, int priority) { + set_shader_input(new ShaderInput(InternalName::make(id), LVecBase4i(n1, n2, n3, n4), priority)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_input +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_input(const string &id, PN_stdfloat n1, PN_stdfloat n2, PN_stdfloat n3, PN_stdfloat n4, int priority) { set_shader_input(new ShaderInput(InternalName::make(id), LVecBase4(n1, n2, n3, n4), priority)); } diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index 4bdbba41ff..5b2b2f3cd5 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -612,42 +612,60 @@ PUBLISHED: void set_shader_auto(int priority = 0); void set_shader_auto(BitMask32 shader_switch, int priority=0); void clear_shader(); - + void set_shader_input(const ShaderInput *inp); void set_shader_input(const InternalName *id, Texture *tex, int priority=0); void set_shader_input(const InternalName *id, const NodePath &np, int priority=0); void set_shader_input(const InternalName *id, const PTA_float &v, int priority=0); void set_shader_input(const InternalName *id, const PTA_double &v, int priority=0); + void set_shader_input(const InternalName *id, const PTA_int &v, int priority=0); void set_shader_input(const InternalName *id, const PTA_LVecBase4 &v, int priority=0); void set_shader_input(const InternalName *id, const PTA_LVecBase3 &v, int priority=0); void set_shader_input(const InternalName *id, const PTA_LVecBase2 &v, int priority=0); - void set_shader_input(const InternalName *id, const PTA_LMatrix4 &v, int priority=0); - void set_shader_input(const InternalName *id, const PTA_LMatrix3 &v, int priority=0); - void set_shader_input(const InternalName *id, const LVecBase4 &v, int priority=0); - void set_shader_input(const InternalName *id, const LVecBase3 &v, int priority=0); - void set_shader_input(const InternalName *id, const LVecBase2 &v, int priority=0); - void set_shader_input(const InternalName *id, const LMatrix4 &v, int priority=0); + void set_shader_input(const InternalName *id, const PTA_LMatrix4 &v, int priority=0); + void set_shader_input(const InternalName *id, const PTA_LMatrix3 &v, int priority=0); + void set_shader_input(const InternalName *id, const LVecBase4 &v, int priority=0); + void set_shader_input(const InternalName *id, const LVecBase3 &v, int priority=0); + void set_shader_input(const InternalName *id, const LVecBase2 &v, int priority=0); + void set_shader_input(const InternalName *id, const LMatrix4 &v, int priority=0); void set_shader_input(const InternalName *id, const LMatrix3 &v, int priority=0); - void set_shader_input(const InternalName *id, double n1=0, double n2=0, double n3=0, - double n4=1, int priority=0); + void set_shader_input(const InternalName *id, const PTA_LVecBase4i &v, int priority=0); + void set_shader_input(const InternalName *id, const PTA_LVecBase3i &v, int priority=0); + void set_shader_input(const InternalName *id, const PTA_LVecBase2i &v, int priority=0); + void set_shader_input(const InternalName *id, const LVecBase4i &v, int priority=0); + void set_shader_input(const InternalName *id, const LVecBase3i &v, int priority=0); + void set_shader_input(const InternalName *id, const LVecBase2i &v, int priority=0); + void set_shader_input(const InternalName *id, int n1, int n2=0, int n3=0, + int n4=0, int priority=0); + void set_shader_input(const InternalName *id, PN_stdfloat n1, PN_stdfloat n2=0, + PN_stdfloat n3=0, PN_stdfloat n4=0, int priority=0); void set_shader_input(const string &id, Texture *tex, int priority=0); void set_shader_input(const string &id, const NodePath &np, int priority=0); - void set_shader_input(const string &id, const PTA_float &v, int priority=0); - void set_shader_input(const string &id, const PTA_double &v, int priority=0); - void set_shader_input(const string &id, const PTA_LVecBase4 &v, int priority=0); - void set_shader_input(const string &id, const PTA_LVecBase3 &v, int priority=0); - void set_shader_input(const string &id, const PTA_LVecBase2 &v, int priority=0); + void set_shader_input(const string &id, const PTA_float &v, int priority=0); + void set_shader_input(const string &id, const PTA_double &v, int priority=0); + void set_shader_input(const string &id, const PTA_int &v, int priority=0); + void set_shader_input(const string &id, const PTA_LVecBase4 &v, int priority=0); + void set_shader_input(const string &id, const PTA_LVecBase3 &v, int priority=0); + void set_shader_input(const string &id, const PTA_LVecBase2 &v, int priority=0); void set_shader_input(const string &id, const PTA_LMatrix4 &v, int priority=0); void set_shader_input(const string &id, const PTA_LMatrix3 &v, int priority=0); - void set_shader_input(const string &id, const LVecBase4 &v, int priority=0); - void set_shader_input(const string &id, const LVecBase3 &v, int priority=0); - void set_shader_input(const string &id, const LVecBase2 &v, int priority=0); - void set_shader_input(const string &id, const LMatrix4 &v, int priority=0); - void set_shader_input(const string &id, const LMatrix3 &v, int priority=0); - void set_shader_input(const string &id, double n1=0, double n2=0, double n3=0, - double n4=1, int priority=0); - + void set_shader_input(const string &id, const LVecBase4 &v, int priority=0); + void set_shader_input(const string &id, const LVecBase3 &v, int priority=0); + void set_shader_input(const string &id, const LVecBase2 &v, int priority=0); + void set_shader_input(const string &id, const LMatrix4 &v, int priority=0); + void set_shader_input(const string &id, const LMatrix3 &v, int priority=0); + void set_shader_input(const string &id, const PTA_LVecBase4i &v, int priority=0); + void set_shader_input(const string &id, const PTA_LVecBase3i &v, int priority=0); + void set_shader_input(const string &id, const PTA_LVecBase2i &v, int priority=0); + void set_shader_input(const string &id, const LVecBase4i &v, int priority=0); + void set_shader_input(const string &id, const LVecBase3i &v, int priority=0); + void set_shader_input(const string &id, const LVecBase2i &v, int priority=0); + void set_shader_input(const string &id, int n1, int n2=0, int n3=0, + int n4=0, int priority=0); + void set_shader_input(const string &id, PN_stdfloat n1, PN_stdfloat n2=0, + PN_stdfloat n3=0, PN_stdfloat n4=0, int priority=0); + void clear_shader_input(const InternalName *id); void clear_shader_input(const string &id); void set_instance_count(int instance_count); diff --git a/panda/src/pgraph/nodePath_ext.cxx b/panda/src/pgraph/nodePath_ext.cxx index 0a9b570194..4192675f1b 100644 --- a/panda/src/pgraph/nodePath_ext.cxx +++ b/panda/src/pgraph/nodePath_ext.cxx @@ -168,7 +168,7 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const { } } - PyObject *result = Py_BuildValue("(O(s#))", func, bam_stream.data(), bam_stream.size()); + PyObject *result = Py_BuildValue("(O(s#))", func, bam_stream.data(), (Py_ssize_t) bam_stream.size()); Py_DECREF(func); Py_DECREF(this_class); return result; diff --git a/panda/src/pgraph/pandaNode.I b/panda/src/pgraph/pandaNode.I index f00b6d00aa..6b3e27275c 100644 --- a/panda/src/pgraph/pandaNode.I +++ b/panda/src/pgraph/pandaNode.I @@ -1315,13 +1315,13 @@ get_parent(int n) const { // Description: //////////////////////////////////////////////////////////////////// INLINE PandaNodePipelineReader:: -PandaNodePipelineReader(const PandaNode *object, Thread *current_thread) : - _object(object), +PandaNodePipelineReader(const PandaNode *node, Thread *current_thread) : + _node(node), _current_thread(current_thread), - _cdata(object->_cycler.read_unlocked(current_thread)) + _cdata(node->_cycler.read_unlocked(current_thread)) { #ifdef _DEBUG - nassertv(_object->test_ref_count_nonzero()); + nassertv(_node->test_ref_count_nonzero()); #endif // _DEBUG #ifdef DO_PIPELINING @@ -1335,11 +1335,11 @@ PandaNodePipelineReader(const PandaNode *object, Thread *current_thread) : //////////////////////////////////////////////////////////////////// // Function: PandaNodePipelineReader::Copy Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE PandaNodePipelineReader:: PandaNodePipelineReader(const PandaNodePipelineReader ©) : - _object(copy._object), + _node(copy._node), _current_thread(copy._current_thread), _cdata(copy._cdata) { @@ -1349,7 +1349,7 @@ PandaNodePipelineReader(const PandaNodePipelineReader ©) : /* if (_cdata != (PandaNode::CData *)NULL) { - _object->_cycler.increment_read(_cdata); + _node->_cycler.increment_read(_cdata); } */ } @@ -1357,7 +1357,7 @@ PandaNodePipelineReader(const PandaNodePipelineReader ©) : //////////////////////////////////////////////////////////////////// // Function: PandaNodePipelineReader::Copy Assignment Operator // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// INLINE void PandaNodePipelineReader:: operator = (const PandaNodePipelineReader ©) { @@ -1365,7 +1365,7 @@ operator = (const PandaNodePipelineReader ©) { /* if (_cdata != (PandaNode::CData *)NULL) { - _object->_cycler.release_read(_cdata); + _node->_cycler.release_read(_cdata); } */ @@ -1373,7 +1373,7 @@ operator = (const PandaNodePipelineReader ©) { node_unref_delete((CycleData *)_cdata); #endif // DO_PIPELINING - _object = copy._object; + _node = copy._node; _cdata = copy._cdata; #ifdef DO_PIPELINING @@ -1382,7 +1382,7 @@ operator = (const PandaNodePipelineReader ©) { /* if (_cdata != (PandaNode::CData *)NULL) { - _object->_cycler.increment_read(_cdata); + _node->_cycler.increment_read(_cdata); } */ } @@ -1396,7 +1396,7 @@ INLINE PandaNodePipelineReader:: ~PandaNodePipelineReader() { /* if (_cdata != (PandaNode::CData *)NULL) { - _object->_cycler.release_read(_cdata); + _node->_cycler.release_read(_cdata); } */ @@ -1405,19 +1405,19 @@ INLINE PandaNodePipelineReader:: #endif // DO_PIPELINING #ifdef _DEBUG - _object = NULL; + _node = NULL; _cdata = NULL; #endif // _DEBUG } //////////////////////////////////////////////////////////////////// -// Function: PandaNodePipelineReader::get_object +// Function: PandaNodePipelineReader::get_node // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE const PandaNode *PandaNodePipelineReader:: -get_object() const { - return _object; +get_node() const { + return _node; } //////////////////////////////////////////////////////////////////// @@ -1440,7 +1440,7 @@ INLINE void PandaNodePipelineReader:: release() { /* if (_cdata != (PandaNode::CData *)NULL) { - _object->_cycler.release_read(_cdata); + _node->_cycler.release_read(_cdata); _cdata = NULL; } */ @@ -1539,7 +1539,7 @@ get_parent(int n) const { //////////////////////////////////////////////////////////////////// INLINE int PandaNodePipelineReader:: find_parent(PandaNode *node) const { - return _object->do_find_parent(node, _cdata); + return _node->do_find_parent(node, _cdata); } //////////////////////////////////////////////////////////////////// @@ -1592,7 +1592,7 @@ get_child_sort(int n) const { //////////////////////////////////////////////////////////////////// INLINE int PandaNodePipelineReader:: find_child(PandaNode *node) const { - return _object->do_find_child(node, _cdata->get_down()); + return _node->do_find_child(node, _cdata->get_down()); } //////////////////////////////////////////////////////////////////// @@ -1645,7 +1645,7 @@ get_stashed_sort(int n) const { //////////////////////////////////////////////////////////////////// INLINE int PandaNodePipelineReader:: find_stashed(PandaNode *node) const { - return _object->do_find_child(node, _cdata->get_stashed()); + return _node->do_find_child(node, _cdata->get_stashed()); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index 2dd7f5a5b6..e1b3b105f2 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -4798,7 +4798,7 @@ check_bounds() const { #endif // DO_PIPELINING ((PandaNodePipelineReader *)this)->_cdata = NULL; int pipeline_stage = _current_thread->get_pipeline_stage(); - PandaNode::CDLockedStageReader fresh_cdata(_object->_cycler, pipeline_stage, _current_thread); + PandaNode::CDLockedStageReader fresh_cdata(_node->_cycler, pipeline_stage, _current_thread); if (fresh_cdata->_last_update == fresh_cdata->_next_update) { // What luck, some other thread has already freshened the // cache for us. Save the new pointer, and let the lock @@ -4814,7 +4814,7 @@ check_bounds() const { // No, the cache is still stale. We have to do the work of // freshening it. PStatTimer timer(PandaNode::_update_bounds_pcollector); - PandaNode::CDStageWriter cdataw = ((PandaNode *)_object)->update_bounds(pipeline_stage, fresh_cdata); + PandaNode::CDStageWriter cdataw = ((PandaNode *)_node)->update_bounds(pipeline_stage, fresh_cdata); nassertv(cdataw->_last_update == cdataw->_next_update); // As above, we save the new pointer, and then let the lock // release itself. diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index 17d93d8248..9cde4a9943 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -800,7 +800,7 @@ public: INLINE ~PandaNodePipelineReader(); ALLOC_DELETED_CHAIN(PandaNodePipelineReader); - INLINE const PandaNode *get_object() const; + INLINE const PandaNode *get_node() const; INLINE Thread *get_current_thread() const; INLINE void release(); @@ -810,7 +810,7 @@ public: INLINE void compose_draw_mask(DrawMask &running_draw_mask) const; INLINE bool compare_draw_mask(DrawMask running_draw_mask, DrawMask camera_mask) const; - + INLINE int get_num_parents() const; INLINE PandaNode *get_parent(int n) const; INLINE int find_parent(PandaNode *node) const; @@ -845,7 +845,7 @@ public: INLINE PandaNode::Parents get_parents() const; private: - const PandaNode *_object; + const PandaNode *_node; Thread *_current_thread; const PandaNode::CData *_cdata; diff --git a/panda/src/pgraph/shaderAttrib.cxx b/panda/src/pgraph/shaderAttrib.cxx index e4289c56d7..354f5ff57f 100755 --- a/panda/src/pgraph/shaderAttrib.cxx +++ b/panda/src/pgraph/shaderAttrib.cxx @@ -52,13 +52,18 @@ make_off() { // set. //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) ShaderAttrib:: -make() { +make(const Shader *shader) { static CPT(RenderAttrib) _null_attrib; if (_null_attrib == 0) { ShaderAttrib *attrib = new ShaderAttrib; _null_attrib = return_new(attrib); } - return _null_attrib; + + if (shader == NULL) { + return _null_attrib; + } else { + return DCAST(ShaderAttrib, _null_attrib)->set_shader(shader); + } } //////////////////////////////////////////////////////////////////// @@ -560,6 +565,55 @@ get_shader_input_texture(const InternalName *id) const { } } +//////////////////////////////////////////////////////////////////// +// Function: ShaderAttrib::get_shader_input_matrix +// Access: Published +// Description: Returns the ShaderInput as a matrix. Assertion +// fails if there is none, or if it is not a matrix +// or NodePath. +//////////////////////////////////////////////////////////////////// +const LMatrix4 &ShaderAttrib:: +get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const { + Inputs::const_iterator i = _inputs.find(id); + if (i == _inputs.end()) { + ostringstream strm; + strm << "Shader input " << id->get_name() << " is not present.\n"; + nassert_raise(strm.str()); + return LMatrix4::ident_mat(); + } else { + const ShaderInput *p = (*i).second; + + if (p->get_value_type() == ShaderInput::M_nodepath) { + const NodePath &np = p->get_nodepath(); + nassertr(!np.is_empty(), LMatrix4::ident_mat()); + return np.get_transform()->get_mat(); + + } else if (p->get_value_type() == ShaderInput::M_numeric && p->get_ptr()._size == 16) { + const Shader::ShaderPtrData &ptr = p->get_ptr(); + + switch (ptr._type) { + case Shader::SPT_float: { + LMatrix4f matrixf; + memcpy(&matrixf(0, 0), ptr._ptr, sizeof(float) * 16); + matrix = LCAST(PN_stdfloat, matrixf); + return matrix; + } + case Shader::SPT_double: { + LMatrix4d matrixd; + memcpy(&matrixd(0, 0), ptr._ptr, sizeof(double) * 16); + matrix = LCAST(PN_stdfloat, matrixd); + return matrix; + } + } + } + + ostringstream strm; + strm << "Shader input " << id->get_name() << " is not a NodePath or LMatrix4.\n"; + nassert_raise(strm.str()); + return LMatrix4::ident_mat(); + } +} + //////////////////////////////////////////////////////////////////// // Function: ShaderAttrib::get_shader // Access: Published diff --git a/panda/src/pgraph/shaderAttrib.h b/panda/src/pgraph/shaderAttrib.h index 9b83494bc7..0f8f22505c 100755 --- a/panda/src/pgraph/shaderAttrib.h +++ b/panda/src/pgraph/shaderAttrib.h @@ -43,10 +43,10 @@ private: INLINE ShaderAttrib(const ShaderAttrib ©); PUBLISHED: - static CPT(RenderAttrib) make(); + static CPT(RenderAttrib) make(const Shader *shader = NULL); static CPT(RenderAttrib) make_off(); static CPT(RenderAttrib) make_default(); - + enum { F_disable_alpha_write = 0, // Suppress writes to color buffer alpha channel. F_subsume_alpha_test = 1, // Shader promises to subsume the alpha test using TEXKILL @@ -110,6 +110,7 @@ PUBLISHED: const LVecBase4 &get_shader_input_vector(InternalName *id) const; Texture *get_shader_input_texture(const InternalName *id) const; const Shader::ShaderPtrData *get_shader_input_ptr(const InternalName *id) const; + const LMatrix4 &get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const; static void register_with_read_factory(); diff --git a/panda/src/pgraph/shaderInput.I b/panda/src/pgraph/shaderInput.I index 82d55f090c..21dd429695 100644 --- a/panda/src/pgraph/shaderInput.I +++ b/panda/src/pgraph/shaderInput.I @@ -377,6 +377,107 @@ ShaderInput(const InternalName *name, const LMatrix3d &mat, int priority) : { } +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ShaderInput:: +ShaderInput(const InternalName *name, const PTA_int &ptr, int priority) : + _name(name), + _type(M_numeric), + _priority(priority), + _stored_ptr(ptr) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ShaderInput:: +ShaderInput(const InternalName *name, const PTA_LVecBase4i &ptr, int priority) : + _name(name), + _type(M_numeric), + _priority(priority), + _stored_ptr(ptr) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ShaderInput:: +ShaderInput(const InternalName *name, const PTA_LVecBase3i &ptr, int priority) : + _name(name), + _type(M_numeric), + _priority(priority), + _stored_ptr(ptr) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ShaderInput:: +ShaderInput(const InternalName *name, const PTA_LVecBase2i &ptr, int priority) : + _name(name), + _type(M_numeric), + _priority(priority), + _stored_ptr(ptr) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ShaderInput:: +ShaderInput(const InternalName *name, const LVecBase4i &vec, int priority) : + _name(name), + _type(M_numeric), + _priority(priority), + _stored_ptr(vec), + _stored_vector((int)vec.get_x(), (int)vec.get_y(), (int)vec.get_z(), (int)vec.get_w()) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ShaderInput:: +ShaderInput(const InternalName *name, const LVecBase3i &vec, int priority) : + _name(name), + _type(M_numeric), + _priority(priority), + _stored_ptr(vec), + _stored_vector((int)vec.get_x(), (int)vec.get_y(), (int)vec.get_z(), 0.0) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ShaderInput:: +ShaderInput(const InternalName *name, const LVecBase2i &vec, int priority) : + _name(name), + _type(M_numeric), + _priority(priority), + _stored_ptr(vec), + _stored_vector((int)vec.get_x(), (int)vec.get_y(), 0.0, 0.0) +{ +} + //////////////////////////////////////////////////////////////////// // Function: ShaderInput::get_name // Access: Published diff --git a/panda/src/pgraph/shaderInput.h b/panda/src/pgraph/shaderInput.h index 86e473bf04..5a7e5135fb 100644 --- a/panda/src/pgraph/shaderInput.h +++ b/panda/src/pgraph/shaderInput.h @@ -48,29 +48,37 @@ PUBLISHED: INLINE ShaderInput(const InternalName *id, const NodePath &np, int priority=0); INLINE ShaderInput(const InternalName *id, Texture *tex, int priority=0); INLINE ShaderInput(const InternalName *id, const PTA_float &ptr, int priority=0); - INLINE ShaderInput(const InternalName *id, const PTA_LVecBase4f &ptr, int priority=0); - INLINE ShaderInput(const InternalName *id, const PTA_LVecBase3f &ptr, int priority=0); - INLINE ShaderInput(const InternalName *id, const PTA_LVecBase2f &ptr, int priority=0); - INLINE ShaderInput(const InternalName *id, const PTA_LMatrix4f &ptr, int priority=0); - INLINE ShaderInput(const InternalName *id, const PTA_LMatrix3f &ptr, int priority=0); - INLINE ShaderInput(const InternalName *id, const LVecBase4f &vec, int priority=0); - INLINE ShaderInput(const InternalName *id, const LVecBase3f &vec, int priority=0); - INLINE ShaderInput(const InternalName *id, const LVecBase2f &vec, int priority=0); - INLINE ShaderInput(const InternalName *id, const LMatrix4f &mat, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LVecBase4f &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LVecBase3f &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LVecBase2f &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LMatrix4f &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LMatrix3f &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const LVecBase4f &vec, int priority=0); + INLINE ShaderInput(const InternalName *id, const LVecBase3f &vec, int priority=0); + INLINE ShaderInput(const InternalName *id, const LVecBase2f &vec, int priority=0); + INLINE ShaderInput(const InternalName *id, const LMatrix4f &mat, int priority=0); INLINE ShaderInput(const InternalName *id, const LMatrix3f &mat, int priority=0); - INLINE ShaderInput(const InternalName *id, const PTA_double &ptr, int priority=0); - INLINE ShaderInput(const InternalName *id, const PTA_LVecBase4d &ptr, int priority=0); - INLINE ShaderInput(const InternalName *id, const PTA_LVecBase3d &ptr, int priority=0); - INLINE ShaderInput(const InternalName *id, const PTA_LVecBase2d &ptr, int priority=0); - INLINE ShaderInput(const InternalName *id, const PTA_LMatrix4d &ptr, int priority=0); - INLINE ShaderInput(const InternalName *id, const PTA_LMatrix3d &ptr, int priority=0); - INLINE ShaderInput(const InternalName *id, const LVecBase4d &vec, int priority=0); - INLINE ShaderInput(const InternalName *id, const LVecBase3d &vec, int priority=0); - INLINE ShaderInput(const InternalName *id, const LVecBase2d &vec, int priority=0); - INLINE ShaderInput(const InternalName *id, const LMatrix4d &mat, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_double &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LVecBase4d &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LVecBase3d &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LVecBase2d &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LMatrix4d &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LMatrix3d &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const LVecBase4d &vec, int priority=0); + INLINE ShaderInput(const InternalName *id, const LVecBase3d &vec, int priority=0); + INLINE ShaderInput(const InternalName *id, const LVecBase2d &vec, int priority=0); + INLINE ShaderInput(const InternalName *id, const LMatrix4d &mat, int priority=0); INLINE ShaderInput(const InternalName *id, const LMatrix3d &mat, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_int &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LVecBase4i &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LVecBase3i &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const PTA_LVecBase2i &ptr, int priority=0); + INLINE ShaderInput(const InternalName *id, const LVecBase4i &vec, int priority=0); + INLINE ShaderInput(const InternalName *id, const LVecBase3i &vec, int priority=0); + INLINE ShaderInput(const InternalName *id, const LVecBase2i &vec, int priority=0); + enum ShaderInputType { M_invalid = 0, M_texture, diff --git a/panda/src/pgraphnodes/Sources.pp b/panda/src/pgraphnodes/Sources.pp index ae1a137448..08d8108484 100644 --- a/panda/src/pgraphnodes/Sources.pp +++ b/panda/src/pgraphnodes/Sources.pp @@ -14,6 +14,7 @@ #define SOURCES \ ambientLight.h ambientLight.I \ callbackNode.h callbackNode.I \ + computeNode.h computeNode.I \ config_pgraphnodes.h \ directionalLight.h directionalLight.I \ fadeLodNode.I fadeLodNode.h fadeLodNodeData.h \ @@ -33,6 +34,7 @@ #define INCLUDED_SOURCES \ ambientLight.cxx \ callbackNode.cxx \ + computeNode.cxx \ config_pgraphnodes.cxx \ directionalLight.cxx \ fadeLodNode.cxx fadeLodNodeData.cxx \ @@ -52,6 +54,7 @@ #define INSTALL_HEADERS \ ambientLight.h ambientLight.I \ callbackNode.h callbackNode.I \ + computeNode.h computeNode.I \ config_pgraphnodes.h \ directionalLight.h directionalLight.I \ fadeLodNode.I fadeLodNode.h fadeLodNodeData.h \ diff --git a/panda/src/pgraphnodes/computeNode.I b/panda/src/pgraphnodes/computeNode.I new file mode 100644 index 0000000000..f841af6309 --- /dev/null +++ b/panda/src/pgraphnodes/computeNode.I @@ -0,0 +1,87 @@ +// Filename: computeNode.I +// Created by: rdb (20Jun14) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::add_dispatch +// Access: Published +// Description: Adds a dispatch command with the given number of +// work groups in the X, Y, and Z dimensions. Any +// of these values may be set to 1 if the respective +// dimension should not be used. +//////////////////////////////////////////////////////////////////// +INLINE void ComputeNode:: +add_dispatch(const LVecBase3i &num_groups) { + Dispatcher::CDWriter cdata(_dispatcher->_cycler); + cdata->_dispatches.push_back(num_groups); +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::add_dispatch +// Access: Published +// Description: Adds a dispatch command with the given number of +// work groups in the X, Y, and Z dimensions. Any +// of these values may be set to 1 if the respective +// dimension should not be used. +//////////////////////////////////////////////////////////////////// +INLINE void ComputeNode:: +add_dispatch(int num_groups_x, int num_groups_y, int num_groups_z) { + LVecBase3i num_groups(num_groups_x, num_groups_y, num_groups_z); + add_dispatch(num_groups); +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::get_num_dispatches +// Access: Published +// Description: Returns the number of times add_dispatch has been +// called on this object. +//////////////////////////////////////////////////////////////////// +INLINE int ComputeNode:: +get_num_dispatches() const { + Dispatcher::CDReader cdata(_dispatcher->_cycler); + return cdata->_dispatches.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::get_dispatch +// Access: Published +// Description: Returns the group counts of the nth dispatch +// associated with this object. +//////////////////////////////////////////////////////////////////// +INLINE const LVecBase3i &ComputeNode:: +get_dispatch(int n) const { + Dispatcher::CDReader cdata(_dispatcher->_cycler); + nassertr(n >= 0 && n < cdata->_dispatches.size(), LVecBase3i::zero()); + return cdata->_dispatches[n]; +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::Dispatcher::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ComputeNode::Dispatcher::CData:: +CData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::Dispatcher::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ComputeNode::Dispatcher::CData:: +CData(const ComputeNode::Dispatcher::CData ©) : + _dispatches(copy._dispatches) +{ +} diff --git a/panda/src/pgraphnodes/computeNode.cxx b/panda/src/pgraphnodes/computeNode.cxx new file mode 100644 index 0000000000..bae35b0e85 --- /dev/null +++ b/panda/src/pgraphnodes/computeNode.cxx @@ -0,0 +1,274 @@ +// Filename: computeNode.cxx +// Created by: rdb (19Jun14) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "pandabase.h" +#include "computeNode.h" +#include "cullTraverser.h" +#include "cullableObject.h" +#include "cullHandler.h" +#include "geomDrawCallbackData.h" +#include "omniBoundingVolume.h" +#include "config_pgraph.h" + +TypeHandle ComputeNode::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::Constructor +// Access: Published +// Description: Creates a ComputeNode with the given name. Use +// add_dispatch and also assign a shader using a +// ShaderAttrib. +//////////////////////////////////////////////////////////////////// +ComputeNode:: +ComputeNode(const string &name) : + PandaNode(name), + _dispatcher(new ComputeNode::Dispatcher) +{ + set_internal_bounds(new OmniBoundingVolume); +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::Copy Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +ComputeNode:: +ComputeNode(const ComputeNode ©) : + PandaNode(copy), + _dispatcher(new ComputeNode::Dispatcher(*copy._dispatcher)) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::make_copy +// Access: Public, Virtual +// Description: Returns a newly-allocated Node that is a shallow copy +// of this one. It will be a different Node pointer, +// but its internal data may or may not be shared with +// that of the original Node. +//////////////////////////////////////////////////////////////////// +PandaNode *ComputeNode:: +make_copy() const { + return new ComputeNode(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::safe_to_combine +// Access: Public, Virtual +// Description: Returns true if it is generally safe to combine this +// particular kind of PandaNode with other kinds of +// PandaNodes of compatible type, adding children or +// whatever. For instance, an LODNode should not be +// combined with any other PandaNode, because its set of +// children is meaningful. +//////////////////////////////////////////////////////////////////// +bool ComputeNode:: +safe_to_combine() const { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::is_renderable +// Access: Public, Virtual +// Description: Returns true if there is some value to visiting this +// particular node during the cull traversal for any +// camera, false otherwise. This will be used to +// optimize the result of get_net_draw_show_mask(), so +// that any subtrees that contain only nodes for which +// is_renderable() is false need not be visited. +//////////////////////////////////////////////////////////////////// +bool ComputeNode:: +is_renderable() const { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::add_for_draw +// Access: Public, Virtual +// Description: Adds the node's contents to the CullResult we are +// building up during the cull traversal, so that it +// will be drawn at render time. For most nodes other +// than GeomNodes, this is a do-nothing operation. +//////////////////////////////////////////////////////////////////// +void ComputeNode:: +add_for_draw(CullTraverser *trav, CullTraverserData &data) { + if (pgraph_cat.is_spam()) { + pgraph_cat.spam() + << "Found " << *this << " in state " << *data._state + << " draw_mask = " << data._draw_mask << "\n"; + } + + // OK, render this node. Rendering this node means creating a + // CullableObject for the Dispatcher. We don't need to pass + // any Geoms, however. + CullableObject *object = + new CullableObject(NULL, data._state, + data.get_net_transform(trav), + data.get_modelview_transform(trav), + trav->get_scene()); + object->set_draw_callback(_dispatcher); + trav->get_cull_handler()->record_object(object, trav); +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::output +// Access: Public, Virtual +// Description: Writes a brief description of the node to the +// indicated output stream. This is invoked by the << +// operator. It may be overridden in derived classes to +// include some information relevant to the class. +//////////////////////////////////////////////////////////////////// +void ComputeNode:: +output(ostream &out) const { + PandaNode::output(out); +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::Dispatcher::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +ComputeNode::Dispatcher:: +Dispatcher() { +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::Dispatcher::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +ComputeNode::Dispatcher:: +Dispatcher(const Dispatcher ©) : + _cycler(copy._cycler) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::Dispatcher::do_callback +// Access: Public, Virtual +// Description: Asks the GSG to dispatch the compute shader. +//////////////////////////////////////////////////////////////////// +void ComputeNode::Dispatcher:: +do_callback(CallbackData *cbdata) { + GeomDrawCallbackData *data = (GeomDrawCallbackData *)cbdata; + GraphicsStateGuardianBase *gsg = data->get_gsg(); + + CDReader cdata(_cycler); + + Dispatches::const_iterator it; + for (it = cdata->_dispatches.begin(); it != cdata->_dispatches.end(); ++it) { + gsg->dispatch_compute(it->get_x(), it->get_y(), it->get_z()); + } + + // No need to upcall; we don't have any geometry, after all. +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// ComputeNode. +//////////////////////////////////////////////////////////////////// +void ComputeNode:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void ComputeNode:: +write_datagram(BamWriter *manager, Datagram &dg) { + PandaNode::write_datagram(manager, dg); + manager->write_cdata(dg, _dispatcher->_cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type ComputeNode is encountered +// in the Bam file. It should create the ComputeNode +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *ComputeNode:: +make_from_bam(const FactoryParams ¶ms) { + ComputeNode *node = new ComputeNode(""); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + node->fillin(scan, manager); + + return node; +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::fillin +// Access: Protected +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new ComputeNode. +//////////////////////////////////////////////////////////////////// +void ComputeNode:: +fillin(DatagramIterator &scan, BamReader *manager) { + PandaNode::fillin(scan, manager); + manager->read_cdata(scan, _dispatcher->_cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::Dispatcher::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *ComputeNode::Dispatcher::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::Dispatcher::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void ComputeNode::Dispatcher::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { + dg.add_uint16(_dispatches.size()); + + Dispatches::const_iterator it; + for (it = _dispatches.begin(); it != _dispatches.end(); ++it) { + generic_write_datagram(dg, *it); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ComputeNode::Dispatcher::CData::fillin +// Access: Public, Virtual +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new ComputeNode. +//////////////////////////////////////////////////////////////////// +void ComputeNode::Dispatcher::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { + int num_dispatches = scan.get_uint16(); + _dispatches.resize(num_dispatches); + + for (int i = 0; i < num_dispatches; ++i) { + generic_read_datagram(_dispatches[i], scan); + } +} diff --git a/panda/src/pgraphnodes/computeNode.h b/panda/src/pgraphnodes/computeNode.h new file mode 100644 index 0000000000..1a24b6df7f --- /dev/null +++ b/panda/src/pgraphnodes/computeNode.h @@ -0,0 +1,115 @@ +// Filename: computeNode.h +// Created by: rdb (19Jun14) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef COMPUTENODE_H +#define COMPUTENODE_H + +#include "pandabase.h" +#include "pandaNode.h" +#include "callbackObject.h" +#include "pointerTo.h" + +//////////////////////////////////////////////////////////////////// +// Class : ComputeNode +// Description : A special node, the sole purpose of which is to +// invoke a dispatch operation on the assigned +// compute shader. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA_PGRAPHNODES ComputeNode : public PandaNode { +PUBLISHED: + ComputeNode(const string &name); + + INLINE void add_dispatch(const LVecBase3i &num_groups); + INLINE void add_dispatch(int num_groups_x, int num_groups_y, int num_groups_z); + + INLINE int get_num_dispatches() const; + INLINE const LVecBase3i &get_dispatch(int i) const; + MAKE_SEQ(get_dispatches, get_num_dispatches, get_dispatch); + +public: + ComputeNode(const ComputeNode ©); + + virtual PandaNode *make_copy() const; + virtual bool safe_to_combine() const; + + virtual bool is_renderable() const; + virtual void add_for_draw(CullTraverser *trav, CullTraverserData &data); + + virtual void output(ostream &out) const; + +public: + class EXPCL_PANDA_PGRAPHNODES Dispatcher : public CallbackObject { + friend class ComputeNode; + public: + ALLOC_DELETED_CHAIN(Dispatcher); + Dispatcher(); + Dispatcher(const Dispatcher ©); + + virtual void do_callback(CallbackData *cbdata); + + typedef pvector Dispatches; + + class EXPCL_PANDA_PGRAPHNODES CData : public CycleData { + public: + INLINE CData(); + INLINE CData(const CData ©); + virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual void fillin(DatagramIterator &scan, BamReader *manager); + virtual TypeHandle get_parent_type() const { + return CallbackNode::get_class_type(); + } + + Dispatches _dispatches; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + + }; + +private: + // One per ComputeNode. + PT(Dispatcher) _dispatcher; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + PandaNode::init_type(); + register_type(_type_handle, "ComputeNode", + PandaNode::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "computeNode.I" + +#endif diff --git a/panda/src/pgraphnodes/config_pgraphnodes.cxx b/panda/src/pgraphnodes/config_pgraphnodes.cxx index 79423f9b7a..0973afe91a 100644 --- a/panda/src/pgraphnodes/config_pgraphnodes.cxx +++ b/panda/src/pgraphnodes/config_pgraphnodes.cxx @@ -18,6 +18,7 @@ #include "callbackData.h" #include "callbackNode.h" #include "callbackObject.h" +#include "computeNode.h" #include "directionalLight.h" #include "fadeLodNode.h" #include "fadeLodNodeData.h" @@ -113,6 +114,7 @@ init_libpgraphnodes() { CallbackData::init_type(); CallbackNode::init_type(); CallbackObject::init_type(); + ComputeNode::init_type(); DirectionalLight::init_type(); FadeLODNode::init_type(); FadeLODNodeData::init_type(); @@ -130,6 +132,7 @@ init_libpgraphnodes() { AmbientLight::register_with_read_factory(); CallbackNode::register_with_read_factory(); + ComputeNode::register_with_read_factory(); DirectionalLight::register_with_read_factory(); FadeLODNode::register_with_read_factory(); LightNode::register_with_read_factory(); diff --git a/panda/src/pgraphnodes/p3pgraphnodes_composite1.cxx b/panda/src/pgraphnodes/p3pgraphnodes_composite1.cxx index 94b499f94f..67f6fff97c 100644 --- a/panda/src/pgraphnodes/p3pgraphnodes_composite1.cxx +++ b/panda/src/pgraphnodes/p3pgraphnodes_composite1.cxx @@ -1,5 +1,6 @@ #include "ambientLight.cxx" #include "callbackNode.cxx" +#include "computeNode.cxx" #include "config_pgraphnodes.cxx" #include "directionalLight.cxx" #include "fadeLodNode.cxx" diff --git a/panda/src/pgraphnodes/shaderGenerator.cxx b/panda/src/pgraphnodes/shaderGenerator.cxx index 14bae605fe..d864a1825c 100644 --- a/panda/src/pgraphnodes/shaderGenerator.cxx +++ b/panda/src/pgraphnodes/shaderGenerator.cxx @@ -720,7 +720,7 @@ synthesize_shader(const RenderState *rs) { text << "\t out float4 l_eye_normal : " << eye_normal_freg << ",\n"; } if (_map_index_height >= 0 || _need_world_normal || _need_eye_normal) { - text << "\t in float4 vtx_normal : NORMAL,\n"; + text << "\t in float3 vtx_normal : NORMAL,\n"; } if (_map_index_height >= 0) { text << "\t uniform float4 mspos_view,\n"; @@ -765,13 +765,13 @@ synthesize_shader(const RenderState *rs) { text << "\t l_world_position = mul(trans_model_to_world, vtx_position);\n"; } if (_need_world_normal) { - text << "\t l_world_normal = mul(trans_model_to_world, vtx_normal);\n"; + text << "\t l_world_normal = mul(trans_model_to_world, float4(vtx_normal, 0));\n"; } if (_need_eye_position) { text << "\t l_eye_position = mul(trans_model_to_view, vtx_position);\n"; } if (_need_eye_normal) { - text << "\t l_eye_normal.xyz = mul((float3x3)tpose_view_to_model, vtx_normal.xyz);\n"; + text << "\t l_eye_normal.xyz = mul((float3x3)tpose_view_to_model, vtx_normal);\n"; text << "\t l_eye_normal.w = 0;\n"; } pmap::const_iterator it; @@ -806,7 +806,7 @@ synthesize_shader(const RenderState *rs) { text << "\t float3 eyedir = mspos_view.xyz - vtx_position.xyz;\n"; text << "\t l_eyevec.x = dot(vtx_" << tangent_input << ".xyz, eyedir);\n"; text << "\t l_eyevec.y = dot(vtx_" << binormal_input << ".xyz, eyedir);\n"; - text << "\t l_eyevec.z = dot(vtx_normal.xyz, eyedir);\n"; + text << "\t l_eyevec.z = dot(vtx_normal, eyedir);\n"; text << "\t l_eyevec = normalize(l_eyevec);\n"; } text << "}\n\n"; diff --git a/panda/src/pnmimage/pfmFile.cxx b/panda/src/pnmimage/pfmFile.cxx index bae7793e45..b0a4ddd712 100644 --- a/panda/src/pnmimage/pfmFile.cxx +++ b/panda/src/pnmimage/pfmFile.cxx @@ -213,11 +213,10 @@ read(PNMReader *reader) { // Description: Writes the PFM data to the indicated file, returning // true on success, false on failure. // -// This can also handle writing a standard image file -// supported by PNMImage, if the filename extension is -// some image type's extension other than "pfm"; it -// will be quietly converted to the appropriate integer -// type. +// If the type implied by the filename extension +// supports floating-point, the data will be written +// directly; otherwise, the floating-point data will be +// quietly converted to the appropriate integer type. //////////////////////////////////////////////////////////////////// bool PfmFile:: write(const Filename &fullpath) { @@ -234,21 +233,6 @@ write(const Filename &fullpath) { << "Unable to open " << filename << "\n"; return false; } - - string extension = downcase(fullpath.get_extension()); - if (extension != "pfm") { - // Maybe we're trying to write a different kind of image file. - PNMImage pnm; - PNMWriter *writer = pnm.make_writer(&out, false, fullpath, NULL); - if (writer != (PNMWriter *)NULL) { - // Yep. - if (store(pnm)) { - return pnm.write(writer); - } - // Couldn't make an image. Carry on directly. - delete writer; - } - } if (pnmimage_cat.is_debug()) { pnmimage_cat.debug() diff --git a/panda/src/pnmimagetypes/pnmFileTypePfm.cxx b/panda/src/pnmimagetypes/pnmFileTypePfm.cxx index cc7b5181ff..09623e496a 100644 --- a/panda/src/pnmimagetypes/pnmFileTypePfm.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypePfm.cxx @@ -165,6 +165,8 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) : return; } + _maxval = PGM_MAXMAXVAL; + (*_file) >> _x_size >> _y_size >> _scale; if (!(*_file)) { pnmimage_cat.debug() diff --git a/panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx b/panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx index 5e7655cb18..1461ed2f98 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx @@ -21,6 +21,7 @@ #include "pnmFileTypeRegistry.h" #include "bamReader.h" #include "ppmcmap.h" +#include "pfmFile.h" // Tiff will want to re-typedef these things. #define int8 tiff_int8 @@ -76,9 +77,6 @@ short tiff_predictor = 0; /* 0, 1, or 2; meaningful when tiff_compression == COMPRESSION_LZW. */ -long tiff_rowsperstrip = 0; -/* 0 or any positive number */ - #ifndef PHOTOMETRIC_DEPTH #define PHOTOMETRIC_DEPTH 32768 #endif @@ -369,6 +367,8 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) : } if (_is_valid) { + if ( ! TIFFGetField( tif, TIFFTAG_SAMPLEFORMAT, &sample_format ) ) + sample_format = SAMPLEFORMAT_UINT; if ( ! TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bps ) ) bps = 1; if ( ! TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &spp ) ) @@ -378,6 +378,20 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) : pnmimage_tiff_cat.error() << "Error getting photometric from TIFF file.\n"; _is_valid = false; + + } else if (sample_format == SAMPLEFORMAT_IEEEFP) { + // Floating-point TIFF. We only accept 32-bit floats. + if (bps != 32) { + pnmimage_tiff_cat.error() + << "Can only read 32-bit float TIFF files, not " << bps << "-bit.\n"; + _is_valid = false; + } + + } else if (sample_format != SAMPLEFORMAT_UINT) { + // Can't understand other kinds of sample formats. + pnmimage_tiff_cat.error() + << "Can't understand sample format\n"; + _is_valid = false; } } @@ -565,6 +579,54 @@ PNMFileTypeTIFF::Reader:: } } +//////////////////////////////////////////////////////////////////// +// Function: PNMFileTypeTIFF::Reader::is_floating_point +// Access: Public, Virtual +// Description: Returns true if this PNMFileType represents a +// floating-point image type, false if it is a normal, +// integer type. If this returns true, read_pfm() is +// implemented instead of read_data(). +//////////////////////////////////////////////////////////////////// +bool PNMFileTypeTIFF::Reader:: +is_floating_point() { + return sample_format = SAMPLEFORMAT_IEEEFP; +} + +//////////////////////////////////////////////////////////////////// +// Function: PNMFileTypeTIFF::Reader::read_pfm +// Access: Public, Virtual +// Description: Reads floating-point data directly into the indicated +// PfmFile. Returns true on success, false on failure. +//////////////////////////////////////////////////////////////////// +bool PNMFileTypeTIFF::Reader:: +read_pfm(PfmFile &pfm) { + if (!is_valid()) { + return false; + } + + int x_size = get_x_size(); + int y_size = get_y_size(); + int num_channels = get_num_channels(); + + pfm.clear(x_size, y_size, num_channels); + vector_float table; + pfm.swap_table(table); + + for (int yi = 0; yi < y_size; ++yi) { + float *row = &table[(yi * x_size) * _num_channels]; + + if (TIFFReadScanline(tif, row, yi, 0 ) < 0 ) { + pnmimage_tiff_cat.error() + << "failed a scanline read on row " << yi << "\n"; + pfm.swap_table(table); + return false; + } + } + + pfm.swap_table(table); + return true; +} + //////////////////////////////////////////////////////////////////// // Function: PNMFileTypeTIFF::Reader::supports_read_row // Access: Public, Virtual @@ -855,6 +917,91 @@ Writer(PNMFileType *type, ostream *file, bool owns_file) : { } +//////////////////////////////////////////////////////////////////// +// Function: PNMFileTypeTIFF::Writer::supports_floating_point +// Access: Public, Virtual +// Description: Returns true if this PNMFileType can accept a +// floating-point image type, false if it can only +// accept a normal, integer type. If this returns true, +// write_pfm() is implemented. +//////////////////////////////////////////////////////////////////// +bool PNMFileTypeTIFF::Writer:: +supports_floating_point() { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: PNMFileTypeTIFF::Writer::supports_integer +// Access: Public, Virtual +// Description: Returns true if this PNMFileType can accept an +// integer image type, false if it can only +// accept a floating-point type. If this returns true, +// write_data() or write_row() is implemented. +//////////////////////////////////////////////////////////////////// +bool PNMFileTypeTIFF::Writer:: +supports_integer() { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: PNMFileTypeTIFF::Writer::write_pfm +// Access: Public, Virtual +// Description: Writes floating-point data from the indicated +// PfmFile. Returns true on success, false on failure. +//////////////////////////////////////////////////////////////////// +bool PNMFileTypeTIFF::Writer:: +write_pfm(const PfmFile &pfm) { + struct tiff *tif; + + // Open output file. + tif = TIFFClientOpen("TIFF file", "w", + (thandle_t) _file, + ostream_dont_read, ostream_write, + (TIFFSeekProc)ostream_seek, + iostream_dont_close, ostream_size, + iostream_map, iostream_unmap); + if (tif == NULL) { + return false; + } + + int x_size = pfm.get_x_size(); + int y_size = pfm.get_y_size(); + int num_channels = pfm.get_num_channels(); + + int photometric = 0; + if (num_channels >= 3) { + photometric = PHOTOMETRIC_RGB; + } + + // Set TIFF parameters. + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, x_size); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, y_size); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32); + TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric); + TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Generated via pnmimage.\n" ); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, num_channels); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + + const vector_float &table = pfm.get_table(); + for (int yi = 0; yi < y_size; ++yi) { + const float *row = &table[(yi * x_size) * _num_channels]; + + if (TIFFWriteScanline(tif, (tdata_t)row, yi, 0 ) < 0) { + pnmimage_tiff_cat.error() + << "failed a scanline write on row " << yi << "\n"; + return false; + } + } + + TIFFFlushData(tif); + TIFFClose(tif); + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: PNMFileTypeTIFF::Writer::write_data // Access: Public, Virtual @@ -992,8 +1139,6 @@ write_data(xel *array, xelval *alpha) { break; } - if ( tiff_rowsperstrip == 0 ) - tiff_rowsperstrip = ( 8 * 1024 ) / bytesperrow; buf = (unsigned char*) malloc( bytesperrow ); if ( buf == (unsigned char*) 0 ) { pnmimage_tiff_cat.error() @@ -1004,6 +1149,7 @@ write_data(xel *array, xelval *alpha) { /* Set TIFF parameters. */ TIFFSetField( tif, TIFFTAG_IMAGEWIDTH, _x_size ); TIFFSetField( tif, TIFFTAG_IMAGELENGTH, _y_size ); + TIFFSetField( tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT ); TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, bitspersample ); TIFFSetField( tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT ); TIFFSetField( tif, TIFFTAG_COMPRESSION, tiff_compression ); @@ -1020,8 +1166,6 @@ write_data(xel *array, xelval *alpha) { if (has_alpha()) { TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, extra_samples); } - TIFFSetField( tif, TIFFTAG_ROWSPERSTRIP, tiff_rowsperstrip ); - /* TIFFSetField( tif, TIFFTAG_STRIPBYTECOUNTS, _y_size / tiff_rowsperstrip ); */ TIFFSetField( tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG ); if ( chv == (colorhist_vector) 0 ) { diff --git a/panda/src/pnmimagetypes/pnmFileTypeTIFF.h b/panda/src/pnmimagetypes/pnmFileTypeTIFF.h index 3f8ecf5e30..07f54faf82 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeTIFF.h +++ b/panda/src/pnmimagetypes/pnmFileTypeTIFF.h @@ -55,6 +55,8 @@ public: Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number); virtual ~Reader(); + virtual bool is_floating_point(); + virtual bool read_pfm(PfmFile &pfm); virtual bool supports_read_row() const; virtual bool read_row(xel *array, xelval *alpha, int x_size, int y_size); @@ -65,6 +67,7 @@ public: xelval next_sample_32(unsigned char *&buf_ptr, int &bits_left) const; xelval next_sample_general(unsigned char *&buf_ptr, int &bits_left) const; + unsigned short sample_format; unsigned short photomet; unsigned short bps, spp; unsigned short unassoc_alpha_sample, assoc_alpha_sample; @@ -78,6 +81,9 @@ public: public: Writer(PNMFileType *type, ostream *file, bool owns_file); + virtual bool supports_floating_point(); + virtual bool supports_integer(); + virtual bool write_pfm(const PfmFile &pfm); virtual int write_data(xel *array, xelval *alpha); }; diff --git a/panda/src/putil/copyOnWritePointer.I b/panda/src/putil/copyOnWritePointer.I index a87e7a967c..d36558fbbd 100644 --- a/panda/src/putil/copyOnWritePointer.I +++ b/panda/src/putil/copyOnWritePointer.I @@ -20,10 +20,10 @@ //////////////////////////////////////////////////////////////////// INLINE CopyOnWritePointer:: CopyOnWritePointer(CopyOnWriteObject *object) : - _object(object) + _cow_object(object) { - if (_object != (CopyOnWriteObject *)NULL) { - _object->cache_ref(); + if (_cow_object != (CopyOnWriteObject *)NULL) { + _cow_object->cache_ref(); } } @@ -34,10 +34,10 @@ CopyOnWritePointer(CopyOnWriteObject *object) : //////////////////////////////////////////////////////////////////// INLINE CopyOnWritePointer:: CopyOnWritePointer(const CopyOnWritePointer ©) : - _object(copy._object) + _cow_object(copy._cow_object) { - if (_object != (CopyOnWriteObject *)NULL) { - _object->cache_ref(); + if (_cow_object != (CopyOnWriteObject *)NULL) { + _cow_object->cache_ref(); } } @@ -48,7 +48,7 @@ CopyOnWritePointer(const CopyOnWritePointer ©) : //////////////////////////////////////////////////////////////////// INLINE void CopyOnWritePointer:: operator = (const CopyOnWritePointer ©) { - operator = (copy._object); + operator = (copy._cow_object); } //////////////////////////////////////////////////////////////////// @@ -58,13 +58,13 @@ operator = (const CopyOnWritePointer ©) { //////////////////////////////////////////////////////////////////// INLINE void CopyOnWritePointer:: operator = (CopyOnWriteObject *object) { - if (_object != object) { - if (_object != (CopyOnWriteObject *)NULL) { - cache_unref_delete(_object); + if (_cow_object != object) { + if (_cow_object != (CopyOnWriteObject *)NULL) { + cache_unref_delete(_cow_object); } - _object = object; - if (_object != (CopyOnWriteObject *)NULL) { - _object->cache_ref(); + _cow_object = object; + if (_cow_object != (CopyOnWriteObject *)NULL) { + _cow_object->cache_ref(); } } } @@ -76,8 +76,8 @@ operator = (CopyOnWriteObject *object) { //////////////////////////////////////////////////////////////////// INLINE CopyOnWritePointer:: ~CopyOnWritePointer() { - if (_object != (CopyOnWriteObject *)NULL) { - cache_unref_delete(_object); + if (_cow_object != (CopyOnWriteObject *)NULL) { + cache_unref_delete(_cow_object); } } @@ -88,7 +88,7 @@ INLINE CopyOnWritePointer:: //////////////////////////////////////////////////////////////////// INLINE bool CopyOnWritePointer:: operator == (const CopyOnWritePointer &other) const { - return _object == other._object; + return _cow_object == other._cow_object; } //////////////////////////////////////////////////////////////////// @@ -98,7 +98,7 @@ operator == (const CopyOnWritePointer &other) const { //////////////////////////////////////////////////////////////////// INLINE bool CopyOnWritePointer:: operator != (const CopyOnWritePointer &other) const { - return _object != other._object; + return _cow_object != other._cow_object; } //////////////////////////////////////////////////////////////////// @@ -108,7 +108,7 @@ operator != (const CopyOnWritePointer &other) const { //////////////////////////////////////////////////////////////////// INLINE bool CopyOnWritePointer:: operator < (const CopyOnWritePointer &other) const { - return _object < other._object; + return _cow_object < other._cow_object; } #ifndef COW_THREADED @@ -124,7 +124,7 @@ operator < (const CopyOnWritePointer &other) const { //////////////////////////////////////////////////////////////////// INLINE const CopyOnWriteObject *CopyOnWritePointer:: get_read_pointer() const { - return _object; + return _cow_object; } #endif // COW_THREADED @@ -144,16 +144,16 @@ get_read_pointer() const { //////////////////////////////////////////////////////////////////// INLINE CopyOnWriteObject *CopyOnWritePointer:: get_write_pointer() { - if (_object == (CopyOnWriteObject *)NULL) { + if (_cow_object == (CopyOnWriteObject *)NULL) { return NULL; } - if (_object->get_cache_ref_count() > 1) { - PT(CopyOnWriteObject) new_object = _object->make_cow_copy(); - cache_unref_delete(_object); - _object = new_object; - _object->cache_ref(); + if (_cow_object->get_cache_ref_count() > 1) { + PT(CopyOnWriteObject) new_object = _cow_object->make_cow_copy(); + cache_unref_delete(_cow_object); + _cow_object = new_object; + _cow_object->cache_ref(); } - return _object; + return _cow_object; } #endif // COW_THREADED @@ -167,7 +167,7 @@ get_write_pointer() { //////////////////////////////////////////////////////////////////// INLINE CopyOnWriteObject *CopyOnWritePointer:: get_unsafe_pointer() { - return _object; + return _cow_object; } //////////////////////////////////////////////////////////////////// @@ -178,7 +178,7 @@ get_unsafe_pointer() { //////////////////////////////////////////////////////////////////// bool CopyOnWritePointer:: is_null() const { - return (_object == (CopyOnWriteObject *)NULL); + return (_cow_object == (CopyOnWriteObject *)NULL); } //////////////////////////////////////////////////////////////////// @@ -188,10 +188,10 @@ is_null() const { //////////////////////////////////////////////////////////////////// void CopyOnWritePointer:: clear() { - if (_object != (CopyOnWriteObject *)NULL) { - cache_unref_delete(_object); + if (_cow_object != (CopyOnWriteObject *)NULL) { + cache_unref_delete(_cow_object); } - _object = NULL; + _cow_object = NULL; } //////////////////////////////////////////////////////////////////// @@ -203,8 +203,8 @@ clear() { //////////////////////////////////////////////////////////////////// INLINE bool CopyOnWritePointer:: test_ref_count_integrity() const { - nassertr(_object != (CopyOnWriteObject *)NULL, false); - return _object->test_ref_count_integrity(); + nassertr(_cow_object != (CopyOnWriteObject *)NULL, false); + return _cow_object->test_ref_count_integrity(); } //////////////////////////////////////////////////////////////////// @@ -216,8 +216,8 @@ test_ref_count_integrity() const { //////////////////////////////////////////////////////////////////// INLINE bool CopyOnWritePointer:: test_ref_count_nonzero() const { - nassertr(_object != (CopyOnWriteObject *)NULL, false); - return _object->test_ref_count_nonzero(); + nassertr(_cow_object != (CopyOnWriteObject *)NULL, false); + return _cow_object->test_ref_count_nonzero(); } #ifndef CPPPARSER diff --git a/panda/src/putil/copyOnWritePointer.cxx b/panda/src/putil/copyOnWritePointer.cxx index 82437dd4b4..38ba2d63a5 100644 --- a/panda/src/putil/copyOnWritePointer.cxx +++ b/panda/src/putil/copyOnWritePointer.cxx @@ -30,29 +30,29 @@ //////////////////////////////////////////////////////////////////// CPT(CopyOnWriteObject) CopyOnWritePointer:: get_read_pointer() const { - if (_object == (CopyOnWriteObject *)NULL) { + if (_cow_object == (CopyOnWriteObject *)NULL) { return NULL; } Thread *current_thread = Thread::get_current_thread(); - MutexHolder holder(_object->_lock_mutex); - while (_object->_lock_status == CopyOnWriteObject::LS_locked_write) { - if (_object->_locking_thread == current_thread) { - return _object; + MutexHolder holder(_cow_object->_lock_mutex); + while (_cow_object->_lock_status == CopyOnWriteObject::LS_locked_write) { + if (_cow_object->_locking_thread == current_thread) { + return _cow_object; } if (util_cat.is_debug()) { - util_cat.debug() - << *current_thread << " waiting on " << _object->get_type() - << " " << _object << ", held by " << *_object->_locking_thread + util_cat.debug() + << *current_thread << " waiting on " << _cow_object->get_type() + << " " << _cow_object << ", held by " << *_cow_object->_locking_thread << "\n"; } - _object->_lock_cvar.wait(); + _cow_object->_lock_cvar.wait(); } - _object->_lock_status = CopyOnWriteObject::LS_locked_read; - _object->_locking_thread = current_thread; - return _object; + _cow_object->_lock_status = CopyOnWriteObject::LS_locked_read; + _cow_object->_locking_thread = current_thread; + return _cow_object; } #endif // COW_THREADED @@ -72,52 +72,52 @@ get_read_pointer() const { //////////////////////////////////////////////////////////////////// PT(CopyOnWriteObject) CopyOnWritePointer:: get_write_pointer() { - if (_object == (CopyOnWriteObject *)NULL) { + if (_cow_object == (CopyOnWriteObject *)NULL) { return NULL; } Thread *current_thread = Thread::get_current_thread(); - MutexHolder holder(_object->_lock_mutex); - while (_object->_lock_status == CopyOnWriteObject::LS_locked_write && - _object->_locking_thread != current_thread) { + MutexHolder holder(_cow_object->_lock_mutex); + while (_cow_object->_lock_status == CopyOnWriteObject::LS_locked_write && + _cow_object->_locking_thread != current_thread) { if (util_cat.is_debug()) { - util_cat.debug() - << *current_thread << " waiting on " << _object->get_type() - << " " << _object << ", held by " << *_object->_locking_thread + util_cat.debug() + << *current_thread << " waiting on " << _cow_object->get_type() + << " " << _cow_object << ", held by " << *_cow_object->_locking_thread << "\n"; } - _object->_lock_cvar.wait(); + _cow_object->_lock_cvar.wait(); } - if (_object->_lock_status == CopyOnWriteObject::LS_locked_read) { - nassertr(_object->get_ref_count() > _object->get_cache_ref_count(), NULL); + if (_cow_object->_lock_status == CopyOnWriteObject::LS_locked_read) { + nassertr(_cow_object->get_ref_count() > _cow_object->get_cache_ref_count(), NULL); if (util_cat.is_debug()) { util_cat.debug() - << "Making copy of " << _object->get_type() + << "Making copy of " << _cow_object->get_type() << " because it is locked in read mode.\n"; } - PT(CopyOnWriteObject) new_object = _object->make_cow_copy(); - cache_unref_delete(_object); - _object = new_object; - _object->cache_ref(); + PT(CopyOnWriteObject) new_object = _cow_object->make_cow_copy(); + cache_unref_delete(_cow_object); + _cow_object = new_object; + _cow_object->cache_ref(); - } else if (_object->get_cache_ref_count() > 1) { + } else if (_cow_object->get_cache_ref_count() > 1) { // No one else has it specifically read-locked, but there are // other CopyOnWritePointers holding the same object, so we should // make our own writable copy anyway. if (util_cat.is_debug()) { util_cat.debug() - << "Making copy of " << _object->get_type() - << " because it is shared by " << _object->get_ref_count() + << "Making copy of " << _cow_object->get_type() + << " because it is shared by " << _cow_object->get_ref_count() << " pointers.\n"; } - PT(CopyOnWriteObject) new_object = _object->make_cow_copy(); - cache_unref_delete(_object); - _object = new_object; - _object->cache_ref(); + PT(CopyOnWriteObject) new_object = _cow_object->make_cow_copy(); + cache_unref_delete(_cow_object); + _cow_object = new_object; + _cow_object->cache_ref(); } else { // No other thread has the pointer locked, and we're the only @@ -128,9 +128,9 @@ get_write_pointer() { // references to it, though, since the creator of the object might // have saved himself a reference. } - _object->_lock_status = CopyOnWriteObject::LS_locked_write; - _object->_locking_thread = current_thread; + _cow_object->_lock_status = CopyOnWriteObject::LS_locked_write; + _cow_object->_locking_thread = current_thread; - return _object; + return _cow_object; } #endif // COW_THREADED diff --git a/panda/src/putil/copyOnWritePointer.h b/panda/src/putil/copyOnWritePointer.h index d0dd679ed7..eb985250a3 100644 --- a/panda/src/putil/copyOnWritePointer.h +++ b/panda/src/putil/copyOnWritePointer.h @@ -61,7 +61,7 @@ public: INLINE bool test_ref_count_nonzero() const; private: - CopyOnWriteObject *_object; + CopyOnWriteObject *_cow_object; }; diff --git a/panda/src/putil/typedWritable_ext.cxx b/panda/src/putil/typedWritable_ext.cxx index ebe5f966d5..1cf11e0852 100644 --- a/panda/src/putil/typedWritable_ext.cxx +++ b/panda/src/putil/typedWritable_ext.cxx @@ -119,7 +119,7 @@ __reduce_persist__(PyObject *self, PyObject *pickler) const { } } - PyObject *result = Py_BuildValue("(O(Os#))", func, this_class, bam_stream.data(), bam_stream.size()); + PyObject *result = Py_BuildValue("(O(Os#))", func, this_class, bam_stream.data(), (Py_ssize_t) bam_stream.size()); Py_DECREF(func); Py_DECREF(this_class); return result; @@ -234,10 +234,10 @@ py_decode_TypedWritable_from_bam_stream_persist(PyObject *pickler, PyObject *thi PyObject *result; if (py_reader != NULL){ - result = PyObject_CallFunction(func, (char *)"(s#O)", data.data(), data.size(), py_reader); + result = PyObject_CallFunction(func, (char *)"(s#O)", data.data(), (Py_ssize_t) data.size(), py_reader); Py_DECREF(py_reader); } else { - result = PyObject_CallFunction(func, (char *)"(s#)", data.data(), data.size()); + result = PyObject_CallFunction(func, (char *)"(s#)", data.data(), (Py_ssize_t) data.size()); } if (result == NULL) { diff --git a/panda/src/text/config_text.cxx b/panda/src/text/config_text.cxx index 3bd2792425..8372aa96a1 100644 --- a/panda/src/text/config_text.cxx +++ b/panda/src/text/config_text.cxx @@ -181,7 +181,7 @@ ConfigVariableDouble text_default_underscore_height "to the text baseline, when underscoring is enabled.")); ConfigVariableEnum text_minfilter -("text-minfilter", Texture::FT_linear_mipmap_linear, +("text-minfilter", Texture::FT_linear, PRC_DESC("The default texture minfilter type for dynamic text fonts")); ConfigVariableEnum text_magfilter ("text-magfilter", Texture::FT_linear, diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx index dc34fb3b9e..a0bcc99504 100755 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx @@ -171,11 +171,11 @@ get_properties_advanced(FrameBufferProperties &properties, int iattrib_list[max_attrib_list]; int ivalue_list[max_attrib_list]; int ni = 0; - + int acceleration_i, pixel_type_i, double_buffer_i, stereo_i, color_bits_i, alpha_bits_i, accum_bits_i, depth_bits_i, - stencil_bits_i, multisamples_i; - + stencil_bits_i, multisamples_i, srgb_capable_i; + iattrib_list[acceleration_i = ni++] = WGL_ACCELERATION_ARB; iattrib_list[pixel_type_i = ni++] = WGL_PIXEL_TYPE_ARB; iattrib_list[double_buffer_i = ni++] = WGL_DOUBLE_BUFFER_ARB; @@ -185,43 +185,48 @@ get_properties_advanced(FrameBufferProperties &properties, iattrib_list[accum_bits_i = ni++] = WGL_ACCUM_BITS_ARB; iattrib_list[depth_bits_i = ni++] = WGL_DEPTH_BITS_ARB; iattrib_list[stencil_bits_i = ni++] = WGL_STENCIL_BITS_ARB; - + iattrib_list[srgb_capable_i = ni++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB; + if (_supports_wgl_multisample) { iattrib_list[multisamples_i = ni++] = WGL_SAMPLES_ARB; } - + // Terminate the list. nassertr(ni <= max_attrib_list, false); - + if (!_wglGetPixelFormatAttribivARB(window_dc, pfnum, 0, ni, iattrib_list, ivalue_list)) { return false; } - + properties.clear(); properties.set_all_specified(); int frame_buffer_mode = 0; if (ivalue_list[acceleration_i] == WGL_NO_ACCELERATION_ARB) { - properties.set_force_software(1); + properties.set_force_software(true); } else { - properties.set_force_hardware(1); + properties.set_force_hardware(true); } - + if (ivalue_list[pixel_type_i] == WGL_TYPE_COLORINDEX_ARB) { - properties.set_indexed_color(1); + properties.set_indexed_color(true); } else { - properties.set_rgb_color(1); + properties.set_rgb_color(true); } if (ivalue_list[double_buffer_i]) { properties.set_back_buffers(1); } - + if (ivalue_list[stereo_i]) { - properties.set_stereo(1); + properties.set_stereo(true); } - + + if (ivalue_list[srgb_capable_i]) { + properties.set_srgb_color(true); + } + if (ivalue_list[alpha_bits_i] != 0) { properties.set_alpha_bits(ivalue_list[alpha_bits_i]); } @@ -229,7 +234,7 @@ get_properties_advanced(FrameBufferProperties &properties, if (ivalue_list[accum_bits_i] != 0) { properties.set_accum_bits(ivalue_list[accum_bits_i]); } - + if (ivalue_list[depth_bits_i] != 0) { properties.set_depth_bits(ivalue_list[depth_bits_i]); } @@ -243,9 +248,9 @@ get_properties_advanced(FrameBufferProperties &properties, properties.set_multisamples(ivalue_list[multisamples_i]); } } - + properties.set_color_bits(ivalue_list[color_bits_i]); - + return true; } @@ -429,7 +434,11 @@ choose_pixel_format(const FrameBufferProperties &properties, } } } - + + if (!properties.get_srgb_color()) { + best_prop.set_srgb_color(false); + } + _pfnum = best_pfnum; _pfnum_supports_pbuffer = need_pbuffer; _pfnum_properties = best_prop; @@ -583,9 +592,8 @@ get_extra_extensions() { // not defined. //////////////////////////////////////////////////////////////////// void *wglGraphicsStateGuardian:: -do_get_extension_func(const char *prefix, const char *name) { - string fullname = string(prefix) + string(name); - return (void*) wglGetProcAddress(fullname.c_str()); +do_get_extension_func(const char *name) { + return (void*) wglGetProcAddress(name); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.h b/panda/src/wgldisplay/wglGraphicsStateGuardian.h index e8fe61177a..4fa70b2a46 100755 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.h +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.h @@ -58,7 +58,7 @@ public: protected: virtual void get_extra_extensions(); - virtual void *do_get_extension_func(const char *prefix, const char *name); + virtual void *do_get_extension_func(const char *name); private: void make_context(HDC hdc); diff --git a/panda/src/wgldisplay/wglext.h b/panda/src/wgldisplay/wglext.h index e5c61dd792..6e57a2b8b0 100644 --- a/panda/src/wgldisplay/wglext.h +++ b/panda/src/wgldisplay/wglext.h @@ -1,37 +1,39 @@ #ifndef __wglext_h_ -#define __wglext_h_ +#define __wglext_h_ 1 #ifdef __cplusplus extern "C" { #endif /* -** License Applicability. Except to the extent portions of this file are -** made subject to an alternative license as permitted in the SGI Free -** Software License B, Version 1.1 (the "License"), the contents of this -** file are subject only to the provisions of the License. You may not use -** this file except in compliance with the License. You may obtain a copy -** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 -** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** -** http://oss.sgi.com/projects/FreeB -** -** Note that, as provided in the License, the Software is distributed on an -** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS -** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND -** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A -** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** -** Original Code. The Original Code is: OpenGL Sample Implementation, -** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, -** Inc. The Original Code is Copyright (c) 1991-2002 Silicon Graphics, Inc. -** Copyright in any portions created by third parties is as indicated -** elsewhere herein. All Rights Reserved. -** -** Additional Notice Provisions: This software was created using the -** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has -** not been independently verified as being compliant with the OpenGL(R) -** version 1.2.1 Specification. +** Copyright (c) 2013-2014 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ +/* +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** http://www.opengl.org/registry/ +** +** Khronos $Revision$ on $Date$ */ #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) @@ -39,514 +41,501 @@ extern "C" { #include #endif -#ifndef APIENTRY -#define APIENTRY -#endif -#ifndef APIENTRYP -#define APIENTRYP APIENTRY * -#endif -#ifndef GLAPI -#define GLAPI extern -#endif +#define WGL_WGLEXT_VERSION 20140416 -/*************************************************************/ - -/* Header file version number */ -/* wglext.h last updated 2002/03/22 */ -/* Current version at http://oss.sgi.com/projects/ogl-sample/registry/ */ -#define WGL_WGLEXT_VERSION 4 +/* Generated C header for: + * API: wgl + * Versions considered: .* + * Versions emitted: _nomatch_^ + * Default extensions included: wgl + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ #ifndef WGL_ARB_buffer_region -#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 -#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 -#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 -#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 +#define WGL_ARB_buffer_region 1 +#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 +#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 +#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 +#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 +typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); +typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); +typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); +typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); +#ifdef WGL_WGLEXT_PROTOTYPES +HANDLE WINAPI wglCreateBufferRegionARB (HDC hDC, int iLayerPlane, UINT uType); +VOID WINAPI wglDeleteBufferRegionARB (HANDLE hRegion); +BOOL WINAPI wglSaveBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height); +BOOL WINAPI wglRestoreBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); #endif +#endif /* WGL_ARB_buffer_region */ -#ifndef WGL_ARB_multisample -#define WGL_SAMPLE_BUFFERS_ARB 0x2041 -#define WGL_SAMPLES_ARB 0x2042 +#ifndef WGL_ARB_create_context +#define WGL_ARB_create_context 1 +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define ERROR_INVALID_VERSION_ARB 0x2095 +typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList); +#ifdef WGL_WGLEXT_PROTOTYPES +HGLRC WINAPI wglCreateContextAttribsARB (HDC hDC, HGLRC hShareContext, const int *attribList); #endif +#endif /* WGL_ARB_create_context */ + +#ifndef WGL_ARB_create_context_profile +#define WGL_ARB_create_context_profile 1 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define ERROR_INVALID_PROFILE_ARB 0x2096 +#endif /* WGL_ARB_create_context_profile */ + +#ifndef WGL_ARB_create_context_robustness +#define WGL_ARB_create_context_robustness 1 +#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261 +#endif /* WGL_ARB_create_context_robustness */ #ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 +typedef const char *(WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); +#ifdef WGL_WGLEXT_PROTOTYPES +const char *WINAPI wglGetExtensionsStringARB (HDC hdc); #endif +#endif /* WGL_ARB_extensions_string */ -#ifndef WGL_ARB_pixel_format -#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_DRAW_TO_BITMAP_ARB 0x2002 -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_NEED_PALETTE_ARB 0x2004 -#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 -#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 -#define WGL_SWAP_METHOD_ARB 0x2007 -#define WGL_NUMBER_OVERLAYS_ARB 0x2008 -#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 -#define WGL_TRANSPARENT_ARB 0x200A -#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 -#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 -#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 -#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A -#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B -#define WGL_SHARE_DEPTH_ARB 0x200C -#define WGL_SHARE_STENCIL_ARB 0x200D -#define WGL_SHARE_ACCUM_ARB 0x200E -#define WGL_SUPPORT_GDI_ARB 0x200F -#define WGL_SUPPORT_OPENGL_ARB 0x2010 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_STEREO_ARB 0x2012 -#define WGL_PIXEL_TYPE_ARB 0x2013 -#define WGL_COLOR_BITS_ARB 0x2014 -#define WGL_RED_BITS_ARB 0x2015 -#define WGL_RED_SHIFT_ARB 0x2016 -#define WGL_GREEN_BITS_ARB 0x2017 -#define WGL_GREEN_SHIFT_ARB 0x2018 -#define WGL_BLUE_BITS_ARB 0x2019 -#define WGL_BLUE_SHIFT_ARB 0x201A -#define WGL_ALPHA_BITS_ARB 0x201B -#define WGL_ALPHA_SHIFT_ARB 0x201C -#define WGL_ACCUM_BITS_ARB 0x201D -#define WGL_ACCUM_RED_BITS_ARB 0x201E -#define WGL_ACCUM_GREEN_BITS_ARB 0x201F -#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 -#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_AUX_BUFFERS_ARB 0x2024 -#define WGL_NO_ACCELERATION_ARB 0x2025 -#define WGL_GENERIC_ACCELERATION_ARB 0x2026 -#define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_SWAP_EXCHANGE_ARB 0x2028 -#define WGL_SWAP_COPY_ARB 0x2029 -#define WGL_SWAP_UNDEFINED_ARB 0x202A -#define WGL_TYPE_RGBA_ARB 0x202B -#define WGL_TYPE_COLORINDEX_ARB 0x202C -#endif +#ifndef WGL_ARB_framebuffer_sRGB +#define WGL_ARB_framebuffer_sRGB 1 +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 +#endif /* WGL_ARB_framebuffer_sRGB */ #ifndef WGL_ARB_make_current_read -#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 +#define WGL_ARB_make_current_read 1 +#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 #define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglMakeContextCurrentARB (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +HDC WINAPI wglGetCurrentReadDCARB (void); #endif +#endif /* WGL_ARB_make_current_read */ + +#ifndef WGL_ARB_multisample +#define WGL_ARB_multisample 1 +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 +#endif /* WGL_ARB_multisample */ #ifndef WGL_ARB_pbuffer -#define WGL_DRAW_TO_PBUFFER_ARB 0x202D -#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E -#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F -#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 -#define WGL_PBUFFER_LARGEST_ARB 0x2033 -#define WGL_PBUFFER_WIDTH_ARB 0x2034 -#define WGL_PBUFFER_HEIGHT_ARB 0x2035 -#define WGL_PBUFFER_LOST_ARB 0x2036 +#define WGL_ARB_pbuffer 1 +DECLARE_HANDLE(HPBUFFERARB); +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 +typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); +#ifdef WGL_WGLEXT_PROTOTYPES +HPBUFFERARB WINAPI wglCreatePbufferARB (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB hPbuffer); +int WINAPI wglReleasePbufferDCARB (HPBUFFERARB hPbuffer, HDC hDC); +BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB hPbuffer); +BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); #endif +#endif /* WGL_ARB_pbuffer */ + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglGetPixelFormatAttribivARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); +BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); +BOOL WINAPI wglChoosePixelFormatARB (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif +#endif /* WGL_ARB_pixel_format */ + +#ifndef WGL_ARB_pixel_format_float +#define WGL_ARB_pixel_format_float 1 +#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 +#endif /* WGL_ARB_pixel_format_float */ #ifndef WGL_ARB_render_texture -#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 -#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 -#define WGL_TEXTURE_FORMAT_ARB 0x2072 -#define WGL_TEXTURE_TARGET_ARB 0x2073 -#define WGL_MIPMAP_TEXTURE_ARB 0x2074 -#define WGL_TEXTURE_RGB_ARB 0x2075 -#define WGL_TEXTURE_RGBA_ARB 0x2076 -#define WGL_NO_TEXTURE_ARB 0x2077 -#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 -#define WGL_TEXTURE_1D_ARB 0x2079 -#define WGL_TEXTURE_2D_ARB 0x207A -#define WGL_MIPMAP_LEVEL_ARB 0x207B -#define WGL_CUBE_MAP_FACE_ARB 0x207C +#define WGL_ARB_render_texture 1 +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_MIPMAP_LEVEL_ARB 0x207B +#define WGL_CUBE_MAP_FACE_ARB 0x207C #define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 -#define WGL_FRONT_LEFT_ARB 0x2083 -#define WGL_FRONT_RIGHT_ARB 0x2084 -#define WGL_BACK_LEFT_ARB 0x2085 -#define WGL_BACK_RIGHT_ARB 0x2086 -#define WGL_AUX0_ARB 0x2087 -#define WGL_AUX1_ARB 0x2088 -#define WGL_AUX2_ARB 0x2089 -#define WGL_AUX3_ARB 0x208A -#define WGL_AUX4_ARB 0x208B -#define WGL_AUX5_ARB 0x208C -#define WGL_AUX6_ARB 0x208D -#define WGL_AUX7_ARB 0x208E -#define WGL_AUX8_ARB 0x208F -#define WGL_AUX9_ARB 0x2090 -#endif - -#ifndef WGL_EXT_make_current_read -#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 -#endif - -#ifndef WGL_EXT_pixel_format -#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 -#define WGL_DRAW_TO_WINDOW_EXT 0x2001 -#define WGL_DRAW_TO_BITMAP_EXT 0x2002 -#define WGL_ACCELERATION_EXT 0x2003 -#define WGL_NEED_PALETTE_EXT 0x2004 -#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 -#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 -#define WGL_SWAP_METHOD_EXT 0x2007 -#define WGL_NUMBER_OVERLAYS_EXT 0x2008 -#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 -#define WGL_TRANSPARENT_EXT 0x200A -#define WGL_TRANSPARENT_VALUE_EXT 0x200B -#define WGL_SHARE_DEPTH_EXT 0x200C -#define WGL_SHARE_STENCIL_EXT 0x200D -#define WGL_SHARE_ACCUM_EXT 0x200E -#define WGL_SUPPORT_GDI_EXT 0x200F -#define WGL_SUPPORT_OPENGL_EXT 0x2010 -#define WGL_DOUBLE_BUFFER_EXT 0x2011 -#define WGL_STEREO_EXT 0x2012 -#define WGL_PIXEL_TYPE_EXT 0x2013 -#define WGL_COLOR_BITS_EXT 0x2014 -#define WGL_RED_BITS_EXT 0x2015 -#define WGL_RED_SHIFT_EXT 0x2016 -#define WGL_GREEN_BITS_EXT 0x2017 -#define WGL_GREEN_SHIFT_EXT 0x2018 -#define WGL_BLUE_BITS_EXT 0x2019 -#define WGL_BLUE_SHIFT_EXT 0x201A -#define WGL_ALPHA_BITS_EXT 0x201B -#define WGL_ALPHA_SHIFT_EXT 0x201C -#define WGL_ACCUM_BITS_EXT 0x201D -#define WGL_ACCUM_RED_BITS_EXT 0x201E -#define WGL_ACCUM_GREEN_BITS_EXT 0x201F -#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 -#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 -#define WGL_DEPTH_BITS_EXT 0x2022 -#define WGL_STENCIL_BITS_EXT 0x2023 -#define WGL_AUX_BUFFERS_EXT 0x2024 -#define WGL_NO_ACCELERATION_EXT 0x2025 -#define WGL_GENERIC_ACCELERATION_EXT 0x2026 -#define WGL_FULL_ACCELERATION_EXT 0x2027 -#define WGL_SWAP_EXCHANGE_EXT 0x2028 -#define WGL_SWAP_COPY_EXT 0x2029 -#define WGL_SWAP_UNDEFINED_EXT 0x202A -#define WGL_TYPE_RGBA_EXT 0x202B -#define WGL_TYPE_COLORINDEX_EXT 0x202C -#endif - -#ifndef WGL_EXT_pbuffer -#define WGL_DRAW_TO_PBUFFER_EXT 0x202D -#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E -#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F -#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 -#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 -#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 -#define WGL_PBUFFER_LARGEST_EXT 0x2033 -#define WGL_PBUFFER_WIDTH_EXT 0x2034 -#define WGL_PBUFFER_HEIGHT_EXT 0x2035 -#endif - -#ifndef WGL_EXT_depth_float -#define WGL_DEPTH_FLOAT_EXT 0x2040 -#endif - -#ifndef WGL_3DFX_multisample -#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 -#define WGL_SAMPLES_3DFX 0x2061 -#endif - -#ifndef WGL_EXT_multisample -#define WGL_SAMPLE_BUFFERS_EXT 0x2041 -#define WGL_SAMPLES_EXT 0x2042 -#endif - -#ifndef WGL_I3D_digital_video_control -#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 -#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 -#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 -#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 -#endif - -#ifndef WGL_I3D_gamma -#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E -#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F -#endif - -#ifndef WGL_I3D_genlock -#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 -#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045 -#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046 -#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047 -#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 -#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 -#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A -#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B -#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C -#endif - -#ifndef WGL_I3D_image_buffer -#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 -#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 -#endif - -#ifndef WGL_I3D_swap_frame_lock -#endif - -#ifndef WGL_NV_render_depth_texture -#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 -#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 -#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 -#define WGL_DEPTH_COMPONENT_NV 0x20A7 -#endif - -#ifndef WGL_NV_render_texture_rectangle -#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 -#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 -#endif - -#ifndef WGL_NV_float_buffer -#define WGL_FLOAT_COMPONENTS_NV 0x20B0 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 -#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 -#define WGL_TEXTURE_FLOAT_R_NV 0x20B5 -#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 -#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 -#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 -#endif - - -/*************************************************************/ - -#ifndef WGL_ARB_pbuffer -DECLARE_HANDLE(HPBUFFERARB); -#endif -#ifndef WGL_EXT_pbuffer -DECLARE_HANDLE(HPBUFFEREXT); -#endif - -#ifndef WGL_ARB_buffer_region -#define WGL_ARB_buffer_region 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern HANDLE WINAPI wglCreateBufferRegionARB (HDC, int, UINT); -extern VOID WINAPI wglDeleteBufferRegionARB (HANDLE); -extern BOOL WINAPI wglSaveBufferRegionARB (HANDLE, int, int, int, int); -extern BOOL WINAPI wglRestoreBufferRegionARB (HANDLE, int, int, int, int, int, int); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); -typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); -typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); -typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); -#endif - -#ifndef WGL_ARB_multisample -#define WGL_ARB_multisample 1 -#endif - -#ifndef WGL_ARB_extensions_string -#define WGL_ARB_extensions_string 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern const char * WINAPI wglGetExtensionsStringARB (HDC); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); -#endif - -#ifndef WGL_ARB_pixel_format -#define WGL_ARB_pixel_format 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglGetPixelFormatAttribivARB (HDC, int, int, UINT, const int *, int *); -extern BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC, int, int, UINT, const int *, FLOAT *); -extern BOOL WINAPI wglChoosePixelFormatARB (HDC, const int *, const FLOAT *, UINT, int *, UINT *); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); -typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); -typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); -#endif - -#ifndef WGL_ARB_make_current_read -#define WGL_ARB_make_current_read 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglMakeContextCurrentARB (HDC, HDC, HGLRC); -extern HDC WINAPI wglGetCurrentReadDCARB (void); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); -typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void); -#endif - -#ifndef WGL_ARB_pbuffer -#define WGL_ARB_pbuffer 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern HPBUFFERARB WINAPI wglCreatePbufferARB (HDC, int, int, int, const int *); -extern HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB); -extern int WINAPI wglReleasePbufferDCARB (HPBUFFERARB, HDC); -extern BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB); -extern BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB, int, int *); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); -typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); -typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); -typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); -typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); -#endif - -#ifndef WGL_ARB_render_texture -#define WGL_ARB_render_texture 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglBindTexImageARB (HPBUFFERARB, int); -extern BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB, int); -extern BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB, const int *); -#endif /* WGL_WGLEXT_PROTOTYPES */ +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#define WGL_AUX0_ARB 0x2087 +#define WGL_AUX1_ARB 0x2088 +#define WGL_AUX2_ARB 0x2089 +#define WGL_AUX3_ARB 0x208A +#define WGL_AUX4_ARB 0x208B +#define WGL_AUX5_ARB 0x208C +#define WGL_AUX6_ARB 0x208D +#define WGL_AUX7_ARB 0x208E +#define WGL_AUX8_ARB 0x208F +#define WGL_AUX9_ARB 0x2090 typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglBindTexImageARB (HPBUFFERARB hPbuffer, int iBuffer); +BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB hPbuffer, int iBuffer); +BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB hPbuffer, const int *piAttribList); #endif +#endif /* WGL_ARB_render_texture */ + +#ifndef WGL_ARB_robustness_application_isolation +#define WGL_ARB_robustness_application_isolation 1 +#define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008 +#endif /* WGL_ARB_robustness_application_isolation */ + +#ifndef WGL_ARB_robustness_share_group_isolation +#define WGL_ARB_robustness_share_group_isolation 1 +#endif /* WGL_ARB_robustness_share_group_isolation */ + +#ifndef WGL_3DFX_multisample +#define WGL_3DFX_multisample 1 +#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 +#define WGL_SAMPLES_3DFX 0x2061 +#endif /* WGL_3DFX_multisample */ + +#ifndef WGL_3DL_stereo_control +#define WGL_3DL_stereo_control 1 +#define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055 +#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056 +#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057 +#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058 +typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglSetStereoEmitterState3DL (HDC hDC, UINT uState); +#endif +#endif /* WGL_3DL_stereo_control */ + +#ifndef WGL_AMD_gpu_association +#define WGL_AMD_gpu_association 1 +#define WGL_GPU_VENDOR_AMD 0x1F00 +#define WGL_GPU_RENDERER_STRING_AMD 0x1F01 +#define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 +#define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 +#define WGL_GPU_RAM_AMD 0x21A3 +#define WGL_GPU_CLOCK_AMD 0x21A4 +#define WGL_GPU_NUM_PIPES_AMD 0x21A5 +#define WGL_GPU_NUM_SIMD_AMD 0x21A6 +#define WGL_GPU_NUM_RB_AMD 0x21A7 +#define WGL_GPU_NUM_SPI_AMD 0x21A8 +typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT *ids); +typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, int property, GLenum dataType, UINT size, void *data); +typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc); +typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id); +typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int *attribList); +typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc); +typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc); +typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void); +typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#ifdef WGL_WGLEXT_PROTOTYPES +UINT WINAPI wglGetGPUIDsAMD (UINT maxCount, UINT *ids); +INT WINAPI wglGetGPUInfoAMD (UINT id, int property, GLenum dataType, UINT size, void *data); +UINT WINAPI wglGetContextGPUIDAMD (HGLRC hglrc); +HGLRC WINAPI wglCreateAssociatedContextAMD (UINT id); +HGLRC WINAPI wglCreateAssociatedContextAttribsAMD (UINT id, HGLRC hShareContext, const int *attribList); +BOOL WINAPI wglDeleteAssociatedContextAMD (HGLRC hglrc); +BOOL WINAPI wglMakeAssociatedContextCurrentAMD (HGLRC hglrc); +HGLRC WINAPI wglGetCurrentAssociatedContextAMD (void); +VOID WINAPI wglBlitContextFramebufferAMD (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif +#endif /* WGL_AMD_gpu_association */ + +#ifndef WGL_ATI_pixel_format_float +#define WGL_ATI_pixel_format_float 1 +#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 +#endif /* WGL_ATI_pixel_format_float */ + +#ifndef WGL_EXT_create_context_es2_profile +#define WGL_EXT_create_context_es2_profile 1 +#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 +#endif /* WGL_EXT_create_context_es2_profile */ + +#ifndef WGL_EXT_create_context_es_profile +#define WGL_EXT_create_context_es_profile 1 +#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004 +#endif /* WGL_EXT_create_context_es_profile */ + +#ifndef WGL_EXT_depth_float +#define WGL_EXT_depth_float 1 +#define WGL_DEPTH_FLOAT_EXT 0x2040 +#endif /* WGL_EXT_depth_float */ #ifndef WGL_EXT_display_color_table #define WGL_EXT_display_color_table 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort); -extern GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *, GLuint); -extern GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort); -extern VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort); -#endif /* WGL_WGLEXT_PROTOTYPES */ typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length); typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); +#ifdef WGL_WGLEXT_PROTOTYPES +GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort id); +GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *table, GLuint length); +GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort id); +VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort id); #endif +#endif /* WGL_EXT_display_color_table */ #ifndef WGL_EXT_extensions_string #define WGL_EXT_extensions_string 1 +typedef const char *(WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); #ifdef WGL_WGLEXT_PROTOTYPES -extern const char * WINAPI wglGetExtensionsStringEXT (void); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); +const char *WINAPI wglGetExtensionsStringEXT (void); #endif +#endif /* WGL_EXT_extensions_string */ + +#ifndef WGL_EXT_framebuffer_sRGB +#define WGL_EXT_framebuffer_sRGB 1 +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 +#endif /* WGL_EXT_framebuffer_sRGB */ #ifndef WGL_EXT_make_current_read #define WGL_EXT_make_current_read 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglMakeContextCurrentEXT (HDC, HDC, HGLRC); -extern HDC WINAPI wglGetCurrentReadDCEXT (void); -#endif /* WGL_WGLEXT_PROTOTYPES */ +#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglMakeContextCurrentEXT (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +HDC WINAPI wglGetCurrentReadDCEXT (void); #endif +#endif /* WGL_EXT_make_current_read */ + +#ifndef WGL_EXT_multisample +#define WGL_EXT_multisample 1 +#define WGL_SAMPLE_BUFFERS_EXT 0x2041 +#define WGL_SAMPLES_EXT 0x2042 +#endif /* WGL_EXT_multisample */ #ifndef WGL_EXT_pbuffer #define WGL_EXT_pbuffer 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC, int, int, int, const int *); -extern HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT); -extern int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT, HDC); -extern BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT); -extern BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT, int, int *); -#endif /* WGL_WGLEXT_PROTOTYPES */ +DECLARE_HANDLE(HPBUFFEREXT); +#define WGL_DRAW_TO_PBUFFER_EXT 0x202D +#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E +#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 +#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 +#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 +#define WGL_PBUFFER_LARGEST_EXT 0x2033 +#define WGL_PBUFFER_WIDTH_EXT 0x2034 +#define WGL_PBUFFER_HEIGHT_EXT 0x2035 typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); +#ifdef WGL_WGLEXT_PROTOTYPES +HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT hPbuffer); +int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT hPbuffer, HDC hDC); +BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT hPbuffer); +BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); #endif +#endif /* WGL_EXT_pbuffer */ #ifndef WGL_EXT_pixel_format #define WGL_EXT_pixel_format 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC, int, int, UINT, int *, int *); -extern BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC, int, int, UINT, int *, FLOAT *); -extern BOOL WINAPI wglChoosePixelFormatEXT (HDC, const int *, const FLOAT *, UINT, int *, UINT *); -#endif /* WGL_WGLEXT_PROTOTYPES */ +#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 +#define WGL_DRAW_TO_WINDOW_EXT 0x2001 +#define WGL_DRAW_TO_BITMAP_EXT 0x2002 +#define WGL_ACCELERATION_EXT 0x2003 +#define WGL_NEED_PALETTE_EXT 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 +#define WGL_SWAP_METHOD_EXT 0x2007 +#define WGL_NUMBER_OVERLAYS_EXT 0x2008 +#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 +#define WGL_TRANSPARENT_EXT 0x200A +#define WGL_TRANSPARENT_VALUE_EXT 0x200B +#define WGL_SHARE_DEPTH_EXT 0x200C +#define WGL_SHARE_STENCIL_EXT 0x200D +#define WGL_SHARE_ACCUM_EXT 0x200E +#define WGL_SUPPORT_GDI_EXT 0x200F +#define WGL_SUPPORT_OPENGL_EXT 0x2010 +#define WGL_DOUBLE_BUFFER_EXT 0x2011 +#define WGL_STEREO_EXT 0x2012 +#define WGL_PIXEL_TYPE_EXT 0x2013 +#define WGL_COLOR_BITS_EXT 0x2014 +#define WGL_RED_BITS_EXT 0x2015 +#define WGL_RED_SHIFT_EXT 0x2016 +#define WGL_GREEN_BITS_EXT 0x2017 +#define WGL_GREEN_SHIFT_EXT 0x2018 +#define WGL_BLUE_BITS_EXT 0x2019 +#define WGL_BLUE_SHIFT_EXT 0x201A +#define WGL_ALPHA_BITS_EXT 0x201B +#define WGL_ALPHA_SHIFT_EXT 0x201C +#define WGL_ACCUM_BITS_EXT 0x201D +#define WGL_ACCUM_RED_BITS_EXT 0x201E +#define WGL_ACCUM_GREEN_BITS_EXT 0x201F +#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 +#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 +#define WGL_DEPTH_BITS_EXT 0x2022 +#define WGL_STENCIL_BITS_EXT 0x2023 +#define WGL_AUX_BUFFERS_EXT 0x2024 +#define WGL_NO_ACCELERATION_EXT 0x2025 +#define WGL_GENERIC_ACCELERATION_EXT 0x2026 +#define WGL_FULL_ACCELERATION_EXT 0x2027 +#define WGL_SWAP_EXCHANGE_EXT 0x2028 +#define WGL_SWAP_COPY_EXT 0x2029 +#define WGL_SWAP_UNDEFINED_EXT 0x202A +#define WGL_TYPE_RGBA_EXT 0x202B +#define WGL_TYPE_COLORINDEX_EXT 0x202C typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); +BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); +BOOL WINAPI wglChoosePixelFormatEXT (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); #endif +#endif /* WGL_EXT_pixel_format */ + +#ifndef WGL_EXT_pixel_format_packed_float +#define WGL_EXT_pixel_format_packed_float 1 +#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8 +#endif /* WGL_EXT_pixel_format_packed_float */ #ifndef WGL_EXT_swap_control #define WGL_EXT_swap_control 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglSwapIntervalEXT (int); -extern int WINAPI wglGetSwapIntervalEXT (void); -#endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); -#endif - -#ifndef WGL_EXT_depth_float -#define WGL_EXT_depth_float 1 -#endif - -#ifndef WGL_NV_vertex_array_range -#define WGL_NV_vertex_array_range 1 #ifdef WGL_WGLEXT_PROTOTYPES -extern void* WINAPI wglAllocateMemoryNV (GLsizei, GLfloat, GLfloat, GLfloat); -extern void WINAPI wglFreeMemoryNV (void *); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef void* (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); -typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); +BOOL WINAPI wglSwapIntervalEXT (int interval); +int WINAPI wglGetSwapIntervalEXT (void); #endif +#endif /* WGL_EXT_swap_control */ -#ifndef WGL_3DFX_multisample -#define WGL_3DFX_multisample 1 -#endif - -#ifndef WGL_EXT_multisample -#define WGL_EXT_multisample 1 -#endif - -#ifndef WGL_OML_sync_control -#define WGL_OML_sync_control 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglGetSyncValuesOML (HDC, INT64 *, INT64 *, INT64 *); -extern BOOL WINAPI wglGetMscRateOML (HDC, INT32 *, INT32 *); -extern INT64 WINAPI wglSwapBuffersMscOML (HDC, INT64, INT64, INT64); -extern INT64 WINAPI wglSwapLayerBuffersMscOML (HDC, int, INT64, INT64, INT64); -extern BOOL WINAPI wglWaitForMscOML (HDC, INT64, INT64, INT64, INT64 *, INT64 *, INT64 *); -extern BOOL WINAPI wglWaitForSbcOML (HDC, INT64, INT64 *, INT64 *, INT64 *); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); -typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator); -typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); -typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); -typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); -typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); -#endif +#ifndef WGL_EXT_swap_control_tear +#define WGL_EXT_swap_control_tear 1 +#endif /* WGL_EXT_swap_control_tear */ #ifndef WGL_I3D_digital_video_control #define WGL_I3D_digital_video_control 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC, int, int *); -extern BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC, int, const int *); -#endif /* WGL_WGLEXT_PROTOTYPES */ +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 +#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 +#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC hDC, int iAttribute, int *piValue); +BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC hDC, int iAttribute, const int *piValue); #endif +#endif /* WGL_I3D_digital_video_control */ #ifndef WGL_I3D_gamma #define WGL_I3D_gamma 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglGetGammaTableParametersI3D (HDC, int, int *); -extern BOOL WINAPI wglSetGammaTableParametersI3D (HDC, int, const int *); -extern BOOL WINAPI wglGetGammaTableI3D (HDC, int, USHORT *, USHORT *, USHORT *); -extern BOOL WINAPI wglSetGammaTableI3D (HDC, int, const USHORT *, const USHORT *, const USHORT *); -#endif /* WGL_WGLEXT_PROTOTYPES */ +#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E +#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglGetGammaTableParametersI3D (HDC hDC, int iAttribute, int *piValue); +BOOL WINAPI wglSetGammaTableParametersI3D (HDC hDC, int iAttribute, const int *piValue); +BOOL WINAPI wglGetGammaTableI3D (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); +BOOL WINAPI wglSetGammaTableI3D (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); #endif +#endif /* WGL_I3D_gamma */ #ifndef WGL_I3D_genlock #define WGL_I3D_genlock 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglEnableGenlockI3D (HDC); -extern BOOL WINAPI wglDisableGenlockI3D (HDC); -extern BOOL WINAPI wglIsEnabledGenlockI3D (HDC, BOOL *); -extern BOOL WINAPI wglGenlockSourceI3D (HDC, UINT); -extern BOOL WINAPI wglGetGenlockSourceI3D (HDC, UINT *); -extern BOOL WINAPI wglGenlockSourceEdgeI3D (HDC, UINT); -extern BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC, UINT *); -extern BOOL WINAPI wglGenlockSampleRateI3D (HDC, UINT); -extern BOOL WINAPI wglGetGenlockSampleRateI3D (HDC, UINT *); -extern BOOL WINAPI wglGenlockSourceDelayI3D (HDC, UINT); -extern BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC, UINT *); -extern BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC, UINT *, UINT *); -#endif /* WGL_WGLEXT_PROTOTYPES */ +#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 +#define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045 +#define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046 +#define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047 +#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 +#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 +#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A +#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B +#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL *pFlag); @@ -559,50 +548,283 @@ typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT *uRate) typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT *uDelay); typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglEnableGenlockI3D (HDC hDC); +BOOL WINAPI wglDisableGenlockI3D (HDC hDC); +BOOL WINAPI wglIsEnabledGenlockI3D (HDC hDC, BOOL *pFlag); +BOOL WINAPI wglGenlockSourceI3D (HDC hDC, UINT uSource); +BOOL WINAPI wglGetGenlockSourceI3D (HDC hDC, UINT *uSource); +BOOL WINAPI wglGenlockSourceEdgeI3D (HDC hDC, UINT uEdge); +BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC hDC, UINT *uEdge); +BOOL WINAPI wglGenlockSampleRateI3D (HDC hDC, UINT uRate); +BOOL WINAPI wglGetGenlockSampleRateI3D (HDC hDC, UINT *uRate); +BOOL WINAPI wglGenlockSourceDelayI3D (HDC hDC, UINT uDelay); +BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC hDC, UINT *uDelay); +BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); #endif +#endif /* WGL_I3D_genlock */ #ifndef WGL_I3D_image_buffer #define WGL_I3D_image_buffer 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern LPVOID WINAPI wglCreateImageBufferI3D (HDC, DWORD, UINT); -extern BOOL WINAPI wglDestroyImageBufferI3D (HDC, LPVOID); -extern BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC, const HANDLE *, const LPVOID *, const DWORD *, UINT); -extern BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC, const LPVOID *, UINT); -#endif /* WGL_WGLEXT_PROTOTYPES */ +#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 +#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID *pAddress, UINT count); +#ifdef WGL_WGLEXT_PROTOTYPES +LPVOID WINAPI wglCreateImageBufferI3D (HDC hDC, DWORD dwSize, UINT uFlags); +BOOL WINAPI wglDestroyImageBufferI3D (HDC hDC, LPVOID pAddress); +BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); +BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC hDC, const LPVOID *pAddress, UINT count); #endif +#endif /* WGL_I3D_image_buffer */ #ifndef WGL_I3D_swap_frame_lock #define WGL_I3D_swap_frame_lock 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglEnableFrameLockI3D (void); -extern BOOL WINAPI wglDisableFrameLockI3D (void); -extern BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *); -extern BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *); -#endif /* WGL_WGLEXT_PROTOTYPES */ typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (void); typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (void); typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL *pFlag); typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL *pFlag); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglEnableFrameLockI3D (void); +BOOL WINAPI wglDisableFrameLockI3D (void); +BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *pFlag); +BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *pFlag); #endif +#endif /* WGL_I3D_swap_frame_lock */ #ifndef WGL_I3D_swap_frame_usage #define WGL_I3D_swap_frame_usage 1 -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglGetFrameUsageI3D (PN_stdfloat *); -extern BOOL WINAPI wglBeginFrameTrackingI3D (void); -extern BOOL WINAPI wglEndFrameTrackingI3D (void); -extern BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *, DWORD *, PN_stdfloat *); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (PN_stdfloat *pUsage); +typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float *pUsage); typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void); typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void); -typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, PN_stdfloat *pLastMissedUsage); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglGetFrameUsageI3D (float *pUsage); +BOOL WINAPI wglBeginFrameTrackingI3D (void); +BOOL WINAPI wglEndFrameTrackingI3D (void); +BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); #endif +#endif /* WGL_I3D_swap_frame_usage */ +#ifndef WGL_NV_DX_interop +#define WGL_NV_DX_interop 1 +#define WGL_ACCESS_READ_ONLY_NV 0x00000000 +#define WGL_ACCESS_READ_WRITE_NV 0x00000001 +#define WGL_ACCESS_WRITE_DISCARD_NV 0x00000002 +typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void *dxObject, HANDLE shareHandle); +typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void *dxDevice); +typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice); +typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access); +typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject); +typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access); +typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects); +typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglDXSetResourceShareHandleNV (void *dxObject, HANDLE shareHandle); +HANDLE WINAPI wglDXOpenDeviceNV (void *dxDevice); +BOOL WINAPI wglDXCloseDeviceNV (HANDLE hDevice); +HANDLE WINAPI wglDXRegisterObjectNV (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access); +BOOL WINAPI wglDXUnregisterObjectNV (HANDLE hDevice, HANDLE hObject); +BOOL WINAPI wglDXObjectAccessNV (HANDLE hObject, GLenum access); +BOOL WINAPI wglDXLockObjectsNV (HANDLE hDevice, GLint count, HANDLE *hObjects); +BOOL WINAPI wglDXUnlockObjectsNV (HANDLE hDevice, GLint count, HANDLE *hObjects); +#endif +#endif /* WGL_NV_DX_interop */ + +#ifndef WGL_NV_DX_interop2 +#define WGL_NV_DX_interop2 1 +#endif /* WGL_NV_DX_interop2 */ + +#ifndef WGL_NV_copy_image +#define WGL_NV_copy_image 1 +typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglCopyImageSubDataNV (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); +#endif +#endif /* WGL_NV_copy_image */ + +#ifndef WGL_NV_delay_before_swap +#define WGL_NV_delay_before_swap 1 +typedef BOOL (WINAPI * PFNWGLDELAYBEFORESWAPNVPROC) (HDC hDC, GLfloat seconds); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglDelayBeforeSwapNV (HDC hDC, GLfloat seconds); +#endif +#endif /* WGL_NV_delay_before_swap */ + +#ifndef WGL_NV_float_buffer +#define WGL_NV_float_buffer 1 +#define WGL_FLOAT_COMPONENTS_NV 0x20B0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 +#define WGL_TEXTURE_FLOAT_R_NV 0x20B5 +#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 +#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 +#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 +#endif /* WGL_NV_float_buffer */ + +#ifndef WGL_NV_gpu_affinity +#define WGL_NV_gpu_affinity 1 +DECLARE_HANDLE(HGPUNV); +struct _GPU_DEVICE { + DWORD cb; + CHAR DeviceName[32]; + CHAR DeviceString[128]; + DWORD Flags; + RECT rcVirtualScreen; +}; +typedef struct _GPU_DEVICE *PGPU_DEVICE; +#define ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 +#define ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 +typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu); +typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); +typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList); +typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); +typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglEnumGpusNV (UINT iGpuIndex, HGPUNV *phGpu); +BOOL WINAPI wglEnumGpuDevicesNV (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); +HDC WINAPI wglCreateAffinityDCNV (const HGPUNV *phGpuList); +BOOL WINAPI wglEnumGpusFromAffinityDCNV (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); +BOOL WINAPI wglDeleteDCNV (HDC hdc); +#endif +#endif /* WGL_NV_gpu_affinity */ + +#ifndef WGL_NV_multisample_coverage +#define WGL_NV_multisample_coverage 1 +#define WGL_COVERAGE_SAMPLES_NV 0x2042 +#define WGL_COLOR_SAMPLES_NV 0x20B9 +#endif /* WGL_NV_multisample_coverage */ + +#ifndef WGL_NV_present_video +#define WGL_NV_present_video 1 +DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV); +#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0 +typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList); +typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList); +typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int *piValue); +#ifdef WGL_WGLEXT_PROTOTYPES +int WINAPI wglEnumerateVideoDevicesNV (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList); +BOOL WINAPI wglBindVideoDeviceNV (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList); +BOOL WINAPI wglQueryCurrentContextNV (int iAttribute, int *piValue); +#endif +#endif /* WGL_NV_present_video */ + +#ifndef WGL_NV_render_depth_texture +#define WGL_NV_render_depth_texture 1 +#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 +#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 +#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 +#define WGL_DEPTH_COMPONENT_NV 0x20A7 +#endif /* WGL_NV_render_depth_texture */ + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_NV_render_texture_rectangle 1 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 +#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 +#endif /* WGL_NV_render_texture_rectangle */ + +#ifndef WGL_NV_swap_group +#define WGL_NV_swap_group 1 +typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); +typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); +typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint *group, GLuint *barrier); +typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint *count); +typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglJoinSwapGroupNV (HDC hDC, GLuint group); +BOOL WINAPI wglBindSwapBarrierNV (GLuint group, GLuint barrier); +BOOL WINAPI wglQuerySwapGroupNV (HDC hDC, GLuint *group, GLuint *barrier); +BOOL WINAPI wglQueryMaxSwapGroupsNV (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers); +BOOL WINAPI wglQueryFrameCountNV (HDC hDC, GLuint *count); +BOOL WINAPI wglResetFrameCountNV (HDC hDC); +#endif +#endif /* WGL_NV_swap_group */ + +#ifndef WGL_NV_vertex_array_range +#define WGL_NV_vertex_array_range 1 +typedef void *(WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); +typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); +#ifdef WGL_WGLEXT_PROTOTYPES +void *WINAPI wglAllocateMemoryNV (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); +void WINAPI wglFreeMemoryNV (void *pointer); +#endif +#endif /* WGL_NV_vertex_array_range */ + +#ifndef WGL_NV_video_capture +#define WGL_NV_video_capture 1 +DECLARE_HANDLE(HVIDEOINPUTDEVICENV); +#define WGL_UNIQUE_ID_NV 0x20CE +#define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF +typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice); +typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList); +typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); +typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglBindVideoCaptureDeviceNV (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice); +UINT WINAPI wglEnumerateVideoCaptureDevicesNV (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList); +BOOL WINAPI wglLockVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice); +BOOL WINAPI wglQueryVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue); +BOOL WINAPI wglReleaseVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice); +#endif +#endif /* WGL_NV_video_capture */ + +#ifndef WGL_NV_video_output +#define WGL_NV_video_output 1 +DECLARE_HANDLE(HPVIDEODEV); +#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0 +#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1 +#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2 +#define WGL_VIDEO_OUT_COLOR_NV 0x20C3 +#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4 +#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5 +#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define WGL_VIDEO_OUT_FRAME 0x20C8 +#define WGL_VIDEO_OUT_FIELD_1 0x20C9 +#define WGL_VIDEO_OUT_FIELD_2 0x20CA +#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB +#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC +typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice); +typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock); +typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglGetVideoDeviceNV (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice); +BOOL WINAPI wglReleaseVideoDeviceNV (HPVIDEODEV hVideoDevice); +BOOL WINAPI wglBindVideoImageNV (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); +BOOL WINAPI wglReleaseVideoImageNV (HPBUFFERARB hPbuffer, int iVideoBuffer); +BOOL WINAPI wglSendPbufferToVideoNV (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock); +BOOL WINAPI wglGetVideoInfoNV (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +#endif +#endif /* WGL_NV_video_output */ + +#ifndef WGL_OML_sync_control +#define WGL_OML_sync_control 1 +typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); +typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator); +typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); +typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); +#ifdef WGL_WGLEXT_PROTOTYPES +BOOL WINAPI wglGetSyncValuesOML (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); +BOOL WINAPI wglGetMscRateOML (HDC hdc, INT32 *numerator, INT32 *denominator); +INT64 WINAPI wglSwapBuffersMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); +INT64 WINAPI wglSwapLayerBuffersMscOML (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); +BOOL WINAPI wglWaitForMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); +BOOL WINAPI wglWaitForSbcOML (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); +#endif +#endif /* WGL_OML_sync_control */ #ifdef __cplusplus } diff --git a/pandatool/src/mayaegg/mayaToEggConverter.cxx b/pandatool/src/mayaegg/mayaToEggConverter.cxx index b9b979d66c..ff0337248b 100644 --- a/pandatool/src/mayaegg/mayaToEggConverter.cxx +++ b/pandatool/src/mayaegg/mayaToEggConverter.cxx @@ -981,7 +981,7 @@ process_model_node(MayaNodeDesc *node_desc) { mayaegg_cat.debug() << "\"" << dag_path.partialPathName() << "\" : \n"; // Get the translation/rotation/scale data - MObject transformNode = dag_path.transform(&status); + MObject transformNode = dag_path.transform(&status); // This node has no transform - i.e., it's the world node if (!status && status.statusCode () == MStatus::kInvalidParameter) return false; @@ -990,8 +990,8 @@ process_model_node(MayaNodeDesc *node_desc) { status.perror("MFnDagNode constructor"); return false; } - MTransformationMatrix matrix (transform.transformationMatrix()); - MVector tl = matrix.getTranslation(MSpace::kWorld); + MTransformationMatrix matrix (transform.transformationMatrix()); + MVector tl = matrix.translation(MSpace::kWorld); // Stop rediculously small values like -4.43287e-013 if (tl.x < 0.0001) { tl.x = 0;