Merge branch 'master' into cmake
This commit is contained in:
commit
76a7c84330
|
|
@ -77,7 +77,7 @@ public:
|
|||
// Place this macro within a class definition to define appropriate operator
|
||||
// new and delete methods that take advantage of DeletedChain.
|
||||
#define ALLOC_DELETED_CHAIN(Type) \
|
||||
inline void *operator new(size_t size) { \
|
||||
inline void *operator new(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT) { \
|
||||
return (void *)StaticDeletedChain< Type >::allocate(size, get_type_handle(Type)); \
|
||||
} \
|
||||
inline void *operator new(size_t size, void *ptr) { \
|
||||
|
|
@ -96,7 +96,7 @@ public:
|
|||
// Use this variant of the above macro in cases in which the compiler fails to
|
||||
// unify the static template pointers properly, to prevent leaks.
|
||||
#define ALLOC_DELETED_CHAIN_DECL(Type) \
|
||||
inline void *operator new(size_t size) { \
|
||||
inline void *operator new(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT) { \
|
||||
return (void *)_deleted_chain.allocate(size, get_type_handle(Type)); \
|
||||
} \
|
||||
inline void *operator new(size_t size, void *ptr) { \
|
||||
|
|
|
|||
|
|
@ -76,6 +76,10 @@
|
|||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
// Use NODEFAULT to optimize a switch() stmt to tell MSVC to automatically go
|
||||
// to the final untested case after it has failed all the other cases (i.e.
|
||||
// 'assume at least one of the cases is always true')
|
||||
|
|
@ -96,6 +100,12 @@
|
|||
#define ASSUME_ALIGNED(x, y) (x)
|
||||
#endif
|
||||
|
||||
#if __has_attribute(assume_aligned) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||
#define RETURNS_ALIGNED(x) __attribute__((assume_aligned(x)))
|
||||
#else
|
||||
#define RETURNS_ALIGNED(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
include win32 defns for everything up to WinServer2003, and assume
|
||||
I'm smart enough to use GetProcAddress for backward compat on
|
||||
|
|
@ -400,6 +410,35 @@ typedef struct _object PyObject;
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef LINMATH_ALIGN
|
||||
/* We require 16-byte alignment of certain structures, to support SSE2. We
|
||||
don't strictly have to align everything, but it's just easier to do so. */
|
||||
#if defined(HAVE_EIGEN) && defined(__AVX__) && defined(STDFLOAT_DOUBLE)
|
||||
/* Eigen uses AVX instructions, but let's only enable this when compiling with
|
||||
double precision, so that we can keep our ABI a bit more stable. */
|
||||
#define MEMORY_HOOK_ALIGNMENT 32
|
||||
#else
|
||||
#define MEMORY_HOOK_ALIGNMENT 16
|
||||
#endif
|
||||
/* Otherwise, align to two words. This seems to be pretty standard to the
|
||||
point where some code may rely on this being the case. */
|
||||
#elif defined(IS_OSX) || NATIVE_WORDSIZE >= 64
|
||||
#define MEMORY_HOOK_ALIGNMENT 16
|
||||
#else
|
||||
#define MEMORY_HOOK_ALIGNMENT 8
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EIGEN
|
||||
/* Make sure that Eigen doesn't assume alignment guarantees we don't offer. */
|
||||
#define EIGEN_MAX_ALIGN_BYTES MEMORY_HOOK_ALIGNMENT
|
||||
#ifndef EIGEN_MPL2_ONLY
|
||||
#define EIGEN_MPL2_ONLY 1
|
||||
#endif
|
||||
#if !defined(_DEBUG) && !defined(EIGEN_NO_DEBUG)
|
||||
#define EIGEN_NO_DEBUG 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Determine our memory-allocation requirements. */
|
||||
#if defined(USE_MEMORY_PTMALLOC2) || defined(USE_MEMORY_DLMALLOC) || defined(DO_MEMORY_USAGE) || defined(MEMORY_HOOK_DO_ALIGN)
|
||||
/* In this case we have some custom memory management requirements. */
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#ifndef USE_MEMORY_NOWRAPPERS
|
||||
|
||||
#define ALLOC_MEMORY_BASE \
|
||||
inline void *operator new(size_t size) { \
|
||||
inline void *operator new(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT) { \
|
||||
return PANDA_MALLOC_SINGLE(size); \
|
||||
} \
|
||||
inline void *operator new(size_t size, void *ptr) { \
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
} \
|
||||
inline void operator delete(void *, void *) { \
|
||||
} \
|
||||
inline void *operator new[](size_t size) { \
|
||||
inline void *operator new[](size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT) { \
|
||||
return PANDA_MALLOC_ARRAY(size); \
|
||||
} \
|
||||
inline void *operator new[](size_t size, void *ptr) { \
|
||||
|
|
|
|||
|
|
@ -63,14 +63,24 @@ round_up_to_page_size(size_t size) const {
|
|||
|
||||
/**
|
||||
* Given a pointer that was returned by a MemoryHook allocation, returns the
|
||||
* number of bytes that were allocated for it. Returns 0 if not compiling
|
||||
* with DO_MEMORY_USAGE.
|
||||
* number of bytes that were allocated for it. This may be slightly larger
|
||||
* than the number of bytes requested.
|
||||
* The behavior of this function is undefined if the given pointer was not
|
||||
* returned by the MemoryHook allocator or was already freed.
|
||||
* May return 0 if not compiling with DO_MEMORY_USAGE.
|
||||
*
|
||||
* This is only defined publicly so TypeHandle can get at it; it really
|
||||
* shouldn't be used outside of dtoolbase.
|
||||
*/
|
||||
INLINE size_t MemoryHook::
|
||||
get_ptr_size(void *ptr) {
|
||||
#if defined(MEMORY_HOOK_DO_ALIGN)
|
||||
uintptr_t *root = (uintptr_t *)ptr;
|
||||
return (size_t)root[-2];
|
||||
#elif defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
|
||||
// If we are using dlmalloc, we know how it stores the size.
|
||||
size_t *root = (size_t *)ptr;
|
||||
return (root[-1] & ~0x7) - sizeof(size_t);
|
||||
#elif defined(DO_MEMORY_USAGE)
|
||||
size_t *root = (size_t *)((char *)ptr - MEMORY_HOOK_ALIGNMENT);
|
||||
return *root;
|
||||
|
|
@ -78,68 +88,3 @@ get_ptr_size(void *ptr) {
|
|||
return 0;
|
||||
#endif // DO_MEMORY_USAGE
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the amount of requested size as necessary to accommodate the
|
||||
* extra data we might piggyback on each allocated block.
|
||||
*/
|
||||
INLINE size_t MemoryHook::
|
||||
inflate_size(size_t size) {
|
||||
#if defined(MEMORY_HOOK_DO_ALIGN)
|
||||
// If we're aligning, we need to request the header size, plus extra bytes
|
||||
// to give us wiggle room to adjust the pointer.
|
||||
return size + sizeof(uintptr_t) * 2 + MEMORY_HOOK_ALIGNMENT - 1;
|
||||
#elif defined(DO_MEMORY_USAGE)
|
||||
// If we're not aligning, but we're tracking memory allocations, we just
|
||||
// need the header size extra (this gives us a place to store the size of
|
||||
// the allocated block). However, we do need to make sure that any
|
||||
// alignment guarantee is kept.
|
||||
return size + MEMORY_HOOK_ALIGNMENT;
|
||||
#else
|
||||
// If we're not doing any of that, we can just allocate the precise
|
||||
// requested amount.
|
||||
return size;
|
||||
#endif // DO_MEMORY_USAGE
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an allocated pointer to a pointer returnable to the application.
|
||||
* Stuffs size in the first n bytes of the allocated space.
|
||||
*/
|
||||
INLINE void *MemoryHook::
|
||||
alloc_to_ptr(void *alloc, size_t size) {
|
||||
#if defined(MEMORY_HOOK_DO_ALIGN)
|
||||
// Add room for two uintptr_t values.
|
||||
uintptr_t *root = (uintptr_t *)((char *)alloc + sizeof(uintptr_t) * 2);
|
||||
// Align this to the requested boundary.
|
||||
root = (uintptr_t *)(((uintptr_t)root + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1));
|
||||
root[-2] = size;
|
||||
root[-1] = (uintptr_t)alloc; // Save the pointer we originally allocated.
|
||||
return (void *)root;
|
||||
#elif defined(DO_MEMORY_USAGE)
|
||||
size_t *root = (size_t *)alloc;
|
||||
root[0] = size;
|
||||
return (void *)((char *)root + MEMORY_HOOK_ALIGNMENT);
|
||||
#else
|
||||
return alloc;
|
||||
#endif // DO_MEMORY_USAGE
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an application pointer back to the original allocated pointer.
|
||||
* Extracts size from the first n bytes of the allocated space.
|
||||
*/
|
||||
INLINE void *MemoryHook::
|
||||
ptr_to_alloc(void *ptr, size_t &size) {
|
||||
#if defined(MEMORY_HOOK_DO_ALIGN)
|
||||
uintptr_t *root = (uintptr_t *)ptr;
|
||||
size = root[-2];
|
||||
return (void *)root[-1]; // Get the pointer we originally allocated.
|
||||
#elif defined(DO_MEMORY_USAGE)
|
||||
size_t *root = (size_t *)((char *)ptr - MEMORY_HOOK_ALIGNMENT);
|
||||
size = root[0];
|
||||
return (void *)root;
|
||||
#else
|
||||
return ptr;
|
||||
#endif // DO_MEMORY_USAGE
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include "memoryHook.h"
|
||||
#include "deletedBufferChain.h"
|
||||
#include <stdlib.h>
|
||||
#include "typeRegistry.h"
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
|
|
@ -104,6 +105,83 @@ static_assert((MEMORY_HOOK_ALIGNMENT & (MEMORY_HOOK_ALIGNMENT - 1)) == 0,
|
|||
|
||||
#endif // USE_MEMORY_*
|
||||
|
||||
/**
|
||||
* Increments the amount of requested size as necessary to accommodate the
|
||||
* extra data we might piggyback on each allocated block.
|
||||
*/
|
||||
INLINE static size_t
|
||||
inflate_size(size_t size) {
|
||||
#if defined(MEMORY_HOOK_DO_ALIGN)
|
||||
// If we're aligning, we need to request the header size, plus extra bytes
|
||||
// to give us wiggle room to adjust the pointer.
|
||||
return size + sizeof(uintptr_t) * 2 + MEMORY_HOOK_ALIGNMENT - 1;
|
||||
#elif defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
|
||||
// If we are can access the allocator's bookkeeping to figure out how many
|
||||
// bytes were allocated, we don't need to add our own information.
|
||||
return size;
|
||||
#elif defined(DO_MEMORY_USAGE)
|
||||
// If we're not aligning, but we're tracking memory allocations, we just
|
||||
// need the header size extra (this gives us a place to store the size of
|
||||
// the allocated block). However, we do need to make sure that any
|
||||
// alignment guarantee is kept.
|
||||
return size + MEMORY_HOOK_ALIGNMENT;
|
||||
#else
|
||||
// If we're not doing any of that, we can just allocate the precise
|
||||
// requested amount.
|
||||
return size;
|
||||
#endif // DO_MEMORY_USAGE
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an allocated pointer to a pointer returnable to the application.
|
||||
* Stuffs size in the first n bytes of the allocated space.
|
||||
*/
|
||||
INLINE static void *
|
||||
alloc_to_ptr(void *alloc, size_t size) {
|
||||
#if defined(MEMORY_HOOK_DO_ALIGN)
|
||||
// Add room for two uintptr_t values.
|
||||
uintptr_t *root = (uintptr_t *)((char *)alloc + sizeof(uintptr_t) * 2);
|
||||
// Align this to the requested boundary.
|
||||
root = (uintptr_t *)(((uintptr_t)root + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1));
|
||||
root[-2] = size;
|
||||
root[-1] = (uintptr_t)alloc; // Save the pointer we originally allocated.
|
||||
return (void *)root;
|
||||
#elif defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
|
||||
return alloc;
|
||||
#elif defined(DO_MEMORY_USAGE)
|
||||
size_t *root = (size_t *)alloc;
|
||||
root[0] = size;
|
||||
return (void *)((char *)root + MEMORY_HOOK_ALIGNMENT);
|
||||
#else
|
||||
return alloc;
|
||||
#endif // DO_MEMORY_USAGE
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an application pointer back to the original allocated pointer.
|
||||
* Extracts size from the first n bytes of the allocated space, but only if
|
||||
* DO_MEMORY_USAGE is defined.
|
||||
*/
|
||||
INLINE static void *
|
||||
ptr_to_alloc(void *ptr, size_t &size) {
|
||||
#if defined(MEMORY_HOOK_DO_ALIGN)
|
||||
uintptr_t *root = (uintptr_t *)ptr;
|
||||
size = root[-2];
|
||||
return (void *)root[-1]; // Get the pointer we originally allocated.
|
||||
#elif defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
size = MemoryHook::get_ptr_size(ptr);
|
||||
#endif
|
||||
return ptr;
|
||||
#elif defined(DO_MEMORY_USAGE)
|
||||
size_t *root = (size_t *)((char *)ptr - MEMORY_HOOK_ALIGNMENT);
|
||||
size = root[0];
|
||||
return (void *)root;
|
||||
#else
|
||||
return ptr;
|
||||
#endif // DO_MEMORY_USAGE
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -195,6 +273,11 @@ heap_alloc_single(size_t size) {
|
|||
#ifdef DO_MEMORY_USAGE
|
||||
// In the DO_MEMORY_USAGE case, we want to track the total size of allocated
|
||||
// bytes on the heap.
|
||||
#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
|
||||
// dlmalloc may slightly overallocate, however.
|
||||
size = get_ptr_size(alloc);
|
||||
inflated_size = size;
|
||||
#endif
|
||||
AtomicAdjust::add(_total_heap_single_size, (AtomicAdjust::Integer)size);
|
||||
if ((size_t)AtomicAdjust::get(_total_heap_single_size) +
|
||||
(size_t)AtomicAdjust::get(_total_heap_array_size) >
|
||||
|
|
@ -204,8 +287,10 @@ heap_alloc_single(size_t size) {
|
|||
#endif // DO_MEMORY_USAGE
|
||||
|
||||
void *ptr = alloc_to_ptr(alloc, size);
|
||||
#ifdef _DEBUG
|
||||
assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0);
|
||||
assert(ptr >= alloc && (char *)ptr + size <= (char *)alloc + inflated_size);
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
|
@ -265,6 +350,11 @@ heap_alloc_array(size_t size) {
|
|||
#ifdef DO_MEMORY_USAGE
|
||||
// In the DO_MEMORY_USAGE case, we want to track the total size of allocated
|
||||
// bytes on the heap.
|
||||
#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
|
||||
// dlmalloc may slightly overallocate, however.
|
||||
size = get_ptr_size(alloc);
|
||||
inflated_size = size;
|
||||
#endif
|
||||
AtomicAdjust::add(_total_heap_array_size, (AtomicAdjust::Integer)size);
|
||||
if ((size_t)AtomicAdjust::get(_total_heap_single_size) +
|
||||
(size_t)AtomicAdjust::get(_total_heap_array_size) >
|
||||
|
|
@ -274,8 +364,10 @@ heap_alloc_array(size_t size) {
|
|||
#endif // DO_MEMORY_USAGE
|
||||
|
||||
void *ptr = alloc_to_ptr(alloc, size);
|
||||
#ifdef _DEBUG
|
||||
assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0);
|
||||
assert(ptr >= alloc && (char *)ptr + size <= (char *)alloc + inflated_size);
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
|
@ -287,11 +379,6 @@ heap_realloc_array(void *ptr, size_t size) {
|
|||
size_t orig_size;
|
||||
void *alloc = ptr_to_alloc(ptr, orig_size);
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
assert((AtomicAdjust::Integer)orig_size <= _total_heap_array_size);
|
||||
AtomicAdjust::add(_total_heap_array_size, (AtomicAdjust::Integer)size-(AtomicAdjust::Integer)orig_size);
|
||||
#endif // DO_MEMORY_USAGE
|
||||
|
||||
size_t inflated_size = inflate_size(size);
|
||||
|
||||
void *alloc1 = alloc;
|
||||
|
|
@ -318,6 +405,16 @@ heap_realloc_array(void *ptr, size_t size) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
|
||||
// dlmalloc may slightly overallocate, however.
|
||||
size = get_ptr_size(alloc1);
|
||||
inflated_size = size;
|
||||
#endif
|
||||
assert((AtomicAdjust::Integer)orig_size <= _total_heap_array_size);
|
||||
AtomicAdjust::add(_total_heap_array_size, (AtomicAdjust::Integer)size-(AtomicAdjust::Integer)orig_size);
|
||||
#endif // DO_MEMORY_USAGE
|
||||
|
||||
// Align this to the requested boundary.
|
||||
#ifdef MEMORY_HOOK_DO_ALIGN
|
||||
// This copies the code from alloc_to_ptr, since we can't write the size and
|
||||
|
|
@ -337,8 +434,11 @@ heap_realloc_array(void *ptr, size_t size) {
|
|||
#else
|
||||
void *ptr1 = alloc_to_ptr(alloc1, size);
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
assert(ptr1 >= alloc1 && (char *)ptr1 + size <= (char *)alloc1 + inflated_size);
|
||||
assert(((uintptr_t)ptr1 % MEMORY_HOOK_ALIGNMENT) == 0);
|
||||
#endif
|
||||
return ptr1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,22 +20,6 @@
|
|||
#include "mutexImpl.h"
|
||||
#include <map>
|
||||
|
||||
#ifdef LINMATH_ALIGN
|
||||
// We require 16-byte alignment of certain structures, to support SSE2. We
|
||||
// don't strictly have to align *everything*, but it's just easier to do so.
|
||||
#ifdef __AVX__
|
||||
#define MEMORY_HOOK_ALIGNMENT 32
|
||||
#else
|
||||
#define MEMORY_HOOK_ALIGNMENT 16
|
||||
#endif
|
||||
// Otherwise, align to two words. This seems to be pretty standard to the
|
||||
// point where some code may rely on this being the case.
|
||||
#elif defined(IS_OSX) || NATIVE_WORDSIZE >= 64
|
||||
#define MEMORY_HOOK_ALIGNMENT 16
|
||||
#else
|
||||
#define MEMORY_HOOK_ALIGNMENT 8
|
||||
#endif
|
||||
|
||||
class DeletedBufferChain;
|
||||
|
||||
/**
|
||||
|
|
@ -83,11 +67,6 @@ public:
|
|||
|
||||
INLINE static size_t get_ptr_size(void *ptr);
|
||||
|
||||
private:
|
||||
INLINE static size_t inflate_size(size_t size);
|
||||
INLINE static void *alloc_to_ptr(void *alloc, size_t size);
|
||||
INLINE static void *ptr_to_alloc(void *ptr, size_t &size);
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
protected:
|
||||
TVOLATILE AtomicAdjust::Integer _total_heap_single_size;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ pallocator_single(TypeHandle type_handle) NOEXCEPT :
|
|||
}
|
||||
|
||||
template<class Type>
|
||||
INLINE TYPENAME pallocator_single<Type>::pointer pallocator_single<Type>::
|
||||
INLINE Type *pallocator_single<Type>::
|
||||
allocate(TYPENAME pallocator_single<Type>::size_type n, TYPENAME allocator<void>::const_pointer) {
|
||||
TAU_PROFILE("pallocator_single:allocate()", " ", TAU_USER);
|
||||
// This doesn't support allocating arrays.
|
||||
|
|
@ -43,34 +43,14 @@ pallocator_array(TypeHandle type_handle) NOEXCEPT :
|
|||
}
|
||||
|
||||
template<class Type>
|
||||
INLINE TYPENAME pallocator_array<Type>::pointer pallocator_array<Type>::
|
||||
INLINE Type *pallocator_array<Type>::
|
||||
allocate(TYPENAME pallocator_array<Type>::size_type n, TYPENAME allocator<void>::const_pointer) {
|
||||
TAU_PROFILE("pallocator_array:allocate()", " ", TAU_USER);
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
size_t alloc_size = n * sizeof(Type);
|
||||
void *ptr = (TYPENAME pallocator_array<Type>::pointer)PANDA_MALLOC_ARRAY(alloc_size);
|
||||
#ifdef _DEBUG
|
||||
assert(alloc_size == MemoryHook::get_ptr_size(ptr));
|
||||
#endif
|
||||
_type_handle.inc_memory_usage(TypeHandle::MC_array, alloc_size);
|
||||
return (TYPENAME pallocator_array<Type>::pointer)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT);
|
||||
#else
|
||||
return (TYPENAME pallocator_array<Type>::pointer)PANDA_MALLOC_ARRAY(n * sizeof(Type));
|
||||
#endif // DO_MEMORY_USAGE
|
||||
return (TYPENAME pallocator_array<Type>::pointer)
|
||||
ASSUME_ALIGNED(_type_handle.allocate_array(n * sizeof(Type)), MEMORY_HOOK_ALIGNMENT);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
INLINE void pallocator_array<Type>::
|
||||
deallocate(TYPENAME pallocator_array<Type>::pointer p, TYPENAME pallocator_array<Type>::size_type) {
|
||||
TAU_PROFILE("pallocator_array:deallocate()", " ", TAU_USER);
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
// Now we need to recover the total number of bytes. Fortunately, in the
|
||||
// case of DO_MEMORY_USAGE, MemoryHook already keeps track of this.
|
||||
void *ptr = (void *)p;
|
||||
size_t alloc_size = MemoryHook::get_ptr_size(ptr);
|
||||
_type_handle.dec_memory_usage(TypeHandle::MC_array, alloc_size);
|
||||
PANDA_FREE_ARRAY(ptr);
|
||||
#else
|
||||
PANDA_FREE_ARRAY(p);
|
||||
#endif // DO_MEMORY_USAGE
|
||||
_type_handle.deallocate_array((void *)p);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ public:
|
|||
INLINE pallocator_single(const pallocator_single<U> ©) NOEXCEPT :
|
||||
_type_handle(copy._type_handle) { }
|
||||
|
||||
INLINE pointer allocate(size_type n, allocator<void>::const_pointer hint = 0);
|
||||
INLINE Type *allocate(size_type n, allocator<void>::const_pointer hint = 0)
|
||||
RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||
INLINE void deallocate(pointer p, size_type n);
|
||||
|
||||
template<class U> struct rebind {
|
||||
|
|
@ -87,7 +88,8 @@ public:
|
|||
INLINE pallocator_array(const pallocator_array<U> ©) NOEXCEPT :
|
||||
_type_handle(copy._type_handle) { }
|
||||
|
||||
INLINE pointer allocate(size_type n, allocator<void>::const_pointer hint = 0);
|
||||
INLINE Type *allocate(size_type n, allocator<void>::const_pointer hint = 0)
|
||||
RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||
INLINE void deallocate(pointer p, size_type n);
|
||||
|
||||
template<class U> struct rebind {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
// This is initialized to zero by static initialization.
|
||||
TypeHandle TypeHandle::_none;
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
/**
|
||||
* Returns the total allocated memory used by objects of this type, for the
|
||||
* indicated memory class. This is only updated if track-memory-usage is set
|
||||
|
|
@ -26,6 +25,7 @@ TypeHandle TypeHandle::_none;
|
|||
*/
|
||||
size_t TypeHandle::
|
||||
get_memory_usage(MemoryClass memory_class) const {
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit);
|
||||
if ((*this) == TypeHandle::none()) {
|
||||
return 0;
|
||||
|
|
@ -34,16 +34,17 @@ get_memory_usage(MemoryClass memory_class) const {
|
|||
assert(rnode != (TypeRegistryNode *)NULL);
|
||||
return (size_t)AtomicAdjust::get(rnode->_memory_usage[memory_class]);
|
||||
}
|
||||
}
|
||||
#endif // DO_MEMORY_USAGE
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
/**
|
||||
* Adds the indicated amount to the record for the total allocated memory for
|
||||
* objects of this type.
|
||||
*/
|
||||
void TypeHandle::
|
||||
inc_memory_usage(MemoryClass memory_class, size_t size) {
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit);
|
||||
if ((*this) != TypeHandle::none()) {
|
||||
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
|
||||
|
|
@ -52,20 +53,20 @@ inc_memory_usage(MemoryClass memory_class, size_t size) {
|
|||
// cerr << *this << ".inc(" << memory_class << ", " << size << ") -> " <<
|
||||
// rnode->_memory_usage[memory_class] << "\n";
|
||||
if (rnode->_memory_usage[memory_class] < 0) {
|
||||
cerr << "Memory usage overflow for type " << *this << ".\n";
|
||||
cerr << "Memory usage overflow for type " << rnode->_name << ".\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // DO_MEMORY_USAGE
|
||||
}
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
/**
|
||||
* Subtracts the indicated amount from the record for the total allocated
|
||||
* memory for objects of this type.
|
||||
*/
|
||||
void TypeHandle::
|
||||
dec_memory_usage(MemoryClass memory_class, size_t size) {
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit);
|
||||
if ((*this) != TypeHandle::none()) {
|
||||
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
|
||||
|
|
@ -75,8 +76,81 @@ dec_memory_usage(MemoryClass memory_class, size_t size) {
|
|||
// rnode->_memory_usage[memory_class] << "\n";
|
||||
assert(rnode->_memory_usage[memory_class] >= 0);
|
||||
}
|
||||
}
|
||||
#endif // DO_MEMORY_USAGE
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates memory, adding it to the total amount of memory allocated for
|
||||
* this type.
|
||||
*/
|
||||
void *TypeHandle::
|
||||
allocate_array(size_t size) {
|
||||
TAU_PROFILE("TypeHandle:allocate_array()", " ", TAU_USER);
|
||||
|
||||
void *ptr = PANDA_MALLOC_ARRAY(size);
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
if ((*this) != TypeHandle::none()) {
|
||||
size_t alloc_size = MemoryHook::get_ptr_size(ptr);
|
||||
#ifdef _DEBUG
|
||||
assert(size <= alloc_size);
|
||||
#endif
|
||||
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
|
||||
assert(rnode != (TypeRegistryNode *)NULL);
|
||||
AtomicAdjust::add(rnode->_memory_usage[MC_array], (AtomicAdjust::Integer)alloc_size);
|
||||
if (rnode->_memory_usage[MC_array] < 0) {
|
||||
cerr << "Memory usage overflow for type " << rnode->_name << ".\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif // DO_MEMORY_USAGE
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reallocates memory, adjusting the total amount of memory allocated for this
|
||||
* type.
|
||||
*/
|
||||
void *TypeHandle::
|
||||
reallocate_array(void *old_ptr, size_t size) {
|
||||
TAU_PROFILE("TypeHandle:reallocate_array()", " ", TAU_USER);
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
size_t old_size = MemoryHook::get_ptr_size(old_ptr);
|
||||
void *new_ptr = PANDA_REALLOC_ARRAY(old_ptr, size);
|
||||
|
||||
if ((*this) != TypeHandle::none()) {
|
||||
size_t new_size = MemoryHook::get_ptr_size(new_ptr);
|
||||
|
||||
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
|
||||
assert(rnode != (TypeRegistryNode *)NULL);
|
||||
AtomicAdjust::add(rnode->_memory_usage[MC_array], (AtomicAdjust::Integer)new_size - (AtomicAdjust::Integer)old_size);
|
||||
assert(rnode->_memory_usage[MC_array] >= 0);
|
||||
}
|
||||
#else
|
||||
void *new_ptr = PANDA_REALLOC_ARRAY(old_ptr, size);
|
||||
#endif
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deallocates memory, subtracting it from the total amount of memory
|
||||
* allocated for this type.
|
||||
*/
|
||||
void TypeHandle::
|
||||
deallocate_array(void *ptr) {
|
||||
TAU_PROFILE("TypeHandle:deallocate_array()", " ", TAU_USER);
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
size_t alloc_size = MemoryHook::get_ptr_size(ptr);
|
||||
if ((*this) != TypeHandle::none()) {
|
||||
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
|
||||
assert(rnode != (TypeRegistryNode *)NULL);
|
||||
AtomicAdjust::add(rnode->_memory_usage[MC_array], -(AtomicAdjust::Integer)alloc_size);
|
||||
assert(rnode->_memory_usage[MC_array] >= 0);
|
||||
}
|
||||
#endif // DO_MEMORY_USAGE
|
||||
PANDA_FREE_ARRAY(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Index of the BEst fit Classs from a set
|
||||
|
|
|
|||
|
|
@ -18,25 +18,49 @@
|
|||
|
||||
#include <set>
|
||||
|
||||
// The following illustrates the convention for declaring a type that uses
|
||||
// TypeHandle. In this example, ThisThingie inherits from TypedObject, which
|
||||
// automatically supplies some type-differentiation functions at the cost of
|
||||
// one virtual function, get_type(); however, this inheritance is optional,
|
||||
// and may be omitted to avoid the virtual function pointer overhead. (If you
|
||||
// do use TypedObject, be sure to consider whether your destructor should also
|
||||
// be virtual.)
|
||||
|
||||
/*
|
||||
* class ThatThingie : public SimpleTypedObject { public: static TypeHandle
|
||||
* get_class_type() { return _type_handle; } static void init_type() {
|
||||
* register_type(_type_handle, "ThatThingie"); } private: static TypeHandle
|
||||
* _type_handle; }; class ThisThingie : public ThatThingie, publid TypedObject
|
||||
* { public: static TypeHandle get_class_type() { return _type_handle; }
|
||||
* static void init_type() { ThatThingie::init_type();
|
||||
* TypedObject::init_type(); register_type(_type_handle, "ThisThingie",
|
||||
* ThatThingie::get_class_type(), TypedObject::get_class_type()); } virtual
|
||||
* TypeHandle get_type() const { return get_class_type(); } private: static
|
||||
* TypeHandle _type_handle; };
|
||||
/**
|
||||
* The following illustrates the convention for declaring a type that uses
|
||||
* TypeHandle. In this example, ThisThingie inherits from TypedObject, which
|
||||
* automatically supplies some type-differentiation functions at the cost of
|
||||
* one virtual function, get_type(); however, this inheritance is optional,
|
||||
* and may be omitted to avoid the virtual function pointer overhead. (If you
|
||||
* do use TypedObject, be sure to consider whether your destructor should also
|
||||
* be virtual.)
|
||||
*
|
||||
* @code
|
||||
* class ThatThingie : public SimpleTypedObject {
|
||||
* public:
|
||||
* static TypeHandle get_class_type() {
|
||||
* return _type_handle;
|
||||
* }
|
||||
* static void init_type() {
|
||||
* register_type(_type_handle, "ThatThingie");
|
||||
* }
|
||||
*
|
||||
* private:
|
||||
* static TypeHandle _type_handle;
|
||||
* };
|
||||
*
|
||||
* class ThisThingie : public ThatThingie, publid TypedObject {
|
||||
* public:
|
||||
* static TypeHandle get_class_type() {
|
||||
* return _type_handle;
|
||||
* }
|
||||
* static void init_type() {
|
||||
* ThatThingie::init_type();
|
||||
* TypedObject::init_type();
|
||||
* register_type(_type_handle, "ThisThingie",
|
||||
* ThatThingie::get_class_type(),
|
||||
* TypedObject::get_class_type());
|
||||
* }
|
||||
* virtual TypeHandle get_type() const {
|
||||
* return get_class_type();
|
||||
* }
|
||||
*
|
||||
* private:
|
||||
* static TypeHandle _type_handle;
|
||||
* };
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
class TypedObject;
|
||||
|
|
@ -97,15 +121,9 @@ PUBLISHED:
|
|||
|
||||
int get_best_parent_from_Set(const std::set< int > &legal_vals) const;
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
size_t get_memory_usage(MemoryClass memory_class) const;
|
||||
void inc_memory_usage(MemoryClass memory_class, size_t size);
|
||||
void dec_memory_usage(MemoryClass memory_class, size_t size);
|
||||
#else
|
||||
static CONSTEXPR size_t get_memory_usage(MemoryClass) { return 0; }
|
||||
INLINE void inc_memory_usage(MemoryClass, size_t) { }
|
||||
INLINE void dec_memory_usage(MemoryClass, size_t) { }
|
||||
#endif // DO_MEMORY_USAGE
|
||||
|
||||
INLINE int get_index() const;
|
||||
INLINE void output(ostream &out) const;
|
||||
|
|
@ -118,6 +136,10 @@ PUBLISHED:
|
|||
MAKE_SEQ_PROPERTY(child_classes, get_num_child_classes, get_child_class);
|
||||
|
||||
public:
|
||||
void *allocate_array(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||
void *reallocate_array(void *ptr, size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||
void deallocate_array(void *ptr);
|
||||
|
||||
INLINE static TypeHandle from_index(int index);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -23,6 +23,19 @@ freshen_derivations() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pointer to the global TypeRegistry object.
|
||||
*/
|
||||
INLINE TypeRegistry *TypeRegistry::
|
||||
ptr() {
|
||||
// It's OK that we don't acquire the lock, because we guarantee that this is
|
||||
// called at static init time.
|
||||
if (_global_pointer == NULL) {
|
||||
init_global_pointer();
|
||||
}
|
||||
return _global_pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the lock pointer has been allocated.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -488,20 +488,6 @@ write(ostream &out) const {
|
|||
_lock->release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pointer to the global TypeRegistry object.
|
||||
*/
|
||||
TypeRegistry *TypeRegistry::
|
||||
ptr() {
|
||||
init_lock();
|
||||
_lock->acquire();
|
||||
if (_global_pointer == NULL) {
|
||||
init_global_pointer();
|
||||
}
|
||||
_lock->release();
|
||||
return _global_pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -531,6 +517,7 @@ TypeRegistry() {
|
|||
*/
|
||||
void TypeRegistry::
|
||||
init_global_pointer() {
|
||||
init_lock();
|
||||
init_memory_hook();
|
||||
_global_pointer = new TypeRegistry;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ PUBLISHED:
|
|||
void write(ostream &out) const;
|
||||
|
||||
// ptr() returns the pointer to the global TypeRegistry object.
|
||||
static TypeRegistry *ptr();
|
||||
static INLINE TypeRegistry *ptr();
|
||||
|
||||
MAKE_SEQ_PROPERTY(typehandles, get_num_typehandles, get_typehandle);
|
||||
MAKE_SEQ_PROPERTY(root_classes, get_num_root_classes, get_root_class);
|
||||
|
|
|
|||
|
|
@ -591,8 +591,8 @@ read_args() {
|
|||
dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map);
|
||||
|
||||
while (map != NULL) {
|
||||
char *tail = strrchr(map->l_name, '/');
|
||||
char *head = strchr(map->l_name, '/');
|
||||
const char *tail = strrchr(map->l_name, '/');
|
||||
const char *head = strchr(map->l_name, '/');
|
||||
if (tail && head && (strcmp(tail, "/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
|
||||
|| strcmp(tail, "/libp3dtool.so") == 0)) {
|
||||
_dtool_name = head;
|
||||
|
|
@ -615,8 +615,8 @@ read_args() {
|
|||
char buffer[PATH_MAX];
|
||||
buffer[0] = 0;
|
||||
maps.getline(buffer, PATH_MAX);
|
||||
char *tail = strrchr(buffer, '/');
|
||||
char *head = strchr(buffer, '/');
|
||||
const char *tail = strrchr(buffer, '/');
|
||||
const char *head = strchr(buffer, '/');
|
||||
if (tail && head && (strcmp(tail, "/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
|
||||
|| strcmp(tail, "/libp3dtool.so") == 0)) {
|
||||
_dtool_name = head;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ match_files(vector_string &results, const Filename &cwd) const {
|
|||
pattern = source;
|
||||
} else {
|
||||
pattern = source.substr(0, slash);
|
||||
suffix = source.substr(slash + 1);
|
||||
suffix = source.substr(slash);
|
||||
}
|
||||
|
||||
GlobPattern glob(pattern);
|
||||
|
|
@ -118,11 +118,21 @@ r_match_files(const Filename &prefix, const string &suffix,
|
|||
size_t slash = suffix.find('/');
|
||||
if (slash == string::npos) {
|
||||
next_pattern = suffix;
|
||||
} else if (slash + 1 == suffix.size()) {
|
||||
// If the slash is at the end, we need to keep it, since it indicates that
|
||||
// we only want to match directories.
|
||||
next_pattern = suffix.substr(0, slash);
|
||||
next_suffix = "/";
|
||||
} else {
|
||||
next_pattern = suffix.substr(0, slash);
|
||||
next_suffix = suffix.substr(slash + 1);
|
||||
}
|
||||
|
||||
if (_pattern == "**" && next_pattern == "**") {
|
||||
// Collapse consecutive globstar patterns.
|
||||
return r_match_files(prefix, next_suffix, results, cwd);
|
||||
}
|
||||
|
||||
Filename parent_dir;
|
||||
if (prefix.is_local() && !cwd.empty()) {
|
||||
parent_dir = Filename(cwd, prefix);
|
||||
|
|
@ -136,19 +146,24 @@ r_match_files(const Filename &prefix, const string &suffix,
|
|||
if (!has_glob_characters()) {
|
||||
// If there are no special characters in the pattern, it's a literal
|
||||
// match.
|
||||
Filename fn(parent_dir, _pattern);
|
||||
if (suffix.empty()) {
|
||||
// Time to stop.
|
||||
Filename single_filename(parent_dir, _pattern);
|
||||
if (single_filename.exists()) {
|
||||
if (fn.exists()) {
|
||||
results.push_back(Filename(prefix, _pattern));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} else if (fn.is_directory()) {
|
||||
// If the pattern ends with a slash, match a directory only.
|
||||
if (suffix == "/") {
|
||||
results.push_back(Filename(prefix, _pattern + "/"));
|
||||
return 1;
|
||||
} else {
|
||||
return next_glob.r_match_files(Filename(prefix, _pattern),
|
||||
next_suffix, results, cwd);
|
||||
}
|
||||
}
|
||||
|
||||
return next_glob.r_match_files(Filename(prefix, _pattern),
|
||||
next_suffix, results, cwd);
|
||||
|
||||
}
|
||||
|
||||
// If there *are* special glob characters, we must attempt to match the
|
||||
|
|
@ -164,18 +179,44 @@ r_match_files(const Filename &prefix, const string &suffix,
|
|||
// the pattern.
|
||||
int num_matched = 0;
|
||||
|
||||
// A globstar pattern matches zero or more directories.
|
||||
if (_pattern == "**") {
|
||||
// Try to match this directory (as if the globstar wasn't there)
|
||||
if (suffix.empty()) {
|
||||
// This is a directory. Add it.
|
||||
results.push_back(Filename(prefix));
|
||||
num_matched++;
|
||||
} else if (suffix == "/") {
|
||||
// Keep the trailing slash, but be sure not to duplicate it.
|
||||
results.push_back(Filename(prefix, ""));
|
||||
num_matched++;
|
||||
} else {
|
||||
num_matched += next_glob.r_match_files(prefix, next_suffix, results, cwd);
|
||||
}
|
||||
next_suffix = suffix;
|
||||
next_glob = *this;
|
||||
}
|
||||
|
||||
vector_string::const_iterator fi;
|
||||
for (fi = dir_files.begin(); fi != dir_files.end(); ++fi) {
|
||||
const string &local_file = (*fi);
|
||||
if (_pattern[0] == '.' || (local_file.empty() || local_file[0] != '.')) {
|
||||
if (matches(local_file)) {
|
||||
// We have a match; continue.
|
||||
if (suffix.empty()) {
|
||||
if (Filename(parent_dir, local_file).is_directory()) {
|
||||
if (suffix.empty() && _pattern != "**") {
|
||||
results.push_back(Filename(prefix, local_file));
|
||||
num_matched++;
|
||||
} else if (suffix == "/" && _pattern != "**") {
|
||||
results.push_back(Filename(prefix, local_file + "/"));
|
||||
num_matched++;
|
||||
} else {
|
||||
num_matched += next_glob.r_match_files(Filename(prefix, local_file),
|
||||
next_suffix, results, cwd);
|
||||
}
|
||||
} else if (suffix.empty()) {
|
||||
results.push_back(Filename(prefix, local_file));
|
||||
num_matched++;
|
||||
} else {
|
||||
num_matched += next_glob.r_match_files(Filename(prefix, local_file),
|
||||
next_suffix, results, cwd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,11 @@ PandaSystem() :
|
|||
#else
|
||||
set_system_tag("eigen", "vectorize", "0");
|
||||
#endif
|
||||
#ifdef __AVX__
|
||||
set_system_tag("eigen", "avx", "1");
|
||||
#else
|
||||
set_system_tag("eigen", "avx", "0");
|
||||
#endif
|
||||
#endif // HAVE_EIGEN
|
||||
|
||||
#ifdef USE_MEMORY_DLMALLOC
|
||||
|
|
@ -189,6 +194,14 @@ is_official_version() {
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the memory alignment that Panda's allocators are using.
|
||||
*/
|
||||
int PandaSystem::
|
||||
get_memory_alignment() {
|
||||
return MEMORY_HOOK_ALIGNMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string defined by the distributor of this version of Panda, or
|
||||
* "homebuilt" if this version was built directly from the sources by the end-
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ PUBLISHED:
|
|||
static int get_sequence_version();
|
||||
static bool is_official_version();
|
||||
|
||||
static int get_memory_alignment();
|
||||
|
||||
static string get_distributor();
|
||||
static string get_compiler();
|
||||
static string get_build_date();
|
||||
|
|
|
|||
|
|
@ -6219,7 +6219,7 @@ write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
|
|||
// the assumption that the called method doesn't do anything with this
|
||||
// tuple other than unpack it (which is a fairly safe assumption to make).
|
||||
out << " PyTupleObject args;\n";
|
||||
out << " (void)PyObject_INIT_VAR(&args, &PyTuple_Type, 1);\n";
|
||||
out << " (void)PyObject_INIT_VAR((PyVarObject *)&args, &PyTuple_Type, 1);\n";
|
||||
}
|
||||
|
||||
out <<
|
||||
|
|
|
|||
|
|
@ -303,8 +303,14 @@ template<class T> INLINE bool DTOOL_Call_ExtractThisPointer(PyObject *self, T *&
|
|||
// Functions related to error reporting.
|
||||
EXPCL_INTERROGATEDB bool _Dtool_CheckErrorOccurred();
|
||||
|
||||
// _PyErr_OCCURRED is an undocumented macro version of PyErr_Occurred.
|
||||
// Some implementations of the CPython API (e.g. PyPy's cpyext) do not define
|
||||
// it, so in these cases we just silently fall back to PyErr_Occurred.
|
||||
#ifndef _PyErr_OCCURRED
|
||||
#define _PyErr_OCCURRED() PyErr_Occurred()
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
// _PyErr_OCCURRED is an undocumented inline version of PyErr_Occurred.
|
||||
#define Dtool_CheckErrorOccurred() (_PyErr_OCCURRED() != NULL)
|
||||
#else
|
||||
#define Dtool_CheckErrorOccurred() _Dtool_CheckErrorOccurred()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#ifndef EVP_H
|
||||
#define EVP_H
|
||||
|
||||
struct EVP_CIPHER_CTX;
|
||||
struct EVP_PKEY;
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@
|
|||
#ifndef SSL_H
|
||||
#define SSL_H
|
||||
|
||||
struct BIO;
|
||||
struct SSL_CTX;
|
||||
struct EVP_CIPHER_CTX;
|
||||
struct EVP_PKEY;
|
||||
struct X509;
|
||||
struct X509_STORE;
|
||||
struct X509_NAME;
|
||||
typedef struct bio_st BIO;
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
|
||||
typedef struct evp_pkey_st EVP_PKEY;
|
||||
typedef struct x509_st X509;
|
||||
typedef struct x509_store_st X509_STORE;
|
||||
typedef struct X509_name_st X509_NAME;
|
||||
typedef struct ssl_cipher_st SSL_CIPHER;
|
||||
struct SSL;
|
||||
#define STACK_OF(type) struct stack_st_##type
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@
|
|||
#ifndef X509_H
|
||||
#define X509_H
|
||||
|
||||
struct X509;
|
||||
struct X509_STORE;
|
||||
struct X509_NAME;
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#ifdef HAVE_OPENSSL
|
||||
|
||||
#include "openssl/rand.h"
|
||||
#include "openssl/evp.h"
|
||||
|
||||
#ifndef HAVE_STREAMSIZE
|
||||
// Some compilers (notably SGI) don't define this for us
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// This module is not compiled if OpenSSL is not available.
|
||||
#ifdef HAVE_OPENSSL
|
||||
|
||||
#include "openssl/evp.h"
|
||||
typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
|
||||
|
||||
/**
|
||||
* The streambuf object that implements IDecompressStream and OCompressStream.
|
||||
|
|
|
|||
|
|
@ -19,8 +19,12 @@
|
|||
|
||||
#ifdef HAVE_OPENSSL
|
||||
|
||||
#include "openssl/evp.h"
|
||||
#include "openssl/pem.h"
|
||||
|
||||
// Some versions of OpenSSL appear to define this as a macro. Yucky.
|
||||
#undef set_key
|
||||
|
||||
PrcKeyRegistry *PrcKeyRegistry::_global_ptr = NULL;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -22,10 +22,8 @@
|
|||
#ifdef HAVE_OPENSSL
|
||||
|
||||
#include <vector>
|
||||
#include "openssl/evp.h"
|
||||
|
||||
// Some versions of OpenSSL appear to define this as a macro. Yucky.
|
||||
#undef set_key
|
||||
typedef struct evp_pkey_st EVP_PKEY;
|
||||
|
||||
/**
|
||||
* This class records the set of public keys used to verify the signature on a
|
||||
|
|
|
|||
|
|
@ -973,9 +973,7 @@ if GetTarget() == 'android':
|
|||
DefSymbol("ALWAYS", "ANDROID")
|
||||
|
||||
if not PkgSkip("EIGEN"):
|
||||
DefSymbol("ALWAYS", "EIGEN_MPL2_ONLY")
|
||||
if GetOptimize() >= 3:
|
||||
DefSymbol("ALWAYS", "EIGEN_NO_DEBUG")
|
||||
if COMPILER == "MSVC":
|
||||
# Squeeze out a bit more performance on MSVC builds...
|
||||
# Only do this if EIGEN_NO_DEBUG is also set, otherwise it
|
||||
|
|
@ -1292,7 +1290,7 @@ def CompileCxx(obj,src,opts):
|
|||
cmd += " -fno-strict-aliasing"
|
||||
|
||||
if optlevel >= 3:
|
||||
cmd += " -ffast-math"
|
||||
cmd += " -ffast-math -fno-stack-protector"
|
||||
if optlevel == 3:
|
||||
# Fast math is nice, but we'd like to see NaN in dev builds.
|
||||
cmd += " -fno-finite-math-only"
|
||||
|
|
|
|||
|
|
@ -84,10 +84,27 @@ finish_cull(SceneSetup *, Thread *current_thread) {
|
|||
void CullBinBackToFront::
|
||||
draw(bool force, Thread *current_thread) {
|
||||
PStatTimer timer(_draw_this_pcollector, current_thread);
|
||||
|
||||
GeomPipelineReader geom_reader(current_thread);
|
||||
GeomVertexDataPipelineReader data_reader(current_thread);
|
||||
|
||||
Objects::const_iterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
||||
CullableObject *object = (*oi)._object;
|
||||
CullHandler::draw(object, _gsg, force, current_thread);
|
||||
|
||||
if (object->_draw_callback == nullptr) {
|
||||
nassertd(object->_geom != nullptr) continue;
|
||||
|
||||
_gsg->set_state_and_transform(object->_state, object->_internal_transform);
|
||||
data_reader.set_object(object->_munged_data);
|
||||
data_reader.check_array_readers();
|
||||
geom_reader.set_object(object->_geom);
|
||||
geom_reader.draw(_gsg, object->_munger, &data_reader, force);
|
||||
} else {
|
||||
// It has a callback associated.
|
||||
object->draw_callback(_gsg, force, current_thread);
|
||||
// Now the callback has taken care of drawing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,10 +70,27 @@ finish_cull(SceneSetup *, Thread *current_thread) {
|
|||
void CullBinFixed::
|
||||
draw(bool force, Thread *current_thread) {
|
||||
PStatTimer timer(_draw_this_pcollector, current_thread);
|
||||
|
||||
GeomPipelineReader geom_reader(current_thread);
|
||||
GeomVertexDataPipelineReader data_reader(current_thread);
|
||||
|
||||
Objects::const_iterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
||||
CullableObject *object = (*oi)._object;
|
||||
CullHandler::draw(object, _gsg, force, current_thread);
|
||||
|
||||
if (object->_draw_callback == nullptr) {
|
||||
nassertd(object->_geom != nullptr) continue;
|
||||
|
||||
_gsg->set_state_and_transform(object->_state, object->_internal_transform);
|
||||
data_reader.set_object(object->_munged_data);
|
||||
data_reader.check_array_readers();
|
||||
geom_reader.set_object(object->_geom);
|
||||
geom_reader.draw(_gsg, object->_munger, &data_reader, force);
|
||||
} else {
|
||||
// It has a callback associated.
|
||||
object->draw_callback(_gsg, force, current_thread);
|
||||
// Now the callback has taken care of drawing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,10 +84,27 @@ finish_cull(SceneSetup *, Thread *current_thread) {
|
|||
void CullBinFrontToBack::
|
||||
draw(bool force, Thread *current_thread) {
|
||||
PStatTimer timer(_draw_this_pcollector, current_thread);
|
||||
|
||||
GeomPipelineReader geom_reader(current_thread);
|
||||
GeomVertexDataPipelineReader data_reader(current_thread);
|
||||
|
||||
Objects::const_iterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
||||
CullableObject *object = (*oi)._object;
|
||||
CullHandler::draw(object, _gsg, force, current_thread);
|
||||
|
||||
if (object->_draw_callback == nullptr) {
|
||||
nassertd(object->_geom != nullptr) continue;
|
||||
|
||||
_gsg->set_state_and_transform(object->_state, object->_internal_transform);
|
||||
data_reader.set_object(object->_munged_data);
|
||||
data_reader.check_array_readers();
|
||||
geom_reader.set_object(object->_geom);
|
||||
geom_reader.draw(_gsg, object->_munger, &data_reader, force);
|
||||
} else {
|
||||
// It has a callback associated.
|
||||
object->draw_callback(_gsg, force, current_thread);
|
||||
// Now the callback has taken care of drawing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,10 +69,27 @@ finish_cull(SceneSetup *, Thread *current_thread) {
|
|||
void CullBinStateSorted::
|
||||
draw(bool force, Thread *current_thread) {
|
||||
PStatTimer timer(_draw_this_pcollector, current_thread);
|
||||
|
||||
GeomPipelineReader geom_reader(current_thread);
|
||||
GeomVertexDataPipelineReader data_reader(current_thread);
|
||||
|
||||
Objects::const_iterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
||||
CullableObject *object = (*oi)._object;
|
||||
CullHandler::draw(object, _gsg, force, current_thread);
|
||||
|
||||
if (object->_draw_callback == nullptr) {
|
||||
nassertd(object->_geom != nullptr) continue;
|
||||
|
||||
_gsg->set_state_and_transform(object->_state, object->_internal_transform);
|
||||
data_reader.set_object(object->_munged_data);
|
||||
data_reader.check_array_readers();
|
||||
geom_reader.set_object(object->_geom);
|
||||
geom_reader.draw(_gsg, object->_munger, &data_reader, force);
|
||||
} else {
|
||||
// It has a callback associated.
|
||||
object->draw_callback(_gsg, force, current_thread);
|
||||
// Now the callback has taken care of drawing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,10 +54,27 @@ add_object(CullableObject *object, Thread *current_thread) {
|
|||
void CullBinUnsorted::
|
||||
draw(bool force, Thread *current_thread) {
|
||||
PStatTimer timer(_draw_this_pcollector, current_thread);
|
||||
|
||||
GeomPipelineReader geom_reader(current_thread);
|
||||
GeomVertexDataPipelineReader data_reader(current_thread);
|
||||
|
||||
Objects::iterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
||||
CullableObject *object = (*oi);
|
||||
CullHandler::draw(object, _gsg, force, current_thread);
|
||||
|
||||
if (object->_draw_callback == nullptr) {
|
||||
nassertd(object->_geom != nullptr) continue;
|
||||
|
||||
_gsg->set_state_and_transform(object->_state, object->_internal_transform);
|
||||
data_reader.set_object(object->_munged_data);
|
||||
data_reader.check_array_readers();
|
||||
geom_reader.set_object(object->_geom);
|
||||
geom_reader.draw(_gsg, object->_munger, &data_reader, force);
|
||||
} else {
|
||||
// It has a callback associated.
|
||||
object->draw_callback(_gsg, force, current_thread);
|
||||
// Now the callback has taken care of drawing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -491,6 +491,12 @@ get_screenshot() {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
{
|
||||
// Make sure that the correct viewport is active.
|
||||
DisplayRegionPipelineReader dr_reader(this, current_thread);
|
||||
gsg->prepare_display_region(&dr_reader);
|
||||
}
|
||||
|
||||
PT(Texture) tex = new Texture;
|
||||
|
||||
RenderBuffer buffer = gsg->get_render_buffer(get_screenshot_buffer_type(),
|
||||
|
|
|
|||
|
|
@ -1328,21 +1328,24 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
|
|||
GraphicsStateGuardian *gsg = win->get_gsg();
|
||||
nassertv(gsg != (GraphicsStateGuardian *)NULL);
|
||||
|
||||
DisplayRegionPipelineReader *dr_reader =
|
||||
new DisplayRegionPipelineReader(dr, current_thread);
|
||||
PT(SceneSetup) scene_setup;
|
||||
|
||||
win->change_scenes(dr_reader);
|
||||
gsg->prepare_display_region(dr_reader);
|
||||
{
|
||||
DisplayRegionPipelineReader dr_reader(dr, current_thread);
|
||||
win->change_scenes(&dr_reader);
|
||||
gsg->prepare_display_region(&dr_reader);
|
||||
|
||||
if (dr_reader->is_any_clear_active()) {
|
||||
gsg->clear(dr);
|
||||
if (dr_reader.is_any_clear_active()) {
|
||||
gsg->clear(dr);
|
||||
}
|
||||
|
||||
scene_setup = setup_scene(gsg, &dr_reader);
|
||||
}
|
||||
|
||||
PT(SceneSetup) scene_setup = setup_scene(gsg, dr_reader);
|
||||
if (scene_setup == (SceneSetup *)NULL) {
|
||||
// Never mind.
|
||||
|
||||
} else if (dr_reader->get_object()->is_stereo()) {
|
||||
} else if (dr->is_stereo()) {
|
||||
// Don't draw stereo DisplayRegions directly.
|
||||
|
||||
} else if (!gsg->set_scene(scene_setup)) {
|
||||
|
|
@ -1353,9 +1356,6 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
|
|||
} else {
|
||||
DrawCullHandler cull_handler(gsg);
|
||||
if (gsg->begin_scene()) {
|
||||
delete dr_reader;
|
||||
dr_reader = NULL;
|
||||
|
||||
CallbackObject *cbobj = dr->get_cull_callback();
|
||||
if (cbobj != (CallbackObject *)NULL) {
|
||||
// Issue the cull callback on this DisplayRegion.
|
||||
|
|
@ -1372,10 +1372,6 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
|
|||
gsg->end_scene();
|
||||
}
|
||||
}
|
||||
|
||||
if (dr_reader != (DisplayRegionPipelineReader *)NULL) {
|
||||
delete dr_reader;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1399,27 +1395,41 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
|
|||
for (size_t wi = 0; wi < wlist_size; ++wi) {
|
||||
GraphicsOutput *win = wlist[wi];
|
||||
if (win->is_active() && win->get_gsg()->is_active()) {
|
||||
GraphicsStateGuardian *gsg = win->get_gsg();
|
||||
PStatTimer timer(win->get_cull_window_pcollector(), current_thread);
|
||||
int num_display_regions = win->get_num_active_display_regions();
|
||||
for (int i = 0; i < num_display_regions; ++i) {
|
||||
DisplayRegion *dr = win->get_active_display_region(i);
|
||||
if (dr != (DisplayRegion *)NULL) {
|
||||
DisplayRegionPipelineReader *dr_reader =
|
||||
new DisplayRegionPipelineReader(dr, current_thread);
|
||||
|
||||
if (dr != nullptr) {
|
||||
PT(SceneSetup) scene_setup;
|
||||
PT(CullResult) cull_result;
|
||||
CullKey key;
|
||||
key._gsg = win->get_gsg();
|
||||
key._camera = dr_reader->get_camera();
|
||||
key._lens_index = dr_reader->get_lens_index();
|
||||
{
|
||||
PStatTimer timer(_cull_setup_pcollector, current_thread);
|
||||
DisplayRegionPipelineReader dr_reader(dr, current_thread);
|
||||
scene_setup = setup_scene(gsg, &dr_reader);
|
||||
if (scene_setup == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(key, (DisplayRegion *)NULL)).first;
|
||||
if ((*aci).second == NULL) {
|
||||
key._gsg = gsg;
|
||||
key._camera = dr_reader.get_camera();
|
||||
key._lens_index = dr_reader.get_lens_index();
|
||||
}
|
||||
|
||||
AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(move(key), nullptr)).first;
|
||||
if ((*aci).second == nullptr) {
|
||||
// We have not used this camera already in this thread. Perform
|
||||
// the cull operation.
|
||||
delete dr_reader;
|
||||
dr_reader = NULL;
|
||||
cull_result = dr->get_cull_result(current_thread);
|
||||
if (cull_result != nullptr) {
|
||||
cull_result = cull_result->make_next();
|
||||
} else {
|
||||
// This DisplayRegion has no cull results; draw it.
|
||||
cull_result = new CullResult(gsg, dr->get_draw_region_pcollector());
|
||||
}
|
||||
(*aci).second = dr;
|
||||
cull_to_bins(win, dr, current_thread);
|
||||
cull_to_bins(win, gsg, dr, scene_setup, cull_result, current_thread);
|
||||
|
||||
} else {
|
||||
// We have already culled a scene using this camera in this
|
||||
|
|
@ -1429,14 +1439,11 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
|
|||
// image.) Of course, the cull result will be the same, so just
|
||||
// use the result from the other DisplayRegion.
|
||||
DisplayRegion *other_dr = (*aci).second;
|
||||
dr->set_cull_result(other_dr->get_cull_result(current_thread),
|
||||
setup_scene(win->get_gsg(), dr_reader),
|
||||
current_thread);
|
||||
cull_result = other_dr->get_cull_result(current_thread);
|
||||
}
|
||||
|
||||
if (dr_reader != (DisplayRegionPipelineReader *)NULL) {
|
||||
delete dr_reader;
|
||||
}
|
||||
// Save the results for next frame.
|
||||
dr->set_cull_result(MOVE(cull_result), MOVE(scene_setup), current_thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1447,50 +1454,26 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
|
|||
* Called only within the inner loop of cull_to_bins(), above.
|
||||
*/
|
||||
void GraphicsEngine::
|
||||
cull_to_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
|
||||
GraphicsStateGuardian *gsg = win->get_gsg();
|
||||
if (gsg == (GraphicsStateGuardian *)NULL) {
|
||||
return;
|
||||
cull_to_bins(GraphicsOutput *win, GraphicsStateGuardian *gsg,
|
||||
DisplayRegion *dr, SceneSetup *scene_setup,
|
||||
CullResult *cull_result, Thread *current_thread) {
|
||||
|
||||
BinCullHandler cull_handler(cull_result);
|
||||
CallbackObject *cbobj = dr->get_cull_callback();
|
||||
if (cbobj != (CallbackObject *)NULL) {
|
||||
// Issue the cull callback on this DisplayRegion.
|
||||
DisplayRegionCullCallbackData cbdata(&cull_handler, scene_setup);
|
||||
cbobj->do_callback(&cbdata);
|
||||
|
||||
// The callback has taken care of the culling.
|
||||
|
||||
} else {
|
||||
// Perform the cull normally.
|
||||
dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
|
||||
}
|
||||
|
||||
PT(CullResult) cull_result;
|
||||
PT(SceneSetup) scene_setup;
|
||||
{
|
||||
PStatTimer timer(_cull_setup_pcollector, current_thread);
|
||||
DisplayRegionPipelineReader dr_reader(dr, current_thread);
|
||||
scene_setup = setup_scene(gsg, &dr_reader);
|
||||
cull_result = dr->get_cull_result(current_thread);
|
||||
|
||||
if (cull_result != (CullResult *)NULL) {
|
||||
cull_result = cull_result->make_next();
|
||||
|
||||
} else {
|
||||
// This DisplayRegion has no cull results; draw it.
|
||||
cull_result = new CullResult(gsg, dr->get_draw_region_pcollector());
|
||||
}
|
||||
}
|
||||
|
||||
if (scene_setup != (SceneSetup *)NULL) {
|
||||
BinCullHandler cull_handler(cull_result);
|
||||
CallbackObject *cbobj = dr->get_cull_callback();
|
||||
if (cbobj != (CallbackObject *)NULL) {
|
||||
// Issue the cull callback on this DisplayRegion.
|
||||
DisplayRegionCullCallbackData cbdata(&cull_handler, scene_setup);
|
||||
cbobj->do_callback(&cbdata);
|
||||
|
||||
// The callback has taken care of the culling.
|
||||
|
||||
} else {
|
||||
// Perform the cull normally.
|
||||
dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
|
||||
}
|
||||
|
||||
PStatTimer timer(_cull_sort_pcollector, current_thread);
|
||||
cull_result->finish_cull(scene_setup, current_thread);
|
||||
}
|
||||
|
||||
// Save the results for next frame.
|
||||
dr->set_cull_result(MOVE(cull_result), MOVE(scene_setup), current_thread);
|
||||
PStatTimer timer(_cull_sort_pcollector, current_thread);
|
||||
cull_result->finish_cull(scene_setup, current_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1538,7 +1521,7 @@ draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
|
|||
for (int i = 0; i < num_display_regions; ++i) {
|
||||
DisplayRegion *dr = win->get_active_display_region(i);
|
||||
if (dr != (DisplayRegion *)NULL) {
|
||||
draw_bins(win, dr, current_thread);
|
||||
do_draw(win, gsg, dr, current_thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1582,22 +1565,6 @@ draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This variant on draw_bins() is only called from draw_bins(), above. It
|
||||
* draws the cull result for a particular DisplayRegion.
|
||||
*/
|
||||
void GraphicsEngine::
|
||||
draw_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
|
||||
GraphicsStateGuardian *gsg = win->get_gsg();
|
||||
if (gsg == (GraphicsStateGuardian *)NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
PT(CullResult) cull_result = dr->get_cull_result(current_thread);
|
||||
PT(SceneSetup) scene_setup = dr->get_scene_setup(current_thread);
|
||||
do_draw(cull_result, scene_setup, win, dr, current_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called in the draw thread, this calls make_context() on each window on the
|
||||
* list to guarantee its gsg and graphics context both get created.
|
||||
|
|
@ -1899,15 +1866,20 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) {
|
|||
* Draws the previously-culled scene.
|
||||
*/
|
||||
void GraphicsEngine::
|
||||
do_draw(CullResult *cull_result, SceneSetup *scene_setup,
|
||||
GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
|
||||
|
||||
CallbackObject *cbobj;
|
||||
GraphicsStateGuardian *gsg = win->get_gsg();
|
||||
|
||||
do_draw(GraphicsOutput *win, GraphicsStateGuardian *gsg, DisplayRegion *dr, Thread *current_thread) {
|
||||
// Statistics
|
||||
PStatGPUTimer timer(gsg, dr->get_draw_region_pcollector(), current_thread);
|
||||
|
||||
PT(CullResult) cull_result;
|
||||
PT(SceneSetup) scene_setup;
|
||||
{
|
||||
DisplayRegion::CDCullReader cdata(dr->_cycler_cull, current_thread);
|
||||
cull_result = cdata->_cull_result;
|
||||
scene_setup = cdata->_scene_setup;
|
||||
}
|
||||
|
||||
CallbackObject *cbobj;
|
||||
|
||||
{
|
||||
DisplayRegionPipelineReader dr_reader(dr, current_thread);
|
||||
win->change_scenes(&dr_reader);
|
||||
|
|
|
|||
|
|
@ -147,9 +147,10 @@ private:
|
|||
Thread *current_thread);
|
||||
|
||||
void cull_to_bins(const Windows &wlist, Thread *current_thread);
|
||||
void cull_to_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
|
||||
void cull_to_bins(GraphicsOutput *win, GraphicsStateGuardian *gsg,
|
||||
DisplayRegion *dr, SceneSetup *scene_setup,
|
||||
CullResult *cull_result, Thread *current_thread);
|
||||
void draw_bins(const Windows &wlist, Thread *current_thread);
|
||||
void draw_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
|
||||
void make_contexts(const Windows &wlist, Thread *current_thread);
|
||||
|
||||
void process_events(const Windows &wlist, Thread *current_thread);
|
||||
|
|
@ -162,8 +163,8 @@ private:
|
|||
|
||||
PT(SceneSetup) setup_scene(GraphicsStateGuardian *gsg,
|
||||
DisplayRegionPipelineReader *dr);
|
||||
void do_draw(CullResult *cull_result, SceneSetup *scene_setup,
|
||||
GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
|
||||
void do_draw(GraphicsOutput *win, GraphicsStateGuardian *gsg,
|
||||
DisplayRegion *dr, Thread *current_thread);
|
||||
|
||||
void do_add_window(GraphicsOutput *window,
|
||||
const GraphicsThreadingModel &threading_model);
|
||||
|
|
|
|||
|
|
@ -23,11 +23,8 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef IS_OSX
|
||||
#if defined(IS_OSX) || defined(IS_FREEBSD)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef IS_FREEBSD
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -538,6 +538,14 @@ get_supports_depth_stencil() const {
|
|||
return _supports_depth_stencil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this particular GSG supports luminance textures.
|
||||
*/
|
||||
INLINE bool GraphicsStateGuardian::
|
||||
get_supports_luminance_texture() const {
|
||||
return _supports_luminance_texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this particular GSG supports the filter mode FT_shadow for
|
||||
* depth textures.
|
||||
|
|
|
|||
|
|
@ -253,6 +253,9 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
|
|||
_supports_geometry_instancing = false;
|
||||
_supports_indirect_draw = false;
|
||||
|
||||
// We are safe assuming it has luminance support
|
||||
_supports_luminance_texture = true;
|
||||
|
||||
// Assume a maximum of 1 render target in absence of MRT.
|
||||
_max_color_targets = 1;
|
||||
_supports_dual_source_blending = false;
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ PUBLISHED:
|
|||
INLINE bool get_supports_generate_mipmap() const;
|
||||
INLINE bool get_supports_depth_texture() const;
|
||||
INLINE bool get_supports_depth_stencil() const;
|
||||
INLINE bool get_supports_luminance_texture() const;
|
||||
INLINE bool get_supports_shadow_filter() const;
|
||||
INLINE bool get_supports_sampler_objects() const;
|
||||
INLINE bool get_supports_basic_shaders() const;
|
||||
|
|
@ -203,6 +204,7 @@ PUBLISHED:
|
|||
MAKE_PROPERTY(supports_generate_mipmap, get_supports_generate_mipmap);
|
||||
MAKE_PROPERTY(supports_depth_texture, get_supports_depth_texture);
|
||||
MAKE_PROPERTY(supports_depth_stencil, get_supports_depth_stencil);
|
||||
MAKE_PROPERTY(supports_luminance_texture, get_supports_luminance_texture);
|
||||
MAKE_PROPERTY(supports_shadow_filter, get_supports_shadow_filter);
|
||||
MAKE_PROPERTY(supports_sampler_objects, get_supports_sampler_objects);
|
||||
MAKE_PROPERTY(supports_basic_shaders, get_supports_basic_shaders);
|
||||
|
|
@ -597,6 +599,7 @@ protected:
|
|||
bool _supports_generate_mipmap;
|
||||
bool _supports_depth_texture;
|
||||
bool _supports_depth_stencil;
|
||||
bool _supports_luminance_texture;
|
||||
bool _supports_shadow_filter;
|
||||
bool _supports_sampler_objects;
|
||||
bool _supports_basic_shaders;
|
||||
|
|
|
|||
|
|
@ -18,14 +18,6 @@ INLINE BioPtr::
|
|||
BioPtr(BIO *bio) : _bio(bio) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE bool BioPtr::
|
||||
should_retry() const {
|
||||
return (_bio != NULL) && BIO_should_retry(_bio);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
#include "urlSpec.h"
|
||||
#include "config_downloader.h"
|
||||
|
||||
#include "openSSLWrapper.h" // must be included before any other openssl.
|
||||
#include "openssl/ssl.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
|
|
@ -199,7 +202,7 @@ connect() {
|
|||
|
||||
if (result != 0 && BIO_sock_should_retry(-1)) {
|
||||
// It's still in progress; we should retry later. This causes
|
||||
// should_reply() to return true.
|
||||
// should_retry() to return true.
|
||||
BIO_set_flags(_bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
_connecting = true;
|
||||
return false;
|
||||
|
|
@ -218,6 +221,14 @@ connect() {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
bool BioPtr::
|
||||
should_retry() const {
|
||||
return (_bio != NULL) && BIO_should_retry(_bio);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -19,13 +19,7 @@
|
|||
// This module is not compiled if OpenSSL is not available.
|
||||
#ifdef HAVE_OPENSSL
|
||||
|
||||
#ifndef OPENSSL_NO_KRB5
|
||||
#define OPENSSL_NO_KRB5
|
||||
#endif
|
||||
|
||||
#include "referenceCount.h"
|
||||
#include "openSSLWrapper.h" // must be included before any other openssl.
|
||||
#include "openssl/ssl.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
|
|
@ -35,6 +29,8 @@
|
|||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
typedef struct bio_st BIO;
|
||||
|
||||
class URLSpec;
|
||||
|
||||
/**
|
||||
|
|
@ -52,7 +48,7 @@ public:
|
|||
void set_nbio(bool nbio);
|
||||
bool connect();
|
||||
|
||||
INLINE bool should_retry() const;
|
||||
bool should_retry() const;
|
||||
|
||||
INLINE BIO &operator *() const;
|
||||
INLINE BIO *operator -> () const;
|
||||
|
|
|
|||
|
|
@ -19,14 +19,8 @@
|
|||
// This module is not compiled if OpenSSL is not available.
|
||||
#ifdef HAVE_OPENSSL
|
||||
|
||||
#ifndef OPENSSL_NO_KRB5
|
||||
#define OPENSSL_NO_KRB5
|
||||
#endif
|
||||
|
||||
#include "bioPtr.h"
|
||||
#include "pointerTo.h"
|
||||
#include "openSSLWrapper.h" // must be included before any other openssl.
|
||||
#include "openssl/ssl.h"
|
||||
|
||||
/**
|
||||
* The streambuf object that implements IBioStream.
|
||||
|
|
|
|||
|
|
@ -19,14 +19,8 @@
|
|||
// This module is not compiled if OpenSSL is not available.
|
||||
#ifdef HAVE_OPENSSL
|
||||
|
||||
#ifndef OPENSSL_NO_KRB5
|
||||
#define OPENSSL_NO_KRB5
|
||||
#endif
|
||||
|
||||
#include "bioStream.h"
|
||||
#include "referenceCount.h"
|
||||
#include "openSSLWrapper.h" // must be included before any other openssl.
|
||||
#include "openssl/ssl.h"
|
||||
|
||||
/**
|
||||
* A wrapper around an BioStream object to make a reference-counting pointer
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#ifdef HAVE_OPENSSL
|
||||
|
||||
#include "openSSLWrapper.h"
|
||||
|
||||
#if defined(WIN32_VC) || defined(WIN64_VC)
|
||||
#include <WinSock2.h>
|
||||
#include <windows.h> // for select()
|
||||
|
|
|
|||
|
|
@ -22,10 +22,6 @@
|
|||
|
||||
#ifdef HAVE_OPENSSL
|
||||
|
||||
#ifndef OPENSSL_NO_KRB5
|
||||
#define OPENSSL_NO_KRB5
|
||||
#endif
|
||||
|
||||
#include "httpClient.h"
|
||||
#include "httpEnum.h"
|
||||
#include "urlSpec.h"
|
||||
|
|
@ -37,10 +33,10 @@
|
|||
#include "pointerTo.h"
|
||||
#include "config_downloader.h"
|
||||
#include "filename.h"
|
||||
#include "openSSLWrapper.h" // must be included before any other openssl.
|
||||
#include "openssl/ssl.h"
|
||||
#include "typedReferenceCount.h"
|
||||
|
||||
typedef struct bio_st BIO;
|
||||
|
||||
class Ramfile;
|
||||
class HTTPClient;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#ifdef HAVE_OPENSSL
|
||||
|
||||
#include "openSSLWrapper.h"
|
||||
|
||||
PT(HTTPClient) HTTPClient::_global_ptr;
|
||||
|
||||
/**
|
||||
|
|
@ -68,6 +70,68 @@ tokenize(const string &str, vector_string &words, const string &delimiters) {
|
|||
words.push_back(string());
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
/**
|
||||
* This method is attached as a callback for SSL messages only when debug
|
||||
* output is enabled.
|
||||
*/
|
||||
static void
|
||||
ssl_msg_callback(int write_p, int version, int content_type,
|
||||
const void *, size_t len, SSL *, void *) {
|
||||
ostringstream describe;
|
||||
if (write_p) {
|
||||
describe << "sent ";
|
||||
} else {
|
||||
describe << "received ";
|
||||
}
|
||||
switch (version) {
|
||||
case SSL2_VERSION:
|
||||
describe << "SSL 2.0 ";
|
||||
break;
|
||||
|
||||
case SSL3_VERSION:
|
||||
describe << "SSL 3.0 ";
|
||||
break;
|
||||
|
||||
case TLS1_VERSION:
|
||||
describe << "TLS 1.0 ";
|
||||
break;
|
||||
|
||||
default:
|
||||
describe << "unknown protocol ";
|
||||
}
|
||||
|
||||
describe << "message: ";
|
||||
|
||||
if (version != SSL2_VERSION) {
|
||||
switch (content_type) {
|
||||
case 20:
|
||||
describe << "change cipher spec, ";
|
||||
break;
|
||||
|
||||
case 21:
|
||||
describe << "alert, ";
|
||||
break;
|
||||
|
||||
case 22:
|
||||
describe << "handshake, ";
|
||||
break;
|
||||
|
||||
case 23:
|
||||
describe << "application data, ";
|
||||
break;
|
||||
|
||||
default:
|
||||
describe << "unknown content type, ";
|
||||
}
|
||||
}
|
||||
|
||||
describe << len << " bytes.\n";
|
||||
|
||||
downloader_cat.debug() << describe.str();
|
||||
}
|
||||
#endif // !defined(NDEBUG)
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -1564,68 +1628,6 @@ split_whitespace(string &a, string &b, const string &c) {
|
|||
b = c.substr(p);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
/**
|
||||
* This method is attached as a callback for SSL messages only when debug
|
||||
* output is enabled.
|
||||
*/
|
||||
void HTTPClient::
|
||||
ssl_msg_callback(int write_p, int version, int content_type,
|
||||
const void *, size_t len, SSL *, void *) {
|
||||
ostringstream describe;
|
||||
if (write_p) {
|
||||
describe << "sent ";
|
||||
} else {
|
||||
describe << "received ";
|
||||
}
|
||||
switch (version) {
|
||||
case SSL2_VERSION:
|
||||
describe << "SSL 2.0 ";
|
||||
break;
|
||||
|
||||
case SSL3_VERSION:
|
||||
describe << "SSL 3.0 ";
|
||||
break;
|
||||
|
||||
case TLS1_VERSION:
|
||||
describe << "TLS 1.0 ";
|
||||
break;
|
||||
|
||||
default:
|
||||
describe << "unknown protocol ";
|
||||
}
|
||||
|
||||
describe << "message: ";
|
||||
|
||||
if (version != SSL2_VERSION) {
|
||||
switch (content_type) {
|
||||
case 20:
|
||||
describe << "change cipher spec, ";
|
||||
break;
|
||||
|
||||
case 21:
|
||||
describe << "alert, ";
|
||||
break;
|
||||
|
||||
case 22:
|
||||
describe << "handshake, ";
|
||||
break;
|
||||
|
||||
case 23:
|
||||
describe << "application data, ";
|
||||
break;
|
||||
|
||||
default:
|
||||
describe << "unknown content type, ";
|
||||
}
|
||||
}
|
||||
|
||||
describe << len << " bytes.\n";
|
||||
|
||||
downloader_cat.debug() << describe.str();
|
||||
}
|
||||
#endif // !defined(NDEBUG)
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -32,7 +32,11 @@
|
|||
#include "pmap.h"
|
||||
#include "pset.h"
|
||||
#include "referenceCount.h"
|
||||
#include "openSSLWrapper.h"
|
||||
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
typedef struct x509_st X509;
|
||||
typedef struct X509_name_st X509_NAME;
|
||||
typedef struct evp_pkey_st EVP_PKEY;
|
||||
|
||||
class Filename;
|
||||
class HTTPChannel;
|
||||
|
|
@ -155,12 +159,6 @@ private:
|
|||
|
||||
static void split_whitespace(string &a, string &b, const string &c);
|
||||
|
||||
#ifndef NDEBUG
|
||||
static void ssl_msg_callback(int write_p, int version, int content_type,
|
||||
const void *buf, size_t len, SSL *ssl,
|
||||
void *arg);
|
||||
#endif
|
||||
|
||||
typedef pvector<URLSpec> Proxies;
|
||||
typedef pmap<string, Proxies> ProxiesByScheme;
|
||||
ProxiesByScheme _proxies_by_scheme;
|
||||
|
|
|
|||
|
|
@ -132,8 +132,7 @@ allocate_ibuffer(DXScreenData &scrn,
|
|||
dxgsg9_cat.debug()
|
||||
<< "creating index buffer " << _ibuffer << ": "
|
||||
<< reader->get_num_vertices() << " indices ("
|
||||
<< reader->get_vertices_reader()->get_array_format()->get_column(0)->get_numeric_type()
|
||||
<< ")\n";
|
||||
<< reader->get_index_type() << ")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -482,7 +482,7 @@ convert_collision_node(CollisionNode *node, const WorkingNodePath &node_path,
|
|||
} else if (child->is_of_type(CollisionSphere::get_class_type())) {
|
||||
CPT(CollisionSphere) sphere = DCAST(CollisionSphere, child);
|
||||
LPoint3 center = sphere->get_center();
|
||||
LVector3 offset(sphere->get_radius(), 0, 0);
|
||||
PN_stdfloat radius = sphere->get_radius();
|
||||
|
||||
EggGroup *egg_sphere;
|
||||
if (num_solids == 1) {
|
||||
|
|
@ -499,15 +499,19 @@ convert_collision_node(CollisionNode *node, const WorkingNodePath &node_path,
|
|||
}
|
||||
egg_sphere->set_collide_flags(flags);
|
||||
|
||||
EggVertex ev1, ev2;
|
||||
ev1.set_pos(LCAST(double, (center + offset) * net_mat));
|
||||
ev2.set_pos(LCAST(double, (center - offset) * net_mat));
|
||||
EggVertex ev1, ev2, ev3, ev4;
|
||||
ev1.set_pos(LCAST(double, (center + LVector3(radius, 0, 0)) * net_mat));
|
||||
ev2.set_pos(LCAST(double, (center + LVector3(0, radius, 0)) * net_mat));
|
||||
ev3.set_pos(LCAST(double, (center + LVector3(-radius, 0, 0)) * net_mat));
|
||||
ev4.set_pos(LCAST(double, (center + LVector3(0, -radius, 0)) * net_mat));
|
||||
|
||||
EggPolygon *egg_poly = new EggPolygon;
|
||||
egg_sphere->add_child(egg_poly);
|
||||
|
||||
egg_poly->add_vertex(cvpool->create_unique_vertex(ev1));
|
||||
egg_poly->add_vertex(cvpool->create_unique_vertex(ev2));
|
||||
egg_poly->add_vertex(cvpool->create_unique_vertex(ev3));
|
||||
egg_poly->add_vertex(cvpool->create_unique_vertex(ev4));
|
||||
|
||||
} else if (child->is_of_type(CollisionPlane::get_class_type())) {
|
||||
LPlane plane = DCAST(CollisionPlane, child)->get_plane();
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include <iterator>
|
||||
#include <time.h>
|
||||
|
||||
#include "openSSLWrapper.h"
|
||||
|
||||
// This sequence of bytes begins each Multifile to identify it as a Multifile.
|
||||
const char Multifile::_header[] = "pmf\0\n\r";
|
||||
const size_t Multifile::_header_size = 6;
|
||||
|
|
@ -768,43 +770,6 @@ add_signature(const Filename &composite, const string &password) {
|
|||
}
|
||||
#endif // HAVE_OPENSSL
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
/**
|
||||
* Adds a new signature to the Multifile. This signature associates the
|
||||
* indicated certificate with the current contents of the Multifile. When the
|
||||
* Multifile is read later, the signature will still be present only if the
|
||||
* Multifile is unchanged; any subsequent changes to the Multifile will
|
||||
* automatically invalidate and remove the signature.
|
||||
*
|
||||
* If chain is non-NULL, it represents the certificate chain that validates
|
||||
* the certificate.
|
||||
*
|
||||
* The specified private key must match the certificate, and the Multifile
|
||||
* must be open in read-write mode. The private key is only used for
|
||||
* generating the signature; it is not written to the Multifile and cannot be
|
||||
* retrieved from the Multifile later. (However, the certificate *can* be
|
||||
* retrieved from the Multifile later, to identify the entity that created the
|
||||
* signature.)
|
||||
*
|
||||
* This implicitly causes a repack() operation if one is needed. Returns true
|
||||
* on success, false on failure.
|
||||
*/
|
||||
bool Multifile::
|
||||
add_signature(X509 *certificate, STACK_OF(X509) *chain, EVP_PKEY *pkey) {
|
||||
// Convert the certificate and chain into our own CertChain structure.
|
||||
CertChain cert_chain;
|
||||
cert_chain.push_back(CertRecord(certificate));
|
||||
if (chain != NULL) {
|
||||
int num = sk_X509_num(chain);
|
||||
for (int i = 0; i < num; ++i) {
|
||||
cert_chain.push_back(CertRecord((X509 *)sk_X509_value(chain, i)));
|
||||
}
|
||||
}
|
||||
|
||||
return add_signature(cert_chain, pkey);
|
||||
}
|
||||
#endif // HAVE_OPENSSL
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
/**
|
||||
* Adds a new signature to the Multifile. This signature associates the
|
||||
|
|
|
|||
|
|
@ -24,7 +24,11 @@
|
|||
#include "indirectLess.h"
|
||||
#include "referenceCount.h"
|
||||
#include "pvector.h"
|
||||
#include "openSSLWrapper.h"
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
typedef struct x509_st X509;
|
||||
typedef struct evp_pkey_st EVP_PKEY;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A file that contains a set of files.
|
||||
|
|
@ -148,7 +152,6 @@ public:
|
|||
};
|
||||
typedef pvector<CertRecord> CertChain;
|
||||
|
||||
bool add_signature(X509 *certificate, STACK_OF(X509) *chain, EVP_PKEY *pkey);
|
||||
bool add_signature(const CertChain &chain, EVP_PKEY *pkey);
|
||||
|
||||
const CertChain &get_signature(int n) const;
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
|
|||
|
||||
if (cgGetParameterBaseResource(p) == CG_ATTR0) {
|
||||
// The Cg toolkit claims that it is bound to a generic vertex attribute.
|
||||
if (_glsl_program != 0) {
|
||||
if (_glgsg->has_fixed_function_pipeline() && _glsl_program != 0) {
|
||||
// This is where the Cg glslv compiler lies, making the stupid
|
||||
// assumption that we're using an NVIDIA card where generic attributes
|
||||
// are aliased with conventional vertex attributes. Instead, it
|
||||
|
|
@ -246,7 +246,7 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
|
|||
// A conventional texture coordinate set.
|
||||
loc = CA_texcoord + cgGetParameterResourceIndex(p);
|
||||
|
||||
} else {
|
||||
} else if (_glgsg->has_fixed_function_pipeline()) {
|
||||
// Some other conventional vertex attribute.
|
||||
switch (res) {
|
||||
case CG_POSITION0:
|
||||
|
|
@ -276,6 +276,14 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
|
|||
GLCAT.error(false) << ".\n";
|
||||
loc = CA_unknown;
|
||||
}
|
||||
} else {
|
||||
GLCAT.error()
|
||||
<< "Cg varying " << cgGetParameterName(p);
|
||||
if (cgGetParameterSemantic(p)) {
|
||||
GLCAT.error(false) << " : " << cgGetParameterSemantic(p);
|
||||
}
|
||||
GLCAT.error(false) << " is bound to a conventional vertex attribute, "
|
||||
"but the compatibility profile is not enabled.\n";
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
|
@ -916,8 +924,7 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
|
|||
} else {
|
||||
// There is no vertex column with this name; disable the attribute
|
||||
// array.
|
||||
#ifdef SUPPORT_FIXED_FUNCTION
|
||||
if (p == 0) {
|
||||
if (_glgsg->has_fixed_function_pipeline() && p == 0) {
|
||||
// NOTE: if we disable attribute 0 in compatibility profile, the
|
||||
// object will disappear. In GLSL we fix this by forcing the vertex
|
||||
// column to be at 0, but we don't have control over that with Cg.
|
||||
|
|
@ -930,9 +937,7 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
|
|||
_glgsg->_glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
}
|
||||
|
||||
} else
|
||||
#endif // SUPPORT_FIXED_FUNCTION
|
||||
if (p >= 0) {
|
||||
} else if (p >= 0) {
|
||||
_glgsg->disable_vertex_attrib_array(p);
|
||||
|
||||
if (p == _color_attrib_index) {
|
||||
|
|
|
|||
|
|
@ -95,8 +95,7 @@ clear(Thread *current_thread) {
|
|||
return;
|
||||
}
|
||||
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)_gsg.p();
|
||||
|
||||
if (glgsg->_glClearBufferfv == NULL) {
|
||||
// We can't efficiently clear the buffer. Fall back to the inefficient
|
||||
|
|
@ -254,8 +253,7 @@ begin_frame(FrameMode mode, Thread *current_thread) {
|
|||
// until we call glBlitFramebuffer.
|
||||
#ifndef OPENGLES_1
|
||||
if (gl_enable_memory_barriers && _fbo_multisample == 0) {
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_R(glgsg, _gsg, false);
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)_gsg.p();
|
||||
|
||||
TextureContexts::iterator it;
|
||||
for (it = _texture_contexts.begin(); it != _texture_contexts.end(); ++it) {
|
||||
|
|
@ -269,6 +267,9 @@ begin_frame(FrameMode mode, Thread *current_thread) {
|
|||
}
|
||||
}
|
||||
#endif
|
||||
} else if (mode == FM_refresh) {
|
||||
// Just bind the FBO.
|
||||
rebuild_bitplanes();
|
||||
}
|
||||
|
||||
_gsg->set_current_properties(&get_fb_properties());
|
||||
|
|
@ -282,8 +283,7 @@ begin_frame(FrameMode mode, Thread *current_thread) {
|
|||
*/
|
||||
bool CLP(GraphicsBuffer)::
|
||||
check_fbo() {
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_R(glgsg, _gsg, false);
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)_gsg.p();
|
||||
|
||||
GLenum status = glgsg->_glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
|
|
@ -338,8 +338,7 @@ rebuild_bitplanes() {
|
|||
return;
|
||||
}
|
||||
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)_gsg.p();
|
||||
|
||||
if (!_needs_rebuild) {
|
||||
if (_fbo_multisample != 0) {
|
||||
|
|
@ -682,8 +681,7 @@ rebuild_bitplanes() {
|
|||
*/
|
||||
void CLP(GraphicsBuffer)::
|
||||
bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot, GLenum attachpoint) {
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)_gsg.p();
|
||||
|
||||
Texture *tex = attach[slot];
|
||||
|
||||
|
|
@ -1017,8 +1015,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
*/
|
||||
void CLP(GraphicsBuffer)::
|
||||
bind_slot_multisample(bool rb_resize, Texture **attach, RenderTexturePlane slot, GLenum attachpoint) {
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)_gsg.p();
|
||||
|
||||
if ((_rbm[slot] != 0)&&(!rb_resize)) {
|
||||
return;
|
||||
|
|
@ -1141,8 +1138,7 @@ bind_slot_multisample(bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
*/
|
||||
void CLP(GraphicsBuffer)::
|
||||
attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) {
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)_gsg.p();
|
||||
|
||||
if (view >= attach->get_num_views()) {
|
||||
attach->set_num_views(view + 1);
|
||||
|
|
@ -1162,8 +1158,10 @@ attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) {
|
|||
glgsg->apply_texture(gtc);
|
||||
|
||||
#if !defined(OPENGLES) && defined(SUPPORT_FIXED_FUNCTION)
|
||||
GLclampf priority = 1.0f;
|
||||
glPrioritizeTextures(1, >c->_index, &priority);
|
||||
if (glgsg->has_fixed_function_pipeline()) {
|
||||
GLclampf priority = 1.0f;
|
||||
glPrioritizeTextures(1, >c->_index, &priority);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENGLES
|
||||
|
|
@ -1210,8 +1208,7 @@ generate_mipmaps() {
|
|||
return;
|
||||
}
|
||||
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)_gsg.p();
|
||||
|
||||
// PStatGPUTimer timer(glgsg, _generate_mipmap_pcollector);
|
||||
|
||||
|
|
@ -1248,8 +1245,7 @@ end_frame(FrameMode mode, Thread *current_thread) {
|
|||
|
||||
// Unbind the FBO. TODO: calling bind_fbo is slow, so we should probably
|
||||
// move this to begin_frame to prevent unnecessary calls.
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)_gsg.p();
|
||||
glgsg->bind_fbo(0);
|
||||
_bound_tex_page = -1;
|
||||
|
||||
|
|
@ -1288,8 +1284,7 @@ void CLP(GraphicsBuffer)::
|
|||
select_target_tex_page(int page) {
|
||||
nassertv(page >= 0 && page < _fbo.size());
|
||||
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)_gsg.p();
|
||||
|
||||
bool switched_page = (_bound_tex_page != page);
|
||||
|
||||
|
|
@ -1684,8 +1679,7 @@ report_my_errors(int line, const char *file) {
|
|||
GLCAT.error() << file << ", line " << line << ": GL error " << (int)error_code << "\n";
|
||||
}
|
||||
} else {
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)_gsg.p();
|
||||
glgsg->report_my_errors(line, file);
|
||||
}
|
||||
}
|
||||
|
|
@ -1718,8 +1712,7 @@ void CLP(GraphicsBuffer)::
|
|||
resolve_multisamples() {
|
||||
nassertv(_fbo.size() > 0);
|
||||
|
||||
CLP(GraphicsStateGuardian) *glgsg;
|
||||
DCAST_INTO_V(glgsg, _gsg);
|
||||
CLP(GraphicsStateGuardian) *glgsg = (CLP(GraphicsStateGuardian) *)_gsg.p();
|
||||
|
||||
PStatGPUTimer timer(glgsg, _resolve_multisample_pcollector);
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,33 @@ get_gl_version_minor() const {
|
|||
return _gl_version_minor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a core profile or a compatibility mode is considered.
|
||||
*/
|
||||
/*INLINE bool CLP(GraphicsStateGuardian)::
|
||||
has_core_profile() const {
|
||||
return _core_profile;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Returns whether the fixed function pipeline is supported.
|
||||
*/
|
||||
INLINE bool CLP(GraphicsStateGuardian)::
|
||||
has_fixed_function_pipeline() const {
|
||||
#ifndef SUPPORT_FIXED_FUNCTION
|
||||
return false;
|
||||
#elif defined(OPENGLES_1)
|
||||
return true;
|
||||
#elif defined(OPENGLES)
|
||||
return false;
|
||||
#else
|
||||
// Otherwise, we can just check whether we are using a core profile or a
|
||||
// compatibility mode. The variable _core_profile is already taking into
|
||||
// account if a GL < 3.2 is considered (becoming false)
|
||||
return !_core_profile;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls glFinish() if the config variable gl-finish is set True.
|
||||
*/
|
||||
|
|
@ -363,7 +390,7 @@ enable_line_smooth(bool val) {
|
|||
INLINE void CLP(GraphicsStateGuardian)::
|
||||
enable_point_smooth(bool val) {
|
||||
#ifdef SUPPORT_FIXED_FUNCTION
|
||||
if (_point_smooth_enabled != val) {
|
||||
if (has_fixed_function_pipeline() && _point_smooth_enabled != val) {
|
||||
_state_mask.clear_bit(TransparencyAttrib::get_class_slot());
|
||||
_point_smooth_enabled = val;
|
||||
if (val) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -399,6 +399,7 @@ public:
|
|||
INLINE const string &get_gl_version() const;
|
||||
INLINE int get_gl_version_major() const;
|
||||
INLINE int get_gl_version_minor() const;
|
||||
INLINE bool has_fixed_function_pipeline() const;
|
||||
|
||||
virtual void set_state_and_transform(const RenderState *state,
|
||||
const TransformState *transform);
|
||||
|
|
@ -719,6 +720,11 @@ protected:
|
|||
|
||||
pset<string> _extensions;
|
||||
|
||||
#ifndef OPENGLES
|
||||
// True for non-compatibility GL 3.2+ contexts.
|
||||
bool _core_profile;
|
||||
#endif
|
||||
|
||||
public:
|
||||
bool _supports_point_parameters;
|
||||
PFNGLPOINTPARAMETERFVPROC _glPointParameterfv;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ get_geom_rendering() const {
|
|||
INLINE CPT(GeomVertexData) Geom::
|
||||
get_vertex_data(Thread *current_thread) const {
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
return cdata->_data.get_read_pointer();
|
||||
return cdata->_data.get_read_pointer(current_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -514,6 +514,18 @@ CData(const Geom::CData ©) :
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE GeomPipelineReader::
|
||||
GeomPipelineReader(Thread *current_thread) :
|
||||
_object(nullptr),
|
||||
_current_thread(current_thread),
|
||||
_cdata(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -531,34 +543,22 @@ GeomPipelineReader(const Geom *object, Thread *current_thread) :
|
|||
#endif // DO_PIPELINING
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't attempt to copy these objects.
|
||||
*/
|
||||
INLINE GeomPipelineReader::
|
||||
GeomPipelineReader(const GeomPipelineReader &) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't attempt to copy these objects.
|
||||
*/
|
||||
INLINE void GeomPipelineReader::
|
||||
operator = (const GeomPipelineReader &) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE GeomPipelineReader::
|
||||
~GeomPipelineReader() {
|
||||
#ifdef _DEBUG
|
||||
nassertv(_object->test_ref_count_nonzero());
|
||||
if (_object != nullptr) {
|
||||
nassertv(_object->test_ref_count_nonzero());
|
||||
}
|
||||
#endif // _DEBUG
|
||||
// _object->_cycler.release_read(_cdata);
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
unref_delete((CycleData *)_cdata);
|
||||
if (_cdata != nullptr) {
|
||||
unref_delete((CycleData *)_cdata);
|
||||
}
|
||||
#endif // DO_PIPELINING
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
|
@ -567,6 +567,30 @@ INLINE GeomPipelineReader::
|
|||
#endif // _DEBUG
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE void GeomPipelineReader::
|
||||
set_object(const Geom *object) {
|
||||
if (object != _object) {
|
||||
// _object->_cycler.release_read(_cdata);
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
if (_cdata != NULL) {
|
||||
unref_delete((CycleData *)_cdata);
|
||||
}
|
||||
#endif // DO_PIPELINING
|
||||
|
||||
_cdata = object->_cycler.read_unlocked(_current_thread);
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
_cdata->ref();
|
||||
#endif // DO_PIPELINING
|
||||
|
||||
_object = object;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ make_nonindexed(bool composite_only) {
|
|||
int num_changed = 0;
|
||||
|
||||
CDWriter cdata(_cycler, true, current_thread);
|
||||
CPT(GeomVertexData) orig_data = cdata->_data.get_read_pointer();
|
||||
CPT(GeomVertexData) orig_data = cdata->_data.get_read_pointer(current_thread);
|
||||
PT(GeomVertexData) new_data = new GeomVertexData(*orig_data);
|
||||
new_data->clear_rows();
|
||||
|
||||
|
|
@ -247,7 +247,7 @@ make_nonindexed(bool composite_only) {
|
|||
Primitives new_prims;
|
||||
new_prims.reserve(cdata->_primitives.size());
|
||||
for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
|
||||
PT(GeomPrimitive) primitive = (*pi).get_read_pointer()->make_copy();
|
||||
PT(GeomPrimitive) primitive = (*pi).get_read_pointer(current_thread)->make_copy();
|
||||
new_prims.push_back(primitive.p());
|
||||
|
||||
// GeomPoints are considered "composite" for the purposes of making
|
||||
|
|
@ -298,7 +298,7 @@ set_primitive(int i, const GeomPrimitive *primitive) {
|
|||
Thread *current_thread = Thread::get_current_thread();
|
||||
CDWriter cdata(_cycler, true, current_thread);
|
||||
nassertv(i >= 0 && i < (int)cdata->_primitives.size());
|
||||
nassertv(primitive->check_valid(cdata->_data.get_read_pointer()));
|
||||
nassertv(primitive->check_valid(cdata->_data.get_read_pointer(current_thread)));
|
||||
|
||||
// All primitives within a particular Geom must have the same fundamental
|
||||
// primitive type (triangles, points, or lines).
|
||||
|
|
@ -339,7 +339,7 @@ add_primitive(const GeomPrimitive *primitive) {
|
|||
Thread *current_thread = Thread::get_current_thread();
|
||||
CDWriter cdata(_cycler, true, current_thread);
|
||||
|
||||
nassertv(primitive->check_valid(cdata->_data.get_read_pointer()));
|
||||
nassertv(primitive->check_valid(cdata->_data.get_read_pointer(current_thread)));
|
||||
|
||||
// All primitives within a particular Geom must have the same fundamental
|
||||
// primitive type (triangles, points, or lines).
|
||||
|
|
@ -426,11 +426,11 @@ decompose_in_place() {
|
|||
#endif
|
||||
Primitives::iterator pi;
|
||||
for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->decompose();
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->decompose();
|
||||
(*pi) = (GeomPrimitive *)new_prim.p();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) {
|
||||
all_is_valid = false;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -460,11 +460,11 @@ doubleside_in_place() {
|
|||
#endif
|
||||
Primitives::iterator pi;
|
||||
for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->doubleside();
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->doubleside();
|
||||
(*pi) = (GeomPrimitive *)new_prim.p();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) {
|
||||
all_is_valid = false;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -494,11 +494,11 @@ reverse_in_place() {
|
|||
#endif
|
||||
Primitives::iterator pi;
|
||||
for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->reverse();
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->reverse();
|
||||
(*pi) = (GeomPrimitive *)new_prim.p();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) {
|
||||
all_is_valid = false;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -528,11 +528,11 @@ rotate_in_place() {
|
|||
#endif
|
||||
Primitives::iterator pi;
|
||||
for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->rotate();
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->rotate();
|
||||
(*pi) = (GeomPrimitive *)new_prim.p();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) {
|
||||
all_is_valid = false;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -596,7 +596,7 @@ unify_in_place(int max_indices, bool preserve_order) {
|
|||
|
||||
Primitives::const_iterator pi;
|
||||
for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
|
||||
CPT(GeomPrimitive) primitive = (*pi).get_read_pointer();
|
||||
CPT(GeomPrimitive) primitive = (*pi).get_read_pointer(current_thread);
|
||||
NewPrims::iterator npi = new_prims.find(primitive->get_type());
|
||||
if (npi == new_prims.end()) {
|
||||
// This is the first primitive of this type.
|
||||
|
|
@ -648,7 +648,7 @@ unify_in_place(int max_indices, bool preserve_order) {
|
|||
for (npi = new_prims.begin(); npi != new_prims.end(); ++npi) {
|
||||
GeomPrimitive *prim = (*npi).second;
|
||||
|
||||
nassertv(prim->check_valid(cdata->_data.get_read_pointer()));
|
||||
nassertv(prim->check_valid(cdata->_data.get_read_pointer(current_thread)));
|
||||
|
||||
// Each new primitive, naturally, inherits the Geom's overall shade model.
|
||||
prim->set_shade_model(cdata->_shade_model);
|
||||
|
|
@ -706,11 +706,11 @@ make_lines_in_place() {
|
|||
#endif
|
||||
Primitives::iterator pi;
|
||||
for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->make_lines();
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->make_lines();
|
||||
(*pi) = (GeomPrimitive *)new_prim.p();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) {
|
||||
all_is_valid = false;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -740,11 +740,11 @@ make_points_in_place() {
|
|||
#endif
|
||||
Primitives::iterator pi;
|
||||
for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->make_points();
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->make_points();
|
||||
(*pi) = (GeomPrimitive *)new_prim.p();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) {
|
||||
all_is_valid = false;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -774,11 +774,11 @@ make_patches_in_place() {
|
|||
#endif
|
||||
Primitives::iterator pi;
|
||||
for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->make_patches();
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->make_patches();
|
||||
(*pi) = (GeomPrimitive *)new_prim.p();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) {
|
||||
all_is_valid = false;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -865,7 +865,9 @@ get_num_bytes() const {
|
|||
*/
|
||||
bool Geom::
|
||||
request_resident() const {
|
||||
CDReader cdata(_cycler);
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
|
||||
bool resident = true;
|
||||
|
||||
|
|
@ -873,7 +875,7 @@ request_resident() const {
|
|||
for (pi = cdata->_primitives.begin();
|
||||
pi != cdata->_primitives.end();
|
||||
++pi) {
|
||||
if (!(*pi).get_read_pointer()->request_resident()) {
|
||||
if (!(*pi).get_read_pointer(current_thread)->request_resident()) {
|
||||
resident = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1197,7 +1199,7 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
|
|||
int num_vertices = 0;
|
||||
|
||||
// Get the vertex data, after animation.
|
||||
CPT(GeomVertexData) vertex_data = cdata->_data.get_read_pointer();
|
||||
CPT(GeomVertexData) vertex_data = cdata->_data.get_read_pointer(current_thread);
|
||||
vertex_data = vertex_data->animate_vertices(true, current_thread);
|
||||
|
||||
// Now actually compute the bounding volume. We do this by using
|
||||
|
|
@ -1296,7 +1298,7 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
|
|||
for (pi = cdata->_primitives.begin();
|
||||
pi != cdata->_primitives.end();
|
||||
++pi) {
|
||||
CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
|
||||
CPT(GeomPrimitive) prim = (*pi).get_read_pointer(current_thread);
|
||||
num_vertices += prim->get_num_vertices();
|
||||
}
|
||||
|
||||
|
|
@ -1327,7 +1329,7 @@ do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
|
|||
for (pi = cdata->_primitives.begin();
|
||||
pi != cdata->_primitives.end();
|
||||
++pi) {
|
||||
CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
|
||||
CPT(GeomPrimitive) prim = (*pi).get_read_pointer(current_thread);
|
||||
prim->calc_tight_bounds(min_point, max_point, sq_center_dist,
|
||||
found_any, vertex_data, got_mat, mat,
|
||||
column_name, current_thread);
|
||||
|
|
@ -1345,7 +1347,7 @@ do_calc_sphere_radius(const LPoint3 ¢er, PN_stdfloat &sq_radius,
|
|||
for (pi = cdata->_primitives.begin();
|
||||
pi != cdata->_primitives.end();
|
||||
++pi) {
|
||||
CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
|
||||
CPT(GeomPrimitive) prim = (*pi).get_read_pointer(current_thread);
|
||||
prim->calc_sphere_radius(center, sq_radius, found_any,
|
||||
vertex_data, current_thread);
|
||||
}
|
||||
|
|
@ -1469,8 +1471,10 @@ combine_primitives(GeomPrimitive *a_prim, const GeomPrimitive *b_prim,
|
|||
a_prim->append_unused_vertices(a_vertices, b_vertex);
|
||||
}
|
||||
|
||||
PT(GeomVertexArrayDataHandle) a_handle = a_vertices->modify_handle(current_thread);
|
||||
CPT(GeomVertexArrayDataHandle) b_handle = b_vertices->get_handle(current_thread);
|
||||
PT(GeomVertexArrayDataHandle) a_handle =
|
||||
new GeomVertexArrayDataHandle(move(a_vertices), current_thread);
|
||||
CPT(GeomVertexArrayDataHandle) b_handle =
|
||||
new GeomVertexArrayDataHandle(move(b_vertices), current_thread);
|
||||
|
||||
size_t orig_a_vertices = a_handle->get_num_rows();
|
||||
|
||||
|
|
@ -1683,8 +1687,7 @@ check_valid(const GeomVertexDataPipelineReader *data_reader) const {
|
|||
for (pi = _cdata->_primitives.begin();
|
||||
pi != _cdata->_primitives.end();
|
||||
++pi) {
|
||||
CPT(GeomPrimitive) primitive = (*pi).get_read_pointer();
|
||||
GeomPrimitivePipelineReader reader(primitive, _current_thread);
|
||||
GeomPrimitivePipelineReader reader((*pi).get_read_pointer(_current_thread), _current_thread);
|
||||
reader.check_minmax();
|
||||
if (!reader.check_valid(data_reader)) {
|
||||
return false;
|
||||
|
|
@ -1707,12 +1710,11 @@ draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
|
|||
for (pi = _cdata->_primitives.begin();
|
||||
pi != _cdata->_primitives.end();
|
||||
++pi) {
|
||||
CPT(GeomPrimitive) primitive = (*pi).get_read_pointer();
|
||||
GeomPrimitivePipelineReader reader(primitive, _current_thread);
|
||||
GeomPrimitivePipelineReader reader((*pi).get_read_pointer(_current_thread), _current_thread);
|
||||
if (reader.get_num_vertices() != 0) {
|
||||
reader.check_minmax();
|
||||
nassertr(reader.check_valid(data_reader), false);
|
||||
if (!primitive->draw(gsg, &reader, force)) {
|
||||
if (!reader.draw(gsg, force)) {
|
||||
all_ok = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -401,15 +401,17 @@ private:
|
|||
*/
|
||||
class EXPCL_PANDA_GOBJ GeomPipelineReader : public GeomEnums {
|
||||
public:
|
||||
INLINE GeomPipelineReader(Thread *current_thread);
|
||||
INLINE GeomPipelineReader(const Geom *object, Thread *current_thread);
|
||||
private:
|
||||
INLINE GeomPipelineReader(const GeomPipelineReader ©);
|
||||
INLINE void operator = (const GeomPipelineReader ©);
|
||||
GeomPipelineReader(const GeomPipelineReader ©) DELETED;
|
||||
GeomPipelineReader &operator = (const GeomPipelineReader ©) DELETED_ASSIGN;
|
||||
|
||||
public:
|
||||
INLINE ~GeomPipelineReader();
|
||||
ALLOC_DELETED_CHAIN(GeomPipelineReader);
|
||||
|
||||
INLINE void set_object(const Geom *object);
|
||||
INLINE const Geom *get_object() const;
|
||||
INLINE Thread *get_current_thread() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ PT(GeomCacheEntry) GeomCacheEntry::
|
|||
erase() {
|
||||
nassertr(_next != (GeomCacheEntry *)NULL && _prev != (GeomCacheEntry *)NULL, NULL);
|
||||
|
||||
PT(GeomCacheEntry) keepme = this;
|
||||
unref();
|
||||
PT(GeomCacheEntry) keepme;
|
||||
keepme.cheat() = this;
|
||||
|
||||
if (gobj_cat.is_debug()) {
|
||||
gobj_cat.debug()
|
||||
|
|
|
|||
|
|
@ -235,6 +235,24 @@ get_vertices() const {
|
|||
return cdata->_vertices.get_read_pointer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to get_vertices().get_handle().
|
||||
*/
|
||||
INLINE CPT(GeomVertexArrayDataHandle) GeomPrimitive::
|
||||
get_vertices_handle(Thread *current_thread) const {
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
return new GeomVertexArrayDataHandle(cdata->_vertices.get_read_pointer(current_thread), current_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to modify_vertices().get_handle().
|
||||
*/
|
||||
INLINE PT(GeomVertexArrayDataHandle) GeomPrimitive::
|
||||
modify_vertices_handle(Thread *current_thread) {
|
||||
CDWriter cdata(_cycler, true, current_thread);
|
||||
return new GeomVertexArrayDataHandle(do_modify_vertices(cdata), current_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience function to return the gap between successive index numbers,
|
||||
* in bytes, of the index data.
|
||||
|
|
@ -414,38 +432,32 @@ CData(const GeomPrimitive::CData ©) :
|
|||
*
|
||||
*/
|
||||
INLINE GeomPrimitivePipelineReader::
|
||||
GeomPrimitivePipelineReader(const GeomPrimitive *object,
|
||||
GeomPrimitivePipelineReader(CPT(GeomPrimitive) object,
|
||||
Thread *current_thread) :
|
||||
_object(object),
|
||||
_object(move(object)),
|
||||
_current_thread(current_thread),
|
||||
_cdata(object->_cycler.read_unlocked(current_thread)),
|
||||
_vertices_reader(NULL)
|
||||
#ifndef CPPPARSER
|
||||
_cdata(_object->_cycler.read_unlocked(current_thread)),
|
||||
#endif
|
||||
_vertices_cdata(NULL)
|
||||
{
|
||||
nassertv(_object->test_ref_count_nonzero());
|
||||
#ifdef DO_PIPELINING
|
||||
_cdata->ref();
|
||||
#endif // DO_PIPELINING
|
||||
|
||||
if (!_cdata->_vertices.is_null()) {
|
||||
_vertices_reader = _cdata->_vertices.get_read_pointer()->get_handle();
|
||||
_vertices = _cdata->_vertices.get_read_pointer(current_thread);
|
||||
_vertices_cdata = _vertices->_cycler.read_unlocked(current_thread);
|
||||
#ifdef DO_PIPELINING
|
||||
_vertices_cdata->ref();
|
||||
#endif // DO_PIPELINING
|
||||
// We must grab the lock *after* we have incremented the reference count,
|
||||
// above.
|
||||
_vertices_cdata->_rw_lock.acquire();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't attempt to copy these objects.
|
||||
*/
|
||||
INLINE GeomPrimitivePipelineReader::
|
||||
GeomPrimitivePipelineReader(const GeomPrimitivePipelineReader &) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't attempt to copy these objects.
|
||||
*/
|
||||
INLINE void GeomPrimitivePipelineReader::
|
||||
operator = (const GeomPrimitivePipelineReader &) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -460,8 +472,17 @@ INLINE GeomPrimitivePipelineReader::
|
|||
unref_delete((CycleData *)_cdata);
|
||||
#endif // DO_PIPELINING
|
||||
|
||||
if (_vertices_cdata != nullptr) {
|
||||
// We must release the lock *before* we decrement the reference count,
|
||||
// below.
|
||||
_vertices_cdata->_rw_lock.release();
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
unref_delete((CycleData *)_vertices_cdata);
|
||||
#endif // DO_PIPELINING
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
_vertices_reader = NULL;
|
||||
_object = NULL;
|
||||
_cdata = NULL;
|
||||
#endif // _DEBUG
|
||||
|
|
@ -512,7 +533,7 @@ get_index_type() const {
|
|||
*/
|
||||
INLINE bool GeomPrimitivePipelineReader::
|
||||
is_indexed() const {
|
||||
return (!_cdata->_vertices.is_null());
|
||||
return (!_vertices.is_null());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -523,8 +544,10 @@ get_num_vertices() const {
|
|||
if (_cdata->_num_vertices != -1) {
|
||||
return _cdata->_num_vertices;
|
||||
} else {
|
||||
nassertr(!_cdata->_vertices.is_null(), 0);
|
||||
return _vertices_reader->get_num_rows();
|
||||
nassertr(!_vertices.is_null(), 0);
|
||||
size_t stride = _vertices->_array_format->get_stride();
|
||||
nassertr(stride != 0, 0);
|
||||
return get_data_size_bytes() / stride;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -551,7 +574,7 @@ get_max_vertex() const {
|
|||
*/
|
||||
INLINE int GeomPrimitivePipelineReader::
|
||||
get_data_size_bytes() const {
|
||||
return _vertices_reader->get_data_size_bytes();
|
||||
return _vertices_cdata->_buffer.get_size();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -568,15 +591,7 @@ get_modified() const {
|
|||
INLINE int GeomPrimitivePipelineReader::
|
||||
get_index_stride() const {
|
||||
nassertr(is_indexed(), 0);
|
||||
return _cdata->_vertices.get_read_pointer()->get_array_format()->get_stride();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE const GeomVertexArrayDataHandle *GeomPrimitivePipelineReader::
|
||||
get_vertices_reader() const {
|
||||
return _vertices_reader;
|
||||
return _vertices->_array_format->get_stride();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -584,7 +599,8 @@ get_vertices_reader() const {
|
|||
*/
|
||||
INLINE const unsigned char *GeomPrimitivePipelineReader::
|
||||
get_read_pointer(bool force) const {
|
||||
return _vertices_reader->get_read_pointer(force);
|
||||
((GeomVertexArrayData *)_vertices.p())->mark_used();
|
||||
return _vertices_cdata->_buffer.get_read_pointer(force);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -632,6 +648,14 @@ prepare_now(PreparedGraphicsObjects *prepared_objects,
|
|||
return ((GeomPrimitive *)_object.p())->prepare_now(prepared_objects, gsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the appropriate method on the GSG to draw the primitive.
|
||||
*/
|
||||
INLINE bool GeomPrimitivePipelineReader::
|
||||
draw(GraphicsStateGuardianBase *gsg, bool force) const {
|
||||
return _object->draw(gsg, this, force);
|
||||
}
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const GeomPrimitive &obj) {
|
||||
obj.output(out);
|
||||
|
|
|
|||
|
|
@ -1036,23 +1036,23 @@ get_num_bytes() const {
|
|||
* shortly; try again later.
|
||||
*/
|
||||
bool GeomPrimitive::
|
||||
request_resident() const {
|
||||
CDReader cdata(_cycler);
|
||||
request_resident(Thread *current_thread) const {
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
|
||||
bool resident = true;
|
||||
|
||||
if (!cdata->_vertices.is_null() &&
|
||||
!cdata->_vertices.get_read_pointer()->request_resident()) {
|
||||
!cdata->_vertices.get_read_pointer(current_thread)->request_resident(current_thread)) {
|
||||
resident = false;
|
||||
}
|
||||
|
||||
if (is_composite() && cdata->_got_minmax) {
|
||||
if (!cdata->_mins.is_null() &&
|
||||
!cdata->_mins.get_read_pointer()->request_resident()) {
|
||||
!cdata->_mins.get_read_pointer(current_thread)->request_resident(current_thread)) {
|
||||
resident = false;
|
||||
}
|
||||
if (!cdata->_maxs.is_null() &&
|
||||
!cdata->_maxs.get_read_pointer()->request_resident()) {
|
||||
!cdata->_maxs.get_read_pointer(current_thread)->request_resident(current_thread)) {
|
||||
resident = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -2178,14 +2178,17 @@ check_minmax() const {
|
|||
*/
|
||||
int GeomPrimitivePipelineReader::
|
||||
get_first_vertex() const {
|
||||
if (_cdata->_vertices.is_null()) {
|
||||
if (_vertices.is_null()) {
|
||||
return _cdata->_first_vertex;
|
||||
} else if (_vertices_reader->get_num_rows() == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
GeomVertexReader index(_cdata->_vertices.get_read_pointer(), 0);
|
||||
return index.get_data1i();
|
||||
}
|
||||
|
||||
size_t size = _vertices_cdata->_buffer.get_size();
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GeomVertexReader index(_vertices, 0);
|
||||
return index.get_data1i();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2193,11 +2196,11 @@ get_first_vertex() const {
|
|||
*/
|
||||
int GeomPrimitivePipelineReader::
|
||||
get_vertex(int i) const {
|
||||
if (!_cdata->_vertices.is_null()) {
|
||||
if (!_vertices.is_null()) {
|
||||
// The indexed case.
|
||||
nassertr(i >= 0 && i < _vertices_reader->get_num_rows(), -1);
|
||||
nassertr(i >= 0 && i < get_num_vertices(), -1);
|
||||
|
||||
GeomVertexReader index(_cdata->_vertices.get_read_pointer(), 0);
|
||||
GeomVertexReader index(_vertices, 0);
|
||||
index.set_row_unsafe(i);
|
||||
return index.get_data1i();
|
||||
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ PUBLISHED:
|
|||
MAKE_PROPERTY(data_size_bytes, get_data_size_bytes);
|
||||
MAKE_PROPERTY(modified, get_modified);
|
||||
|
||||
bool request_resident() const;
|
||||
bool request_resident(Thread *current_thread = Thread::get_current_thread()) const;
|
||||
|
||||
INLINE bool check_valid(const GeomVertexData *vertex_data) const;
|
||||
|
||||
|
|
@ -162,7 +162,9 @@ PUBLISHED:
|
|||
*/
|
||||
|
||||
INLINE CPT(GeomVertexArrayData) get_vertices() const;
|
||||
INLINE CPT(GeomVertexArrayDataHandle) get_vertices_handle(Thread *current_thread) const;
|
||||
PT(GeomVertexArrayData) modify_vertices(int num_vertices = -1);
|
||||
INLINE PT(GeomVertexArrayDataHandle) modify_vertices_handle(Thread *current_thread);
|
||||
void set_vertices(const GeomVertexArrayData *vertices, int num_vertices = -1);
|
||||
void set_nonindexed_vertices(int first_vertex, int num_vertices);
|
||||
|
||||
|
|
@ -347,10 +349,10 @@ private:
|
|||
*/
|
||||
class EXPCL_PANDA_GOBJ GeomPrimitivePipelineReader : public GeomEnums {
|
||||
public:
|
||||
INLINE GeomPrimitivePipelineReader(const GeomPrimitive *object, Thread *current_thread);
|
||||
INLINE GeomPrimitivePipelineReader(CPT(GeomPrimitive) object, Thread *current_thread);
|
||||
private:
|
||||
INLINE GeomPrimitivePipelineReader(const GeomPrimitivePipelineReader ©);
|
||||
INLINE void operator = (const GeomPrimitivePipelineReader ©);
|
||||
GeomPrimitivePipelineReader(const GeomPrimitivePipelineReader ©) DELETED;
|
||||
GeomPrimitivePipelineReader &operator = (const GeomPrimitivePipelineReader ©) DELETED_ASSIGN;
|
||||
|
||||
public:
|
||||
INLINE ~GeomPrimitivePipelineReader();
|
||||
|
|
@ -375,7 +377,6 @@ public:
|
|||
INLINE UpdateSeq get_modified() const;
|
||||
bool check_valid(const GeomVertexDataPipelineReader *data_reader) const;
|
||||
INLINE int get_index_stride() const;
|
||||
INLINE const GeomVertexArrayDataHandle *get_vertices_reader() const;
|
||||
INLINE const unsigned char *get_read_pointer(bool force) const;
|
||||
INLINE int get_strip_cut_index() const;
|
||||
INLINE CPTA_int get_ends() const;
|
||||
|
|
@ -384,13 +385,15 @@ public:
|
|||
|
||||
INLINE IndexBufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
|
||||
GraphicsStateGuardianBase *gsg) const;
|
||||
INLINE bool draw(GraphicsStateGuardianBase *gsg, bool force) const;
|
||||
|
||||
private:
|
||||
CPT(GeomPrimitive) _object;
|
||||
Thread *_current_thread;
|
||||
const GeomPrimitive::CData *_cdata;
|
||||
|
||||
CPT(GeomVertexArrayDataHandle) _vertices_reader;
|
||||
CPT(GeomVertexArrayData) _vertices;
|
||||
const GeomVertexArrayData::CData *_vertices_cdata;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
|
|||
|
|
@ -130,9 +130,25 @@ get_modified() const {
|
|||
* back into memory shortly; try again later.
|
||||
*/
|
||||
INLINE bool GeomVertexArrayData::
|
||||
request_resident() const {
|
||||
CPT(GeomVertexArrayDataHandle) handle = get_handle();
|
||||
return handle->request_resident();
|
||||
request_resident(Thread *current_thread) const {
|
||||
const GeomVertexArrayData::CData *cdata = _cycler.read_unlocked(current_thread);
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
cdata->ref();
|
||||
#endif
|
||||
|
||||
cdata->_rw_lock.acquire();
|
||||
|
||||
((GeomVertexArrayData *)this)->mark_used();
|
||||
bool is_resident = (cdata->_buffer.get_read_pointer(false) != nullptr);
|
||||
|
||||
cdata->_rw_lock.release();
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
unref_delete((CycleData *)cdata);
|
||||
#endif
|
||||
|
||||
return is_resident;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -143,9 +159,7 @@ request_resident() const {
|
|||
*/
|
||||
INLINE CPT(GeomVertexArrayDataHandle) GeomVertexArrayData::
|
||||
get_handle(Thread *current_thread) const {
|
||||
const CData *cdata = _cycler.read_unlocked(current_thread);
|
||||
return new GeomVertexArrayDataHandle(this, current_thread,
|
||||
cdata, false);
|
||||
return new GeomVertexArrayDataHandle(this, current_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -156,9 +170,7 @@ get_handle(Thread *current_thread) const {
|
|||
*/
|
||||
INLINE PT(GeomVertexArrayDataHandle) GeomVertexArrayData::
|
||||
modify_handle(Thread *current_thread) {
|
||||
CData *cdata = _cycler.write_upstream(true, current_thread);
|
||||
return new GeomVertexArrayDataHandle(this, current_thread,
|
||||
cdata, true);
|
||||
return new GeomVertexArrayDataHandle(PT(GeomVertexArrayData)(this), current_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -202,6 +214,17 @@ set_lru_size(size_t lru_size) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
INLINE void GeomVertexArrayData::
|
||||
mark_used() {
|
||||
if ((int)get_lru_size() <= vertex_data_small_size) {
|
||||
SimpleLruPage::mark_used_lru(&_small_lru);
|
||||
} else {
|
||||
SimpleLruPage::mark_used_lru(&_independent_lru);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -238,15 +261,40 @@ operator = (const GeomVertexArrayData::CData ©) {
|
|||
*
|
||||
*/
|
||||
INLINE GeomVertexArrayDataHandle::
|
||||
GeomVertexArrayDataHandle(const GeomVertexArrayData *object,
|
||||
Thread *current_thread,
|
||||
const GeomVertexArrayData::CData *cdata,
|
||||
bool writable) :
|
||||
_object((GeomVertexArrayData *)object),
|
||||
GeomVertexArrayDataHandle(CPT(GeomVertexArrayData) object,
|
||||
Thread *current_thread) :
|
||||
_current_thread(current_thread),
|
||||
_cdata((GeomVertexArrayData::CData *)cdata),
|
||||
_writable(writable)
|
||||
_cdata((GeomVertexArrayData::CData *)object->_cycler.read_unlocked(current_thread)),
|
||||
_writable(false)
|
||||
{
|
||||
_object.swap(object);
|
||||
|
||||
#ifdef _DEBUG
|
||||
nassertv(_object->test_ref_count_nonzero());
|
||||
#endif // _DEBUG
|
||||
#ifdef DO_PIPELINING
|
||||
_cdata->ref();
|
||||
#endif // DO_PIPELINING
|
||||
// We must grab the lock *after* we have incremented the reference count,
|
||||
// above.
|
||||
_cdata->_rw_lock.acquire();
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
MemoryUsage::update_type(this, get_class_type());
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE GeomVertexArrayDataHandle::
|
||||
GeomVertexArrayDataHandle(PT(GeomVertexArrayData) object,
|
||||
Thread *current_thread) :
|
||||
_current_thread(current_thread),
|
||||
_cdata(object->_cycler.write_upstream(true, current_thread)),
|
||||
_writable(true)
|
||||
{
|
||||
_object.swap(object);
|
||||
|
||||
#ifdef _DEBUG
|
||||
nassertv(_object->test_ref_count_nonzero());
|
||||
#endif // _DEBUG
|
||||
|
|
@ -265,7 +313,8 @@ GeomVertexArrayDataHandle(const GeomVertexArrayData *object,
|
|||
* Don't attempt to copy these objects.
|
||||
*/
|
||||
INLINE GeomVertexArrayDataHandle::
|
||||
GeomVertexArrayDataHandle(const GeomVertexArrayDataHandle ©) {
|
||||
GeomVertexArrayDataHandle(const GeomVertexArrayDataHandle ©)
|
||||
: _current_thread(copy._current_thread) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
|
|
@ -448,7 +497,7 @@ get_subdata(size_t start, size_t size) const {
|
|||
*/
|
||||
void GeomVertexArrayDataHandle::
|
||||
mark_used() const {
|
||||
_object->set_lru_size(_object->get_lru_size());
|
||||
_object->mark_used();
|
||||
}
|
||||
|
||||
INLINE ostream &
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ PUBLISHED:
|
|||
void output(ostream &out) const;
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
INLINE bool request_resident() const;
|
||||
INLINE bool request_resident(Thread *current_thread = Thread::get_current_thread()) const;
|
||||
|
||||
INLINE CPT(GeomVertexArrayDataHandle) get_handle(Thread *current_thread = Thread::get_current_thread()) const;
|
||||
INLINE PT(GeomVertexArrayDataHandle) modify_handle(Thread *current_thread = Thread::get_current_thread());
|
||||
|
|
@ -124,6 +124,7 @@ public:
|
|||
|
||||
private:
|
||||
INLINE void set_lru_size(size_t lru_size);
|
||||
INLINE void mark_used();
|
||||
|
||||
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
|
||||
void reverse_data_endianness(unsigned char *dest,
|
||||
|
|
@ -230,6 +231,7 @@ private:
|
|||
friend class GeomVertexData;
|
||||
friend class PreparedGraphicsObjects;
|
||||
friend class GeomVertexArrayDataHandle;
|
||||
friend class GeomPrimitivePipelineReader;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -246,10 +248,10 @@ private:
|
|||
*/
|
||||
class EXPCL_PANDA_GOBJ GeomVertexArrayDataHandle : public ReferenceCount, public GeomEnums {
|
||||
private:
|
||||
INLINE GeomVertexArrayDataHandle(const GeomVertexArrayData *object,
|
||||
Thread *current_thread,
|
||||
const GeomVertexArrayData::CData *_cdata,
|
||||
bool writable);
|
||||
INLINE GeomVertexArrayDataHandle(CPT(GeomVertexArrayData) object,
|
||||
Thread *current_thread);
|
||||
INLINE GeomVertexArrayDataHandle(PT(GeomVertexArrayData) object,
|
||||
Thread *current_thread);
|
||||
INLINE GeomVertexArrayDataHandle(const GeomVertexArrayDataHandle &);
|
||||
INLINE void operator = (const GeomVertexArrayDataHandle &);
|
||||
|
||||
|
|
@ -261,8 +263,8 @@ public:
|
|||
|
||||
INLINE Thread *get_current_thread() const;
|
||||
|
||||
INLINE const unsigned char *get_read_pointer(bool force) const;
|
||||
unsigned char *get_write_pointer();
|
||||
INLINE const unsigned char *get_read_pointer(bool force) const RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||
unsigned char *get_write_pointer() RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE const GeomVertexArrayData *get_object() const;
|
||||
|
|
@ -316,7 +318,7 @@ PUBLISHED:
|
|||
|
||||
private:
|
||||
PT(GeomVertexArrayData) _object;
|
||||
Thread *_current_thread;
|
||||
Thread *const _current_thread;
|
||||
GeomVertexArrayData::CData *_cdata;
|
||||
bool _writable;
|
||||
|
||||
|
|
@ -333,6 +335,11 @@ public:
|
|||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class Geom;
|
||||
friend class GeomPrimitive;
|
||||
friend class GeomVertexData;
|
||||
friend class GeomVertexDataPipelineReader;
|
||||
friend class GeomVertexDataPipelineWriter;
|
||||
friend class GeomVertexArrayData;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -147,6 +147,17 @@ get_array(int i) const {
|
|||
return cdata->_arrays[i].get_read_pointer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to get_array(i).get_handle().
|
||||
*/
|
||||
INLINE CPT(GeomVertexArrayDataHandle) GeomVertexData::
|
||||
get_array_handle(int i) const {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
CDReader cdata(_cycler, current_thread);
|
||||
nassertr(i >= 0 && i < (int)cdata->_arrays.size(), NULL);
|
||||
return new GeomVertexArrayDataHandle(cdata->_arrays[i].get_read_pointer(), current_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a modifiable pointer to the indicated vertex array, so that
|
||||
* application code may directly manipulate the data. You should avoid
|
||||
|
|
@ -162,6 +173,16 @@ modify_array(int i) {
|
|||
return writer.modify_array(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to modify_array(i).modify_handle().
|
||||
*/
|
||||
INLINE PT(GeomVertexArrayDataHandle) GeomVertexData::
|
||||
modify_array_handle(int i) {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
GeomVertexDataPipelineWriter writer(this, true, current_thread);
|
||||
return new GeomVertexArrayDataHandle(writer.modify_array(i), current_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the indicated vertex data array with a completely new array. You
|
||||
* should be careful that the new array has the same length and format as the
|
||||
|
|
@ -575,6 +596,17 @@ CData(const GeomVertexData::CData ©) :
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE GeomVertexDataPipelineBase::
|
||||
GeomVertexDataPipelineBase(Thread *current_thread) :
|
||||
_object(nullptr),
|
||||
_current_thread(current_thread),
|
||||
_cdata(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -600,11 +632,15 @@ GeomVertexDataPipelineBase(GeomVertexData *object,
|
|||
INLINE GeomVertexDataPipelineBase::
|
||||
~GeomVertexDataPipelineBase() {
|
||||
#ifdef _DEBUG
|
||||
nassertv(_object->test_ref_count_nonzero());
|
||||
if (_object != nullptr) {
|
||||
nassertv(_object->test_ref_count_nonzero());
|
||||
}
|
||||
#endif // _DEBUG
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
unref_delete((CycleData *)_cdata);
|
||||
if (_cdata != nullptr) {
|
||||
unref_delete((CycleData *)_cdata);
|
||||
}
|
||||
#endif // DO_PIPELINING
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
|
@ -694,6 +730,16 @@ get_modified() const {
|
|||
return _cdata->_modified;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE GeomVertexDataPipelineReader::
|
||||
GeomVertexDataPipelineReader(Thread *current_thread) :
|
||||
GeomVertexDataPipelineBase(current_thread),
|
||||
_got_array_readers(false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -706,33 +752,23 @@ GeomVertexDataPipelineReader(const GeomVertexData *object,
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't attempt to copy these objects.
|
||||
*/
|
||||
INLINE GeomVertexDataPipelineReader::
|
||||
GeomVertexDataPipelineReader(const GeomVertexDataPipelineReader ©) :
|
||||
GeomVertexDataPipelineBase(copy)
|
||||
{
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't attempt to copy these objects.
|
||||
*/
|
||||
INLINE void GeomVertexDataPipelineReader::
|
||||
operator = (const GeomVertexDataPipelineReader &) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE GeomVertexDataPipelineReader::
|
||||
~GeomVertexDataPipelineReader() {
|
||||
if (_got_array_readers) {
|
||||
delete_array_readers();
|
||||
INLINE void GeomVertexDataPipelineReader::
|
||||
set_object(CPT(GeomVertexData) object) {
|
||||
#ifdef DO_PIPELINING
|
||||
if (_cdata != NULL) {
|
||||
unref_delete((CycleData *)_cdata);
|
||||
}
|
||||
// _object->_cycler.release_read(_cdata);
|
||||
#endif // DO_PIPELINING
|
||||
_array_readers.clear();
|
||||
|
||||
_object.swap(object);
|
||||
_cdata = (GeomVertexData::CData *)_object->_cycler.read_unlocked(_current_thread);
|
||||
_got_array_readers = false;
|
||||
|
||||
_cdata->ref();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -819,24 +855,6 @@ GeomVertexDataPipelineWriter(GeomVertexData *object, bool force_to_0,
|
|||
#endif // _DEBUG
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't attempt to copy these objects.
|
||||
*/
|
||||
INLINE GeomVertexDataPipelineWriter::
|
||||
GeomVertexDataPipelineWriter(const GeomVertexDataPipelineWriter ©) :
|
||||
GeomVertexDataPipelineBase(copy)
|
||||
{
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't attempt to copy these objects.
|
||||
*/
|
||||
INLINE void GeomVertexDataPipelineWriter::
|
||||
operator = (const GeomVertexDataPipelineWriter &) {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -516,9 +516,7 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
|
|||
if (keep_data_objects) {
|
||||
// Copy the data, but keep the same GeomVertexArrayData object.
|
||||
|
||||
PT(GeomVertexArrayData) dest_data = modify_array(dest_i);
|
||||
CPT(GeomVertexArrayData) source_data = source->get_array(source_i);
|
||||
dest_data->modify_handle()->copy_data_from(source_data->get_handle());
|
||||
modify_array_handle(dest_i)->copy_data_from(source->get_array_handle(source_i));
|
||||
} else {
|
||||
// Copy the GeomVertexArrayData object.
|
||||
if (get_array(dest_i) != source->get_array(source_i)) {
|
||||
|
|
@ -533,13 +531,16 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
|
|||
}
|
||||
|
||||
// Now make sure the arrays we didn't share are all filled in.
|
||||
reserve_num_rows(num_rows);
|
||||
set_num_rows(num_rows);
|
||||
{
|
||||
GeomVertexDataPipelineWriter writer(this, true, Thread::get_current_thread());
|
||||
writer.check_array_writers();
|
||||
writer.reserve_num_rows(num_rows);
|
||||
writer.set_num_rows(num_rows);
|
||||
}
|
||||
|
||||
// Now go back through and copy any data that's left over.
|
||||
for (source_i = 0; source_i < num_arrays; ++source_i) {
|
||||
CPT(GeomVertexArrayData) array_obj = source->get_array(source_i);
|
||||
CPT(GeomVertexArrayDataHandle) array_handle = array_obj->get_handle();
|
||||
CPT(GeomVertexArrayDataHandle) array_handle = source->get_array_handle(source_i);
|
||||
const unsigned char *array_data = array_handle->get_read_pointer(true);
|
||||
const GeomVertexArrayFormat *source_array_format = source_format->get_array(source_i);
|
||||
int num_columns = source_array_format->get_num_columns();
|
||||
|
|
@ -557,8 +558,7 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
|
|||
|
||||
if (dest_column->is_bytewise_equivalent(*source_column)) {
|
||||
// We can do a quick bytewise copy.
|
||||
PT(GeomVertexArrayData) dest_array_obj = modify_array(dest_i);
|
||||
PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle();
|
||||
PT(GeomVertexArrayDataHandle) dest_handle = modify_array_handle(dest_i);
|
||||
unsigned char *dest_array_data = dest_handle->get_write_pointer();
|
||||
|
||||
bytewise_copy(dest_array_data + dest_column->get_start(),
|
||||
|
|
@ -569,8 +569,7 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
|
|||
} else if (dest_column->is_packed_argb() &&
|
||||
source_column->is_uint8_rgba()) {
|
||||
// A common special case: OpenGL color to DirectX color.
|
||||
PT(GeomVertexArrayData) dest_array_obj = modify_array(dest_i);
|
||||
PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle();
|
||||
PT(GeomVertexArrayDataHandle) dest_handle = modify_array_handle(dest_i);
|
||||
unsigned char *dest_array_data = dest_handle->get_write_pointer();
|
||||
|
||||
uint8_rgba_to_packed_argb
|
||||
|
|
@ -582,8 +581,7 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
|
|||
} else if (dest_column->is_uint8_rgba() &&
|
||||
source_column->is_packed_argb()) {
|
||||
// Another common special case: DirectX color to OpenGL color.
|
||||
PT(GeomVertexArrayData) dest_array_obj = modify_array(dest_i);
|
||||
PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle();
|
||||
PT(GeomVertexArrayDataHandle) dest_handle = modify_array_handle(dest_i);
|
||||
unsigned char *dest_array_data = dest_handle->get_write_pointer();
|
||||
|
||||
packed_argb_to_uint8_rgba
|
||||
|
|
@ -700,12 +698,10 @@ copy_row_from(int dest_row, const GeomVertexData *source,
|
|||
int num_arrays = source_format->get_num_arrays();
|
||||
|
||||
for (int i = 0; i < num_arrays; ++i) {
|
||||
PT(GeomVertexArrayData) dest_array_obj = modify_array(i);
|
||||
PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle();
|
||||
PT(GeomVertexArrayDataHandle) dest_handle = modify_array_handle(i);
|
||||
unsigned char *dest_array_data = dest_handle->get_write_pointer();
|
||||
|
||||
CPT(GeomVertexArrayData) source_array_obj = source->get_array(i);
|
||||
CPT(GeomVertexArrayDataHandle) source_array_handle = source_array_obj->get_handle();
|
||||
CPT(GeomVertexArrayDataHandle) source_array_handle = source->get_array_handle(i);
|
||||
const unsigned char *source_array_data = source_array_handle->get_read_pointer(true);
|
||||
|
||||
const GeomVertexArrayFormat *array_format = source_format->get_array(i);
|
||||
|
|
@ -1144,8 +1140,7 @@ do_set_color(GeomVertexData *vdata, const LColor &color) {
|
|||
packer->set_data4f(buffer, color);
|
||||
#endif
|
||||
|
||||
PT(GeomVertexArrayDataHandle) handle =
|
||||
vdata->modify_array(array_index)->modify_handle();
|
||||
PT(GeomVertexArrayDataHandle) handle = vdata->modify_array_handle(array_index);
|
||||
unsigned char *write_ptr = handle->get_write_pointer();
|
||||
unsigned char *end_ptr = write_ptr + handle->get_data_size_bytes();
|
||||
write_ptr += column->get_start();
|
||||
|
|
@ -1586,7 +1581,7 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
|
|||
}
|
||||
|
||||
// Then apply the transforms.
|
||||
CPT(TransformBlendTable) tb_table = cdata->_transform_blend_table.get_read_pointer();
|
||||
CPT(TransformBlendTable) tb_table = cdata->_transform_blend_table.get_read_pointer(current_thread);
|
||||
if (tb_table != (TransformBlendTable *)NULL) {
|
||||
// Recompute all the blends up front, so we don't have to test each one
|
||||
// for staleness at each vertex.
|
||||
|
|
@ -1617,7 +1612,8 @@ update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
|
|||
if (blend_array_format->get_stride() == 2 &&
|
||||
blend_array_format->get_column(0)->get_component_bytes() == 2) {
|
||||
// The blend indices are a table of ushorts. Optimize this common case.
|
||||
CPT(GeomVertexArrayDataHandle) blend_array_handle = cdata->_arrays[blend_array_index].get_read_pointer()->get_handle(current_thread);
|
||||
CPT(GeomVertexArrayDataHandle) blend_array_handle =
|
||||
new GeomVertexArrayDataHandle(cdata->_arrays[blend_array_index].get_read_pointer(current_thread), current_thread);
|
||||
const unsigned short *blendt = (const unsigned short *)blend_array_handle->get_read_pointer(true);
|
||||
|
||||
size_t ci;
|
||||
|
|
@ -2399,24 +2395,12 @@ make_array_readers() {
|
|||
_array_readers.reserve(_cdata->_arrays.size());
|
||||
GeomVertexData::Arrays::const_iterator ai;
|
||||
for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
|
||||
CPT(GeomVertexArrayData) array_obj = (*ai).get_read_pointer();
|
||||
_array_readers.push_back(array_obj->get_handle(_current_thread));
|
||||
_array_readers.push_back(new GeomVertexArrayDataHandle((*ai).get_read_pointer(_current_thread), _current_thread));
|
||||
}
|
||||
|
||||
_got_array_readers = true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void GeomVertexDataPipelineReader::
|
||||
delete_array_readers() {
|
||||
nassertv(_got_array_readers);
|
||||
|
||||
_array_readers.clear();
|
||||
_got_array_readers = false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -2610,7 +2594,7 @@ set_array(int i, const GeomVertexArrayData *array) {
|
|||
_cdata->_animated_vertices_modified = UpdateSeq();
|
||||
|
||||
if (_got_array_writers) {
|
||||
_array_writers[i] = _cdata->_arrays[i].get_write_pointer()->modify_handle(_current_thread);
|
||||
_array_writers[i] = new GeomVertexArrayDataHandle(_cdata->_arrays[i].get_write_pointer(), _current_thread);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2624,8 +2608,7 @@ make_array_writers() {
|
|||
_array_writers.reserve(_cdata->_arrays.size());
|
||||
GeomVertexData::Arrays::iterator ai;
|
||||
for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
|
||||
PT(GeomVertexArrayData) array_obj = (*ai).get_write_pointer();
|
||||
_array_writers.push_back(array_obj->modify_handle(_current_thread));
|
||||
_array_writers.push_back(new GeomVertexArrayDataHandle((*ai).get_write_pointer(), _current_thread));
|
||||
}
|
||||
|
||||
_object->clear_cache_stage();
|
||||
|
|
|
|||
|
|
@ -107,8 +107,10 @@ PUBLISHED:
|
|||
|
||||
INLINE int get_num_arrays() const;
|
||||
INLINE CPT(GeomVertexArrayData) get_array(int i) const;
|
||||
INLINE CPT(GeomVertexArrayDataHandle) get_array_handle(int i) const;
|
||||
MAKE_SEQ(get_arrays, get_num_arrays, get_array);
|
||||
INLINE PT(GeomVertexArrayData) modify_array(int i);
|
||||
INLINE PT(GeomVertexArrayDataHandle) modify_array_handle(int i);
|
||||
INLINE void set_array(int i, const GeomVertexArrayData *array);
|
||||
MAKE_SEQ_PROPERTY(arrays, get_num_arrays, get_array, set_array);
|
||||
|
||||
|
|
@ -402,10 +404,15 @@ private:
|
|||
*/
|
||||
class EXPCL_PANDA_GOBJ GeomVertexDataPipelineBase : public GeomEnums {
|
||||
protected:
|
||||
INLINE GeomVertexDataPipelineBase(Thread *current_thread);
|
||||
INLINE GeomVertexDataPipelineBase(GeomVertexData *object,
|
||||
Thread *current_thread,
|
||||
GeomVertexData::CData *cdata);
|
||||
|
||||
private:
|
||||
GeomVertexDataPipelineBase(const GeomVertexDataPipelineBase ©) DELETED;
|
||||
GeomVertexDataPipelineBase &operator = (const GeomVertexDataPipelineBase ©) DELETED_ASSIGN;
|
||||
|
||||
public:
|
||||
INLINE ~GeomVertexDataPipelineBase();
|
||||
|
||||
|
|
@ -436,15 +443,12 @@ protected:
|
|||
*/
|
||||
class EXPCL_PANDA_GOBJ GeomVertexDataPipelineReader : public GeomVertexDataPipelineBase {
|
||||
public:
|
||||
INLINE GeomVertexDataPipelineReader(Thread *current_thread);
|
||||
INLINE GeomVertexDataPipelineReader(const GeomVertexData *object, Thread *current_thread);
|
||||
private:
|
||||
INLINE GeomVertexDataPipelineReader(const GeomVertexDataPipelineReader ©);
|
||||
INLINE void operator = (const GeomVertexDataPipelineReader ©);
|
||||
|
||||
public:
|
||||
INLINE ~GeomVertexDataPipelineReader();
|
||||
ALLOC_DELETED_CHAIN(GeomVertexDataPipelineReader);
|
||||
|
||||
INLINE void set_object(CPT(GeomVertexData) object);
|
||||
INLINE const GeomVertexData *get_object() const;
|
||||
|
||||
INLINE void check_array_readers() const;
|
||||
|
|
@ -480,7 +484,6 @@ public:
|
|||
|
||||
private:
|
||||
void make_array_readers();
|
||||
void delete_array_readers();
|
||||
|
||||
bool _got_array_readers;
|
||||
typedef pvector<CPT(GeomVertexArrayDataHandle) > ArrayReaders;
|
||||
|
|
@ -506,11 +509,7 @@ class EXPCL_PANDA_GOBJ GeomVertexDataPipelineWriter : public GeomVertexDataPipel
|
|||
public:
|
||||
INLINE GeomVertexDataPipelineWriter(GeomVertexData *object, bool force_to_0,
|
||||
Thread *current_thread);
|
||||
private:
|
||||
INLINE GeomVertexDataPipelineWriter(const GeomVertexDataPipelineWriter ©);
|
||||
INLINE void operator = (const GeomVertexDataPipelineWriter ©);
|
||||
|
||||
public:
|
||||
INLINE ~GeomVertexDataPipelineWriter();
|
||||
ALLOC_DELETED_CHAIN(GeomVertexDataPipelineWriter);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#include "geomVertexWriter.h"
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
#ifdef _DEBUG
|
||||
// This is defined just for the benefit of having something non-NULL to
|
||||
// return from a nassertr() call.
|
||||
unsigned char GeomVertexWriter::empty_buffer[100] = { 0 };
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ private:
|
|||
|
||||
int _start_row;
|
||||
|
||||
#ifndef NDEBUG
|
||||
#ifdef _DEBUG
|
||||
// This is defined just for the benefit of having something non-NULL to
|
||||
// return from a nassertr() call.
|
||||
static unsigned char empty_buffer[100];
|
||||
|
|
|
|||
|
|
@ -27,15 +27,13 @@ operator = (const VertexDataBuffer ©) {
|
|||
|
||||
if (_resident_data != (unsigned char *)NULL) {
|
||||
nassertv(_reserved_size != 0);
|
||||
get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_reserved_size);
|
||||
PANDA_FREE_ARRAY(_resident_data);
|
||||
get_class_type().deallocate_array(_resident_data);
|
||||
_resident_data = NULL;
|
||||
}
|
||||
if (copy._resident_data != (unsigned char *)NULL && copy._size != 0) {
|
||||
// We only allocate _size bytes, not the full _reserved_size allocated by
|
||||
// the original copy.
|
||||
get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)copy._size);
|
||||
_resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(copy._size);
|
||||
_resident_data = (unsigned char *)get_class_type().allocate_array(copy._size);
|
||||
memcpy(_resident_data, copy._resident_data, copy._size);
|
||||
}
|
||||
_size = copy._size;
|
||||
|
|
@ -55,17 +53,16 @@ swap(VertexDataBuffer &other) {
|
|||
unsigned char *resident_data = _resident_data;
|
||||
size_t size = _size;
|
||||
size_t reserved_size = _reserved_size;
|
||||
PT(VertexDataBlock) block = _block;
|
||||
|
||||
_block.swap(other._block);
|
||||
|
||||
_resident_data = other._resident_data;
|
||||
_size = other._size;
|
||||
_reserved_size = other._reserved_size;
|
||||
_block = other._block;
|
||||
|
||||
other._resident_data = resident_data;
|
||||
other._size = size;
|
||||
other._reserved_size = reserved_size;
|
||||
other._block = block;
|
||||
nassertv(_reserved_size >= _size);
|
||||
}
|
||||
|
||||
|
|
@ -94,13 +91,12 @@ do_clean_realloc(size_t reserved_size) {
|
|||
do_page_in();
|
||||
}
|
||||
|
||||
get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)reserved_size - (int)_reserved_size);
|
||||
if (_reserved_size == 0) {
|
||||
nassertv(_resident_data == (unsigned char *)NULL);
|
||||
_resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(reserved_size);
|
||||
_resident_data = (unsigned char *)get_class_type().allocate_array(reserved_size);
|
||||
} else {
|
||||
nassertv(_resident_data != (unsigned char *)NULL);
|
||||
_resident_data = (unsigned char *)PANDA_REALLOC_ARRAY(_resident_data, reserved_size);
|
||||
_resident_data = (unsigned char *)get_class_type().reallocate_array(_resident_data, reserved_size);
|
||||
}
|
||||
nassertv(_resident_data != (unsigned char *)NULL);
|
||||
_reserved_size = reserved_size;
|
||||
|
|
@ -129,16 +125,14 @@ do_unclean_realloc(size_t reserved_size) {
|
|||
if (_resident_data != (unsigned char *)NULL) {
|
||||
nassertv(_reserved_size != 0);
|
||||
|
||||
get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_reserved_size);
|
||||
PANDA_FREE_ARRAY(_resident_data);
|
||||
get_class_type().deallocate_array(_resident_data);
|
||||
_resident_data = NULL;
|
||||
_reserved_size = 0;
|
||||
}
|
||||
|
||||
if (reserved_size != 0) {
|
||||
get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)reserved_size);
|
||||
nassertv(_resident_data == (unsigned char *)NULL);
|
||||
_resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(reserved_size);
|
||||
_resident_data = (unsigned char *)get_class_type().allocate_array(reserved_size);
|
||||
}
|
||||
|
||||
_reserved_size = reserved_size;
|
||||
|
|
@ -166,8 +160,7 @@ do_page_out(VertexDataBook &book) {
|
|||
if (_size == 0) {
|
||||
// It's an empty buffer. Just deallocate it; don't bother to create a
|
||||
// block.
|
||||
get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_reserved_size);
|
||||
PANDA_FREE_ARRAY(_resident_data);
|
||||
get_class_type().deallocate_array(_resident_data);
|
||||
_resident_data = NULL;
|
||||
_reserved_size = 0;
|
||||
|
||||
|
|
@ -180,8 +173,7 @@ do_page_out(VertexDataBook &book) {
|
|||
nassertv(pointer != (unsigned char *)NULL);
|
||||
memcpy(pointer, _resident_data, _size);
|
||||
|
||||
get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_reserved_size);
|
||||
PANDA_FREE_ARRAY(_resident_data);
|
||||
get_class_type().deallocate_array(_resident_data);
|
||||
_resident_data = NULL;
|
||||
|
||||
_reserved_size = _size;
|
||||
|
|
@ -205,8 +197,7 @@ do_page_in() {
|
|||
nassertv(_block != (VertexDataBlock *)NULL);
|
||||
nassertv(_reserved_size == _size);
|
||||
|
||||
get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)_size);
|
||||
_resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(_size);
|
||||
_resident_data = (unsigned char *)get_class_type().allocate_array(_size);
|
||||
nassertv(_resident_data != (unsigned char *)NULL);
|
||||
|
||||
memcpy(_resident_data, _block->get_pointer(true), _size);
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ public:
|
|||
void operator = (const VertexDataBuffer ©);
|
||||
INLINE ~VertexDataBuffer();
|
||||
|
||||
INLINE const unsigned char *get_read_pointer(bool force) const;
|
||||
INLINE unsigned char *get_write_pointer();
|
||||
INLINE const unsigned char *get_read_pointer(bool force) const RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||
INLINE unsigned char *get_write_pointer() RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||
|
||||
INLINE size_t get_size() const;
|
||||
INLINE size_t get_reserved_size() const;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
TypeHandle MeshDrawer::_type_handle;
|
||||
|
||||
PN_stdfloat randFloat() {
|
||||
return ((PN_stdfloat) rand() / (PN_stdfloat) 0x7fffffff);
|
||||
return ((PN_stdfloat)rand() / (PN_stdfloat)RAND_MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -42,39 +42,43 @@ PN_stdfloat randFloat() {
|
|||
void MeshDrawer::generator(int budget) {
|
||||
// create enough triangles for budget:
|
||||
_vdata = new GeomVertexData(_root.get_name(), GeomVertexFormat::get_v3n3c4t2(), Geom::UH_static);//UH_dynamic);
|
||||
GeomVertexWriter *tvertex = new GeomVertexWriter(_vdata, "vertex");
|
||||
GeomVertexWriter *tnormal = new GeomVertexWriter(_vdata, "normal");
|
||||
GeomVertexWriter *tuv = new GeomVertexWriter(_vdata, "texcoord");
|
||||
GeomVertexWriter *tcolor = new GeomVertexWriter(_vdata, "color");
|
||||
_prim = new GeomTriangles(Geom::UH_static);
|
||||
_vdata->unclean_set_num_rows(budget * 3);
|
||||
|
||||
// iterate and fill _up a geom with random data so that it will not be
|
||||
// optimized out by panda3d system
|
||||
for(int i = 0; i < budget; i++) {
|
||||
for( int vert = 0; vert < 3; vert++) {
|
||||
LVector3 vec3 = LVector3(randFloat()+1000,randFloat(),randFloat())*.001;
|
||||
LVector4 vec4 = LVector4(1,1,1,randFloat());
|
||||
LVector2 vec2 = LVector2(0,randFloat());
|
||||
tvertex->add_data3(vec3);
|
||||
tcolor->add_data4(vec4);
|
||||
tuv->add_data2(vec2);
|
||||
tnormal->add_data3(vec3);
|
||||
{
|
||||
GeomVertexWriter tvertex(_vdata, "vertex");
|
||||
GeomVertexWriter tnormal(_vdata, "normal");
|
||||
GeomVertexWriter tuv(_vdata, "texcoord");
|
||||
GeomVertexWriter tcolor(_vdata, "color");
|
||||
|
||||
// iterate and fill _up a geom with random data so that it will not be
|
||||
// optimized out by panda3d system
|
||||
for (int i = 0; i < budget; i++) {
|
||||
for (int vert = 0; vert < 3; vert++) {
|
||||
LVector3 vec3 = LVector3(randFloat()+1000,randFloat(),randFloat())*.001;
|
||||
LVector4 vec4 = LVector4(1,1,1,randFloat());
|
||||
LVector2 vec2 = LVector2(0,randFloat());
|
||||
tvertex.set_data3(vec3);
|
||||
tcolor.set_data4(vec4);
|
||||
tuv.set_data2(vec2);
|
||||
tnormal.set_data3(vec3);
|
||||
}
|
||||
}
|
||||
_prim->add_vertices(i * 3, i * 3 + 1, i * 3 + 2);
|
||||
}
|
||||
|
||||
// create our node and attach it to this node path
|
||||
_prim = new GeomTriangles(Geom::UH_static);
|
||||
_prim->add_next_vertices(budget * 3);
|
||||
_prim->close_primitive();
|
||||
_geom = new Geom(_vdata);
|
||||
_geom->add_primitive(_prim);
|
||||
_geomnode = new GeomNode("__MeshDrawer_GeomNode");
|
||||
if (_geomnode == NULL) {
|
||||
_geomnode = new GeomNode("__MeshDrawer_GeomNode");
|
||||
_root.attach_new_node(_geomnode);
|
||||
} else {
|
||||
_geomnode->remove_all_geoms();
|
||||
}
|
||||
_geomnode->add_geom(_geom);
|
||||
_root.attach_new_node(_geomnode);
|
||||
_last_clear_index = budget;
|
||||
|
||||
delete tvertex;
|
||||
delete tnormal;
|
||||
delete tuv;
|
||||
delete tcolor;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -451,8 +455,9 @@ link_segment(const LVector3 &pos, const LVector4 &frame,
|
|||
LVector3 cam_stop3d = _camera.get_relative_point(_render, stop);
|
||||
LPoint2 cam_stop2d = LVector2();
|
||||
|
||||
PT(Camera) camera = DCAST(Camera, _camera.node());
|
||||
PT(Lens) lens = camera->get_lens();
|
||||
const Camera *camera;
|
||||
DCAST_INTO_V(camera, _camera.node());
|
||||
const Lens *lens = camera->get_lens();
|
||||
|
||||
lens->project(cam_start3d, cam_start2d);
|
||||
lens->project(cam_stop3d, cam_stop2d);
|
||||
|
|
|
|||
|
|
@ -528,7 +528,7 @@ void ShaderTerrainMesh::add_for_draw(CullTraverser *trav, CullTraverserData &dat
|
|||
state = state->set_attrib(current_shader_attrib, 10000);
|
||||
|
||||
// Emit chunk
|
||||
CullableObject *object = new CullableObject(_chunk_geom, state, modelview_transform);
|
||||
CullableObject *object = new CullableObject(_chunk_geom, move(state), move(modelview_transform));
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
|
||||
// After rendering, increment the view index
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ private:
|
|||
#endif // HAVE_EIGEN
|
||||
|
||||
// This is as good a place as any to define this alignment macro.
|
||||
#if defined(LINMATH_ALIGN) && defined(HAVE_EIGEN) && defined(__AVX__)
|
||||
#if defined(LINMATH_ALIGN) && defined(HAVE_EIGEN) && defined(__AVX__) && defined(STDFLOAT_DOUBLE)
|
||||
#define ALIGN_LINMATH ALIGN_32BYTE
|
||||
#elif defined(LINMATH_ALIGN)
|
||||
#define ALIGN_LINMATH ALIGN_16BYTE
|
||||
|
|
|
|||
|
|
@ -163,7 +163,9 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
register_type(_type_handle, "HermiteCurve");
|
||||
PiecewiseCurve::init_type();
|
||||
register_type(_type_handle, "HermiteCurve",
|
||||
PiecewiseCurve::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ apply_transform_and_state(CullTraverser *trav,
|
|||
if (clip_plane_cull) {
|
||||
_cull_planes = _cull_planes->apply_state(trav, this,
|
||||
(const ClipPlaneAttrib *)node_state->get_attrib(ClipPlaneAttrib::get_class_slot()),
|
||||
DCAST(ClipPlaneAttrib, off_clip_planes),
|
||||
(const ClipPlaneAttrib *)off_clip_planes,
|
||||
(const OccluderEffect *)node_effects->get_effect(OccluderEffect::get_class_type()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@ CullableObject() {
|
|||
* render state and transform.
|
||||
*/
|
||||
INLINE CullableObject::
|
||||
CullableObject(const Geom *geom, const RenderState *state,
|
||||
const TransformState *internal_transform) :
|
||||
_geom(geom),
|
||||
_state(state),
|
||||
_internal_transform(internal_transform)
|
||||
CullableObject(CPT(Geom) geom, CPT(RenderState) state,
|
||||
CPT(TransformState) internal_transform) :
|
||||
_geom(move(geom)),
|
||||
_state(move(state)),
|
||||
_internal_transform(move(internal_transform))
|
||||
{
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
MemoryUsage::update_type(this, get_class_type());
|
||||
|
|
@ -135,6 +135,21 @@ draw_inline(GraphicsStateGuardianBase *gsg, bool force, Thread *current_thread)
|
|||
_geom->draw(gsg, _munger, _munged_data, force, current_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the draw callback, assuming one is set. Crashes if not.
|
||||
*/
|
||||
INLINE void CullableObject::
|
||||
draw_callback(GraphicsStateGuardianBase *gsg, bool force, Thread *current_thread) {
|
||||
gsg->clear_before_callback();
|
||||
gsg->set_state_and_transform(_state, _internal_transform);
|
||||
GeomDrawCallbackData cbdata(this, gsg, force);
|
||||
_draw_callback->do_callback(&cbdata);
|
||||
if (cbdata.get_lost_state()) {
|
||||
// Tell the GSG to forget its state.
|
||||
gsg->clear_state_and_transform();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ class EXPCL_PANDA_PGRAPH CullableObject
|
|||
{
|
||||
public:
|
||||
INLINE CullableObject();
|
||||
INLINE CullableObject(const Geom *geom, const RenderState *state,
|
||||
const TransformState *internal_transform);
|
||||
INLINE CullableObject(CPT(Geom) geom, CPT(RenderState) state,
|
||||
CPT(TransformState) internal_transform);
|
||||
|
||||
INLINE CullableObject(const CullableObject ©);
|
||||
INLINE void operator = (const CullableObject ©);
|
||||
|
|
@ -63,6 +63,11 @@ public:
|
|||
|
||||
INLINE void set_draw_callback(CallbackObject *draw_callback);
|
||||
|
||||
INLINE void draw_inline(GraphicsStateGuardianBase *gsg,
|
||||
bool force, Thread *current_thread);
|
||||
INLINE void draw_callback(GraphicsStateGuardianBase *gsg,
|
||||
bool force, Thread *current_thread);
|
||||
|
||||
public:
|
||||
ALLOC_DELETED_CHAIN(CullableObject);
|
||||
|
||||
|
|
@ -82,9 +87,6 @@ private:
|
|||
static CPT(RenderState) get_flash_cpu_state();
|
||||
static CPT(RenderState) get_flash_hardware_state();
|
||||
|
||||
INLINE void draw_inline(GraphicsStateGuardianBase *gsg,
|
||||
bool force, Thread *current_thread);
|
||||
|
||||
private:
|
||||
// This class is used internally by munge_points_to_quads().
|
||||
class PointData {
|
||||
|
|
|
|||
|
|
@ -515,7 +515,7 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
|||
CPT(TransformState) internal_transform = data.get_internal_transform(trav);
|
||||
|
||||
for (int i = 0; i < num_geoms; i++) {
|
||||
const Geom *geom = geoms.get_geom(i);
|
||||
CPT(Geom) geom = geoms.get_geom(i);
|
||||
if (geom->is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -558,7 +558,7 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
|||
}
|
||||
|
||||
CullableObject *object =
|
||||
new CullableObject(geom, state, internal_transform);
|
||||
new CullableObject(move(geom), move(state), internal_transform);
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1243,16 +1243,14 @@ apply_collect_changes() {
|
|||
void GeomTransformer::NewCollectedData::
|
||||
append_vdata(const GeomVertexData *vdata, int vertex_offset) {
|
||||
for (int i = 0; i < vdata->get_num_arrays(); ++i) {
|
||||
PT(GeomVertexArrayData) new_array = _new_data->modify_array(i);
|
||||
CPT(GeomVertexArrayData) old_array = vdata->get_array(i);
|
||||
PT(GeomVertexArrayDataHandle) new_handle = _new_data->modify_array_handle(i);
|
||||
CPT(GeomVertexArrayDataHandle) old_handle = vdata->get_array_handle(i);
|
||||
size_t stride = (size_t)_new_format->get_array(i)->get_stride();
|
||||
size_t start_byte = (size_t)vertex_offset * stride;
|
||||
size_t copy_bytes = old_array->get_data_size_bytes();
|
||||
nassertv(start_byte + copy_bytes <= new_array->get_data_size_bytes());
|
||||
size_t copy_bytes = old_handle->get_data_size_bytes();
|
||||
nassertv(start_byte + copy_bytes <= new_handle->get_data_size_bytes());
|
||||
|
||||
new_array->modify_handle()->copy_subdata_from
|
||||
(start_byte, copy_bytes,
|
||||
old_array->get_handle(), 0, copy_bytes);
|
||||
new_handle->copy_subdata_from(start_byte, copy_bytes, old_handle, 0, copy_bytes);
|
||||
}
|
||||
|
||||
// Also, copy the animation data (if any). This means combining transform
|
||||
|
|
|
|||
|
|
@ -799,12 +799,10 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedWritable::init_type();
|
||||
ReferenceCount::init_type();
|
||||
TypedWritableReferenceCount::init_type();
|
||||
Namable::init_type();
|
||||
register_type(_type_handle, "PandaNode",
|
||||
TypedWritable::get_class_type(),
|
||||
ReferenceCount::get_class_type(),
|
||||
TypedWritableReferenceCount::get_class_type(),
|
||||
Namable::get_class_type());
|
||||
CData::init_type();
|
||||
Down::init_type();
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ WorkingNodePath(const WorkingNodePath ©) :
|
|||
* traversal to the next node.
|
||||
*/
|
||||
INLINE WorkingNodePath::
|
||||
WorkingNodePath(const WorkingNodePath &parent, PandaNode *child) {
|
||||
_next = &parent;
|
||||
_start = (NodePathComponent *)NULL;
|
||||
_node = child;
|
||||
WorkingNodePath(const WorkingNodePath &parent, PandaNode *child) :
|
||||
_next(&parent),
|
||||
_start(nullptr),
|
||||
_node(child) {
|
||||
nassertv(_node != _next->_node);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -151,9 +151,9 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedObject::init_type();
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "ShaderGenerator",
|
||||
TypedObject::get_class_type());
|
||||
TypedReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
@ -173,9 +173,9 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedObject::init_type();
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "ShaderGenerator",
|
||||
TypedObject::get_class_type());
|
||||
TypedReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -73,7 +73,16 @@ get_unique_id() const {
|
|||
*/
|
||||
INLINE int Thread::
|
||||
get_pipeline_stage() const {
|
||||
#if !defined(_DEBUG) && defined(__has_builtin) && __has_builtin(__builtin_assume)
|
||||
// Because this is a signed int, this results in a sign extend on x86-64.
|
||||
// However, since we guarantee that this is never less than zero, clang
|
||||
// offers a nice way to avoid that.
|
||||
int pipeline_stage = _pipeline_stage;
|
||||
__builtin_assume(_pipeline_stage >= 0);
|
||||
return pipeline_stage;
|
||||
#else
|
||||
return _pipeline_stage;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ operator < (const CopyOnWritePointer &other) const {
|
|||
* This flavor of the method is written for the non-threaded case.
|
||||
*/
|
||||
INLINE const CopyOnWriteObject *CopyOnWritePointer::
|
||||
get_read_pointer() const {
|
||||
get_read_pointer(Thread *current_thread) const {
|
||||
return _cow_object;
|
||||
}
|
||||
#endif // COW_THREADED
|
||||
|
|
@ -362,8 +362,14 @@ operator = (PointerTo<T> &&from) NOEXCEPT {
|
|||
*/
|
||||
template<class T>
|
||||
INLINE CPT(TYPENAME CopyOnWritePointerTo<T>::To) CopyOnWritePointerTo<T>::
|
||||
get_read_pointer() const {
|
||||
return (const To *)(CopyOnWritePointer::get_read_pointer().p());
|
||||
get_read_pointer(Thread *current_thread) const {
|
||||
// This is necessary because we don't currently have a way to cast between
|
||||
// two compatible PointerTo types without losing the reference count.
|
||||
CPT(TYPENAME CopyOnWritePointerTo<T>::To) to;
|
||||
CPT(CopyOnWriteObject) from = CopyOnWritePointer::get_read_pointer(current_thread);
|
||||
to.cheat() = (const To *)from.p();
|
||||
from.cheat() = nullptr;
|
||||
return to;
|
||||
}
|
||||
#else // COW_THREADED
|
||||
/**
|
||||
|
|
@ -371,8 +377,8 @@ get_read_pointer() const {
|
|||
*/
|
||||
template<class T>
|
||||
INLINE const TYPENAME CopyOnWritePointerTo<T>::To *CopyOnWritePointerTo<T>::
|
||||
get_read_pointer() const {
|
||||
return (const To *)CopyOnWritePointer::get_read_pointer();
|
||||
get_read_pointer(Thread *current_thread) const {
|
||||
return (const To *)CopyOnWritePointer::get_read_pointer(current_thread);
|
||||
}
|
||||
#endif // COW_THREADED
|
||||
#endif // CPPPARSER
|
||||
|
|
@ -385,7 +391,13 @@ get_read_pointer() const {
|
|||
template<class T>
|
||||
INLINE PT(TYPENAME CopyOnWritePointerTo<T>::To) CopyOnWritePointerTo<T>::
|
||||
get_write_pointer() {
|
||||
return (To *)(CopyOnWritePointer::get_write_pointer().p());
|
||||
// This is necessary because we don't currently have a way to cast between
|
||||
// two compatible PointerTo types without losing the reference count.
|
||||
PT(TYPENAME CopyOnWritePointerTo<T>::To) to;
|
||||
PT(CopyOnWriteObject) from = CopyOnWritePointer::get_write_pointer();
|
||||
to.cheat() = (To *)from.p();
|
||||
from.cheat() = nullptr;
|
||||
return to;
|
||||
}
|
||||
#else // COW_THREADED
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -23,13 +23,11 @@
|
|||
* This flavor of the method is written for the threaded case.
|
||||
*/
|
||||
CPT(CopyOnWriteObject) CopyOnWritePointer::
|
||||
get_read_pointer() const {
|
||||
get_read_pointer(Thread *current_thread) const {
|
||||
if (_cow_object == (CopyOnWriteObject *)NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
|
||||
MutexHolder holder(_cow_object->_lock_mutex);
|
||||
while (_cow_object->_lock_status == CopyOnWriteObject::LS_locked_write) {
|
||||
if (_cow_object->_locking_thread == current_thread) {
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@ public:
|
|||
INLINE bool operator < (const CopyOnWritePointer &other) const;
|
||||
|
||||
#ifdef COW_THREADED
|
||||
CPT(CopyOnWriteObject) get_read_pointer() const;
|
||||
CPT(CopyOnWriteObject) get_read_pointer(Thread *current_thread) const;
|
||||
PT(CopyOnWriteObject) get_write_pointer();
|
||||
#else
|
||||
INLINE const CopyOnWriteObject *get_read_pointer() const;
|
||||
INLINE const CopyOnWriteObject *get_read_pointer(Thread *current_thread) const;
|
||||
INLINE CopyOnWriteObject *get_write_pointer();
|
||||
#endif // COW_THREADED
|
||||
|
||||
|
|
@ -93,10 +93,10 @@ public:
|
|||
#endif
|
||||
|
||||
#ifdef COW_THREADED
|
||||
INLINE CPT(To) get_read_pointer() const;
|
||||
INLINE CPT(To) get_read_pointer(Thread *current_thread = Thread::get_current_thread()) const;
|
||||
INLINE PT(To) get_write_pointer();
|
||||
#else
|
||||
INLINE const To *get_read_pointer() const;
|
||||
INLINE const To *get_read_pointer(Thread *current_thread = Thread::get_current_thread()) const;
|
||||
INLINE To *get_write_pointer();
|
||||
#endif // COW_THREADED
|
||||
|
||||
|
|
|
|||
|
|
@ -1142,7 +1142,6 @@ generate_quads(GeomNode *geom_node, const QuadMap &quad_map) {
|
|||
} else {
|
||||
tris->set_index_type(GeomEnums::NT_uint16);
|
||||
}
|
||||
PT(GeomVertexArrayData) indices = tris->modify_vertices();
|
||||
|
||||
int i = 0;
|
||||
|
||||
|
|
@ -1150,9 +1149,10 @@ generate_quads(GeomNode *geom_node, const QuadMap &quad_map) {
|
|||
// bottleneck. So, I've written this out the hard way instead. Two
|
||||
// versions of the loop: one for 32-bit indices, one for 16-bit.
|
||||
{
|
||||
PT(GeomVertexArrayDataHandle) vtx_handle = vdata->modify_array(0)->modify_handle();
|
||||
PT(GeomVertexArrayDataHandle) vtx_handle = vdata->modify_array_handle(0);
|
||||
vtx_handle->unclean_set_num_rows(quads.size() * 4);
|
||||
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
unsigned char *write_ptr = vtx_handle->get_write_pointer();
|
||||
size_t stride = format->get_array(0)->get_stride() / sizeof(PN_float32);
|
||||
|
||||
|
|
@ -1163,7 +1163,7 @@ generate_quads(GeomNode *geom_node, const QuadMap &quad_map) {
|
|||
|
||||
if (tris->get_index_type() == GeomEnums::NT_uint32) {
|
||||
// 32-bit index case.
|
||||
PT(GeomVertexArrayDataHandle) idx_handle = indices->modify_handle();
|
||||
PT(GeomVertexArrayDataHandle) idx_handle = tris->modify_vertices_handle(current_thread);
|
||||
idx_handle->unclean_set_num_rows(quads.size() * 6);
|
||||
uint32_t *idx_ptr = (uint32_t *)idx_handle->get_write_pointer();
|
||||
|
||||
|
|
@ -1219,7 +1219,7 @@ generate_quads(GeomNode *geom_node, const QuadMap &quad_map) {
|
|||
}
|
||||
} else {
|
||||
// 16-bit index case.
|
||||
PT(GeomVertexArrayDataHandle) idx_handle = indices->modify_handle();
|
||||
PT(GeomVertexArrayDataHandle) idx_handle = tris->modify_vertices_handle(current_thread);
|
||||
idx_handle->unclean_set_num_rows(quads.size() * 6);
|
||||
uint16_t *idx_ptr = (uint16_t *)idx_handle->get_write_pointer();
|
||||
|
||||
|
|
|
|||
|
|
@ -2612,12 +2612,10 @@ setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels) {
|
|||
|
||||
if (gltex->total_bytecount != total_bytecount) {
|
||||
if (gltex->allocated_buffer != NULL) {
|
||||
PANDA_FREE_ARRAY(gltex->allocated_buffer);
|
||||
TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
|
||||
TinyTextureContext::get_class_type().deallocate_array(gltex->allocated_buffer);
|
||||
}
|
||||
gltex->allocated_buffer = PANDA_MALLOC_ARRAY(total_bytecount);
|
||||
gltex->allocated_buffer = TinyTextureContext::get_class_type().allocate_array(total_bytecount);
|
||||
gltex->total_bytecount = total_bytecount;
|
||||
TinyTextureContext::get_class_type().inc_memory_usage(TypeHandle::MC_array, total_bytecount);
|
||||
}
|
||||
|
||||
char *next_buffer = (char *)gltex->allocated_buffer;
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@ TinyTextureContext::
|
|||
GLTexture *gltex = &_gltex;
|
||||
if (gltex->allocated_buffer != NULL) {
|
||||
nassertv(gltex->num_levels != 0);
|
||||
TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
|
||||
PANDA_FREE_ARRAY(gltex->allocated_buffer);
|
||||
get_class_type().deallocate_array(gltex->allocated_buffer);
|
||||
gltex->allocated_buffer = NULL;
|
||||
gltex->total_bytecount = 0;
|
||||
gltex->num_levels = 0;
|
||||
|
|
@ -51,8 +50,7 @@ evict_lru() {
|
|||
GLTexture *gltex = &_gltex;
|
||||
if (gltex->allocated_buffer != NULL) {
|
||||
nassertv(gltex->num_levels != 0);
|
||||
TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
|
||||
PANDA_FREE_ARRAY(gltex->allocated_buffer);
|
||||
get_class_type().deallocate_array(gltex->allocated_buffer);
|
||||
gltex->allocated_buffer = NULL;
|
||||
gltex->total_bytecount = 0;
|
||||
gltex->num_levels = 0;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ from direct.showbase.DirectObject import DirectObject
|
|||
from direct.task.Task import Task
|
||||
import sys
|
||||
|
||||
# First we define some contants for the colors
|
||||
# First we define some constants for the colors
|
||||
BLACK = (0, 0, 0, 1)
|
||||
WHITE = (1, 1, 1, 1)
|
||||
HIGHLIGHT = (0, 1, 1, 1)
|
||||
|
|
@ -33,7 +33,7 @@ PIECEBLACK = (.15, .15, .15, 1)
|
|||
# This is how we know where to position an object in 3D space based on a 2D mouse
|
||||
# position. It also assumes that we are dragging in the XY plane.
|
||||
#
|
||||
# This is derived from the mathmatical of a plane, solved for a given point
|
||||
# This is derived from the mathematical of a plane, solved for a given point
|
||||
def PointAtZ(z, point, vec):
|
||||
return point + vec * ((z - point.getZ()) / vec.getZ())
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ def PointAtZ(z, point, vec):
|
|||
def SquarePos(i):
|
||||
return LPoint3((i % 8) - 3.5, int(i // 8) - 3.5, 0)
|
||||
|
||||
# Helper function for determining wheter a square should be white or black
|
||||
# Helper function for determining whether a square should be white or black
|
||||
# The modulo operations (%) generate the every-other pattern of a chess-board
|
||||
def SquareColor(i):
|
||||
if (i + ((i // 8) % 2)) % 2:
|
||||
|
|
@ -84,7 +84,7 @@ class ChessboardDemo(ShowBase):
|
|||
# relative to it
|
||||
self.pickerNP = camera.attachNewNode(self.pickerNode)
|
||||
# Everything to be picked will use bit 1. This way if we were doing other
|
||||
# collision we could seperate it
|
||||
# collision we could separate it
|
||||
self.pickerNode.setFromCollideMask(BitMask32.bit(1))
|
||||
self.pickerRay = CollisionRay() # Make our ray
|
||||
# Add it to the collision node
|
||||
|
|
@ -96,7 +96,7 @@ class ChessboardDemo(ShowBase):
|
|||
# Now we create the chess board and its pieces
|
||||
|
||||
# We will attach all of the squares to their own root. This way we can do the
|
||||
# collision pass just on the sqaures and save the time of checking the rest
|
||||
# collision pass just on the squares and save the time of checking the rest
|
||||
# of the scene
|
||||
self.squareRoot = render.attachNewNode("squareRoot")
|
||||
|
||||
|
|
@ -240,7 +240,7 @@ class ChessboardDemo(ShowBase):
|
|||
render.setLight(render.attachNewNode(ambientLight))
|
||||
|
||||
|
||||
# Class for a piece. This just handels loading the model and setting initial
|
||||
# Class for a piece. This just handles loading the model and setting initial
|
||||
# position and color
|
||||
class Piece(object):
|
||||
def __init__(self, square, color):
|
||||
|
|
|
|||
Loading…
Reference in New Issue