Merge branch 'master' into cmake

This commit is contained in:
Sam Edwards 2014-10-11 18:09:26 -07:00
commit 62d08ec8bf
130 changed files with 14693 additions and 2436 deletions

View File

@ -1184,6 +1184,7 @@ string AIBehaviors::behavior_status(string ai_type) {
default:
cout<<"Invalid value!"<<endl;
return "invalid";
}
}

View File

@ -880,13 +880,13 @@ HTML_STYLESHEET = $(DOXYGEN_HTML_STYLESHEET)
# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
# The allowed range is 0 to 359.
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_HUE = 228
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
# the colors in the HTML output. For a value of 0 the output will use
# grayscales only. A value of 255 will produce the most vivid colors.
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_SAT = 99
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
# the luminance component of the colors in the HTML output. Values below
@ -895,7 +895,7 @@ HTML_COLORSTYLE_SAT = 100
# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
# and 100 does not change the gamma.
HTML_COLORSTYLE_GAMMA = 80
HTML_COLORSTYLE_GAMMA = 56
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting
@ -1451,6 +1451,7 @@ INCLUDE_FILE_PATTERNS =
PREDEFINED = TVOLATILE= \
INLINE=inline \
PUBLISHED=public \
protected=private \
INLINE_LINMATH=inline \
INLINE_MATHUTIL=inline \
EXTENSION(x)= \

View File

@ -863,13 +863,13 @@ HTML_STYLESHEET = $(DOXYGEN_HTML_STYLESHEET)
# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
# The allowed range is 0 to 359.
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_HUE = 228
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
# the colors in the HTML output. For a value of 0 the output will use
# grayscales only. A value of 255 will produce the most vivid colors.
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_SAT = 99
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
# the luminance component of the colors in the HTML output. Values below
@ -878,7 +878,7 @@ HTML_COLORSTYLE_SAT = 100
# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
# and 100 does not change the gamma.
HTML_COLORSTYLE_GAMMA = 80
HTML_COLORSTYLE_GAMMA = 56
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting

View File

@ -20,21 +20,17 @@ from pandac.PandaModules import Point3, Vec3, Vec4, Point2
from pandac.PandaModules import NodePath, PandaNode
from pandac.PandaModules import Filename
from pandac.PandaModules import AuxBitplaneAttrib
from pandac.PandaModules import RenderState, Texture, Shader
from pandac.PandaModules import RenderState, Texture, Shader, ATSNone
import sys,os
CARTOON_BODY="""
float4 cartoondelta = k_cartoonseparation * texpix_txaux.xwyw;
float4 cartoon_p0 = l_texcoordN + cartoondelta.xyzw;
float4 cartoon_c0 = tex2D(k_txaux, cartoon_p0.xy);
float4 cartoon_p1 = l_texcoordN - cartoondelta.xyzw;
float4 cartoon_c1 = tex2D(k_txaux, cartoon_p1.xy);
float4 cartoon_p2 = l_texcoordN + cartoondelta.wzyx;
float4 cartoon_c2 = tex2D(k_txaux, cartoon_p2.xy);
float4 cartoon_p3 = l_texcoordN - cartoondelta.wzyx;
float4 cartoon_c3 = tex2D(k_txaux, cartoon_p3.xy);
float4 cartoon_mx = max(cartoon_c0,max(cartoon_c1,max(cartoon_c2,cartoon_c3)));
float4 cartoon_mn = min(cartoon_c0,min(cartoon_c1,min(cartoon_c2,cartoon_c3)));
float4 cartoon_c0 = tex2D(k_txaux, %(texcoord)s + cartoondelta.xy);
float4 cartoon_c1 = tex2D(k_txaux, %(texcoord)s - cartoondelta.xy);
float4 cartoon_c2 = tex2D(k_txaux, %(texcoord)s + cartoondelta.wz);
float4 cartoon_c3 = tex2D(k_txaux, %(texcoord)s - cartoondelta.wz);
float4 cartoon_mx = max(cartoon_c0, max(cartoon_c1, max(cartoon_c2, cartoon_c3)));
float4 cartoon_mn = min(cartoon_c0, min(cartoon_c1, min(cartoon_c2, cartoon_c3)));
float cartoon_thresh = saturate(dot(cartoon_mx - cartoon_mn, float4(3,3,0,0)) - 0.5);
o_color = lerp(o_color, k_cartooncolor, cartoon_thresh);
"""
@ -125,7 +121,6 @@ class CommonFilters:
self.task = None
def reconfigure(self, fullrebuild, changed):
""" Reconfigure is called whenever any configuration change is made. """
configuration = self.configuration
@ -138,36 +133,46 @@ class CommonFilters:
return
auxbits = 0
needtex = {}
needtex["color"] = True
needtex = set(["color"])
needtexcoord = set(["color"])
if ("CartoonInk" in configuration):
needtex["aux"] = True
needtex.add("aux")
auxbits |= AuxBitplaneAttrib.ABOAuxNormal
needtexcoord.add("aux")
if ("AmbientOcclusion" in configuration):
needtex["depth"] = True
needtex["ssao0"] = True
needtex["ssao1"] = True
needtex["ssao2"] = True
needtex["aux"] = True
needtex.add("depth")
needtex.add("ssao0")
needtex.add("ssao1")
needtex.add("ssao2")
needtex.add("aux")
auxbits |= AuxBitplaneAttrib.ABOAuxNormal
needtexcoord.add("ssao2")
if ("BlurSharpen" in configuration):
needtex["blur0"] = True
needtex["blur1"] = True
needtex.add("blur0")
needtex.add("blur1")
needtexcoord.add("blur1")
if ("Bloom" in configuration):
needtex["bloom0"] = True
needtex["bloom1"] = True
needtex["bloom2"] = True
needtex["bloom3"] = True
needtex.add("bloom0")
needtex.add("bloom1")
needtex.add("bloom2")
needtex.add("bloom3")
auxbits |= AuxBitplaneAttrib.ABOGlow
needtexcoord.add("bloom3")
if ("ViewGlow" in configuration):
auxbits |= AuxBitplaneAttrib.ABOGlow
if ("VolumetricLighting" in configuration):
needtex[configuration["VolumetricLighting"].source] = True
for tex in needtex:
self.textures[tex] = Texture("scene-"+tex)
self.textures[tex] = Texture("scene-" + tex)
self.textures[tex].setWrapU(Texture.WMClamp)
self.textures[tex].setWrapV(Texture.WMClamp)
needtexpix = True
self.finalQuad = self.manager.renderSceneInto(textures = self.textures, auxbits=auxbits)
if (self.finalQuad == None):
@ -228,97 +233,112 @@ class CommonFilters:
self.bloom[3].setShaderInput("src", bloom2)
self.bloom[3].setShader(self.loadShader("filter-bloomy.sha"))
texcoords = {}
texcoordPadding = {}
for tex in needtexcoord:
if self.textures[tex].getAutoTextureScale() != ATSNone or \
"HalfPixelShift" in configuration:
texcoords[tex] = "l_texcoord_" + tex
texcoordPadding["l_texcoord_" + tex] = tex
else:
# Share unpadded texture coordinates.
texcoords[tex] = "l_texcoord"
texcoordPadding["l_texcoord"] = None
texcoordSets = list(enumerate(texcoordPadding.keys()))
text = "//Cg\n"
text += "void vshader(float4 vtx_position : POSITION,\n"
text += " out float4 l_position : POSITION,\n"
text += " uniform float4 texpad_txcolor,\n"
text += " uniform float4 texpix_txcolor,\n"
text += " out float4 l_texcoordC : TEXCOORD0,\n"
if ("CartoonInk" in configuration):
text += " uniform float4 texpad_txaux,\n"
text += " uniform float4 texpix_txaux,\n"
text += " out float4 l_texcoordN : TEXCOORD1,\n"
if ("Bloom" in configuration):
text += " uniform float4 texpad_txbloom3,\n"
text += " out float4 l_texcoordB : TEXCOORD2,\n"
if ("BlurSharpen" in configuration):
text += " uniform float4 texpad_txblur1,\n"
text += " out float4 l_texcoordBS : TEXCOORD3,\n"
if ("AmbientOcclusion" in configuration):
text += " uniform float4 texpad_txssao2,\n"
text += " out float4 l_texcoordAO : TEXCOORD4,\n"
text += " uniform float4x4 mat_modelproj)\n"
text += " out float4 l_position : POSITION,\n"
for texcoord, padTex in texcoordPadding.items():
if padTex is not None:
text += " uniform float4 texpad_tx%s,\n" % (padTex)
if ("HalfPixelShift" in configuration):
text += " uniform float4 texpix_tx%s,\n" % (padTex)
for i, name in texcoordSets:
text += " out float2 %s : TEXCOORD%d,\n" % (name, i)
text += " uniform float4x4 mat_modelproj)\n"
text += "{\n"
text += " l_position=mul(mat_modelproj, vtx_position);\n"
text += " l_texcoordC=(vtx_position.xzxz * texpad_txcolor) + texpad_txcolor;\n"
if ("CartoonInk" in configuration):
text += " l_texcoordN=(vtx_position.xzxz * texpad_txaux) + texpad_txaux;\n"
if ("Bloom" in configuration):
text += " l_texcoordB=(vtx_position.xzxz * texpad_txbloom3) + texpad_txbloom3;\n"
if ("BlurSharpen" in configuration):
text += " l_texcoordBS=(vtx_position.xzxz * texpad_txblur1) + texpad_txblur1;\n"
if ("AmbientOcclusion" in configuration):
text += " l_texcoordAO=(vtx_position.xzxz * texpad_txssao2) + texpad_txssao2;\n"
if ("HalfPixelShift" in configuration):
text += " l_texcoordC+=texpix_txcolor*0.5;\n"
if ("CartoonInk" in configuration):
text += " l_texcoordN+=texpix_txaux*0.5;\n"
text += " l_position = mul(mat_modelproj, vtx_position);\n"
for texcoord, padTex in texcoordPadding.items():
if padTex is None:
text += " %s = vtx_position.xz * float2(0.5, 0.5) + float2(0.5, 0.5);\n" % (texcoord)
else:
text += " %s = (vtx_position.xz * texpad_tx%s.xy) + texpad_tx%s.xy;\n" % (texcoord, padTex, padTex)
if ("HalfPixelShift" in configuration):
text += " %s += texpix_tx%s.xy * 0.5;\n" % (texcoord, padTex)
text += "}\n"
text += "void fshader(\n"
text += "float4 l_texcoordC : TEXCOORD0,\n"
text += "uniform float4 texpix_txcolor,\n"
if ("CartoonInk" in configuration):
text += "float4 l_texcoordN : TEXCOORD1,\n"
text += "uniform float4 texpix_txaux,\n"
if ("Bloom" in configuration):
text += "float4 l_texcoordB : TEXCOORD2,\n"
if ("BlurSharpen" in configuration):
text += "float4 l_texcoordBS : TEXCOORD3,\n"
text += "uniform float4 k_blurval,\n"
if ("AmbientOcclusion" in configuration):
text += "float4 l_texcoordAO : TEXCOORD4,\n"
for i, name in texcoordSets:
text += " float2 %s : TEXCOORD%d,\n" % (name, i)
for key in self.textures:
text += "uniform sampler2D k_tx" + key + ",\n"
text += " uniform sampler2D k_tx" + key + ",\n"
if ("CartoonInk" in configuration):
text += "uniform float4 k_cartoonseparation,\n"
text += "uniform float4 k_cartooncolor,\n"
if ("VolumetricLighting" in configuration):
text += "uniform float4 k_casterpos,\n"
text += "uniform float4 k_vlparams,\n"
text += "out float4 o_color : COLOR)\n"
text += "{\n"
text += " o_color = tex2D(k_txcolor, l_texcoordC.xy);\n"
if ("CartoonInk" in configuration):
text += CARTOON_BODY
if ("AmbientOcclusion" in configuration):
text += "o_color *= tex2D(k_txssao2, l_texcoordAO.xy).r;\n"
text += " uniform float4 k_cartoonseparation,\n"
text += " uniform float4 k_cartooncolor,\n"
text += " uniform float4 texpix_txaux,\n"
if ("BlurSharpen" in configuration):
text += " o_color = lerp(tex2D(k_txblur1, l_texcoordBS.xy), o_color, k_blurval.x);\n"
if ("Bloom" in configuration):
text += "o_color = saturate(o_color);\n";
text += "float4 bloom = 0.5*tex2D(k_txbloom3, l_texcoordB.xy);\n"
text += "o_color = 1-((1-bloom)*(1-o_color));\n"
if ("ViewGlow" in configuration):
text += "o_color.r = o_color.a;\n"
text += " uniform float4 k_blurval,\n"
if ("VolumetricLighting" in configuration):
text += "float decay = 1.0f;\n"
text += "float2 curcoord = l_texcoordC.xy;\n"
text += "float2 lightdir = curcoord - k_casterpos.xy;\n"
text += "lightdir *= k_vlparams.x;\n"
text += "half4 sample = tex2D(k_txcolor, curcoord);\n"
text += "float3 vlcolor = sample.rgb * sample.a;\n"
text += "for (int i = 0; i < %s; i++) {\n" % (int(configuration["VolumetricLighting"].numsamples))
text += " curcoord -= lightdir;\n"
text += " sample = tex2D(k_tx%s, curcoord);\n" % (configuration["VolumetricLighting"].source)
text += " sample *= sample.a * decay;//*weight\n"
text += " vlcolor += sample.rgb;\n"
text += " decay *= k_vlparams.y;\n"
text += "}\n"
text += "o_color += float4(vlcolor * k_vlparams.z, 1);\n"
text += " uniform float4 k_casterpos,\n"
text += " uniform float4 k_vlparams,\n"
text += " out float4 o_color : COLOR)\n"
text += "{\n"
text += " o_color = tex2D(k_txcolor, %s);\n" % (texcoords["color"])
if ("CartoonInk" in configuration):
text += CARTOON_BODY % {"texcoord" : texcoords["aux"]}
if ("AmbientOcclusion" in configuration):
text += " o_color *= tex2D(k_txssao2, %s).r;\n" % (texcoords["ssao2"])
if ("BlurSharpen" in configuration):
text += " o_color = lerp(tex2D(k_txblur1, %s), o_color, k_blurval.x);\n" % (texcoords["blur1"])
if ("Bloom" in configuration):
text += " o_color = saturate(o_color);\n";
text += " float4 bloom = 0.5 * tex2D(k_txbloom3, %s);\n" % (texcoords["bloom3"])
text += " o_color = 1-((1-bloom)*(1-o_color));\n"
if ("ViewGlow" in configuration):
text += " o_color.r = o_color.a;\n"
if ("VolumetricLighting" in configuration):
text += " float decay = 1.0f;\n"
text += " float2 curcoord = %s;\n" % (texcoords["color"])
text += " float2 lightdir = curcoord - k_casterpos.xy;\n"
text += " lightdir *= k_vlparams.x;\n"
text += " half4 sample = tex2D(k_txcolor, curcoord);\n"
text += " float3 vlcolor = sample.rgb * sample.a;\n"
text += " for (int i = 0; i < %s; i++) {\n" % (int(configuration["VolumetricLighting"].numsamples))
text += " curcoord -= lightdir;\n"
text += " sample = tex2D(k_tx%s, curcoord);\n" % (configuration["VolumetricLighting"].source)
text += " sample *= sample.a * decay;//*weight\n"
text += " vlcolor += sample.rgb;\n"
text += " decay *= k_vlparams.y;\n"
text += " }\n"
text += " o_color += float4(vlcolor * k_vlparams.z, 1);\n"
if ("GammaAdjust" in configuration):
gamma = configuration["GammaAdjust"]
if gamma == 0.5:
text += " o_color.rgb = sqrt(o_color.rgb);\n"
elif gamma == 2.0:
text += " o_color.rgb *= o_color.rgb;\n"
elif gamma != 1.0:
text += " o_color.rgb = pow(o_color.rgb, %ff);\n" % (gamma)
if ("Inverted" in configuration):
text += "o_color = float4(1, 1, 1, 1) - o_color;\n"
text += " o_color = float4(1, 1, 1, 1) - o_color;\n"
text += "}\n"
print text
self.finalQuad.setShader(Shader.make(text))
for tex in self.textures:
@ -504,3 +524,17 @@ class CommonFilters:
return self.reconfigure(True, "AmbientOcclusion")
return True
def setGammaAdjust(self, gamma):
""" Applies additional gamma correction to the image. 1.0 = no correction. """
old_gamma = self.configuration.get("GammaAdjust", 1.0)
if old_gamma != gamma:
self.configuration["GammaAdjust"] = gamma
return self.reconfigure(True, "GammaAdjust")
return True
def delGammaAdjust(self):
if ("GammaAdjust" in self.configuration):
old_gamma = self.configuration["GammaAdjust"]
del self.configuration["GammaAdjust"]
return self.reconfigure((old_gamma != 1.0), "GammaAdjust")
return True

View File

@ -4,10 +4,10 @@
#include <list>
#include "socket_base.h"
enum CloseState
enum CloseState
{
ConnectionDoNotClose,
ConnectionDoClose
ConnectionDoNotClose,
ConnectionDoClose
};
// RHH
////////////////////////////////////////////////////////////////////
@ -20,15 +20,15 @@ enum CloseState
//
// The general operation if get connection..
// do you have a message
// process message
// process message
// go back to do you have a message or close connection
//
//
////////////////////////////////////////////////////////////////////
template < class _INCLASS1,class _IN_LISTEN, class MESSAGE_READER_BUF, class MESSAGE_READER_UPPASS> class BaseIncomingSet : public std::list<_INCLASS1 *>
{
typedef std::list<_INCLASS1 *> BaseClass;
typedef TYPENAME BaseClass::iterator iterator;
typedef std::list<_INCLASS1 *> BaseClass;
typedef TYPENAME BaseClass::iterator iterator;
_IN_LISTEN _Listener;
inline void AddFromListener(void);
@ -39,7 +39,7 @@ public:
// typedef typename BaseIncomingSet<_INCLASS1, _IN_LISTEN, MESSAGE_READER_BUF, MESSAGE_READER_UPPASS>::LinkNode LinkNode;
// typedef SentDblLinkListNode_Gm SentDblLinkListNode_Gm;
// typedef SentDblLinkListNode_Gm SentDblLinkListNode_Gm;
inline BaseIncomingSet(void);
inline BaseIncomingSet(BaseIncomingSet &in);
virtual ~BaseIncomingSet();
@ -50,10 +50,6 @@ public:
virtual CloseState ProcessNewConnection(SOCKET socket);
inline void AddToFDSet(Socket_fdset &set);
// inline LinkNode * GetRoot(void) { return &this->sentenal; };
BaseIncomingSet &operator=( BaseIncomingSet &inval);
void Reset();

View File

@ -1,19 +1,19 @@
////////////////////////////////////////////////////////////////////
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddFromListener
// Description : Read incoming connections off the listener
//
// Return type : inline void
//
// Return type : inline void
// Argument : void
////////////////////////////////////////////////////////////////////
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddFromListener(void)
{
Socket_Address Addr1;
SOCKET newsck;
while(_Listener.GetIncomingConnection(newsck,Addr1) == true)
{
{
CloseState cl= ProcessNewConnection(newsck);
if(cl == ConnectionDoNotClose)
{
@ -22,52 +22,52 @@ inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READ
}
else
DO_CLOSE(newsck);
}
}
}
////////////////////////////////////////////////////////////////////
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::PumpReader
// Description : Tries to read a record off the incoming socket
//
// Return type : inline void
//
// Return type : inline void
// Argument : Time_Clock currentTime
////////////////////////////////////////////////////////////////////
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
inline int BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::PumpReader(Time_Clock &currentTime)
{
{
MESSAGE_READER_BUF message;
iterator lpNext, lp;
for (lpNext = lp = BaseClass::begin(); lp != BaseClass::end() ; lp = lpNext)
{
lpNext++;
lpNext++;
int ans = (*lp)->ReadIt(message, sizeof(message),currentTime);
if(ans < 0)
{
delete *lp;
erase(lp);
}
this->erase(lp);
}
if(ans > 0)
{
CloseState cs = (*lp)->ProcessMessage(message,currentTime);
if( cs == ConnectionDoClose)
{
delete *lp;
erase(lp);
this->erase(lp);
}
}
}
return 0;
}
return 0;
}
////////////////////////////////////////////////////////////////////
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddAConection
// Description : Adds a member to the base container
//
// Return type : inline void
//
// Return type : inline void
// Argument : _INCLASS1 * newt
////////////////////////////////////////////////////////////////////
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddAConection(_INCLASS1 * newt)
{
push_back(newt);
@ -75,17 +75,17 @@ inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READ
////////////////////////////////////////////////////////////////////
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::BaseIncomingSet
// Description : core constructor
//
// Return type : inline
//
// Return type : inline
// Argument : void
////////////////////////////////////////////////////////////////////
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
inline BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::BaseIncomingSet(void)
{
}
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::BaseIncomingSet(BaseIncomingSet &in)
{
@ -93,10 +93,10 @@ BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::
////////////////////////////////////////////////////////////////////
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::~BaseIncomingSet
// Description : The Destructot .. will delete all members.. ??
//
// Return type :
//
// Return type :
////////////////////////////////////////////////////////////////////
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::~BaseIncomingSet()
{
for(iterator ii = BaseClass::begin(); ii != BaseClass::end(); ii++)
@ -105,76 +105,76 @@ BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::
////////////////////////////////////////////////////////////////////
// Function name : & BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::GetListener
// Description : Retyurns a pointer to the listener in this class
//
// Return type : inline _IN_LISTEN
//
// Return type : inline _IN_LISTEN
// Argument : void
////////////////////////////////////////////////////////////////////
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
inline _IN_LISTEN & BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::GetListener(void)
{
return this->Listener;
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
inline _IN_LISTEN & BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::GetListener(void)
{
return this->Listener;
};
////////////////////////////////////////////////////////////////////
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::init
// Description : the second part of the 2 phase power up.. Opends the listener
//
// Return type : inline bool
//
// Return type : inline bool
// Argument : Socket_Address &WhereFrom
////////////////////////////////////////////////////////////////////
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
inline bool BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::init(Socket_Address &WhereFrom)
{
if(_Listener.OpenForListen(WhereFrom,true) != true)
return false;
return false;
_Listener.SetNonBlocking();
return true;
}
////////////////////////////////////////////////////////////////////
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::PumpAll
// Description : THis is the polled interface to this class
//
// Return type : inline void
//
// Return type : inline void
// Argument : Time_Clock &currentTime
////////////////////////////////////////////////////////////////////
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::PumpAll(Time_Clock &currentTime)
{
PumpReader(currentTime); // I MOVED ORDER TO FINE TUNE THE READ OPERATIONS
AddFromListener();
AddFromListener();
}
////////////////////////////////////////////////////////////////////
// Function name : BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::ProcessNewConnection
// Description : this is the vertual function call when a new connection is created
// Description : this is the vertual function call when a new connection is created
// manly here for loging if needed...
//
// Return type : CloseState
//
// Return type : CloseState
// Argument : SOCKET socket
////////////////////////////////////////////////////////////////////
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
CloseState BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::ProcessNewConnection(SOCKET socket)
{
return ConnectionDoNotClose;
}
////////////////////////////////////////////////////////////////////
// Function name : void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddToFDSet
// Description : Add LIstener and Client to the FD set for polled reading
//
// Return type : inline
// Description : Add LIstener and Client to the FD set for polled reading
//
// Return type : inline
// Argument : Socket_Selector &set
////////////////////////////////////////////////////////////////////
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::AddToFDSet(Socket_fdset &set1)
{
{
if(_Listener.Active())
set1.setForSocket(_Listener);
iterator lp;
for (lp = BaseClass::begin(); lp != BaseClass::end(); lp = lp++)
set1.setForSocket((*lp)->val);
}
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
inline BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS> &BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::operator=
(BaseIncomingSet &inval)
{
@ -184,18 +184,18 @@ inline BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UP
}
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
template <class _INCLASS1,class _IN_LISTEN,typename MESSAGE_READER_BUF, typename MESSAGE_READER_UPPASS>
inline void BaseIncomingSet<_INCLASS1,_IN_LISTEN,MESSAGE_READER_BUF,MESSAGE_READER_UPPASS>::Reset()
{
_Listener.Close();
iterator lpNext, lp;
for (lpNext = lp = BaseClass::begin(); lp != BaseClass::end() ; lp = lpNext)
{
lpNext++;
lpNext++;
(*lp)->Reset();
delete *lp;
erase(lp);
}
this->erase(lp);
}
}

View File

@ -23,12 +23,21 @@
#include <windows.h>
#include <process.h>
#include <assert.h>
#include <malloc.h>
#define BUFFER_SIZE 1024
/* It makes sense to use "App Paths\panda3d.exe". However, Microsoft
decided in their infinite wisdom to disable Redirection for that
key from Windows 7 onward, so we can't rely on it producing a
result appropriate to the right architecture when both the 32-bit
and 64-bit versions of the runtime are installed. Beh. */
#define UNINST_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Panda3D Game Engine"
int main (int argc, char* argv[]) {
int i;
char buffer [BUFFER_SIZE];
char buffer[BUFFER_SIZE];
char* p3dfile;
char* runtime = NULL;
DWORD size;
@ -37,56 +46,82 @@ int main (int argc, char* argv[]) {
char *cmd;
char *newcmd;
HKEY hKey = 0;
char buf [1024] = {0};
DWORD dwType = 0;
char buf[1024] = {0};
DWORD dwType = REG_SZ;
DWORD dwBufSize = sizeof(buf);
size = GetModuleFileName (NULL, buffer, BUFFER_SIZE);
size = GetModuleFileName(NULL, buffer, BUFFER_SIZE);
assert (size > 0);
/* Chop off the .exe and replace it by .p3d. */
p3dfile = (char*) malloc (size + 1);
memcpy (p3dfile, buffer, size);
p3dfile [size] = 0;
memcpy (p3dfile + size - 3, "p3d", 3);
p3dfile = (char*) _alloca(size + 1);
memcpy(p3dfile, buffer, size);
p3dfile[size] = 0;
memcpy(p3dfile + size - 3, "p3d", 3);
/* Find the Panda3D applet\DefaultIcon key and extract the path to the runtime from there. */
if (RegOpenKey (HKEY_CLASSES_ROOT, "Panda3D applet\\DefaultIcon", &hKey) == ERROR_SUCCESS) {
dwType = REG_SZ;
if (RegQueryValueEx(hKey, 0, 0, &dwType, (BYTE*) buf, &dwBufSize) == ERROR_SUCCESS) {
for (i = dwBufSize - 1; i >= 0; --i) {
if (buf [i] == '/' || buf [i] == '\\') {
runtime = (char*) malloc (i + 13);
memcpy (runtime, buf, i);
runtime [i] = 0;
strcat (runtime, "\\panda3d.exe");
break;
}
/* Find the location of panda3d.exe using the registry path. */
#ifdef _WIN64
/* If we're on 64-bit Windows, try the 64-bit registry first. */
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, UNINST_KEY, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS) {
if (RegQueryValueEx(hKey, "DisplayIcon", 0, &dwType, (BYTE*) buf, &dwBufSize) == ERROR_SUCCESS) {
char *slash = strrchr(buf, '\\');
if (slash != NULL) {
strcpy(slash, "\\panda3d.exe");
runtime = buf;
}
} else {
fprintf (stderr, "Failed to read registry key. Try reinstalling the Panda3D Runtime.\n");
return 1;
}
RegCloseKey(hKey);
} else {
fprintf (stderr, "The Panda3D Runtime does not appear to be installed!\n");
return 1;
}
#endif
/* On 32-bit Windows, or no 64-bit Runtime installed. Try 32-bit registry. */
if (runtime == NULL) {
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, UNINST_KEY, 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hKey) == ERROR_SUCCESS) {
if (RegQueryValueEx(hKey, "DisplayIcon", 0, &dwType, (BYTE*) buf, &dwBufSize) == ERROR_SUCCESS) {
char *slash = strrchr(buf, '\\');
if (slash != NULL) {
strcpy(slash, "\\panda3d.exe");
runtime = buf;
}
}
RegCloseKey(hKey);
}
}
/* Backward compatibility: Runtime 1.0.4 and below looked for the below key, even though the
above keys should work fine, but let's just be certain.
Find the Panda3D applet\DefaultIcon key and extract the path to the runtime from there. */
if (runtime == NULL) {
if (RegOpenKey(HKEY_CLASSES_ROOT, "Panda3D applet\\DefaultIcon", &hKey) == ERROR_SUCCESS) {
if (RegQueryValueEx(hKey, 0, 0, &dwType, (BYTE*) buf, &dwBufSize) == ERROR_SUCCESS) {
char *slash = strrchr(buf, '\\');
if (slash != NULL) {
strcpy(slash, "\\panda3d.exe");
runtime = buf;
}
} else {
fprintf(stderr, "Failed to read registry key. Try reinstalling the Panda3D Runtime.\n");
return 1;
}
RegCloseKey(hKey);
} else {
fprintf(stderr, "The Panda3D Runtime does not appear to be installed!\n");
return 1;
}
}
if (runtime == NULL) {
fprintf (stderr, "Failed to find panda3d.exe in registry. Try reinstalling the Panda3D Runtime.\n");
fprintf(stderr, "Failed to find panda3d.exe in registry. Try reinstalling the Panda3D Runtime.\n");
return 1;
}
/* Build the command-line and run panda3d.exe. */
cmd = GetCommandLine();
newcmd = (char*) malloc (strlen(runtime) + strlen(p3dfile) + strlen (cmd) - strlen (argv[0]) + 7);
sprintf (newcmd, "\"%s\" \"%s\" %s", runtime, p3dfile, cmd + strlen (argv[0]));
newcmd = (char*) _alloca(strlen(runtime) + strlen(p3dfile) + strlen(cmd) - strlen (argv[0]) + 7);
sprintf(newcmd, "\"%s\" \"%s\" %s", runtime, p3dfile, cmd + strlen(argv[0]));
memset(&si, 0, sizeof(si));
si.cb = sizeof(STARTUPINFO);
if (CreateProcess(runtime, newcmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
WaitForSingleObject(pi.hProcess, INFINITE);
}
free (newcmd);
return 0;
}

View File

@ -40,7 +40,7 @@ parser.add_option('-l', '--license', dest = 'license',
default = None)
parser.add_option('-w', '--website', dest = 'website',
help = 'The product website',
default = 'http://www.panda3d.org')
default = 'https://www.panda3d.org')
parser.add_option('', '--start', dest = 'start',
help = 'Specify this option to add a start menu',
action = 'store_true', default = False)
@ -65,6 +65,9 @@ parser.add_option('', '--pvk', dest = 'pvk',
parser.add_option('', '--mssdk', dest = 'mssdk',
help = 'The path to the MS Platform SDK directory (Windows only). mssdk/bin should contain cabarc.exe and signcode.exe.',
default = None)
parser.add_option('', '--regview', dest = 'regview',
help = 'Which registry view to use, 64 or 32.',
default = None)
(options, args) = parser.parse_args()
@ -221,7 +224,7 @@ def parseDependenciesUnix(tempFile):
filenames.append(l.strip().split(' ', 1)[0])
return filenames
def addDependencies(path, pathname, file, pluginDependencies, dependentFiles):
def addDependencies(path, pathname, file, pluginDependencies, dependentFiles, required=True):
""" Checks the named file for DLL dependencies, and adds any
appropriate dependencies found into pluginDependencies and
dependentFiles. """
@ -271,7 +274,10 @@ def addDependencies(path, pathname, file, pluginDependencies, dependentFiles):
break
pathname = None
if not pathname:
sys.exit("Couldn't find %s." % (dfile))
if required:
sys.exit("Couldn't find %s." % (dfile))
sys.stderr.write("Warning: couldn't find %s." % (dfile))
continue
pathname = os.path.abspath(pathname)
dependentFiles[dfilelower] = pathname
@ -553,6 +559,9 @@ def makeInstaller():
CMD += '/DPANDA3DW="' + panda3dw + '" '
CMD += '/DPANDA3DW_PATH="' + pluginFiles[panda3dw] + '" '
if options.regview:
CMD += '/DREGVIEW=%s ' % (options.regview)
dependencies = dependentFiles.items()
for i in range(len(dependencies)):
CMD += '/DDEP%s="%s" ' % (i, dependencies[i][0])

View File

@ -1,6 +1,5 @@
!include "MUI.nsh"
!include LogicLib.nsh
!include FileAssociation.nsh
; Several variables are assumed to be pre-defined by the caller. See
; make_installer.py in this directory.
@ -9,18 +8,18 @@
!define UNINSTALL_CONFIRM "Are you sure you want to completely remove $(^Name) and all of its components?"
!define UNINSTALL_LINK_NAME "Uninstall"
!define WEBSITE_LINK_NAME "Website"
!define PLID "@panda3d.org/Panda3D Runtime,version=0.0"
!define PLID "@panda3d.org/Panda3D Runtime"
; HM NIS Edit Wizard helper defines
!define APP_INTERNAL_NAME "Panda3D"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\${OCX}"
!define PRODUCT_DIR_REGKEY_PANDA3D "Software\Microsoft\Windows\CurrentVersion\App Paths\${PANDA3D}"
!define PRODUCT_DIR_REGKEY_PANDA3DW "Software\Microsoft\Windows\CurrentVersion\App Paths\${PANDA3DW}"
!define PRODUCT_DIR_REGKEY_OCX "Software\Microsoft\Windows\CurrentVersion\App Paths\${OCX}"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
!define PROG_GROUPNAME "${PRODUCT_NAME}"
!define FIREFOX_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe"
SetCompressor lzma
; MUI Settings
@ -60,16 +59,32 @@ InstallDir "${INSTALL_DIR}"
UninstallIcon "${INSTALL_ICON}"
!endif
WindowIcon on
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
ShowInstDetails show
ShowUnInstDetails show
Function .onInit
!ifdef REGVIEW
SetRegView ${REGVIEW}
!endif
ClearErrors
ReadRegStr $0 ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "InstallLocation"
IfErrors +2 0
StrCpy $INSTDIR $0
FunctionEnd
Section "MainSection" SEC01
SetShellVarContext all
SetOutPath "$INSTDIR"
SetOverwrite ifdiff
!ifdef OCX_PATH
File "${OCX_PATH}"
!endif
File "${NPAPI_PATH}"
File "${PANDA3D_PATH}"
File "${PANDA3DW_PATH}"
@ -100,8 +115,6 @@ Section "MainSection" SEC01
!ifdef DEP7P
File "${DEP7P}"
!endif
${registerExtension} "$INSTDIR\${PANDA3DW}" ".p3d" "Panda3D applet"
!ifdef ADD_START_MENU
; Start->Programs links
@ -127,14 +140,41 @@ Section -AdditionalIcons
SectionEnd
Section -Post
!ifdef REGVIEW
SetRegView ${REGVIEW}
!endif
WriteUninstaller "$INSTDIR\uninst.exe"
WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\${OCX}"
WriteRegStr HKCR ".p3d" "" "Panda3D applet"
WriteRegStr HKCR ".p3d" "Content Type" "application/x-panda3d"
WriteRegStr HKCR ".p3d" "PerceivedType" "application"
WriteRegStr HKCR "Panda3D applet" "" "Panda3D applet"
WriteRegStr HKCR "Panda3D applet\DefaultIcon" "" "$INSTDIR\${PANDA3DW}"
WriteRegStr HKCR "Panda3D applet\shell" "" "open"
WriteRegStr HKCR "Panda3D applet\shell\open\command" "" '"$INSTDIR\${PANDA3DW}" "%1"'
WriteRegExpandStr HKCR "Panda3D applet\shell\open2" "" "Open &with Command Prompt"
;WriteRegExpandStr HKCR "Panda3D applet\shell\open2" "MUIVerb" "@%SystemRoot%\System32\wshext.dll,-4511"
WriteRegExpandStr HKCR "Panda3D applet\shell\open2\command" "" '"$INSTDIR\${PANDA3D}" "%1"'
WriteRegStr HKLM "${PRODUCT_DIR_REGKEY_PANDA3D}" "" "$INSTDIR\${PANDA3D}"
WriteRegStr HKLM "${PRODUCT_DIR_REGKEY_PANDA3DW}" "" "$INSTDIR\${PANDA3DW}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\${OCX}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PANDA3D}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "InstallLocation" "$INSTDIR"
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "NoModify" 1
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "NoRepair" 1
SectionGetSize SEC01 $0
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "EstimatedSize" $0
# Delete keys we used in older versions
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY_OCX}"
DeleteRegKey HKCR "Panda3D applet\shell\edit"
SectionEnd
@ -149,16 +189,23 @@ Function un.onInit
FunctionEnd
Function .onInstSuccess
# Register ActiveX
ExecWait 'regsvr32 /s "$INSTDIR/${OCX}"'
# Register ActiveX
ExecWait 'regsvr32 /s "$INSTDIR/${OCX}"'
# Register Mozilla Plugin
WriteRegStr HKLM "SOFTWARE\MozillaPlugins\${PLID}" "Description" "Runs 3-D games and interactive applets"
WriteRegStr HKLM "SOFTWARE\MozillaPlugins\${PLID}" "Path" "$INSTDIR\${NPAPI}"
WriteRegStr HKLM "SOFTWARE\MozillaPlugins\${PLID}" "ProductName" "${PRODUCT_NAME_SHORT}"
WriteRegStr HKLM "SOFTWARE\MozillaPlugins\${PLID}" "Vendor" "${PRODUCT_PUBLISHER}"
WriteRegStr HKLM "SOFTWARE\MozillaPlugins\${PLID}" "Version" "${PRODUCT_VERSION}"
WriteRegStr HKLM "SOFTWARE\MozillaPlugins\${PLID}\MimeTypes" "application/x-panda3d" ""
!ifdef REGVIEW
SetRegView ${REGVIEW}
!endif
# Register Mozilla Plugin
WriteRegStr HKLM "SOFTWARE\MozillaPlugins\${PLID}" "Description" "Runs 3-D games and interactive applets"
WriteRegStr HKLM "SOFTWARE\MozillaPlugins\${PLID}" "Path" "$INSTDIR\${NPAPI}"
WriteRegStr HKLM "SOFTWARE\MozillaPlugins\${PLID}" "ProductName" "${PRODUCT_NAME_SHORT}"
WriteRegStr HKLM "SOFTWARE\MozillaPlugins\${PLID}" "Vendor" "${PRODUCT_PUBLISHER}"
WriteRegStr HKLM "SOFTWARE\MozillaPlugins\${PLID}" "Version" "${PRODUCT_VERSION}"
WriteRegStr HKLM "SOFTWARE\MozillaPlugins\${PLID}\MimeTypes\application/x-panda3d" "Description" "Panda3D applet"
# Remove old stuff
DeleteRegKey HKLM "SOFTWARE\MozillaPlugins\${PLID},version=0.0"
FunctionEnd
@ -196,6 +243,10 @@ Section Uninstall
Delete "$INSTDIR\${DEP7}"
!endif
!ifdef REGVIEW
SetRegView ${REGVIEW}
!endif
# The following loop uninstalls the plugin where it may have been
# copied into one of the Mozilla Extensions dirs. Older versions of
# the installer would have done this, but now we just update the
@ -215,8 +266,10 @@ Mozilla-Uninstall-Loop:
Mozilla-Uninstall-End:
DeleteRegKey HKLM "SOFTWARE\MozillaPlugins\${PLID}"
DeleteRegKey HKLM "SOFTWARE\MozillaPlugins\${PLID},version=0.0"
${unregisterExtension} ".p3d" "Panda3D applet"
DeleteRegKey HKCR ".p3d"
DeleteRegKey HKCR "Panda3D applet"
# Remove the user's "Panda3D" directory, where all of the downloaded
# contents are installed. Too bad we can't do this for every system
@ -239,7 +292,9 @@ Mozilla-Uninstall-End:
RMDir "$INSTDIR"
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY_PANDA3D}"
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY_PANDA3DW}"
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY_OCX}"
SetAutoClose true
SectionEnd

View File

@ -52,7 +52,6 @@ import __builtin__
from StringIO import StringIO
import marshal
import ElementTree as ET
from HTMLParser import HTMLParser
import BpDb
import unicodedata
import bisect
@ -4201,75 +4200,6 @@ if __debug__ and __name__ == '__main__':
assert unescapeHtmlString('as%32df') == 'as2df'
assert unescapeHtmlString('asdf%32') == 'asdf2'
class HTMLStringToElements(HTMLParser):
def __init__(self, str, *a, **kw):
self._elements = []
self._elementStack = Stack()
HTMLParser.__init__(self, *a, **kw)
self.feed(str)
self.close()
def getElements(self):
return self._elements
def _handleNewElement(self, element):
if len(self._elementStack):
self._elementStack.top().append(element)
else:
self._elements.append(element)
self._elementStack.push(element)
def handle_starttag(self, tag, attrs):
kwArgs = {}
for name, value in attrs:
kwArgs[name] = value
el = ET.Element(tag, **kwArgs)
self._handleNewElement(el)
def handle_data(self, data):
# this ignores text outside of a tag
if len(self._elementStack):
self._elementStack.top().text = data
def handle_endtag(self, tag):
top = self._elementStack.top()
if len(top.getchildren()) == 0:
# insert a comment to prevent ElementTree from using <... /> convention
# force it to create a tag closer a la </tag>
# prevents problems in certain browsers
if top.tag == 'script' and top.get('type') == 'text/javascript':
if top.text == None:
top.text = '// force tag closer'
else:
self.handle_comment('force tag closer')
self._elementStack.pop()
self._elementStack.pop()
def handle_comment(self, data):
comment = ET.Comment(data)
self._handleNewElement(comment)
def str2elements(str):
return HTMLStringToElements(str).getElements()
if __debug__ and __name__ == '__main__':
s = ScratchPad()
assert len(str2elements('')) == 0
s.br = str2elements('<br>')
assert len(s.br) == 1
assert s.br[0].tag == 'br'
s.b = str2elements('<b><br></b>')
assert len(s.b) == 1
assert len(s.b[0].getchildren()) == 1
s.a = str2elements('<a href=\'/\'>test</a>')
assert len(s.a) == 1
assert s.a[0].get('href') == '/'
assert s.a[0].text == 'test'
s.c = str2elements('<!--testComment-->')
assert len(s.c) == 1
assert s.c[0].text == 'testComment'
del s
def repeatableRepr(obj):
if type(obj) is types.DictType:
keys = obj.keys()

View File

@ -7,7 +7,8 @@ __all__ = ['ShowBase', 'WindowControls']
# Annoying and very noisy, but sometimes useful
#import VerboseImport
from pandac.PandaModules import *
from panda3d.core import *
from panda3d.direct import *
# This needs to be available early for DirectGUI imports
import __builtin__

View File

@ -3,7 +3,6 @@ import sys
import os
import marshal
import imp
import struct
import types
import __builtin__
@ -286,7 +285,8 @@ class VFSLoader:
code = None
data = vfile.readFile(True)
if data[:4] == imp.get_magic():
t = struct.unpack('<I', data[4:8])[0]
t = ord(data[4]) + (ord(data[5]) << 8) + \
(ord(data[6]) << 16) + (ord(data[7]) << 24)
if not timestamp or t == timestamp:
code = marshal.loads(data[8:])
else:
@ -314,7 +314,10 @@ class VFSLoader:
pass
else:
f.write('\0\0\0\0')
f.write(struct.pack('<I', self.timestamp))
f.write(chr(self.timestamp & 0xff) +
chr((self.timestamp >> 8) & 0xff) +
chr((self.timestamp >> 16) & 0xff) +
chr((self.timestamp >> 24) & 0xff))
f.write(marshal.dumps(code))
f.flush()
f.seek(0, 0)

View File

@ -102,15 +102,16 @@ elif bl.endswith('.exe'):
basename = os.path.splitext(basename)[0]
startfile = args[0]
startmod = startfile
if startfile.endswith('.py') or startfile.endswith('.pyw') or \
startfile.endswith('.pyc') or startfile.endswith('.pyo'):
startfile = os.path.splitext(startfile)[0]
startmod = os.path.splitext(startfile)[0]
compileToExe = False
if outputType == 'dll':
freezer.addModule(startfile)
freezer.addModule(startmod, filename = startfile)
else:
freezer.addModule(startfile, newName = '__main__')
freezer.addModule('__main__', filename = startfile)
compileToExe = True
freezer.done(compileToExe = compileToExe)

View File

@ -390,11 +390,7 @@ cinf(double v) {
////////////////////////////////////////////////////////////////////
INLINE float
make_nan(float) {
#ifndef _WIN32
return nanf("");
#else
return std::numeric_limits<float>::quiet_NaN();
#endif
}
////////////////////////////////////////////////////////////////////
@ -403,11 +399,7 @@ make_nan(float) {
////////////////////////////////////////////////////////////////////
INLINE double
make_nan(double) {
#ifndef _WIN32
return nan("");
#else
return std::numeric_limits<double>::quiet_NaN();
#endif
}
////////////////////////////////////////////////////////////////////

View File

@ -119,3 +119,23 @@ INLINE string ExecutionEnvironment::
get_dtool_name() {
return get_ptr()->ns_get_dtool_name();
}
////////////////////////////////////////////////////////////////////
// Function: ExecutionEnvironment::set_binary_name
// Access: Public, Static
// Description: Do not use.
////////////////////////////////////////////////////////////////////
INLINE void ExecutionEnvironment::
set_binary_name(const string &name) {
get_ptr()->_binary_name = name;
}
////////////////////////////////////////////////////////////////////
// Function: ExecutionEnvironment::set_dtool_name
// Access: Public, Static
// Description: Do not use.
////////////////////////////////////////////////////////////////////
INLINE void ExecutionEnvironment::
set_dtool_name(const string &name) {
get_ptr()->_dtool_name = name;
}

View File

@ -31,6 +31,9 @@
// And this is for GetModuleFileName().
#include <windows.h>
// And this is for CommandLineToArgvW.
#include <shellapi.h>
// SHGetSpecialFolderPath()
#include <shlobj.h>
#endif
@ -74,12 +77,11 @@ extern char **environ;
#define PREREAD_ENVIRONMENT
#endif
// We define the symbol HAVE_GLOBAL_ARGV if we have global variables
// named GLOBAL_ARGC/GLOBAL_ARGV that we can read at static init time
// to determine our command-line arguments.
#if defined(HAVE_GLOBAL_ARGV) && defined(PROTOTYPE_GLOBAL_ARGV)
#if !defined(WIN32_VC) && defined(HAVE_GLOBAL_ARGV) && defined(PROTOTYPE_GLOBAL_ARGV)
extern char **GLOBAL_ARGV;
extern int GLOBAL_ARGC;
#endif
@ -298,7 +300,7 @@ ns_get_environment_variable(const string &var) const {
#endif
}
}
PyGILState_Release(state);
if (main_dir.empty()) {
@ -613,7 +615,7 @@ read_environment_variables() {
////////////////////////////////////////////////////////////////////
void ExecutionEnvironment::
read_args() {
#ifndef ANDROID
// First, we need to fill in _dtool_name. This contains
// the full path to the p3dtool library.
@ -762,7 +764,39 @@ read_args() {
// Next we need to fill in _args, which is a vector containing
// the command-line arguments that the executable was invoked with.
#if defined(IS_FREEBSD)
#if defined(WIN32_VC)
// We cannot rely on __argv when Python is linked in Unicode mode.
// Instead, let's use GetCommandLine.
LPWSTR cmdline = GetCommandLineW();
int argc = 0;
LPWSTR *wargv = CommandLineToArgvW(cmdline, &argc);
if (wargv == NULL) {
cerr << "CommandLineToArgvW failed; command-line arguments unavailable to config.\n";
} else {
TextEncoder encoder;
encoder.set_encoding(Filename::get_filesystem_encoding());
for (int i = 0; i < argc; ++i) {
wstring wtext(wargv[i]);
encoder.set_wtext(wtext);
if (i == 0) {
if (_binary_name.empty()) {
_binary_name = encoder.get_text();
}
} else {
_args.push_back(encoder.get_text());
}
}
LocalFree(wargv);
}
#elif defined(IS_FREEBSD)
// In FreeBSD, we can use sysctl to determine the command-line arguments.
size_t bufsize = 4096;
@ -786,13 +820,17 @@ read_args() {
#elif defined(HAVE_GLOBAL_ARGV)
int argc = GLOBAL_ARGC;
if (_binary_name.empty() && argc > 0) {
_binary_name = GLOBAL_ARGV[0];
// This really needs to be resolved against PATH.
}
// On Windows, __argv can be NULL when the main entry point is
// compiled in Unicode mode (as is the case with Python 3)
if (GLOBAL_ARGV != NULL) {
if (_binary_name.empty() && argc > 0) {
_binary_name = GLOBAL_ARGV[0];
// This really needs to be resolved against PATH.
}
for (int i = 1; i < argc; i++) {
_args.push_back(GLOBAL_ARGV[i]);
for (int i = 1; i < argc; i++) {
_args.push_back(GLOBAL_ARGV[i]);
}
}
#elif defined(HAVE_PROC_SELF_CMDLINE) || defined(HAVE_PROC_CURPROC_CMDLINE)
@ -835,7 +873,7 @@ read_args() {
}
#endif
#ifndef WIN32
#ifndef _WIN32
// Try to use realpath to get cleaner paths.
if (!_binary_name.empty()) {
@ -851,7 +889,9 @@ read_args() {
_dtool_name = newpath;
}
}
#endif
#endif // _WIN32
#endif // ANDROID
if (_dtool_name.empty()) {
_dtool_name = _binary_name;

View File

@ -50,6 +50,9 @@ PUBLISHED:
INLINE static string get_binary_name();
INLINE static string get_dtool_name();
INLINE static void set_binary_name(const string &name);
INLINE static void set_dtool_name(const string &name);
static Filename get_cwd();
private:

View File

@ -61,6 +61,10 @@ TVOLATILE AtomicAdjust::Pointer Filename::_user_appdata_directory;
TVOLATILE AtomicAdjust::Pointer Filename::_common_appdata_directory;
TypeHandle Filename::_type_handle;
#ifdef ANDROID
string Filename::_internal_data_dir;
#endif
#ifdef WIN32
/* begin Win32-specific code */
@ -463,7 +467,7 @@ Filename Filename::
temporary(const string &dirname, const string &prefix, const string &suffix,
Type type) {
Filename fdirname = dirname;
#ifdef WIN32
#if defined(_WIN32) || defined(ANDROID)
// The Windows tempnam() function doesn't do a good job of choosing
// a temporary directory. Choose one ourselves.
if (fdirname.empty()) {
@ -527,7 +531,7 @@ get_home_directory() {
if (home_directory.empty()) {
#ifdef WIN32
wchar_t buffer[MAX_PATH];
// On Windows, fall back to the "My Documents" folder.
if (SHGetSpecialFolderPathW(NULL, buffer, CSIDL_PERSONAL, true)) {
Filename dirname = from_os_specific_w(buffer);
@ -538,15 +542,22 @@ get_home_directory() {
}
}
#elif defined(ANDROID)
// Temporary hack.
home_directory = "/data/data/org.panda3d.sdk";
#elif defined(IS_OSX)
home_directory = get_osx_home_directory();
#elif defined(ANDROID)
home_directory = _internal_data_dir;
#else
// Posix case: check /etc/passwd?
#endif // WIN32
}
if (home_directory.empty()) {
// Fallback case.
home_directory = ExecutionEnvironment::get_cwd();
@ -559,7 +570,7 @@ get_home_directory() {
delete newdir;
}
}
return (*(Filename *)_home_directory);
}
@ -589,6 +600,10 @@ get_temp_directory() {
#elif defined(IS_OSX)
temp_directory = get_osx_temp_directory();
#elif defined(ANDROID)
temp_directory.set_dirname(_internal_data_dir);
temp_directory.set_basename("cache");
#else
// Posix case.
temp_directory = "/tmp";
@ -638,6 +653,10 @@ get_user_appdata_directory() {
#elif defined(IS_OSX)
user_appdata_directory = get_osx_user_appdata_directory();
#elif defined(ANDROID)
user_appdata_directory.set_dirname(_internal_data_dir);
user_appdata_directory.set_basename("files");
#else
// Posix case.
user_appdata_directory = get_home_directory();
@ -687,6 +706,10 @@ get_common_appdata_directory() {
#elif defined(IS_OSX)
common_appdata_directory = get_osx_common_appdata_directory();
#elif defined(ANDROID)
common_appdata_directory.set_dirname(_internal_data_dir);
common_appdata_directory.set_basename("files");
#else
// Posix case.
common_appdata_directory = "/var";

View File

@ -263,6 +263,11 @@ protected:
static TVOLATILE AtomicAdjust::Pointer _user_appdata_directory;
static TVOLATILE AtomicAdjust::Pointer _common_appdata_directory;
#ifdef ANDROID
public:
static string _internal_data_dir;
#endif
public:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -2743,7 +2743,9 @@ int GetParnetDepth(CPPType *type) {
} else if (TypeManager::is_wchar_pointer(type)) {
} else if (TypeManager::is_pointer_to_PyObject(type)) {
} else if (TypeManager::is_pointer_to_Py_buffer(type)) {
} else if (TypeManager::is_pointer(type) || TypeManager::is_reference(type) || TypeManager::is_struct(type)) {
} else if (TypeManager::is_pointer(type) ||
TypeManager::is_reference(type) ||
TypeManager::is_struct(type)) {
++answer;
int deepest = 0;
TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(type)), false);
@ -3276,6 +3278,36 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
only_pyobjects = false;
++num_params;
} else if (TypeManager::is_pointer_to_PyStringObject(type)) {
if (args_type == AT_single_arg) {
// This is a single-arg function, so there's no need
// to convert anything.
param_name = "arg";
extra_param_check += " && PyString_Check(arg)";
} else {
indent(out, indent_level) << "PyStringObject *" << param_name << ";\n";
format_specifiers += "S";
parameter_list += ", &" + param_name;
}
pexpr_string = param_name;
expected_params += "string";
++num_params;
} else if (TypeManager::is_pointer_to_PyUnicodeObject(type)) {
if (args_type == AT_single_arg) {
// This is a single-arg function, so there's no need
// to convert anything.
param_name = "arg";
extra_param_check += " && PyUnicode_Check(arg)";
} else {
indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n";
format_specifiers += "U";
parameter_list += ", &" + param_name;
}
pexpr_string = param_name;
expected_params += "unicode";
++num_params;
} else if (TypeManager::is_pointer_to_PyObject(type)) {
if (args_type == AT_single_arg) {
// This is a single-arg function, so there's no need
@ -3605,7 +3637,7 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
if (true) {
indent(out, indent_level)
<< "if (PyErr_Occurred()) {\n";
delete_return_value(out, indent_level, remap, return_expr);
delete_return_value(out, indent_level + 2, remap, return_expr);
indent(out, indent_level)
<< " if (PyErr_ExceptionMatches(PyExc_TypeError)) {\n";
indent(out, indent_level)

View File

@ -1199,8 +1199,91 @@ is_PyObject(CPPType *type) {
return is_PyObject(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_extension:
case CPPDeclaration::ST_struct:
return (type->get_local_name(&parser) == "PyObject" ||
type->get_local_name(&parser) == "_object");
type->get_local_name(&parser) == "PyTypeObject" ||
type->get_local_name(&parser) == "PyStringObject" ||
type->get_local_name(&parser) == "PyUnicodeObject" ||
type->get_local_name(&parser) == "_object" ||
type->get_local_name(&parser) == "_typeobject");
default:
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::is_pointer_to_PyStringObject
// Access: Public, Static
// Description: Returns true if the indicated type is PyStringObject *.
////////////////////////////////////////////////////////////////////
bool TypeManager::
is_pointer_to_PyStringObject(CPPType *type) {
switch (type->get_subtype()) {
case CPPDeclaration::ST_const:
return is_pointer_to_PyStringObject(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_pointer:
return is_PyStringObject(type->as_pointer_type()->_pointing_at);
default:
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::is_PyStringObject
// Access: Public, Static
// Description: Returns true if the indicated type is PyStringObject.
////////////////////////////////////////////////////////////////////
bool TypeManager::
is_PyStringObject(CPPType *type) {
switch (type->get_subtype()) {
case CPPDeclaration::ST_const:
return is_PyStringObject(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_extension:
case CPPDeclaration::ST_struct:
return (type->get_local_name(&parser) == "PyStringObject");
default:
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::is_pointer_to_PyUnicodeObject
// Access: Public, Static
// Description: Returns true if the indicated type is PyStringObject *.
////////////////////////////////////////////////////////////////////
bool TypeManager::
is_pointer_to_PyUnicodeObject(CPPType *type) {
switch (type->get_subtype()) {
case CPPDeclaration::ST_const:
return is_pointer_to_PyUnicodeObject(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_pointer:
return is_PyUnicodeObject(type->as_pointer_type()->_pointing_at);
default:
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::is_PyUnicodeObject
// Access: Public, Static
// Description: Returns true if the indicated type is PyUnicodeObject.
////////////////////////////////////////////////////////////////////
bool TypeManager::
is_PyUnicodeObject(CPPType *type) {
switch (type->get_subtype()) {
case CPPDeclaration::ST_const:
return is_PyUnicodeObject(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_extension:
case CPPDeclaration::ST_struct:
return (type->get_local_name(&parser) == "PyUnicodeObject");
default:
return false;
@ -1238,6 +1321,7 @@ is_Py_buffer(CPPType *type) {
return is_Py_buffer(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_extension:
case CPPDeclaration::ST_struct:
return (type->get_local_name(&parser) == "Py_buffer");
default:

View File

@ -94,6 +94,10 @@ public:
static bool is_const_ref_to_pointer_to_base(CPPType *type);
static bool is_pointer_to_PyObject(CPPType *type);
static bool is_PyObject(CPPType *type);
static bool is_pointer_to_PyStringObject(CPPType *type);
static bool is_PyStringObject(CPPType *type);
static bool is_pointer_to_PyUnicodeObject(CPPType *type);
static bool is_PyUnicodeObject(CPPType *type);
static bool is_pointer_to_Py_buffer(CPPType *type);
static bool is_Py_buffer(CPPType *type);
static bool involves_unpublished(CPPType *type);

View File

@ -23,6 +23,12 @@
struct _object;
typedef _object PyObject;
struct _typeobject;
typedef _typeobject PyTypeObject;
struct PyStringObject;
struct PyUnicodeObject;
class PyThreadState;
typedef int Py_ssize_t;
struct Py_buffer;

View File

@ -0,0 +1,2 @@
struct AAssetManager;
struct AAsset;

View File

@ -0,0 +1,39 @@
typedef unsigned char jboolean; /* unsigned 8 bits */
typedef signed char jbyte; /* signed 8 bits */
typedef unsigned short jchar; /* unsigned 16 bits */
typedef short jshort; /* signed 16 bits */
typedef int jint; /* signed 32 bits */
typedef long long jlong; /* signed 64 bits */
typedef float jfloat; /* 32-bit IEEE 754 */
typedef double jdouble; /* 64-bit IEEE 754 */
typedef jint jsize;
typedef void* jobject;
typedef jobject jclass;
typedef jobject jstring;
typedef jobject jarray;
typedef jarray jobjectArray;
typedef jarray jbooleanArray;
typedef jarray jbyteArray;
typedef jarray jcharArray;
typedef jarray jshortArray;
typedef jarray jintArray;
typedef jarray jlongArray;
typedef jarray jfloatArray;
typedef jarray jdoubleArray;
typedef jobject jthrowable;
typedef jobject jweak;
struct _jfieldID; /* opaque structure */
typedef struct _jfieldID* jfieldID; /* field IDs */
struct _jmethodID; /* opaque structure */
typedef struct _jmethodID* jmethodID; /* method IDs */
struct JNIInvokeInterface;
struct _JNIEnv;
struct _JavaVM;
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;

View File

@ -121,6 +121,8 @@ extern "C" {
EXPCL_PYSTUB int PyString_AsStringAndSize(...);
EXPCL_PYSTUB int PyString_FromString(...);
EXPCL_PYSTUB int PyString_FromStringAndSize(...);
EXPCL_PYSTUB int PyString_InternFromString(...);
EXPCL_PYSTUB int PyString_InternInPlace(...);
EXPCL_PYSTUB int PyString_Size(...);
EXPCL_PYSTUB int PyString_Type(...);
EXPCL_PYSTUB int PySys_GetObject(...);
@ -152,6 +154,8 @@ extern "C" {
EXPCL_PYSTUB int PyUnicode_FromStringAndSize(...);
EXPCL_PYSTUB int PyUnicode_FromWideChar(...);
EXPCL_PYSTUB int PyUnicode_GetSize(...);
EXPCL_PYSTUB int PyUnicode_InternFromString(...);
EXPCL_PYSTUB int PyUnicode_InternInPlace(...);
EXPCL_PYSTUB int PyUnicode_Type(...);
EXPCL_PYSTUB int Py_BuildValue(...);
EXPCL_PYSTUB int Py_InitModule4(...);
@ -296,6 +300,8 @@ int PyString_AsString(...) { return 0; }
int PyString_AsStringAndSize(...) { return 0; }
int PyString_FromString(...) { return 0; }
int PyString_FromStringAndSize(...) { return 0; }
int PyString_InternFromString(...) { return 0; }
int PyString_InternInPlace(...) { return 0; }
int PyString_Size(...) { return 0; }
int PyString_Type(...) { return 0; }
int PySys_GetObject(...) { return 0; }
@ -327,6 +333,8 @@ int PyUnicode_FromString(...) { return 0; }
int PyUnicode_FromStringAndSize(...) { return 0; }
int PyUnicode_FromWideChar(...) { return 0; }
int PyUnicode_GetSize(...) { return 0; }
int PyUnicode_InternFromString(...) { return 0; }
int PyUnicode_InternInPlace(...) { return 0; }
int PyUnicode_Type(...) { return 0; }
int Py_BuildValue(...) { return 0; }
int Py_InitModule4(...) { return 0; }

View File

@ -30,8 +30,8 @@ import time
import os
import sys
## jGenPyCode tries to get the directory for Direct from the sys.path. This only works if you
## have installed the sdk using a installer. This would not work if the installer was
## jGenPyCode tries to get the directory for Direct from the sys.path. This only works if you
## have installed the sdk using a installer. This would not work if the installer was
## never used and everything was grabbed into a virgin environment using cvs.
sys.path.append(os.getcwd())
@ -88,14 +88,14 @@ PkgListSet(["PYTHON", "DIRECT", # Python support
"VRPN", "OPENSSL", # Transport
"FFTW", # Algorithm helpers
"ARTOOLKIT", "OPENCV", "DIRECTCAM", "VISION", # Augmented Reality
"NPAPI", "AWESOMIUM", # Browser embedding
"GTK2", "WX", "FLTK", # Toolkit support
"ROCKET", # GUI libraries
"GTK2", # GTK2 is used for PStats on Unix
"NPAPI", "MFC", "WX", "FLTK", # Used for web plug-in only
"ROCKET", "AWESOMIUM", # GUI libraries
"CARBON", "COCOA", # Mac OS X toolkits
"X11", "XF86DGA", "XRANDR", "XCURSOR", # Unix platform support
"PANDATOOL", "PVIEW", "DEPLOYTOOLS", # Toolchain
"SKEL", # Example SKEL project
"PANDAFX", # Some distortion special lenses
"PANDAFX", # Some distortion special lenses
"PANDAPARTICLESYSTEM", # Built in particle system
"CONTRIB", # Experimental
"SSE2", "NEON", # Compiler features
@ -216,7 +216,7 @@ def parseopts(args):
if STRDXSDKVERSION == '':
print("No DirectX SDK version specified. Using 'default' DirectX SDK search")
STRDXSDKVERSION = 'default'
elif (option=="--platform-sdk"):
elif (option=="--platform-sdk"):
STRMSPLATFORMVERSION = value.strip().lower()
if STRMSPLATFORMVERSION == '':
print("No MS Platform SDK version specified. Using 'default' MS Platform SDK search")
@ -234,7 +234,7 @@ def parseopts(args):
if (option=="--everything" or option.startswith("--use-")
or option=="--nothing" or option.startswith("--no-")):
anything = 1
except:
except:
usage(0)
print("Exception while parsing commandline:", sys.exc_info()[0])
if (anything==0): usage(0)
@ -492,7 +492,7 @@ if (COMPILER == "MSVC"):
LibName(pkg, 'dxerr.lib')
else:
LibName(pkg, 'dxerrVNUM.lib'.replace("VNUM", vnum))
LibName(pkg, 'ddraw.lib')
#LibName(pkg, 'ddraw.lib')
LibName(pkg, 'dxguid.lib')
IncDirectory("ALWAYS", GetThirdpartyDir() + "extras/include")
LibName("WINSOCK", "wsock32.lib")
@ -536,7 +536,6 @@ if (COMPILER == "MSVC"):
if (PkgSkip("FFTW")==0): LibName("FFTW", GetThirdpartyDir() + "fftw/lib/fftw.lib")
if (PkgSkip("ARTOOLKIT")==0):LibName("ARTOOLKIT",GetThirdpartyDir() + "artoolkit/lib/libAR.lib")
if (PkgSkip("FCOLLADA")==0): LibName("FCOLLADA", GetThirdpartyDir() + "fcollada/lib/FCollada.lib")
if (PkgSkip("SQUISH")==0): LibName("SQUISH", GetThirdpartyDir() + "squish/lib/squish.lib")
if (PkgSkip("OPENCV")==0): LibName("OPENCV", GetThirdpartyDir() + "opencv/lib/cv.lib")
if (PkgSkip("OPENCV")==0): LibName("OPENCV", GetThirdpartyDir() + "opencv/lib/highgui.lib")
if (PkgSkip("OPENCV")==0): LibName("OPENCV", GetThirdpartyDir() + "opencv/lib/cvaux.lib")
@ -548,6 +547,11 @@ if (COMPILER == "MSVC"):
if (PkgSkip("FFMPEG")==0): LibName("FFMPEG", GetThirdpartyDir() + "ffmpeg/lib/avutil.lib")
if (PkgSkip("SWSCALE")==0): LibName("SWSCALE", GetThirdpartyDir() + "ffmpeg/lib/swscale.lib")
if (PkgSkip("SWRESAMPLE")==0):LibName("SWRESAMPLE",GetThirdpartyDir() + "ffmpeg/lib/swresample.lib")
if (PkgSkip("SQUISH")==0):
if GetOptimize() <= 2:
LibName("SQUISH", GetThirdpartyDir() + "squish/lib/squishd.lib")
else:
LibName("SQUISH", GetThirdpartyDir() + "squish/lib/squish.lib")
if (PkgSkip("ROCKET")==0):
LibName("ROCKET", GetThirdpartyDir() + "rocket/lib/RocketCore.lib")
LibName("ROCKET", GetThirdpartyDir() + "rocket/lib/RocketControls.lib")
@ -663,21 +667,6 @@ if (COMPILER=="GCC"):
IncDirectory("ALWAYS", "/usr/local/include")
LibDirectory("ALWAYS", "/usr/local/lib")
if GetHost() != "darwin":
# Workaround for an issue where pkg-config does not include this path
if GetTargetArch() in ("x86_64", "amd64"):
if (os.path.isdir("/usr/lib64/glib-2.0/include")):
IncDirectory("GTK2", "/usr/lib64/glib-2.0/include")
if (os.path.isdir("/usr/lib64/gtk-2.0/include")):
IncDirectory("GTK2", "/usr/lib64/gtk-2.0/include")
if (os.path.isdir("/usr/X11R6/lib64")):
LibDirectory("ALWAYS", "/usr/X11R6/lib64")
else:
LibDirectory("ALWAYS", "/usr/X11R6/lib")
else:
LibDirectory("ALWAYS", "/usr/X11R6/lib")
fcollada_libs = ("FColladaD", "FColladaSD", "FColladaS")
# WARNING! The order of the ffmpeg libraries matters!
ffmpeg_libs = ("libavformat", "libavcodec", "libavutil")
@ -752,6 +741,22 @@ if (COMPILER=="GCC"):
SmartPkgEnable("XF86DGA", "xxf86dga", "Xxf86dga", "X11/extensions/xf86dga.h")
SmartPkgEnable("XCURSOR", "xcursor", "Xcursor", "X11/Xcursor/Xcursor.h")
if GetHost() != "darwin":
# Workaround for an issue where pkg-config does not include this path
if GetTargetArch() in ("x86_64", "amd64"):
if (os.path.isdir("/usr/lib64/glib-2.0/include")):
IncDirectory("GTK2", "/usr/lib64/glib-2.0/include")
if (os.path.isdir("/usr/lib64/gtk-2.0/include")):
IncDirectory("GTK2", "/usr/lib64/gtk-2.0/include")
if not PkgSkip("X11"):
if (os.path.isdir("/usr/X11R6/lib64")):
LibDirectory("ALWAYS", "/usr/X11R6/lib64")
else:
LibDirectory("ALWAYS", "/usr/X11R6/lib")
elif not PkgSkip("X11"):
LibDirectory("ALWAYS", "/usr/X11R6/lib")
if (RUNTIME):
# For the runtime, all packages are required
for pkg in ["OPENSSL", "ZLIB", "NPAPI", "JPEG", "PNG"]:
@ -924,7 +929,7 @@ def CompileCxx(obj,src,opts):
cmd += "/DWINVER=0x601 "
cmd += "/Fo" + obj + " /nologo /c"
if (GetTargetArch() != 'x64' and PkgSkip("SSE2") == 0):
cmd += " /arch:SSE2"
cmd += " /arch:SSE2"
for x in ipath: cmd += " /I" + x
for (opt,dir) in INCDIRECTORIES:
if (opt=="ALWAYS") or (opt in opts): cmd += " /I" + BracketNameWithQuotes(dir)
@ -936,7 +941,7 @@ def CompileCxx(obj,src,opts):
if (optlevel==1): cmd += " /MDd /Zi /RTCs /GS"
if (optlevel==2): cmd += " /MDd /Zi"
if (optlevel==3): cmd += " /MD /Zi /O2 /Ob2 /Oi /Ot /fp:fast /DFORCE_INLINING"
if (optlevel==4):
if (optlevel==4):
cmd += " /MD /Zi /Ox /Ob2 /Oi /Ot /fp:fast /DFORCE_INLINING /DNDEBUG /GL"
cmd += " /Oy /Zp16" # jean-claude add /Zp16 insures correct static alignment for SSEx
@ -982,11 +987,11 @@ def CompileCxx(obj,src,opts):
if (optlevel==3):
cmd += " /MD /Zi /O2 /Oi /Ot /arch:SSE3"
cmd += " /Ob0"
cmd += " /Qipo-" # beware of IPO !!!
cmd += " /Qipo-" # beware of IPO !!!
## Lesson learned: Don't use /GL flag -> end result is MESSY
## ----------------------------------------------------------------
if (optlevel==4):
cmd += " /MD /Zi /O3 /Oi /Ot /Ob0 /Yc /DNDEBUG" # /Ob0 a ete rajoute en cours de route a 47%
cmd += " /MD /Zi /O3 /Oi /Ot /Ob0 /Yc /DNDEBUG" # /Ob0 a ete rajoute en cours de route a 47%
cmd += " /Qipo" # optimization multi file
# for 3 & 4 optimization levels
@ -998,7 +1003,7 @@ def CompileCxx(obj,src,opts):
cmd += " /Qopt-matmul" # needs /O2 or /O3
cmd += " /Qprec-div-"
cmd += " /Qsimd"
cmd += " /QxHost" # compile for target host; Compiling for distribs should probably strictly enforce /arch:..
cmd += " /Quse-intel-optimized-headers" # use intel optimized headers
cmd += " /Qparallel" # enable parallelization
@ -1006,7 +1011,7 @@ def CompileCxx(obj,src,opts):
## PCH files coexistence: the /Qpchi option causes the Intel C++ Compiler to name its
## PCH files with a .pchi filename suffix and reduce build time.
## The /Qpchi option is on by default but interferes with Microsoft libs; so use /Qpchi- to turn it off.
## The /Qpchi option is on by default but interferes with Microsoft libs; so use /Qpchi- to turn it off.
## I need to have a deeper look at this since the compile time is quite influenced by this setting !!!
cmd += " /Qpchi-" # keep it this way!
@ -1024,7 +1029,7 @@ def CompileCxx(obj,src,opts):
## Use this option if you always define a class before you declare a pointer to a member of the class.
## The compiler will issue an error if it encounters a pointer declaration before the class is defined.
## Alternate: #pragma pointers_to_members
cmd += " /Fd" + os.path.splitext(obj)[0] + ".pdb"
building = GetValueOption(opts, "BUILDING:")
if (building): cmd += " /DBUILDING_" + building
@ -1032,10 +1037,10 @@ def CompileCxx(obj,src,opts):
cmd += " /bigobj"
# level of warnings and optimization reports
if GetVerbose():
if GetVerbose():
cmd += " /W3 " # or /W4 or /Wall
cmd += " /Qopt-report:2 /Qopt-report-phase:hlo /Qopt-report-phase:hpo" # some optimization reports
else:
else:
cmd += " /W1 "
cmd += " /EHa /Zm300 /DWIN32_VC /DWIN32"
if GetTargetArch() == 'x64':
@ -1043,10 +1048,10 @@ def CompileCxx(obj,src,opts):
cmd += " " + BracketNameWithQuotes(src)
oscmd(cmd)
if (COMPILER=="GCC"):
if (src.endswith(".c")): cmd = GetCC() +' -fPIC -c -o ' + obj
else: cmd = GetCXX()+' -ftemplate-depth-30 -fPIC -c -o ' + obj
else: cmd = GetCXX()+' -ftemplate-depth-50 -fPIC -c -o ' + obj
for (opt, dir) in INCDIRECTORIES:
if (opt=="ALWAYS") or (opt in opts): cmd += ' -I' + BracketNameWithQuotes(dir)
for (opt,var,val) in DEFSYMBOLS:
@ -1070,9 +1075,12 @@ def CompileCxx(obj,src,opts):
cmd += ' --sysroot=%s -no-canonical-prefixes' % (SDK["SYSROOT"])
# Android-specific flags.
arch = GetTargetArch()
if GetTarget() == "android":
cmd += ' -I%s/include' % (SDK["ANDROID_STL"])
cmd += ' -I%s/libs/%s/include' % (SDK["ANDROID_STL"], SDK["ANDROID_ABI"])
cmd += ' -ffunction-sections -funwind-tables'
arch = GetTargetArch()
if arch == 'armv7a':
cmd += ' -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__'
cmd += ' -fstack-protector -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16'
@ -1111,9 +1119,9 @@ def CompileCxx(obj,src,opts):
else:
cmd += " -pthread"
if PkgSkip("SSE2") == 0:
if PkgSkip("SSE2") == 0 and not arch.startswith("arm"):
cmd += " -msse2"
if (optlevel==1): cmd += " -ggdb -D_DEBUG"
if (optlevel==2): cmd += " -O1 -D_DEBUG"
if (optlevel==3): cmd += " -O2"
@ -1217,7 +1225,7 @@ def CompileIgate(woutd,wsrc,opts):
# NOTE: this 1600 value is the version number for VC2010.
cmd += ' -D_MSC_VER=1600 -D"_declspec(param)=" -D_near -D_far -D__near -D__far -D__stdcall'
if (COMPILER=="GCC"):
cmd += ' -DCPPPARSER -D__STDC__=1 -D__cplusplus -D__inline -D__const=const'
cmd += ' -DCPPPARSER -D__STDC__=1 -D__cplusplus -D__inline -D__const=const -D__attribute__\(x\)='
if GetTargetArch() in ("x86_64", "amd64"):
cmd += ' -D_LP64'
else:
@ -1339,7 +1347,7 @@ def CompileLink(dll, obj, opts):
if ("MFC" not in opts):
cmd += " /NOD:MFC90.LIB /NOD:MFC80.LIB /NOD:LIBCMT"
cmd += " /NOD:LIBCI.LIB /DEBUG"
cmd += " /nod:libc /nod:libcmtd /nod:atlthunk /nod:atls"
cmd += " /nod:libc /nod:libcmtd /nod:atlthunk /nod:atls /nod:atlsd"
if (GetOrigExt(dll) != ".exe"): cmd += " /DLL"
optlevel = GetOptimizeOption(opts)
if (optlevel==1): cmd += " /MAP /MAPINFO:EXPORTS /NOD:MSVCRT.LIB /NOD:MSVCPRT.LIB /NOD:MSVCIRT.LIB"
@ -1390,7 +1398,7 @@ def CompileLink(dll, obj, opts):
oscmd(cmd)
else:
cmd = "xilink"
if GetVerbose(): cmd += " /verbose:lib"
if GetVerbose(): cmd += " /verbose:lib"
if HasTargetArch():
cmd += " /MACHINE:" + GetTargetArch().upper()
if ("MFC" not in opts):
@ -1495,7 +1503,7 @@ def CompileLink(dll, obj, opts):
# Android-specific flags.
if GetTarget() == 'android':
cmd += " -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now"
cmd += " -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now"
if GetTargetArch() == 'armv7a':
cmd += " -march=armv7-a -Wl,--fix-cortex-a8"
cmd += ' -lc -lm'
@ -2130,7 +2138,7 @@ def WriteConfigSettings():
if (PkgSkip("TOUCHINPUT") == 0 and GetTarget() == "windows"):
dtool_config["HAVE_WIN_TOUCHINPUT"] = '1'
if (GetOptimize() <= 3):
dtool_config["HAVE_ROCKET_DEBUGGER"] = '1'
@ -3168,6 +3176,7 @@ if (not RUNTIME):
TargetAdd('libp3gobj.in', opts=['IMOD:panda3d.core', 'ILIB:libp3gobj', 'SRCDIR:panda/src/gobj'])
TargetAdd('libp3gobj_igate.obj', input='libp3gobj.in', opts=["DEPENDENCYONLY"])
TargetAdd('p3gobj_geomVertexArrayData_ext.obj', opts=OPTS, input='geomVertexArrayData_ext.cxx')
TargetAdd('p3gobj_internalName_ext.obj', opts=OPTS, input='internalName_ext.cxx')
#
# DIRECTORY: panda/src/pgraphnodes/
@ -3539,6 +3548,7 @@ if (not RUNTIME):
TargetAdd('libpanda.dll', input='p3putil_typedWritable_ext.obj')
TargetAdd('libpanda.dll', input='p3pnmimage_pfmFile_ext.obj')
TargetAdd('libpanda.dll', input='p3gobj_geomVertexArrayData_ext.obj')
TargetAdd('libpanda.dll', input='p3gobj_internalName_ext.obj')
TargetAdd('libpanda.dll', input='p3pgraph_ext_composite.obj')
TargetAdd('libpanda.dll', input='p3display_graphicsStateGuardian_ext.obj')
@ -3825,16 +3835,15 @@ if (PkgSkip("OPENSSL")==0 and not RTDIST and not RUNTIME and PkgSkip("DEPLOYTOOL
TargetAdd('build_patch.exe', input=COMMON_PANDA_LIBS_PYSTUB)
TargetAdd('build_patch.exe', opts=OPTS)
if not PkgSkip("ZLIB"):
TargetAdd('check_adler_check_adler.obj', opts=OPTS, input='check_adler.cxx')
TargetAdd('check_adler.exe', input=['check_adler_check_adler.obj'])
TargetAdd('check_adler.exe', input=COMMON_PANDA_LIBS_PYSTUB)
TargetAdd('check_adler.exe', opts=OPTS)
TargetAdd('check_adler_check_adler.obj', opts=OPTS, input='check_adler.cxx')
TargetAdd('check_adler.exe', input=['check_adler_check_adler.obj'])
TargetAdd('check_adler.exe', input=COMMON_PANDA_LIBS_PYSTUB)
TargetAdd('check_adler.exe', opts=OPTS)
TargetAdd('check_crc_check_crc.obj', opts=OPTS, input='check_crc.cxx')
TargetAdd('check_crc.exe', input=['check_crc_check_crc.obj'])
TargetAdd('check_crc.exe', input=COMMON_PANDA_LIBS_PYSTUB)
TargetAdd('check_crc.exe', opts=OPTS)
TargetAdd('check_crc_check_crc.obj', opts=OPTS, input='check_crc.cxx')
TargetAdd('check_crc.exe', input=['check_crc_check_crc.obj'])
TargetAdd('check_crc.exe', input=COMMON_PANDA_LIBS_PYSTUB)
TargetAdd('check_crc.exe', opts=OPTS)
TargetAdd('check_md5_check_md5.obj', opts=OPTS, input='check_md5.cxx')
TargetAdd('check_md5.exe', input=['check_md5_check_md5.obj'])
@ -4470,7 +4479,7 @@ if (PkgSkip("DIRECT")==0):
TargetAdd('packpanda.obj', opts=OPTS+['BUILDING:PACKPANDA'], input='ppython.cxx')
TargetAdd('packpanda.exe', input='packpanda.obj')
TargetAdd('packpanda.exe', opts=['PYTHON'])
DefSymbol("BUILDING:EGGCACHER", "IMPORT_MODULE", "direct.directscripts.eggcacher")
TargetAdd('eggcacher.obj', opts=OPTS+['BUILDING:EGGCACHER'], input='ppython.cxx')
TargetAdd('eggcacher.exe', input='eggcacher.obj')
@ -4738,7 +4747,7 @@ if (RUNTIME and PkgSkip("NPAPI")==0):
# DIRECTORY: direct/src/plugin_activex/
#
if (RUNTIME and GetTarget() == 'windows'):
if (RUNTIME and GetTarget() == 'windows' and PkgSkip("MFC")==0):
OPTS=['DIR:direct/src/plugin_activex', 'RUNTIME', 'ACTIVEX', 'MFC']
DefSymbol('ACTIVEX', '_USRDLL', '')
DefSymbol('ACTIVEX', '_WINDLL', '')
@ -5805,7 +5814,7 @@ if (PkgSkip("PYTHON")==0 and not RUNTIME):
TargetAdd('PandaModules.py', input='fx.pyd')
if (PkgSkip("DIRECT")==0):
TargetAdd('PandaModules.py', input='direct.pyd')
if (PkgSkip("VISION")==0):
if (PkgSkip("VISION")==0):
TargetAdd('PandaModules.py', input='vision.pyd')
if (PkgSkip("SKEL")==0):
TargetAdd('PandaModules.py', input='skel.pyd')
@ -6042,11 +6051,25 @@ def MakeInstallerNSIS(file, fullname, smdirectory, installdir):
elif (os.path.isdir(file)):
shutil.rmtree(file)
if GetTargetArch() == 'x64':
regview = '64'
else:
regview = '32'
if (RUNTIME):
# Invoke the make_installer script.
AddToPathEnv("PATH", GetOutputDir() + "\\bin")
AddToPathEnv("PATH", GetOutputDir() + "\\plugins")
oscmd(sys.executable + " -B direct\\src\\plugin_installer\\make_installer.py --version %s" % VERSION)
cmd = sys.executable + " -B -u direct\\src\\plugin_installer\\make_installer.py"
cmd += " --version %s --regview %s" % (VERSION, regview)
if GetTargetArch() == 'x64':
cmd += " --install \"$PROGRAMFILES64\\Panda3D\" "
else:
cmd += " --install \"$PROGRAMFILES32\\Panda3D\" "
oscmd(cmd)
shutil.move("direct\\src\\plugin_installer\\p3d-setup.exe", file)
return
@ -6059,11 +6082,6 @@ def MakeInstallerNSIS(file, fullname, smdirectory, installdir):
psource = os.path.abspath(".")
panda = os.path.abspath(GetOutputDir())
if GetTargetArch() == 'x64':
regview = '64'
else:
regview = '32'
nsis_defs = {
'COMPRESSOR' : COMPRESSOR,
'NAME' : fullname,

View File

@ -37,6 +37,7 @@ HAS_TARGET_ARCH = False
TOOLCHAIN_PREFIX = ""
ANDROID_ABI = None
SYS_LIB_DIRS = []
DEBUG_DEPENDENCIES = False
# Is the current Python a 32-bit or 64-bit build? There doesn't
# appear to be a universal test for this.
@ -220,7 +221,7 @@ def ProgressOutput(progress, msg, target = None):
prefix = "%s[%s %d%%%s] " % (GetColor("yellow"), GetColor("cyan"), progress, GetColor("yellow"))
else:
global THREADS
ident = thread.get_ident()
if (ident not in THREADS):
THREADS[ident] = len(THREADS) + 1
@ -468,7 +469,7 @@ def LocateBinary(binary):
p = os.environ["PATH"]
pathList = p.split(os.pathsep)
if GetHost() == 'windows':
if not binary.endswith('.exe'):
# Append .exe if necessary
@ -652,7 +653,10 @@ def NeedsBuild(files, others):
for file in files:
dates[file] = GetTimestamp(file)
if not os.path.exists(file):
if DEBUG_DEPENDENCIES:
print("rebuilding %s because it does not exist" % (file))
return True
for file in others:
dates[file] = GetTimestamp(file)
@ -661,6 +665,16 @@ def NeedsBuild(files, others):
cached = BUILTFROMCACHE[key]
if cached == dates:
return False
elif DEBUG_DEPENDENCIES:
print("rebuilding %s because:" % (key))
for key in frozenset(cached.keys()) | frozenset(dates.keys()):
if key not in cached:
print(" new dependency: %s" % (key))
elif key not in dates:
print(" removed dependency: %s" % (key))
elif cached[key] != dates[key]:
print(" dependency changed: %s" % (key))
if VERBOSE and frozenset(cached) != frozenset(dates):
print("%sWARNING:%s file dependencies changed: %s%s%s" % (GetColor("red"), GetColor(), GetColor("green"), files, GetColor()))
@ -857,7 +871,7 @@ def CxxCalcDependencies(srcfile, ipath, ignore):
########################################################################
if sys.platform == "win32":
# Note: not supported on cygwin.
# Note: not supported on cygwin.
if sys.version_info >= (3, 0):
import winreg
else:
@ -1118,7 +1132,7 @@ def GetThirdpartyBase():
THIRDPARTYBASE = "thirdparty"
if "MAKEPANDA_THIRDPARTY" in os.environ:
THIRDPARTYBASE = os.environ["MAKEPANDA_THIRDPARTY"]
return THIRDPARTYBASE
def GetThirdpartyDir():
@ -1181,40 +1195,44 @@ def GetThirdpartyDir():
########################################################################
def GetOutputDir():
return OUTPUTDIR
return OUTPUTDIR
def IsCustomOutputDir():
return CUSTOM_OUTPUTDIR
return CUSTOM_OUTPUTDIR
def SetOutputDir(outputdir):
global OUTPUTDIR, CUSTOM_OUTPUTDIR
OUTPUTDIR=outputdir
CUSTOM_OUTPUTDIR=True
global OUTPUTDIR, CUSTOM_OUTPUTDIR
OUTPUTDIR = outputdir
CUSTOM_OUTPUTDIR = True
def GetOptimize():
return int(OPTIMIZE)
return int(OPTIMIZE)
def SetOptimize(optimize):
global OPTIMIZE
OPTIMIZE=optimize
global OPTIMIZE
OPTIMIZE = optimize
def GetVerbose():
return VERBOSE
return VERBOSE
def SetVerbose(verbose):
global VERBOSE
VERBOSE=verbose
global VERBOSE
VERBOSE = verbose
def SetDebugDependencies(dd = True):
global DEBUG_DEPENDENCIES
DEBUG_DEPENDENCIES = dd
def GetLinkAllStatic():
return LINK_ALL_STATIC
return LINK_ALL_STATIC
def SetLinkAllStatic(val = True):
global LINK_ALL_STATIC
LINK_ALL_STATIC = val
global LINK_ALL_STATIC
LINK_ALL_STATIC = val
def UnsetLinkAllStatic():
global LINK_ALL_STATIC
LINK_ALL_STATIC = False
global LINK_ALL_STATIC
LINK_ALL_STATIC = False
########################################################################
##
@ -1292,7 +1310,7 @@ def OverrideValue(parameter, value):
def PkgConfigHavePkg(pkgname, tool = "pkg-config"):
"""Returns a bool whether the pkg-config package is installed."""
if (sys.platform == "win32" or not LocateBinary(tool)):
if (sys.platform == "win32" or CrossCompiling() or not LocateBinary(tool)):
return False
if (tool == "pkg-config"):
handle = os.popen(LocateBinary("pkg-config") + " --silence-errors --modversion " + pkgname)
@ -1307,7 +1325,7 @@ def PkgConfigHavePkg(pkgname, tool = "pkg-config"):
def PkgConfigGetLibs(pkgname, tool = "pkg-config"):
"""Returns a list of libs for the package, prefixed by -l."""
if (sys.platform == "win32" or not LocateBinary(tool)):
if (sys.platform == "win32" or CrossCompiling() or not LocateBinary(tool)):
return []
if (tool == "pkg-config"):
handle = os.popen(LocateBinary("pkg-config") + " --silence-errors --libs-only-l " + pkgname)
@ -1338,7 +1356,7 @@ def PkgConfigGetLibs(pkgname, tool = "pkg-config"):
def PkgConfigGetIncDirs(pkgname, tool = "pkg-config"):
"""Returns a list of includes for the package, NOT prefixed by -I."""
if (sys.platform == "win32" or not LocateBinary(tool)):
if (sys.platform == "win32" or CrossCompiling() or not LocateBinary(tool)):
return []
if (tool == "pkg-config"):
handle = os.popen(LocateBinary("pkg-config") + " --silence-errors --cflags-only-I " + pkgname)
@ -1359,7 +1377,7 @@ def PkgConfigGetIncDirs(pkgname, tool = "pkg-config"):
def PkgConfigGetLibDirs(pkgname, tool = "pkg-config"):
"""Returns a list of library paths for the package, NOT prefixed by -L."""
if (sys.platform == "win32" or not LocateBinary(tool)):
if (sys.platform == "win32" or CrossCompiling() or not LocateBinary(tool)):
return []
if (tool == "pkg-config"):
handle = os.popen(LocateBinary("pkg-config") + " --silence-errors --libs-only-L " + pkgname)
@ -1379,7 +1397,7 @@ def PkgConfigGetLibDirs(pkgname, tool = "pkg-config"):
def PkgConfigGetDefSymbols(pkgname, tool = "pkg-config"):
"""Returns a dictionary of preprocessor definitions."""
if (sys.platform == "win32" or not LocateBinary(tool)):
if (sys.platform == "win32" or CrossCompiling() or not LocateBinary(tool)):
return []
if (tool == "pkg-config"):
handle = os.popen(LocateBinary("pkg-config") + " --silence-errors --cflags " + pkgname)
@ -1411,7 +1429,6 @@ def PkgConfigEnable(opt, pkgname, tool = "pkg-config"):
def LibraryExists(lib, lpath=[]):
""" Returns True if this library was found in the given search path, False otherwise. """
target = GetTarget()
for dir in lpath:
@ -1517,6 +1534,7 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
for d, v in defs.values():
DefSymbol(target_pkg, d, v)
return
elif (GetHost() == "darwin" and framework != None):
if (os.path.isdir("/Library/Frameworks/%s.framework" % framework) or
os.path.isdir("/System/Library/Frameworks/%s.framework" % framework) or
@ -1532,6 +1550,7 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
print("%sERROR:%s Could not locate framework %s, aborting build" % (GetColor("red"), GetColor(), framework))
exit()
return
elif (LocateBinary(tool) != None and (tool != "pkg-config" or pkgconfig != None)):
if (isinstance(pkgconfig, str) or tool != "pkg-config"):
if (PkgConfigHavePkg(pkgconfig, tool)):
@ -1553,6 +1572,7 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
else:
print("%sERROR:%s Could not locate pkg-config package %s, aborting build" % (GetColor("red"), GetColor(), pkgconfig))
exit()
else:
# Okay, our pkg-config attempts failed. Let's try locating the libs by ourselves.
have_pkg = True
@ -1825,56 +1845,84 @@ def SdkLocateMax():
SDK[version+"CS"] = top + subdir
def SdkLocatePython(force_use_sys_executable = False):
if (PkgSkip("PYTHON")==0):
if GetTarget() != GetHost():
exit('Use --no-python when cross-compiling until support has been added')
if PkgSkip("PYTHON"):
SDK["PYTHONEXEC"] = os.path.realpath(sys.executable)
return
if (GetTarget() == 'windows' and not force_use_sys_executable):
SDK["PYTHON"] = GetThirdpartyBase()+"/win-python"
if (GetOptimize() <= 2):
SDK["PYTHON"] += "-dbg"
if (GetTargetArch() == 'x64' and os.path.isdir(SDK["PYTHON"] + "-x64")):
SDK["PYTHON"] += "-x64"
if CrossCompiling():
force_use_sys_executable = False
SDK["PYTHONEXEC"] = SDK["PYTHON"].replace('/', '\\') + "\\python"
if (GetOptimize() <= 2):
SDK["PYTHONEXEC"] += "_d.exe"
else:
SDK["PYTHONEXEC"] += ".exe"
if (not os.path.isfile(SDK["PYTHONEXEC"])):
exit("Could not find %s!" % SDK["PYTHONEXEC"])
# Determine which version it is by checking which dll is in the directory.
if (GetOptimize() <= 2):
py_dlls = glob.glob(SDK["PYTHON"] + "/python[0-9][0-9]_d.dll")
else:
py_dlls = glob.glob(SDK["PYTHON"] + "/python[0-9][0-9].dll")
if len(py_dlls) == 0:
exit("Could not find the Python dll in %s." % (SDK["PYTHON"]))
elif len(py_dlls) > 1:
exit("Found multiple Python dlls in %s." % (SDK["PYTHON"]))
py_dll = os.path.basename(py_dlls[0])
SDK["PYTHONVERSION"] = "python" + py_dll[6] + "." + py_dll[7]
elif (GetTarget() == 'windows'):
SDK["PYTHON"] = os.path.dirname(sysconfig.get_python_inc())
SDK["PYTHONVERSION"] = "python" + sysconfig.get_python_version()
SDK["PYTHONEXEC"] = sys.executable
if (GetTarget() == 'windows' and not force_use_sys_executable):
SDK["PYTHON"] = GetThirdpartyBase() + "/win-python"
if (GetOptimize() <= 2):
SDK["PYTHON"] += "-dbg"
if (GetTargetArch() == 'x64' and os.path.isdir(SDK["PYTHON"] + "-x64")):
SDK["PYTHON"] += "-x64"
SDK["PYTHONEXEC"] = SDK["PYTHON"].replace('/', '\\') + "\\python"
if (GetOptimize() <= 2):
SDK["PYTHONEXEC"] += "_d.exe"
else:
SDK["PYTHON"] = sysconfig.get_python_inc()
SDK["PYTHONVERSION"] = "python" + sysconfig.get_python_version()
SDK["PYTHONEXEC"] = os.path.realpath(sys.executable)
SDK["PYTHONEXEC"] += ".exe"
if GetVerbose():
print("Using Python %s build located at %s" % (SDK["PYTHONVERSION"][6:9], SDK["PYTHON"]))
if (not os.path.isfile(SDK["PYTHONEXEC"])):
exit("Could not find %s!" % SDK["PYTHONEXEC"])
# Determine which version it is by checking which dll is in the directory.
if (GetOptimize() <= 2):
py_dlls = glob.glob(SDK["PYTHON"] + "/python[0-9][0-9]_d.dll")
else:
py_dlls = glob.glob(SDK["PYTHON"] + "/python[0-9][0-9].dll")
if len(py_dlls) == 0:
exit("Could not find the Python dll in %s." % (SDK["PYTHON"]))
elif len(py_dlls) > 1:
exit("Found multiple Python dlls in %s." % (SDK["PYTHON"]))
py_dll = os.path.basename(py_dlls[0])
SDK["PYTHONVERSION"] = "python" + py_dll[6] + "." + py_dll[7]
os.environ["PYTHONHOME"] = SDK["PYTHON"]
elif CrossCompiling():
tp_python = os.path.join(GetThirdpartyDir(), "python")
SDK["PYTHON"] = tp_python + "/include"
if GetTarget() == 'darwin':
py_libs = glob.glob(tp_python + "/lib/libpython[0-9].[0-9].dylib")
else:
py_libs = glob.glob(tp_python + "/lib/libpython[0-9].[0-9].so")
if len(py_libs) == 0:
py_libs = glob.glob(tp_python + "/lib/libpython[0-9].[0-9].a")
if len(py_libs) == 0:
exit("Could not find the Python library in %s." % (tp_python))
elif len(py_libs) > 1:
exit("Found multiple Python libraries in %s." % (tp_python))
py_lib = os.path.basename(py_libs[0])
SDK["PYTHONVERSION"] = "python" + py_lib[9] + "." + py_lib[11]
elif (GetTarget() == 'windows'):
SDK["PYTHON"] = os.path.dirname(sysconfig.get_python_inc())
SDK["PYTHONVERSION"] = "python" + sysconfig.get_python_version()
SDK["PYTHONEXEC"] = sys.executable
else:
SDK["PYTHON"] = sysconfig.get_python_inc()
SDK["PYTHONVERSION"] = "python" + sysconfig.get_python_version()
SDK["PYTHONEXEC"] = os.path.realpath(sys.executable)
if CrossCompiling():
SDK["PYTHONEXEC"] = sys.executable
host_version = "python" + sysconfig.get_python_version()
if SDK["PYTHONVERSION"] != host_version:
exit("Host Python version (%s) must be the same as target Python version (%s)!" % (host_version, SDK["PYTHONVERSION"]))
if GetVerbose():
print("Using Python %s build located at %s" % (SDK["PYTHONVERSION"][6:9], SDK["PYTHON"]))
def SdkLocateVisualStudio():
if (GetHost() != "windows"): return
vcdir = GetRegistryKey("SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7", "10.0")
@ -2025,9 +2073,9 @@ def SdkLocateAndroid():
SDK["ANDROID_NDK"] = ndk_root
# Determine the toolchain location.
gcc_ver = '4.7'
gcc_ver = '4.8'
arch = GetTargetArch()
if arch == 'armv7' or arch == 'arm':
if arch == 'armv7a' or arch == 'arm':
arch = 'arm'
toolchain = 'arm-linux-androideabi-' + gcc_ver
elif arch == 'x86':
@ -2045,8 +2093,10 @@ def SdkLocateAndroid():
#IncDirectory("ALWAYS", os.path.join(SDK["SYSROOT"], 'usr', 'include'))
stdlibc = os.path.join(ndk_root, 'sources', 'cxx-stl', 'gnu-libstdc++', gcc_ver)
IncDirectory("ALWAYS", os.path.join(stdlibc, 'include'))
IncDirectory("ALWAYS", os.path.join(stdlibc, 'libs', abi, 'include'))
SDK["ANDROID_STL"] = stdlibc
#IncDirectory("ALWAYS", os.path.join(stdlibc, 'include'))
#IncDirectory("ALWAYS", os.path.join(stdlibc, 'libs', abi, 'include'))
stl_lib = os.path.join(stdlibc, 'libs', abi, 'libgnustl_shared.so')
LibName("ALWAYS", stl_lib)
@ -2231,7 +2281,9 @@ def SetupBuildEnvironment(compiler):
global SYS_LIB_DIRS
# gcc doesn't add this one, but we do want it:
SYS_LIB_DIRS.append('/usr/local/lib')
local_lib = SDK.get("SYSROOT", "") + "/usr/local/lib"
if os.path.isdir(local_lib):
SYS_LIB_DIRS.append(local_lib)
cmd = GetCXX() + " -print-search-dirs"
@ -2253,7 +2305,8 @@ def SetupBuildEnvironment(compiler):
returnval = handle.close()
if returnval != None and returnval != 0:
print("%sWARNING:%s %s failed" % (GetColor("red"), GetColor(), cmd))
SYS_LIB_DIRS += ['/usr/lib']
SYS_LIB_DIRS += [SDK.get("SYSROOT", "") + "/usr/lib"]
elif GetVerbose():
print("System library search path: %s" % ':'.join(SYS_LIB_DIRS))
@ -2753,4 +2806,4 @@ def TargetAdd(target, dummy=0, opts=0, input=0, dep=0, ipath=0, winrc=0):
t.deps[FindLocation("dtool_have_python.dat", [])] = 1
if target.endswith(".pz") and not CrossCompiling():
t.deps[FindLocation("pzip.exe", [])] = 1
t.deps[FindLocation("pzip.exe", [])] = 1

View File

@ -16,6 +16,7 @@
#include "config_util.h"
#include "virtualFileMountAndroidAsset.h"
#include "virtualFileSystem.h"
#include "filename.h"
#include "config_display.h"
//#define OPENGLES_1
@ -45,9 +46,36 @@ void android_main(struct android_app* app) {
return;
}
// Fetch the data directory.
jclass activity_class = env->GetObjectClass(activity->clazz);
jmethodID get_appinfo = env->GetMethodID(activity_class, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");
jobject appinfo = env->CallObjectMethod(activity->clazz, get_appinfo);
jclass appinfo_class = env->GetObjectClass(appinfo);
// Fetch the path to the data directory.
jfieldID datadir_field = env->GetFieldID(appinfo_class, "dataDir", "Ljava/lang/String;");
jstring datadir = (jstring) env->GetObjectField(appinfo, datadir_field);
const char *data_path = env->GetStringUTFChars(datadir, NULL);
Filename::_internal_data_dir = data_path;
android_cat.info() << "Path to data: " << data_path << "\n";
env->ReleaseStringUTFChars(datadir, data_path);
// Fetch the path to the library directory.
jfieldID libdir_field = env->GetFieldID(appinfo_class, "nativeLibraryDir", "Ljava/lang/String;");
jstring libdir = (jstring) env->GetObjectField(appinfo, libdir_field);
const char *lib_path = env->GetStringUTFChars(libdir, NULL);
string dtool_name = string(lib_path) + "/libp3dtool.so";
ExecutionEnvironment::set_dtool_name(dtool_name);
android_cat.info() << "Path to dtool: " << dtool_name << "\n";
env->ReleaseStringUTFChars(libdir, lib_path);
// Get the path to the APK.
jclass clazz = env->GetObjectClass(activity->clazz);
jmethodID methodID = env->GetMethodID(clazz, "getPackageCodePath", "()Ljava/lang/String;");
jmethodID methodID = env->GetMethodID(activity_class, "getPackageCodePath", "()Ljava/lang/String;");
jstring code_path = (jstring) env->CallObjectMethod(activity->clazz, methodID);
const char* apk_path;

View File

@ -326,7 +326,7 @@ open_window() {
return false;
}
//_fb_properties = androidgsg->get_fb_properties();
_fb_properties = androidgsg->get_fb_properties();
androiddisplay_cat.error() << "open_window done\n";
@ -434,7 +434,7 @@ handle_command(struct android_app *app, int32_t command) {
void AndroidGraphicsWindow::
ns_handle_command(int32_t command) {
WindowProperties properties;
switch (command) {
case APP_CMD_SAVE_STATE:
// The system has asked us to save our current state. Do so.
@ -446,16 +446,25 @@ ns_handle_command(int32_t command) {
// The window is being shown, get it ready.
if (_app->window != NULL) {
create_surface();
properties.set_size(ANativeWindow_getWidth(_app->window),
ANativeWindow_getHeight(_app->window));
properties.set_minimized(false);
system_changed_properties(properties);
}
break;
case APP_CMD_CONFIG_CHANGED:
properties.set_size(ANativeWindow_getWidth(_app->window),
ANativeWindow_getHeight(_app->window));
system_changed_properties(properties);
break;
case APP_CMD_TERM_WINDOW:
destroy_surface();
properties.set_minimized(true);
system_changed_properties(properties);
break;
case APP_CMD_WINDOW_RESIZED:
properties.set_size(ANativeWindow_getWidth(_app->window),
ANativeWindow_getHeight(_app->window));
break;
case APP_CMD_WINDOW_REDRAW_NEEDED:
break;

View File

@ -38,6 +38,7 @@
lru.h \
nativeWindowHandle.I nativeWindowHandle.h \
parasiteBuffer.I parasiteBuffer.h \
pStatGPUTimer.I pStatGPUTimer.h \
windowHandle.I windowHandle.h \
windowProperties.I windowProperties.h \
renderBuffer.h \
@ -112,6 +113,7 @@
lru.h \
nativeWindowHandle.I nativeWindowHandle.h \
parasiteBuffer.I parasiteBuffer.h \
pStatGPUTimer.I pStatGPUTimer.h \
windowHandle.I windowHandle.h \
windowProperties.I windowProperties.h \
renderBuffer.h \

View File

@ -580,9 +580,9 @@ get_region_pixels_i(int i, int &xo, int &yo, int &w, int &h) const {
CDReader cdata(_cycler);
const Region &region = cdata->_regions[i];
xo = region._pixels_i[0];
yo = region._pixels_i[2];
yo = region._pixels_i[3];
w = region._pixels_i[1] - xo;
h = region._pixels_i[3] - yo;
h = region._pixels_i[2] - yo;
}
////////////////////////////////////////////////////////////////////
@ -1068,9 +1068,9 @@ INLINE void DisplayRegionPipelineReader::
get_region_pixels_i(int i, int &xo, int &yo, int &w, int &h) const {
const DisplayRegion::Region &region = _cdata->_regions[i];
xo = region._pixels_i[0];
yo = region._pixels_i[2];
yo = region._pixels_i[3];
w = region._pixels_i[1] - xo;
h = region._pixels_i[3] - yo;
h = region._pixels_i[2] - yo;
}
////////////////////////////////////////////////////////////////////

View File

@ -24,6 +24,7 @@
#include "cullTraverser.h"
#include "clockObject.h"
#include "pStatTimer.h"
#include "pStatGPUTimer.h"
#include "pStatClient.h"
#include "pStatCollector.h"
#include "mutexHolder.h"
@ -52,7 +53,7 @@
#define WINDOWS_LEAN_AND_MEAN
#include <WinSock2.h>
#include <wtypes.h>
#undef WINDOWS_LEAN_AND_MEAN
#undef WINDOWS_LEAN_AND_MEAN
#else
#include <sys/time.h>
#endif
@ -140,7 +141,7 @@ GraphicsEngine(Pipeline *pipeline) :
_windows_sorted = true;
_window_sort_index = 0;
_needs_open_windows = false;
set_threading_model(GraphicsThreadingModel(threading_model));
if (!_threading_model.is_default()) {
display_cat.info()
@ -188,7 +189,7 @@ set_threading_model(const GraphicsThreadingModel &threading_model) {
return;
}
}
#ifndef THREADED_PIPELINE
if (!threading_model.is_single_threaded()) {
display_cat.warning()
@ -238,7 +239,7 @@ get_threading_model() const {
//
// If a null pointer is supplied for the gsg, then this
// routine will create a new gsg.
//
//
// This routine is only called from the app thread.
////////////////////////////////////////////////////////////////////
@ -283,7 +284,7 @@ make_output(GraphicsPipe *pipe,
// already-initialized gsg.
// Simplify the input parameters.
int x_size = 0, y_size = 0;
if (win_prop.has_size()) {
x_size = win_prop.get_x_size();
@ -359,7 +360,7 @@ make_output(GraphicsPipe *pipe,
// an unencumbered GSG.
return NULL;
}
// Determine if a parasite buffer meets the user's specs.
bool can_use_parasite = false;
@ -381,7 +382,7 @@ make_output(GraphicsPipe *pipe,
// Even if prefer-parasite-buffer is set, parasites are not preferred
// if the host window is too small, or if the host window does not
// have the requested properties.
if ((prefer_parasite_buffer) &&
(can_use_parasite) &&
(x_size <= host->get_x_size())&&
@ -408,10 +409,10 @@ make_output(GraphicsPipe *pipe,
}
// Ask the pipe to create a window.
for (int retry=0; retry<10; retry++) {
bool precertify = false;
PT(GraphicsOutput) window =
PT(GraphicsOutput) window =
pipe->make_output(name, fb_prop, win_prop, flags, this, gsg, host, retry, precertify);
if (window != (GraphicsOutput *)NULL) {
window->_sort = sort;
@ -455,11 +456,11 @@ make_output(GraphicsPipe *pipe,
nassertr(removed, NULL);
}
}
// Parasite buffers were not preferred, but the pipe could not
// create a window to the user's specs. Try a parasite as a
// last hope.
if (can_use_parasite) {
ParasiteBuffer *buffer = new ParasiteBuffer(host, name, x_size, y_size, flags);
buffer->_sort = sort;
@ -613,7 +614,7 @@ remove_all_windows() {
// Access: Published
// Description: Resets the framebuffer of the current window. This
// is currently used by DirectX 8 only. It calls a
// reset_window function on each active window to
// reset_window function on each active window to
// release/create old/new framebuffer
////////////////////////////////////////////////////////////////////
void GraphicsEngine::
@ -712,11 +713,11 @@ render_frame() {
if (!_windows_sorted) {
do_resort_windows();
}
if (sync_flip && _flip_state != FS_flip) {
do_flip_frame(current_thread);
}
// Are any of the windows ready to be deleted?
Windows new_windows;
new_windows.reserve(_windows.size());
@ -726,10 +727,10 @@ render_frame() {
nassertv(win != NULL);
if (win->get_delete_flag()) {
do_remove_window(win, current_thread);
} else {
new_windows.push_back(win);
// Let's calculate each scene's bounding volume here in App,
// before we cycle the pipeline. The cull traversal will
// calculate it anyway, but if we calculate it in App first
@ -770,11 +771,11 @@ render_frame() {
}
_loaded_textures.clear();
}
// Now it's time to do any drawing from the main frame--after all of
// the App code has executed, but before we begin the next frame.
_app.do_frame(this, current_thread);
// Grab each thread's mutex again after all windows have flipped,
// and wait for the thread to finish.
{
@ -783,32 +784,32 @@ render_frame() {
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
RenderThread *thread = (*ti).second;
thread->_cv_mutex.acquire();
while (thread->_thread_state != TS_wait) {
thread->_cv_done.wait();
}
}
}
#if defined(THREADED_PIPELINE) && defined(DO_PSTATS)
_cyclers_pcollector.set_level(_pipeline->get_num_cyclers());
_dirty_cyclers_pcollector.set_level(_pipeline->get_num_dirty_cyclers());
#ifdef DEBUG_THREADS
if (PStatClient::is_connected()) {
_pipeline->iterate_all_cycler_types(pstats_count_cycler_type, this);
_pipeline->iterate_dirty_cycler_types(pstats_count_dirty_cycler_type, this);
}
#endif // DEBUG_THREADS
#endif // THREADED_PIPELINE && DO_PSTATS
GeomCacheManager::flush_level();
CullTraverser::flush_level();
RenderState::flush_level();
TransformState::flush_level();
CullableObject::flush_level();
// Now cycle the pipeline and officially begin the next frame.
#ifdef THREADED_PIPELINE
{
@ -816,15 +817,15 @@ render_frame() {
_pipeline->cycle();
}
#endif // THREADED_PIPELINE
global_clock->tick(current_thread);
if (global_clock->check_errors(current_thread)) {
throw_event("clock_error");
}
#ifdef DO_PSTATS
PStatClient::main_tick();
// Reset our pcollectors that track data across the frame.
CullTraverser::_nodes_pcollector.clear_level();
CullTraverser::_geom_nodes_pcollector.clear_level();
@ -833,18 +834,18 @@ render_frame() {
GeomCacheManager::_geom_cache_record_pcollector.clear_level();
GeomCacheManager::_geom_cache_erase_pcollector.clear_level();
GeomCacheManager::_geom_cache_evict_pcollector.clear_level();
GraphicsStateGuardian::init_frame_pstats();
_transform_states_pcollector.set_level(TransformState::get_num_states());
_render_states_pcollector.set_level(RenderState::get_num_states());
if (pstats_unused_states) {
_transform_states_unused_pcollector.set_level(TransformState::get_num_unused_states());
_render_states_unused_pcollector.set_level(RenderState::get_num_unused_states());
}
_sw_sprites_pcollector.clear_level();
_cnode_volume_pcollector.clear_level();
_gnode_volume_pcollector.clear_level();
_geom_volume_pcollector.clear_level();
@ -869,18 +870,18 @@ render_frame() {
_occlusion_passed_pcollector.clear_level();
_occlusion_failed_pcollector.clear_level();
_occlusion_tests_pcollector.clear_level();
if (PStatClient::is_connected()) {
size_t small_buf = GeomVertexArrayData::get_small_lru()->get_total_size();
size_t independent = GeomVertexArrayData::get_independent_lru()->get_total_size();
size_t resident = VertexDataPage::get_global_lru(VertexDataPage::RC_resident)->get_total_size();
size_t compressed = VertexDataPage::get_global_lru(VertexDataPage::RC_compressed)->get_total_size();
size_t pending = VertexDataPage::get_pending_lru()->get_total_size();
VertexDataSaveFile *save_file = VertexDataPage::get_save_file();
size_t total_disk = save_file->get_total_file_size();
size_t used_disk = save_file->get_used_file_size();
_vertex_data_small_pcollector.set_level(small_buf);
_vertex_data_independent_pcollector.set_level(independent);
_vertex_data_pending_pcollector.set_level(pending);
@ -889,11 +890,11 @@ render_frame() {
_vertex_data_unused_disk_pcollector.set_level(total_disk - used_disk);
_vertex_data_used_disk_pcollector.set_level(used_disk);
}
#endif // DO_PSTATS
GeomVertexArrayData::lru_epoch();
// Now signal all of our threads to begin their next frame.
Threads::const_iterator ti;
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
@ -904,24 +905,24 @@ render_frame() {
}
thread->_cv_mutex.release();
}
// Some threads may still be drawing, so indicate that we have to
// wait for those threads before we can flip.
_flip_state = _auto_flip ? FS_flip : FS_draw;
}
// Now the lock is released.
if (yield_timeslice) {
// Nap for a moment to yield the timeslice, to be polite to other
// running applications.
PStatTimer timer(_yield_pcollector, current_thread);
Thread::force_yield();
} else if (!Thread::is_true_threads()) {
} else if (!Thread::is_true_threads()) {
PStatTimer timer(_yield_pcollector, current_thread);
Thread::consider_yield();
}
// Anything that happens outside of GraphicsEngine::render_frame()
// is deemed to be App.
_app_pcollector.start();
@ -961,11 +962,11 @@ open_windows() {
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
RenderThread *thread = (*ti).second;
thread->_cv_mutex.acquire();
while (thread->_thread_state != TS_wait) {
thread->_cv_done.wait();
}
thread->_thread_state = TS_do_windows;
thread->_cv_start.notify();
thread->_cv_mutex.release();
@ -1004,7 +1005,7 @@ sync_frame() {
// we seems to return once all draw calls have been submitted.
// Calling 'flip_frame' after this function should immediately
// cause a buffer flip. This function will only work in
// opengl right now, for all other graphics pipelines it will
// opengl right now, for all other graphics pipelines it will
// simply return immediately. In opengl it's a bit of a hack:
// it will attempt to read a single pixel from the frame buffer to
// force the graphics card to finish drawing before it returns
@ -1082,7 +1083,7 @@ extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg) {
WindowRenderer *wr = get_window_renderer(draw_name, 0);
RenderThread *thread = (RenderThread *)wr;
MutexHolder holder2(thread->_cv_mutex);
while (thread->_thread_state != TS_wait) {
thread->_cv_done.wait();
}
@ -1131,7 +1132,7 @@ dispatch_compute(const LVecBase3i &work_groups, const ShaderAttrib *sattr, Graph
WindowRenderer *wr = get_window_renderer(draw_name, 0);
RenderThread *thread = (RenderThread *)wr;
MutexHolder holder2(thread->_cv_mutex);
while (thread->_thread_state != TS_wait) {
thread->_cv_done.wait();
}
@ -1149,7 +1150,7 @@ dispatch_compute(const LVecBase3i &work_groups, const ShaderAttrib *sattr, Graph
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::get_global_ptr
// Access: Published, Static
// Description:
// Description:
////////////////////////////////////////////////////////////////////
GraphicsEngine *GraphicsEngine::
get_global_ptr() {
@ -1217,7 +1218,7 @@ do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
local_frustum = DCAST(GeometricBoundingVolume, bv->make_copy());
NodePath scene_parent = scene_setup->get_scene_root().get_parent(current_thread);
CPT(TransformState) cull_center_transform =
CPT(TransformState) cull_center_transform =
scene_setup->get_cull_center().get_transform(scene_parent, current_thread);
local_frustum->xform(cull_center_transform->get_mat());
@ -1338,7 +1339,7 @@ cull_and_draw_together(const GraphicsEngine::Windows &wlist,
if (win->begin_frame(GraphicsOutput::FM_render, current_thread)) {
win->clear(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);
@ -1377,7 +1378,7 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
GraphicsStateGuardian *gsg = win->get_gsg();
nassertv(gsg != (GraphicsStateGuardian *)NULL);
DisplayRegionPipelineReader *dr_reader =
DisplayRegionPipelineReader *dr_reader =
new DisplayRegionPipelineReader(dr, current_thread);
win->change_scenes(dr_reader);
@ -1410,9 +1411,9 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
// 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);
@ -1456,7 +1457,7 @@ cull_to_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) {
DisplayRegionPipelineReader *dr_reader =
DisplayRegionPipelineReader *dr_reader =
new DisplayRegionPipelineReader(dr, current_thread);
NodePath camera = dr_reader->get_camera();
AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(camera, (DisplayRegion *)NULL)).first;
@ -1467,7 +1468,7 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
dr_reader = NULL;
(*aci).second = dr;
cull_to_bins(win, dr, current_thread);
} else {
// We have already culled a scene using this camera in
// this thread, and now we're being asked to cull another
@ -1481,7 +1482,7 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
setup_scene(win->get_gsg(), dr_reader),
current_thread);
}
if (dr_reader != (DisplayRegionPipelineReader *)NULL) {
delete dr_reader;
}
@ -1539,7 +1540,7 @@ cull_to_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *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(cull_result, scene_setup, current_thread);
}
@ -1560,53 +1561,73 @@ draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
size_t wlist_size = wlist.size();
for (size_t wi = 0; wi < wlist_size; ++wi) {
GraphicsOutput *win = wlist[wi];
if (win->is_active()) {
if (win->flip_ready()) {
GraphicsStateGuardian *gsg = win->get_gsg();
GraphicsOutput *host = win->get_host();
if (host->flip_ready()) {
{
// We can't use a PStatGPUTimer before begin_frame, so when using GPU
// timing, it is advisable to set auto-flip to #t.
PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
win->begin_flip();
host->begin_flip();
}
{
PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
win->end_flip();
host->end_flip();
}
}
PStatTimer timer(win->get_draw_window_pcollector(), current_thread);
if (win->begin_frame(GraphicsOutput::FM_render, current_thread)) {
win->clear(current_thread);
// We have to place this collector inside begin_frame, because
// we need a current context for PStatGPUTimer to work.
{
PStatGPUTimer timer(win->get_gsg(), win->get_draw_window_pcollector(), current_thread);
win->clear(current_thread);
if (display_cat.is_spam()) {
display_cat.spam()
<< "Drawing window " << win->get_name() << "\n";
}
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) {
draw_bins(win, dr, current_thread);
if (display_cat.is_spam()) {
display_cat.spam()
<< "Drawing window " << win->get_name() << "\n";
}
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) {
draw_bins(win, dr, current_thread);
}
}
}
win->end_frame(GraphicsOutput::FM_render, current_thread);
if (_auto_flip) {
#ifdef DO_PSTATS
// This is a good time to perform a latency query.
if (win->get_gsg()->get_timer_queries_active()) {
win->get_gsg()->issue_timer_query(GraphicsStateGuardian::_command_latency_pcollector.get_index());
}
#endif
if (win->flip_ready()) {
{
// begin_flip doesn't do anything interesting, let's not waste two timer queries on that.
PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
win->begin_flip();
}
{
PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
PStatGPUTimer timer(win->get_gsg(), GraphicsEngine::_flip_end_pcollector, current_thread);
win->end_flip();
}
}
}
} else {
if (display_cat.is_spam()) {
display_cat.spam()
<< "Not drawing window " << win->get_name() << "\n";
}
}
} else {
if (display_cat.is_spam()) {
display_cat.spam()
@ -1723,8 +1744,6 @@ ready_flip_windows(const GraphicsEngine::Windows &wlist, Thread *current_thread)
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::do_sync_frame
// Access: Private
@ -1752,7 +1771,6 @@ do_sync_frame(Thread *current_thread) {
_flip_state = FS_sync;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::do_ready_flip
// Access: Private
@ -1778,8 +1796,6 @@ do_ready_flip(Thread *current_thread) {
}
_app.do_ready_flip(this,current_thread);
_flip_state = FS_sync;
}
////////////////////////////////////////////////////////////////////
@ -1812,7 +1828,7 @@ do_flip_frame(Thread *current_thread) {
}
}
}
// Now signal all of our threads to flip the windows.
_app.do_flip(this, current_thread);
@ -1896,7 +1912,7 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) {
// There must be a singular transform over the scene.
if (!_singular_warning_last_frame) {
display_cat.warning()
<< "Scene " << scene_root << " has net scale ("
<< "Scene " << scene_root << " has net scale ("
<< scene_root.get_scale(NodePath()) << "); cannot render.\n";
_singular_warning_this_frame = true;
}
@ -1907,7 +1923,7 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) {
// There must be a singular transform over the camera.
if (!_singular_warning_last_frame) {
display_cat.warning()
<< "Camera " << camera << " has net scale ("
<< "Camera " << camera << " has net scale ("
<< camera.get_scale(NodePath()) << "); cannot render.\n";
}
_singular_warning_this_frame = true;
@ -1951,11 +1967,12 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) {
void GraphicsEngine::
do_draw(CullResult *cull_result, SceneSetup *scene_setup,
GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
// Statistics
PStatTimer timer(dr->get_draw_region_pcollector(), current_thread);
GraphicsStateGuardian *gsg = win->get_gsg();
CallbackObject *cbobj;
GraphicsStateGuardian *gsg = win->get_gsg();
// Statistics
PStatGPUTimer timer(gsg, dr->get_draw_region_pcollector(), current_thread);
{
DisplayRegionPipelineReader dr_reader(dr, current_thread);
@ -2034,20 +2051,20 @@ do_add_window(GraphicsOutput *window,
_windows_sorted = false;
_windows.push_back(window);
WindowRenderer *cull =
WindowRenderer *cull =
get_window_renderer(threading_model.get_cull_name(),
threading_model.get_cull_stage());
WindowRenderer *draw =
WindowRenderer *draw =
get_window_renderer(threading_model.get_draw_name(),
threading_model.get_draw_stage());
if (threading_model.get_cull_sorting()) {
cull->add_window(cull->_cull, window);
draw->add_window(draw->_draw, window);
} else {
cull->add_window(cull->_cdraw, window);
}
// Ask the pipe which thread it prefers to run its windowing
// commands in (the "window thread"). This is the thread that
// handles the commands to open, resize, etc. the window. X
@ -2057,7 +2074,7 @@ do_add_window(GraphicsOutput *window,
// has been bound in a given thread, it cannot subsequently be bound
// in any other thread, and we have to bind a context in
// open_window()).
switch (window->get_pipe()->get_preferred_window_thread()) {
case GraphicsPipe::PWT_app:
_app.add_window(_app._window, window);
@ -2096,8 +2113,8 @@ do_add_gsg(GraphicsStateGuardian *gsg, GraphicsPipe *pipe,
}
auto_adjust_capabilities(gsg);
WindowRenderer *draw =
WindowRenderer *draw =
get_window_renderer(threading_model.get_draw_name(),
threading_model.get_draw_stage());
@ -2228,7 +2245,7 @@ auto_adjust_capabilities(GraphicsStateGuardian *gsg) {
<< "textures_power_2 to 'up' or 'down'.\n";
textures_power_2 = ATS_down; // Not a fix. Just suppresses further error messages.
}
if (textures_auto_power_2 && !Texture::has_textures_power_2()) {
if (gsg->get_supports_tex_non_pow2()) {
Texture::set_textures_power_2(ATS_none);
@ -2236,13 +2253,13 @@ auto_adjust_capabilities(GraphicsStateGuardian *gsg) {
Texture::set_textures_power_2(textures_power_2);
}
}
if ((Texture::get_textures_power_2() == ATS_none) &&
if ((Texture::get_textures_power_2() == ATS_none) &&
(!gsg->get_supports_tex_non_pow2())) {
// Overaggressive configuration detected
display_cat.error()
display_cat.error()
<< "The 'textures_power_2' configuration is set to 'none', meaning \n"
<< "that non-power-of-two texture support is required, but the video \n"
<< "driver I'm trying to use does not support non-power-of-two textures.\n";
@ -2251,7 +2268,7 @@ auto_adjust_capabilities(GraphicsStateGuardian *gsg) {
display_cat.error()
<< "The 'none' did not come from the config file. In other words,\n"
<< "the variable 'textures_power_2' was altered procedurally.\n";
if (textures_auto_power_2) {
display_cat.error()
<< "It is possible that it was set by panda's automatic mechanisms,\n"
@ -2264,7 +2281,7 @@ auto_adjust_capabilities(GraphicsStateGuardian *gsg) {
}
}
}
if (shader_auto_utilization && (shader_utilization != SUT_none)) {
display_cat.error()
<< "Invalid panda config file: if you set the config-variable\n"
@ -2272,7 +2289,7 @@ auto_adjust_capabilities(GraphicsStateGuardian *gsg) {
<< "shader_utilization to 'none'.\n";
shader_utilization = SUT_none; // Not a fix. Just suppresses further error messages.
}
if (shader_auto_utilization && !Shader::have_shader_utilization()) {
if (gsg->get_supports_basic_shaders()) {
Shader::set_shader_utilization(SUT_basic);
@ -2280,13 +2297,13 @@ auto_adjust_capabilities(GraphicsStateGuardian *gsg) {
Shader::set_shader_utilization(SUT_none);
}
}
if ((Shader::get_shader_utilization() != SUT_none) &&
if ((Shader::get_shader_utilization() != SUT_none) &&
(!gsg->get_supports_basic_shaders())) {
// Overaggressive configuration detected
display_cat.error()
display_cat.error()
<< "The 'shader_utilization' config variable is set, meaning\n"
<< "that panda may try to generate shaders. However, the video \n"
<< "driver I'm trying to use does not support shaders.\n";
@ -2295,7 +2312,7 @@ auto_adjust_capabilities(GraphicsStateGuardian *gsg) {
display_cat.error()
<< "The 'shader_utilization' setting did not come from the config\n"
<< "file. In other words, it was altered procedurally.\n";
if (shader_auto_utilization) {
display_cat.error()
<< "It is possible that it was set by panda's automatic mechanisms,\n"
@ -2323,7 +2340,7 @@ terminate_threads(Thread *current_thread) {
// We spend almost our entire time in this method just waiting for
// threads. Time it appropriately.
PStatTimer timer(_wait_pcollector, current_thread);
// First, wait for all the threads to finish their current frame.
// Grabbing the mutex should achieve that.
Threads::const_iterator ti;
@ -2331,7 +2348,7 @@ terminate_threads(Thread *current_thread) {
RenderThread *thread = (*ti).second;
thread->_cv_mutex.acquire();
}
// Now tell them to close their windows and terminate.
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
RenderThread *thread = (*ti).second;
@ -2345,7 +2362,7 @@ terminate_threads(Thread *current_thread) {
RenderThread *thread = (*ti).second;
thread->join();
}
_threads.clear();
}
@ -2451,7 +2468,7 @@ get_window_renderer(const string &name, int pipeline_stage) {
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::WindowRenderer::Constructor
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
GraphicsEngine::WindowRenderer::
WindowRenderer(const string &name) :
@ -2589,7 +2606,7 @@ do_frame(GraphicsEngine *engine, Thread *current_thread) {
// This one has no outstanding pointers; clean it up.
GraphicsPipe *pipe = gsg->get_pipe();
engine->close_gsg(pipe, gsg);
} else {
} else {
// This one is ok; preserve it.
new_gsgs.insert(gsg);
}
@ -2668,12 +2685,12 @@ do_close(GraphicsEngine *engine, Thread *current_thread) {
// This one has no outstanding pointers; clean it up.
GraphicsPipe *pipe = gsg->get_pipe();
engine->close_gsg(pipe, gsg);
} else {
} else {
// This one is ok; preserve it.
new_gsgs.insert(gsg);
}
}
_gsgs.swap(new_gsgs);
}
@ -2729,10 +2746,10 @@ any_done_gsgs() const {
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::RenderThread::Constructor
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
GraphicsEngine::RenderThread::
RenderThread(const string &name, GraphicsEngine *engine) :
RenderThread(const string &name, GraphicsEngine *engine) :
Thread(name, "Main"),
WindowRenderer(name),
_engine(engine),

View File

@ -1,6 +1,6 @@
// Filename: graphicsStateGuardian.I
// Created by: drose (24Sep99)
// Updated by: fperazzi, PandaSE (29Apr10) (added
// Updated by: fperazzi, PandaSE (29Apr10) (added
// get_max_2d_texture_array_layers and related)
//
////////////////////////////////////////////////////////////////////
@ -334,10 +334,10 @@ get_max_3d_texture_dimension() const {
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_max_2d_texture_array_layers
// Access: Published
// Description: Returns the largest possible number of pages, or -1
// Description: Returns the largest possible number of pages, or -1
// if there is no particular limit. Returns 0 if 2-d
// texture arrays not supported.
//
//
// The value returned may not be meaningful until after
// the graphics context has been fully created (e.g. the
// window has been opened).
@ -447,6 +447,16 @@ get_supports_tex_non_pow2() const {
return _supports_tex_non_pow2;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_supports_texture_srgb
// Access: Published
// Description: Returns true if this GSG can handle sRGB textures.
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsStateGuardian::
get_supports_texture_srgb() const {
return _supports_texture_srgb;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_supports_compressed_texture
// Access: Published
@ -713,6 +723,45 @@ get_supports_geometry_instancing() const {
return _supports_geometry_instancing;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_supports_occlusion_query
// Access: Published
// Description: Returns true if this GSG supports an occlusion query.
// If this is true, then begin_occlusion_query() and
// end_occlusion_query() may be called to bracket a
// sequence of draw_triangles() (or whatever) calls to
// measure pixels that pass the depth test.
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
get_supports_occlusion_query() const {
return _supports_occlusion_query;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_supports_timer_query
// Access: Published
// Description: Returns true if this GSG supports a timer query.
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
get_supports_timer_query() const {
return _supports_timer_query;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_timer_queries_active
// Access: Published
// Description: Returns true if timer queries are currently
// enabled on this GSG.
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
get_timer_queries_active() const {
#ifdef DO_PSTATS
return _timer_queries_active;
#else
return false;
#endif
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_max_color_targets
// Access: Published

View File

@ -28,6 +28,7 @@
#include "throw_event.h"
#include "clockObject.h"
#include "pStatTimer.h"
#include "pStatGPUTimer.h"
#include "geomTristrips.h"
#include "geomTrifans.h"
#include "geomLinestrips.h"
@ -55,6 +56,7 @@
#include "colorScaleAttrib.h"
#include "clipPlaneAttrib.h"
#include "fogAttrib.h"
#include "config_pstats.h"
#include <algorithm>
#include <limits.h>
@ -87,9 +89,19 @@ PStatCollector GraphicsStateGuardian::_draw_primitive_pcollector("Draw:Primitive
PStatCollector GraphicsStateGuardian::_draw_set_state_pcollector("Draw:Set State");
PStatCollector GraphicsStateGuardian::_clear_pcollector("Draw:Clear");
PStatCollector GraphicsStateGuardian::_flush_pcollector("Draw:Flush");
PStatCollector GraphicsStateGuardian::_compute_dispatch_pcollector("Draw:Compute dispatch");
PStatCollector GraphicsStateGuardian::_wait_occlusion_pcollector("Wait:Occlusion");
PStatCollector GraphicsStateGuardian::_wait_timer_pcollector("Wait:Timer Queries");
PStatCollector GraphicsStateGuardian::_timer_queries_pcollector("Timer queries");
PStatCollector GraphicsStateGuardian::_command_latency_pcollector("Command latency");
PStatCollector GraphicsStateGuardian::_prepare_pcollector("Draw:Prepare");
PStatCollector GraphicsStateGuardian::_prepare_texture_pcollector("Draw:Prepare:Texture");
PStatCollector GraphicsStateGuardian::_prepare_geom_pcollector("Draw:Prepare:Geom");
PStatCollector GraphicsStateGuardian::_prepare_shader_pcollector("Draw:Prepare:Shader");
PStatCollector GraphicsStateGuardian::_prepare_vertex_buffer_pcollector("Draw:Prepare:Vertex buffer");
PStatCollector GraphicsStateGuardian::_prepare_index_buffer_pcollector("Draw:Prepare:Index buffer");
PStatCollector GraphicsStateGuardian::_draw_set_state_transform_pcollector("Draw:Set State:Transform");
PStatCollector GraphicsStateGuardian::_draw_set_state_alpha_test_pcollector("Draw:Set State:Alpha test");
@ -115,7 +127,6 @@ PStatCollector GraphicsStateGuardian::_draw_set_state_stencil_pcollector("Draw:S
PStatCollector GraphicsStateGuardian::_draw_set_state_fog_pcollector("Draw:Set State:Fog");
PStatCollector GraphicsStateGuardian::_draw_set_state_scissor_pcollector("Draw:Set State:Scissor");
PT(TextureStage) GraphicsStateGuardian::_alpha_scale_texture_stage = NULL;
TypeHandle GraphicsStateGuardian::_type_handle;
@ -184,6 +195,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
_supports_2d_texture_array = false;
_supports_cube_map = false;
_supports_tex_non_pow2 = false;
_supports_texture_srgb = false;
_supports_compressed_texture = false;
_compressed_texture_formats.clear();
_compressed_texture_formats.set_bit(Texture::CM_off);
@ -197,6 +209,16 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
_max_vertex_transform_indices = 0;
_supports_occlusion_query = false;
_supports_timer_query = false;
#ifdef DO_PSTATS
_timer_queries_active = false;
_last_query_frame = 0;
_last_num_queried = 0;
//_timer_delta = 0.0;
_pstats_gpu_thread = -1;
#endif
// Initially, we set this to false; a GSG that knows it has this
// property should set it to true.
@ -261,7 +283,7 @@ GraphicsStateGuardian::
delete _stencil_render_states;
_stencil_render_states = 0;
}
if (_shader_generator) {
delete _shader_generator;
_shader_generator = 0;
@ -322,7 +344,7 @@ get_supported_geom_rendering() const {
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_supports_cg_profile
// Access: Published, Virtual
// Description: Returns true if this particular GSG supports the
// Description: Returns true if this particular GSG supports the
// specified Cg Shader Profile.
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
@ -405,7 +427,7 @@ get_prepared_objects() {
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
set_gamma(PN_stdfloat gamma) {
_gamma = gamma;
_gamma = gamma;
return false;
}
@ -437,7 +459,7 @@ restore_gamma() {
// function returns false.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
traverse_prepared_textures(GraphicsStateGuardian::TextureCallback *func,
traverse_prepared_textures(GraphicsStateGuardian::TextureCallback *func,
void *callback_arg) {
ReMutexHolder holder(_prepared_objects->_lock);
PreparedGraphicsObjects::Textures::const_iterator ti;
@ -702,20 +724,6 @@ void GraphicsStateGuardian::
release_index_buffer(IndexBufferContext *) {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_supports_occlusion_query
// Access: Public, Virtual
// Description: Returns true if this GSG supports an occlusion query.
// If this is true, then begin_occlusion_query() and
// end_occlusion_query() may be called to bracket a
// sequence of draw_triangles() (or whatever) calls to
// measure pixels that pass the depth test.
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
get_supports_occlusion_query() const {
return _supports_occlusion_query;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::begin_occlusion_query
// Access: Public, Virtual
@ -754,6 +762,17 @@ end_occlusion_query() {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::issue_timer_query
// Access: Public, Virtual
// Description: Adds a timer query to the command stream, associated
// with the given PStats collector index.
////////////////////////////////////////////////////////////////////
PT(TimerQueryContext) GraphicsStateGuardian::
issue_timer_query(int pstats_index) {
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::dispatch_compute
// Access: Public, Virtual
@ -888,7 +907,7 @@ compute_distance_to(const LPoint3 &point) const {
// the need for a separate routine to fetch these values.
//
// The "altered" bits indicate what parts of the
// state_and_transform have changed since the last
// state_and_transform have changed since the last
// time this particular ShaderMatSpec was evaluated.
// This may allow data to be cached and not reevaluated.
//
@ -896,7 +915,7 @@ compute_distance_to(const LPoint3 &point) const {
const LMatrix4 *GraphicsStateGuardian::
fetch_specified_value(Shader::ShaderMatSpec &spec, int altered) {
LVecBase3 v;
if (altered & spec._dep[0]) {
const LMatrix4 *t = fetch_specified_part(spec._part[0], spec._arg[0], spec._cache[0]);
if (t != &spec._cache[0]) {
@ -909,7 +928,7 @@ fetch_specified_value(Shader::ShaderMatSpec &spec, int altered) {
spec._cache[1] = *t;
}
}
switch(spec._func) {
case Shader::SMF_compose:
spec._value.multiply(spec._cache[0], spec._cache[1]);
@ -1470,6 +1489,29 @@ begin_frame(Thread *current_thread) {
_state_rs = RenderState::make_empty();
_state_mask.clear();
#ifdef DO_PSTATS
// We have to do this here instead of in GraphicsEngine because
// we need a current context to issue timer queries.
int frame = ClockObject::get_global_clock()->get_frame_count();
if (_last_query_frame < frame) {
_last_query_frame = frame;
_timer_queries_pcollector.clear_level();
// Now is a good time to flush previous frame's queries. We
// may not actually have all of the previous frame's results
// in yet, but that's okay; the GPU data is allowed to lag a
// few frames behind.
flush_timer_queries();
if (_timer_queries_active) {
// Issue a stop and start event for collector 0, marking the
// beginning of the new frame.
issue_timer_query(0x8000);
issue_timer_query(0x0000);
}
}
#endif
return !_needs_reset;
}
@ -1566,6 +1608,138 @@ end_frame(Thread *current_thread) {
_prepared_objects->_graphics_memory_lru.begin_epoch();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::flush_timer_queries
// Access: Public
// Description: Called by the graphics engine on the draw thread
// to check the status of the running timer queries
// and submit their results to the PStats server.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
flush_timer_queries() {
#ifdef DO_PSTATS
// This uses the lower-level PStats interfaces for now because
// of all the unnecessary overhead that would otherwise be incurred
// when adding such a large amount of data at once.
PStatClient *client = PStatClient::get_global_pstats();
if (!client->client_is_connected()) {
_timer_queries_active = false;
return;
}
if (!_timer_queries_active) {
if (pstats_gpu_timing && _supports_timer_query) {
// Check if timer queries should be enabled.
_timer_queries_active = true;
} else {
return;
}
}
// Currently, we use one thread per GSG, for convenience. In the
// future, we may want to try and use one thread per graphics card.
if (_pstats_gpu_thread == -1) {
_pstats_gpu_thread = client->make_gpu_thread(get_driver_renderer()).get_index();
}
PStatThread gpu_thread(client, _pstats_gpu_thread);
// Get the results of all the timer queries.
int first = 0;
if (!_pending_timer_queries.empty()) {
int count = _pending_timer_queries.size();
if (count == 0) {
return;
}
PStatGPUTimer timer(this, _wait_timer_pcollector);
if (_last_num_queried > 0) {
// We know how many queries were available last frame, and this
// usually stays fairly constant, so use this as a starting point.
int i = min(_last_num_queried, count) - 1;
if (_pending_timer_queries[i]->is_answer_ready()) {
first = count;
while (i < count) {
if (!_pending_timer_queries[++i]->is_answer_ready()) {
first = i;
break;
}
}
} else {
first = 0;
while (i > 0) {
if (_pending_timer_queries[--i]->is_answer_ready()) {
first = i + 1;
break;
}
}
}
} else {
// We figure out which tasks the GPU has already finished by doing
// a binary search for the first query that does not have an answer
// ready. We know then that everything before that must be ready.
while (count > 0) {
int step = count / 2;
int i = first + step;
if (_pending_timer_queries[i]->is_answer_ready()) {
first += step + 1;
count -= step + 1;
} else {
count = step;
}
}
}
if (first <= 0) {
return;
}
_last_num_queried = first;
int frame_index = ClockObject::get_global_clock()->get_frame_count();
for (int i = 0; i < first; ++i) {
CPT(TimerQueryContext) query = _pending_timer_queries[i];
double time_data = query->get_timestamp(); // + _timer_delta;
if (query->_pstats_index == _command_latency_pcollector.get_index()) {
// Special case for the latency pcollector.
PStatCollectorDef *cdef;
cdef = client->get_collector_ptr(query->_pstats_index)->get_def(client, query->_pstats_index);
_pstats_gpu_data.add_level(query->_pstats_index, time_data * cdef->_factor);
} else if (query->_pstats_index & 0x8000) {
_pstats_gpu_data.add_stop(query->_pstats_index & 0x7fff, time_data);
} else {
_pstats_gpu_data.add_start(query->_pstats_index & 0x7fff, time_data);
}
// We found an end-frame marker (a stop event for collector 0).
// This means that the GPU actually caught up with that frame,
// and we can flush the GPU thread's frame data to the pstats server.
if (query->_pstats_index == 0x8000) {
gpu_thread.add_frame(_pstats_gpu_data);
_pstats_gpu_data.clear();
}
}
}
if (first > 0) {
// Do this out of the scope of _wait_timer_pcollector.
_pending_timer_queries.erase(
_pending_timer_queries.begin(),
_pending_timer_queries.begin() + first
);
_timer_queries_pcollector.add_level_now(first);
}
#endif
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::depth_offset_decals
// Access: Public, Virtual
@ -1819,7 +1993,7 @@ reset() {
delete _stencil_render_states;
_stencil_render_states = 0;
}
_stencil_render_states = new StencilRenderStates (this);
_stencil_render_states = new StencilRenderStates(this);
}
////////////////////////////////////////////////////////////////////
@ -1935,12 +2109,12 @@ do_issue_clip_plane() {
enable_clip_planes(true);
_clip_planes_enabled = true;
}
enable_clip_plane(num_enabled, true);
if (num_enabled == 0) {
begin_bind_clip_planes();
}
bind_clip_plane(plane, num_enabled);
num_enabled++;
}
@ -2123,7 +2297,7 @@ do_issue_light() {
if (num_enabled == 0) {
begin_bind_lights();
}
light_obj->bind(this, light, num_enabled);
num_enabled++;
}
@ -2278,24 +2452,24 @@ create_gamma_table (PN_stdfloat gamma, unsigned short *red_table, unsigned short
// avoid divide by zero and negative exponents
gamma = 1.0;
}
for (i = 0; i < 256; i++) {
double g;
double x;
PN_stdfloat gamma_correction;
x = ((double) i / 255.0);
gamma_correction = 1.0 / gamma;
gamma_correction = 1.0 / gamma;
x = pow (x, (double) gamma_correction);
if (x > 1.00) {
x = 1.0;
}
g = x * 65535.0;
g = x * 65535.0;
red_table [i] = (int)g;
green_table [i] = (int)g;
blue_table [i] = (int)g;
}
}
}
////////////////////////////////////////////////////////////////////
@ -2638,7 +2812,7 @@ async_reload_texture(TextureContext *tc) {
string task_name = string("reload:") + tc->get_texture()->get_name();
PT(AsyncTaskManager) task_mgr = _loader->get_task_manager();
// See if we are already loading this task.
AsyncTaskCollection orig_tasks = task_mgr->find_tasks(task_name);
int num_tasks = orig_tasks.get_num_tasks();
@ -2655,7 +2829,7 @@ async_reload_texture(TextureContext *tc) {
// This texture has not yet been queued to be reloaded. Queue it up
// now.
PT(AsyncTask) request =
PT(AsyncTask) request =
new TextureReloadRequest(task_name,
_prepared_objects, tc->get_texture(),
_supports_compressed_texture);
@ -2762,20 +2936,20 @@ make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) {
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_driver_vendor
// Access: Public, Virtual
// Description: Returns the vendor of the video card driver
// Description: Returns the vendor of the video card driver
////////////////////////////////////////////////////////////////////
string GraphicsStateGuardian::
get_driver_vendor() {
return string("0");
return string();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_driver_vendor
// Function: GraphicsStateGuardian::get_driver_renderer
// Access: Public, Virtual
// Description: Returns GL_Renderer
////////////////////////////////////////////////////////////////////
string GraphicsStateGuardian::get_driver_renderer() {
return string("0");
return string();
}
////////////////////////////////////////////////////////////////////
@ -2783,12 +2957,12 @@ string GraphicsStateGuardian::get_driver_renderer() {
// Access: Public, Virtual
// Description: Returns driver version
// This has an implementation-defined meaning, and may
// be "0" if the particular graphics implementation
// be "" if the particular graphics implementation
// does not provide a way to query this information.
////////////////////////////////////////////////////////////////////
string GraphicsStateGuardian::
get_driver_version() {
return string("0");
return string();
}
////////////////////////////////////////////////////////////////////

View File

@ -44,6 +44,7 @@
#include "bitMask.h"
#include "texture.h"
#include "occlusionQueryContext.h"
#include "timerQueryContext.h"
#include "stencilRenderStates.h"
#include "loader.h"
#include "shaderAttrib.h"
@ -126,6 +127,7 @@ PUBLISHED:
INLINE bool get_supports_2d_texture_array() const;
INLINE bool get_supports_cube_map() const;
INLINE bool get_supports_tex_non_pow2() const;
INLINE bool get_supports_texture_srgb() const;
INLINE bool get_supports_compressed_texture() const;
virtual INLINE bool get_supports_compressed_texture_format(int compression_mode) const;
@ -151,6 +153,10 @@ PUBLISHED:
INLINE bool get_supports_two_sided_stencil() const;
INLINE bool get_supports_geometry_instancing() const;
INLINE bool get_supports_occlusion_query() const;
INLINE bool get_supports_timer_query() const;
INLINE bool get_timer_queries_active() const;
INLINE int get_max_color_targets() const;
INLINE int get_maximum_simultaneous_render_targets() const;
@ -200,7 +206,7 @@ PUBLISHED:
virtual int get_driver_version_minor();
virtual int get_driver_shader_version_major();
virtual int get_driver_shader_version_minor();
bool set_scene(SceneSetup *scene_setup);
virtual SceneSetup *get_scene() const;
@ -222,10 +228,11 @@ public:
virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data);
virtual void release_index_buffer(IndexBufferContext *ibc);
virtual bool get_supports_occlusion_query() const;
virtual void begin_occlusion_query();
virtual PT(OcclusionQueryContext) end_occlusion_query();
virtual PT(TimerQueryContext) issue_timer_query(int pstats_index);
virtual void dispatch_compute(int size_x, int size_y, int size_z);
virtual PT(GeomMunger) get_geom_munger(const RenderState *state,
@ -239,7 +246,7 @@ public:
virtual PN_stdfloat compute_distance_to(const LPoint3 &point) const;
virtual void clear(DrawableRegion *clearable);
const LMatrix4 *fetch_specified_value(Shader::ShaderMatSpec &spec, int altered);
const LMatrix4 *fetch_specified_part(Shader::ShaderMatInput input, InternalName *name, LMatrix4 &t);
const Shader::ShaderPtrData *fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec);
@ -260,6 +267,8 @@ PUBLISHED:
public:
virtual void end_frame(Thread *current_thread);
void flush_timer_queries();
void set_current_properties(const FrameBufferProperties *properties);
virtual bool depth_offset_decals();
@ -375,7 +384,7 @@ protected:
// This bitmask contains a 1 bit everywhere that _state_rs has a
// known value. If a bit is 0, the corresponding state must be
// re-sent.
//
//
// Derived GSGs should initialize _inv_state_mask in reset() as a mask of
// 1's where they don't care, and 0's where they do care, about the state.
RenderState::SlotMask _state_mask;
@ -406,7 +415,7 @@ protected:
unsigned int _color_write_mask;
CPT(DisplayRegion) _current_display_region;
PT(DisplayRegion) _current_display_region;
Lens::StereoChannel _current_stereo_channel;
int _current_tex_view_offset;
CPT(Lens) _current_lens;
@ -468,6 +477,7 @@ protected:
bool _supports_2d_texture_array;
bool _supports_cube_map;
bool _supports_tex_non_pow2;
bool _supports_texture_srgb;
bool _supports_compressed_texture;
BitMask32 _compressed_texture_formats;
@ -481,6 +491,19 @@ protected:
bool _supports_occlusion_query;
PT(OcclusionQueryContext) _current_occlusion_query;
bool _supports_timer_query;
#ifdef DO_PSTATS
int _pstats_gpu_thread;
bool _timer_queries_active;
PStatFrameData _pstats_gpu_data;
int _last_query_frame;
int _last_num_queried;
//double _timer_delta;
typedef pdeque<PT(TimerQueryContext)> TimerQueryQueue;
TimerQueryQueue _pending_timer_queries;
#endif
bool _copy_texture_inverted;
bool _supports_multisample;
bool _supports_generate_mipmap;
@ -520,13 +543,13 @@ protected:
PN_stdfloat _gamma;
Texture::QualityLevel _texture_quality_override;
ShaderGenerator* _shader_generator;
#ifndef NDEBUG
PT(Texture) _flash_texture;
#endif
public:
// Statistics
static PStatCollector _vertex_buffer_switch_pcollector;
@ -558,7 +581,18 @@ public:
static PStatCollector _draw_set_state_pcollector;
static PStatCollector _clear_pcollector;
static PStatCollector _flush_pcollector;
static PStatCollector _compute_dispatch_pcollector;
static PStatCollector _wait_occlusion_pcollector;
static PStatCollector _wait_timer_pcollector;
static PStatCollector _timer_queries_pcollector;
static PStatCollector _command_latency_pcollector;
static PStatCollector _prepare_pcollector;
static PStatCollector _prepare_texture_pcollector;
static PStatCollector _prepare_geom_pcollector;
static PStatCollector _prepare_shader_pcollector;
static PStatCollector _prepare_vertex_buffer_pcollector;
static PStatCollector _prepare_index_buffer_pcollector;
// A whole slew of collectors to measure the cost of individual
// state changes. These are disabled by default.

View File

@ -0,0 +1,61 @@
// Filename: pStatGPUTimer.I
// Created by: rdb (21Aug14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifdef DO_PSTATS
////////////////////////////////////////////////////////////////////
// Function: PStatGPUTimer::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE PStatGPUTimer::
PStatGPUTimer(GraphicsStateGuardian *gsg, PStatCollector &collector) :
PStatTimer(collector),
_gsg(gsg)
{
if (gsg->get_timer_queries_active()) {
gsg->issue_timer_query(collector.get_index());
//cerr << "issuing " << collector << " active " << collector.is_active() << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: PStatGPUTimer::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE PStatGPUTimer::
PStatGPUTimer(GraphicsStateGuardian *gsg, PStatCollector &collector, Thread *current_thread) :
PStatTimer(collector, current_thread),
_gsg(gsg)
{
if (gsg->get_timer_queries_active()) {
gsg->issue_timer_query(collector.get_index());
}
}
////////////////////////////////////////////////////////////////////
// Function: PStatGPUTimer::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE PStatGPUTimer::
~PStatGPUTimer() {
if (_gsg->get_timer_queries_active()) {
_gsg->issue_timer_query(_collector.get_index() | 0x8000);
}
}
#endif

View File

@ -0,0 +1,67 @@
// Filename: pStatGPUTimer.h
// Created by: rdb (21Aug14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef PSTATGPUTIMER_H
#define PSTATGPUTIMER_H
#include "pandabase.h"
#include "pStatTimer.h"
#include "pStatCollector.h"
#include "config_pstats.h"
#include "timerQueryContext.h"
class Thread;
class GraphicsStateGuardian;
////////////////////////////////////////////////////////////////////
// Class : PStatGPUTimer
// Description : This is a special type of PStatTimer that also
// uses a timer query on the GSG to measure how long
// a task actually takes to execute on the GPU, rather
// than how long it took for the API commands to be
// queued up.
//
// This class may only be used on the draw thread.
//
// At present, it tracks both the CPU time (like a
// regular PStatTimer does) and the GPU time, which
// is recorded using a special PStatThread.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_DISPLAY PStatGPUTimer : public PStatTimer {
public:
#ifdef DO_PSTATS
INLINE PStatGPUTimer(GraphicsStateGuardian *gsg,
PStatCollector &collector);
INLINE PStatGPUTimer(GraphicsStateGuardian *gsg,
PStatCollector &collector,
Thread *current_thread);
INLINE ~PStatGPUTimer();
GraphicsStateGuardian *_gsg;
private:
#else // DO_PSTATS
INLINE PStatGPUTimer(GraphicsStateGuardian *, PStatCollector &col)
: PStatTimer(col) { }
INLINE PStatGPUTimer(GraphicsStateGuardian *, PStatCollector &col, Thread *)
: PStatTimer(col) { }
INLINE ~PStatGPUTimer() { }
#endif // DO_PSTATS
};
#include "pStatGPUTimer.I"
#endif

View File

@ -178,7 +178,10 @@ munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data,
// Even beyond munging the vertex format, we have to convert the
// Geom itself into a new primitive type the GSG can render
// directly.
if ((unsupported_bits & Geom::GR_composite_bits) != 0) {
// If we don't support a strip cut index, it might be faster to
// just decompose it rather than draw them one by one.
if ((unsupported_bits & Geom::GR_composite_bits) != 0 ||
(unsupported_bits & Geom::GR_strip_cut_index) != 0) {
// This decomposes everything in the primitive, so that if (for
// instance) the primitive contained both strips and fans, but
// the GSG didn't support fans, it would decompose the strips
@ -224,7 +227,10 @@ premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data) {
// Even beyond munging the vertex format, we have to convert the
// Geom itself into a new primitive type the GSG can render
// directly.
if ((unsupported_bits & Geom::GR_composite_bits) != 0) {
// If we don't support a strip cut index, it might be faster to
// just decompose it rather than draw them one by one.
if ((unsupported_bits & Geom::GR_composite_bits) != 0 ||
(unsupported_bits & Geom::GR_strip_cut_index) != 0) {
// This decomposes everything in the primitive, so that if (for
// instance) the primitive contained both strips and fans, but
// the GSG didn't support fans, it would decompose the strips

View File

@ -22,7 +22,7 @@
wdxGraphicsPipe8.I wdxGraphicsPipe8.h \
wdxGraphicsWindow8.I wdxGraphicsWindow8.h \
dxgsg8base.h config_dxgsg8.h dxGraphicsStateGuardian8.I dxGraphicsStateGuardian8.h \
dxVertexBufferContext8.h dxVertexbufferContext8.I \
dxVertexBufferContext8.h dxVertexBufferContext8.I \
dxIndexBufferContext8.h dxIndexBufferContext8.I \
dxTextureContext8.h dxTextureContext8.I \
dxGeomMunger8.h dxGeomMunger8.I \

View File

@ -413,7 +413,7 @@ handle_reshape() {
GdiFlush();
WinGraphicsWindow::handle_reshape();
if (_dxgsg != NULL) {
if (_dxgsg != NULL && _dxgsg->_d3d_device != NULL) {
// create the new resized rendertargets
WindowProperties props = get_properties();
int x_size = props.get_x_size();
@ -422,7 +422,7 @@ handle_reshape() {
if (_wcontext._presentation_params.BackBufferWidth != x_size ||
_wcontext._presentation_params.BackBufferHeight != y_size) {
bool resize_succeeded = reset_device_resize_window(x_size, y_size);
if (wdxdisplay8_cat.is_debug()) {
if (!resize_succeeded) {
wdxdisplay8_cat.debug()

View File

@ -22,7 +22,7 @@
wdxGraphicsPipe9.I wdxGraphicsPipe9.h \
wdxGraphicsWindow9.I wdxGraphicsWindow9.h \
dxgsg9base.h config_dxgsg9.h dxGraphicsStateGuardian9.I dxGraphicsStateGuardian9.h \
dxVertexBufferContext9.h dxVertexbufferContext9.I \
dxVertexBufferContext9.h dxVertexBufferContext9.I \
dxIndexBufferContext9.h dxIndexBufferContext9.I \
dxTextureContext9.h dxTextureContext9.I \
dxGeomMunger9.h dxGeomMunger9.I \

View File

@ -224,6 +224,13 @@ apply_texture(int i, TextureContext *tc) {
DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc);
Texture *tex = tc->get_texture();
//if (tex->get_color_space() == CS_srgb) {
if (Texture::is_srgb(tex->get_format())) {
set_sampler_state(i, D3DSAMP_SRGBTEXTURE, TRUE);
} else {
set_sampler_state(i, D3DSAMP_SRGBTEXTURE, FALSE);
}
Texture::WrapMode wrap_u, wrap_v, wrap_w;
DWORD address_u;
@ -256,7 +263,7 @@ apply_texture(int i, TextureContext *tc) {
int supports_anisotropic_mag_filter;
D3DTEXTUREFILTERTYPE new_mag_filter;
supports_anisotropic_mag_filter = (_screen -> _d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) != 0;
if (aniso_degree <= 1 || supports_anisotropic_mag_filter == 0) {
new_mag_filter = ((ft != Texture::FT_nearest) ? D3DTEXF_LINEAR : D3DTEXF_POINT);
@ -268,8 +275,8 @@ apply_texture(int i, TextureContext *tc) {
hr = set_sampler_state(i, D3DSAMP_MAGFILTER, new_mag_filter);
if (hr != D3D_OK) {
dxgsg9_cat.error()
<< "ERROR: set_sampler_state (D3DSAMP_MAGFILTER, "
<< new_mag_filter << ") failed for texture:" << tex -> get_name() << endl;
<< "ERROR: set_sampler_state (D3DSAMP_MAGFILTER, "
<< new_mag_filter << ") failed for texture:" << tex -> get_name() << endl;
}
// map Panda composite min+mip filter types to d3d's separate min & mip filter types
@ -353,7 +360,7 @@ upload_texture(DXTextureContext9 *dtc, bool force) {
dtc->delete_texture();
dtc->update_data_size_bytes(0);
dtc->mark_unloaded();
if (_effective_incomplete_render && !force) {
bool has_image = _supports_compressed_texture ? tex->has_ram_image() : tex->has_uncompressed_ram_image();
if (!has_image && tex->might_have_ram_image() &&
@ -371,7 +378,7 @@ upload_texture(DXTextureContext9 *dtc, bool force) {
}
}
}
return dtc->create_texture(*_screen);
}
@ -746,7 +753,7 @@ begin_occlusion_query() {
<< "Occlusion query failed.\n";
return;
}
PT(DXOcclusionQueryContext9) queryobj = new DXOcclusionQueryContext9(query);
if (dxgsg9_cat.is_debug()) {
@ -776,7 +783,7 @@ end_occlusion_query() {
PT(OcclusionQueryContext) result = _current_occlusion_query;
IDirect3DQuery9 *query = DCAST(DXOcclusionQueryContext9, result)->_query;
if (dxgsg9_cat.is_debug()) {
dxgsg9_cat.debug()
<< "ending occlusion query " << query << "\n";
@ -857,7 +864,7 @@ clear(DrawableRegion *clearable) {
aux_flags |= D3DCLEAR_ZBUFFER;
HRESULT hr2 = _d3d_device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color_clear_value,
depth_clear_value, stencil_clear_value);
if (FAILED(hr2)) {
if (FAILED(hr2)) {
dxgsg9_cat.error()
<< "Unable to clear depth buffer; removing.\n";
// This is really hacky code.
@ -1040,6 +1047,12 @@ begin_frame(Thread *current_thread) {
return false;
}
if (_current_properties->get_srgb_color()) {
set_render_state(D3DRS_SRGBWRITEENABLE, TRUE);
} else {
set_render_state(D3DRS_SRGBWRITEENABLE, FALSE);
}
return true;
}
@ -1343,14 +1356,14 @@ update_standard_vertex_arrays(bool force) {
dxgsg9_cat.error() << "Unable to get reader for array " << array_index << "\n";
return false;
}
// Get the vertex buffer for this array.
CLP(VertexBufferContext)* dvbc;
if (!setup_array_data(dvbc, array_reader, force)) {
dxgsg9_cat.error() << "Unable to setup vertex buffer for array " << array_index << "\n";
return false;
}
// Bind this array as the data source for the corresponding stream.
const GeomVertexArrayFormat* array_format = array_reader->get_array_format();
hr = _d3d_device->SetStreamSource( array_index, dvbc->_vbuffer, 0, array_format->get_stride() );
@ -2315,7 +2328,7 @@ reset() {
// want gsg to pass all state settings down so any non-matching defaults we set here get overwritten
nassertv(_screen->_d3d9 != NULL);
if (_d3d_device == NULL) {
return;
}
@ -2379,27 +2392,27 @@ reset() {
_shader_caps._ultimate_fprofile = (int)CG_PROFILE_PS_2_0;
*/
}
if (dxgsg9_cat.is_debug()) {
CGprofile vertex_profile;
CGprofile pixel_profile;
vertex_profile = cgD3D9GetLatestVertexProfile();
pixel_profile = cgD3D9GetLatestPixelProfile();
const char *vertex_profile_str =
cgGetProfileString(vertex_profile);
const char *pixel_profile_str =
cgGetProfileString(pixel_profile);
if (vertex_profile_str == NULL) {
vertex_profile_str = "(null)";
}
if (pixel_profile_str == NULL) {
pixel_profile_str = "(null)";
}
dxgsg9_cat.debug()
<< "\nCg vertex profile = " << vertex_profile_str << " id = " << vertex_profile
<< "\nCg pixel profile = " << pixel_profile_str << " id = " << pixel_profile
@ -2495,7 +2508,7 @@ reset() {
<< "\nDirectX SDK version " DIRECTX_SDK_VERSION
<< "\n";
}
// OVERRIDE SUPPORT SINCE IT DOES NOT WORK WELL
_screen->_supports_automatic_mipmap_generation = false;
@ -2618,12 +2631,19 @@ reset() {
_last_testcooplevel_result = D3D_OK;
if (dxgsg9_cat.is_debug()) {
dxgsg9_cat.debug() << "Supported texture formats:\n";
}
for(int i = 0; i < MAX_POSSIBLE_TEXFMTS; i++) {
// look for all possible DX9 texture fmts
D3DFORMAT_FLAG fmtflag = D3DFORMAT_FLAG(1 << i);
hr = _screen->_d3d9->CheckDeviceFormat(_screen->_card_id, D3DDEVTYPE_HAL, _screen->_display_mode.Format,
0x0, D3DRTYPE_TEXTURE, g_D3DFORMATmap[fmtflag]);
if (SUCCEEDED(hr)){
if (SUCCEEDED(hr)) {
if (dxgsg9_cat.is_debug()) {
dxgsg9_cat.debug() << " " << D3DFormatStr(g_D3DFORMATmap[fmtflag]) << "\n";
}
_screen->_supported_tex_formats_mask |= fmtflag;
}
}
@ -2632,7 +2652,7 @@ reset() {
#define CHECK_FOR_DXTVERSION(num) \
if (_screen->_supported_tex_formats_mask & DXT##num##_FLAG) {\
if (dxgsg9_cat.is_debug()) {\
dxgsg9_cat.debug() << "Compressed texture format DXT" << #num << " supported \n";\
dxgsg9_cat.debug() << "Compressed texture format DXT" << #num << " supported\n";\
}\
_supports_compressed_texture = true;\
_compressed_texture_formats.set_bit(Texture::CM_dxt##num);\
@ -2641,9 +2661,9 @@ reset() {
if (_screen->_intel_compressed_texture_bug) {
dxgsg9_cat.info()
<< "Buggy Intel driver detected; disabling compressed textures.\n";
_screen->_supported_tex_formats_mask &=
_screen->_supported_tex_formats_mask &=
~(DXT1_FLAG | DXT2_FLAG | DXT3_FLAG | DXT4_FLAG | DXT5_FLAG);
} else {
// Check for available compressed formats normally.
CHECK_FOR_DXTVERSION(1);
@ -2652,7 +2672,7 @@ reset() {
CHECK_FOR_DXTVERSION(4);
CHECK_FOR_DXTVERSION(5);
}
#undef CHECK_FOR_DXTVERSION
_screen->_supports_rgba16f_texture_format = false;
@ -3292,7 +3312,7 @@ set_state_and_transform(const RenderState *target,
!_state_mask.get_bit(transparency_slot) ||
!_state_mask.get_bit(color_write_slot) ||
!_state_mask.get_bit(color_blend_slot) ||
(_target_shader->get_flag(ShaderAttrib::F_disable_alpha_write) !=
(_target_shader->get_flag(ShaderAttrib::F_disable_alpha_write) !=
_state_shader->get_flag(ShaderAttrib::F_disable_alpha_write))) {
//PStatTimer timer(_draw_set_state_blending_pcollector);
do_issue_blending();
@ -3353,7 +3373,7 @@ set_state_and_transform(const RenderState *target,
do_issue_stencil();
_state_mask.set_bit(stencil_slot);
}
int fog_slot = FogAttrib::get_class_slot();
if (_target_rs->get_attrib(fog_slot) != _state_rs->get_attrib(fog_slot) ||
!_state_mask.get_bit(fog_slot)) {
@ -3446,22 +3466,22 @@ bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
const LMatrix4 &light_mat = transform->get_mat();
LMatrix4 rel_mat = light_mat * LMatrix4::convert_mat(CS_yup_left, CS_default);
LVector3f dir = LCAST(float, light_obj->get_direction() * rel_mat);
D3DCOLORVALUE black;
black.r = black.g = black.b = black.a = 0.0f;
ZeroMemory(&fdata, sizeof(D3DLIGHT9));
fdata.Type = D3DLIGHT_DIRECTIONAL;
fdata.Ambient = black ;
LColorf color = LCAST(float, light_obj->get_specular_color());
fdata.Specular = *(D3DCOLORVALUE *)(color.get_data());
fdata.Direction = *(D3DVECTOR *)dir.get_data();
fdata.Range = __D3DLIGHT_RANGE_MAX;
fdata.Falloff = 1.0f;
fdata.Attenuation0 = 1.0f; // constant
fdata.Attenuation1 = 0.0f; // linear
fdata.Attenuation2 = 0.0f; // quadratic
@ -4125,7 +4145,7 @@ close_gsg() {
if (dxgsg9_cat.is_debug()) {
dxgsg9_cat.debug()
<< "Closing GSG, prepared_objects count = "
<< "Closing GSG, prepared_objects count = "
<< _prepared_objects->get_ref_count() << "\n";
}
@ -4210,9 +4230,9 @@ set_read_buffer(const RenderBuffer &rb) {
if (rb._buffer_type & RenderBuffer::T_front) {
_cur_read_pixel_buffer = RenderBuffer::T_front;
} else if (rb._buffer_type & RenderBuffer::T_back) {
_cur_read_pixel_buffer = RenderBuffer::T_back;
_cur_read_pixel_buffer = RenderBuffer::T_back;
} else if (rb._buffer_type & RenderBuffer::T_aux_rgba_ALL) {
_cur_read_pixel_buffer = RenderBuffer::T_back;
_cur_read_pixel_buffer = RenderBuffer::T_back;
} else {
dxgsg9_cat.error() << "Invalid or unimplemented Argument to set_read_buffer!\n";
}
@ -4816,7 +4836,7 @@ check_cooperative_level() {
case D3DERR_DEVICELOST:
// sleep while the device is lost to free up the CPU
Sleep (10);
if (SUCCEEDED(_last_testcooplevel_result)) {
if (_dx_is_ready) {
_dx_is_ready = false;
@ -4847,7 +4867,7 @@ show_frame() {
if (_swap_chain) {
DWORD flags;
flags = 0;
hr = _swap_chain->Present((CONST RECT*)NULL, (CONST RECT*)NULL, (HWND)NULL, NULL, flags);
} else {
hr = _d3d_device->Present((CONST RECT*)NULL, (CONST RECT*)NULL, (HWND)NULL, NULL);
@ -5220,7 +5240,7 @@ check_dx_allocation (HRESULT result, int allocation_size, int attempts)
// increase the page out size as the number of attempts increases
{
size_t current_size = _prepared_objects->_graphics_memory_lru.get_total_size();
size_t target_size = max(current_size - allocation_size * attempts, 0);
size_t target_size = max(current_size - allocation_size * attempts, (size_t) 0);
_prepared_objects->_graphics_memory_lru.evict_to(target_size);
dxgsg9_cat.info()
<< "Evicted " << current_size - _prepared_objects->_graphics_memory_lru.get_total_size() << " bytes of texture memory to make room for more.\n";
@ -5435,7 +5455,7 @@ do_issue_stencil() {
////////////////////////////////////////////////////////////////////
// Function: dxGraphicsStateGuardian9::do_issue_scissor
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian9::
do_issue_scissor() {
@ -5522,8 +5542,8 @@ void _create_gamma_table (PN_stdfloat gamma, unsigned short *original_red_table,
// avoid divide by zero and negative exponents
gamma = 1.0;
}
gamma_correction = 1.0 / (double) gamma;
gamma_correction = 1.0 / (double) gamma;
for (i = 0; i < 256; i++) {
double r;
double g;
@ -5534,11 +5554,11 @@ void _create_gamma_table (PN_stdfloat gamma, unsigned short *original_red_table,
g = (double) original_green_table [i] / GAMMA_1;
b = (double) original_blue_table [i] / GAMMA_1;
}
else {
else {
r = ((double) i / 255.0);
g = r;
b = r;
}
}
r = pow (r, gamma_correction);
g = pow (g, gamma_correction);
@ -5554,14 +5574,14 @@ void _create_gamma_table (PN_stdfloat gamma, unsigned short *original_red_table,
b = 1.0;
}
r = r * GAMMA_1;
g = g * GAMMA_1;
b = b * GAMMA_1;
r = r * GAMMA_1;
g = g * GAMMA_1;
b = b * GAMMA_1;
red_table [i] = r;
green_table [i] = g;
blue_table [i] = b;
}
}
}
////////////////////////////////////////////////////////////////////
@ -5571,13 +5591,13 @@ void _create_gamma_table (PN_stdfloat gamma, unsigned short *original_red_table,
////////////////////////////////////////////////////////////////////
bool DXGraphicsStateGuardian9::
get_gamma_table(void) {
bool get;
bool get;
get = false;
if (_gamma_table_initialized == false) {
HDC hdc = GetDC(NULL);
if (hdc) {
if (hdc) {
if (GetDeviceGammaRamp (hdc, (LPVOID) _orignial_gamma_table)) {
_gamma_table_initialized = true;
get = true;
@ -5586,26 +5606,26 @@ get_gamma_table(void) {
ReleaseDC (NULL, hdc);
}
}
return get;
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian9::static_set_gamma
// Access: Public, Static
// Description: Static function for setting gamma which is needed
// Description: Static function for setting gamma which is needed
// for atexit.
////////////////////////////////////////////////////////////////////
bool DXGraphicsStateGuardian9::
static_set_gamma(bool restore, PN_stdfloat gamma) {
bool set;
bool set;
HDC hdc = GetDC(NULL);
set = false;
if (hdc) {
if (hdc) {
unsigned short ramp [256 * 3];
if (restore && _gamma_table_initialized) {
if (restore && _gamma_table_initialized) {
_create_gamma_table (gamma, &_orignial_gamma_table [0], &_orignial_gamma_table [256], &_orignial_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
}
else {
@ -5615,7 +5635,7 @@ static_set_gamma(bool restore, PN_stdfloat gamma) {
if (SetDeviceGammaRamp (hdc, ramp)) {
set = true;
}
ReleaseDC (NULL, hdc);
}
@ -5634,7 +5654,7 @@ set_gamma(PN_stdfloat gamma) {
set = static_set_gamma(false, gamma);
if (set) {
_gamma = gamma;
_gamma = gamma;
}
return set;
@ -5664,7 +5684,7 @@ atexit_function(void) {
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian9::get_supports_cg_profile
// Access: Public, Virtual
// Description: Returns true if this particular GSG supports the
// Description: Returns true if this particular GSG supports the
// specified Cg Shader Profile.
////////////////////////////////////////////////////////////////////
bool DXGraphicsStateGuardian9::
@ -5673,7 +5693,7 @@ get_supports_cg_profile(const string &name) const {
return false;
#else
CGprofile profile = cgGetProfile(name.c_str());
if (profile == CG_PROFILE_UNKNOWN) {
dxgsg9_cat.error() << name <<", unknown Cg-profile\n";
return false;

View File

@ -36,9 +36,7 @@
#include "vertexElementArray.h"
#include "dxShaderContext9.h"
enum GsgPageType
{
enum GsgPageType {
GPT_Texture,
GPT_VertexBuffer,
GPT_IndexBuffer,
@ -52,6 +50,8 @@ class DXTextureContext9;
class DXVertexBufferContext9;
class DXIndexBufferContext9;
class wdxGraphicsBuffer9;
////////////////////////////////////////////////////////////////////
// Class : DXGraphicsStateGuardian9
// Description : A GraphicsStateGuardian for rendering into DirectX9
@ -265,7 +265,7 @@ protected:
public:
DXScreenData *_screen;
protected:
LPDIRECT3DDEVICE9 _d3d_device; // same as _screen->_d3d_device, cached for spd
IDirect3DSwapChain9 *_swap_chain;
@ -374,7 +374,7 @@ protected:
list <wdxGraphicsBuffer9 **> _graphics_buffer_list;
int _supports_gamma_calibration;
int _supports_gamma_calibration;
static LPDIRECT3DDEVICE9 _cg_device;

View File

@ -135,13 +135,13 @@ create_texture(DXScreenData &scrn) {
bool texture_wants_compressed = false;
Texture::CompressionMode compression_mode = tex->get_ram_image_compression();
bool texture_stored_compressed = compression_mode != Texture::CM_off;
if (texture_stored_compressed) {
texture_wants_compressed = true;
texture_wants_compressed = true;
} else {
if (tex->get_compression() == Texture::CM_off) {
// no compression
} else {
} else {
if (tex->get_compression() == Texture::CM_default) {
// default = use "compressed-textures" config setting
if (compressed_textures) {
@ -150,9 +150,9 @@ create_texture(DXScreenData &scrn) {
} else {
texture_wants_compressed = true;
}
}
}
}
switch (tex->get_texture_type()) {
case Texture::TT_1d_texture:
case Texture::TT_2d_texture:
@ -197,7 +197,9 @@ create_texture(DXScreenData &scrn) {
if ((tex->get_format() == Texture::F_luminance_alpha)||
(tex->get_format() == Texture::F_luminance_alphamask) ||
(tex->get_format() == Texture::F_luminance)) {
(tex->get_format() == Texture::F_luminance) ||
(tex->get_format() == Texture::F_sluminance_alpha) ||
(tex->get_format() == Texture::F_sluminance)) {
needs_luminance = true;
}
@ -232,7 +234,7 @@ create_texture(DXScreenData &scrn) {
_d3d_format = D3DFMT_A8R8G8B8;
break;
}
// make sure we handled all the possible cases
nassertr(_d3d_format != D3DFMT_UNKNOWN, false);
@ -398,9 +400,9 @@ create_texture(DXScreenData &scrn) {
if (compress_texture) {
if (num_alpha_bits <= 1) {
CHECK_FOR_FMT(DXT1);
CHECK_FOR_FMT(DXT1);
} else if (num_alpha_bits <= 4) {
CHECK_FOR_FMT(DXT3);
CHECK_FOR_FMT(DXT3);
} else {
CHECK_FOR_FMT(DXT5);
}
@ -425,7 +427,7 @@ create_texture(DXScreenData &scrn) {
// array (the texture array contains num_color_channels*8bits)
case 128:
// check if format is supported
// check if format is supported
if (scrn._supports_rgba32_texture_format) {
target_pixel_format = D3DFMT_A32B32G32R32F;
}
@ -435,7 +437,7 @@ create_texture(DXScreenData &scrn) {
goto found_matching_format;
case 64:
// check if format is supported
// check if format is supported
if (scrn._supports_rgba16f_texture_format) {
target_pixel_format = D3DFMT_A16B16G16R16F;
}
@ -443,7 +445,7 @@ create_texture(DXScreenData &scrn) {
target_pixel_format = scrn._render_to_texture_d3d_format;
}
goto found_matching_format;
case 32:
if (!((num_color_channels == 3) || (num_color_channels == 4)))
break; //bail
@ -502,7 +504,7 @@ create_texture(DXScreenData &scrn) {
CHECK_FOR_FMT(X8R8G8B8);
CHECK_FOR_FMT(A8R8G8B8);
// no 24-bit or 32 fmt. look for 16 bit fmt (higher res 565 1st)
CHECK_FOR_FMT(R5G6B5);
CHECK_FOR_FMT(X1R5G5B5);
@ -782,13 +784,13 @@ create_texture(DXScreenData &scrn) {
// REQUIRED PARAMETERS
_managed = false;
_is_render_target = true;
pool = D3DPOOL_DEFAULT;
usage = D3DUSAGE_RENDERTARGET;
if (target_bpp <= 32 ) {
target_pixel_format = scrn._render_to_texture_d3d_format;
}
dxgsg9_cat.debug ()
<< "*** RENDER TO TEXTURE ***: format "
<< D3DFormatStr(target_pixel_format)
@ -848,7 +850,7 @@ create_texture(DXScreenData &scrn) {
data_size *= 6;
}
update_data_size_bytes(data_size);
int attempts;
if (dxgsg9_cat.is_debug()) {
@ -882,7 +884,7 @@ create_texture(DXScreenData &scrn) {
hr = scrn._d3d_device->CreateTexture
(target_width, target_height, mip_level_count, usage,
target_pixel_format, pool, &_d3d_2d_texture, NULL);
_d3d_texture = _d3d_2d_texture;
_d3d_texture = _d3d_2d_texture;
break;
case Texture::TT_3d_texture:
@ -952,7 +954,7 @@ create_texture(DXScreenData &scrn) {
scrn._dxgsg9->get_engine()->texture_uploaded(tex);
}
mark_loaded();
return true;
error_exit:
@ -967,7 +969,7 @@ create_texture(DXScreenData &scrn) {
////////////////////////////////////////////////////////////////////
// Function: DXTextureContext9::create_simple_texture
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
bool DXTextureContext9::
create_simple_texture(DXScreenData &scrn) {
@ -993,7 +995,7 @@ create_simple_texture(DXScreenData &scrn) {
hr = scrn._d3d_device->CreateTexture
(target_width, target_height, mip_level_count, usage,
target_pixel_format, pool, &_d3d_2d_texture, NULL);
_d3d_texture = _d3d_2d_texture;
_d3d_texture = _d3d_2d_texture;
if (FAILED(hr)) {
dxgsg9_cat.error()
<< "D3D create_simple_texture failed!" << D3DERRORSTRING(hr);
@ -1032,13 +1034,13 @@ create_simple_texture(DXScreenData &scrn) {
RELEASE(surface, dxgsg9, "create_simple_texture Surface", RELEASE_ONCE);
}
if (FAILED(hr)) {
dxgsg9_cat.debug ()
<< "*** fill_d3d_texture_pixels failed ***: format "
<< target_pixel_format
<< "\n";
goto error_exit;
}
@ -1084,7 +1086,7 @@ bool DXTextureContext9::
extract_texture_data(DXScreenData &screen) {
bool state;
HRESULT hr;
state = false;
Texture *tex = get_texture();
if (tex->get_texture_type() != Texture::TT_2d_texture) {
@ -1147,7 +1149,7 @@ extract_texture_data(DXScreenData &screen) {
default:
dxgsg9_cat.error()
<< "Cannot extract texture data: unhandled surface format "
<< "Cannot extract texture data: unhandled surface format "
<< desc.Format << "\n";
return state;
}
@ -1164,13 +1166,13 @@ extract_texture_data(DXScreenData &screen) {
if (_is_render_target) {
IDirect3DSurface9* source_surface;
IDirect3DSurface9* destination_surface;
source_surface = 0;
destination_surface = 0;
hr = _d3d_2d_texture -> GetSurfaceLevel (0, &source_surface);
if (hr == D3D_OK) {
if (hr == D3D_OK) {
D3DPOOL pool;
D3DSURFACE_DESC surface_description;
@ -1186,7 +1188,7 @@ extract_texture_data(DXScreenData &screen) {
NULL);
if (hr == D3D_OK) {
if (source_surface && destination_surface) {
hr = screen._d3d_device -> GetRenderTargetData (source_surface, destination_surface);
hr = screen._d3d_device -> GetRenderTargetData (source_surface, destination_surface);
if (hr == D3D_OK) {
D3DLOCKED_RECT rect;
@ -1200,13 +1202,13 @@ extract_texture_data(DXScreenData &screen) {
int surface_bytes_per_line;
unsigned char *surface_pointer;
bytes_per_line = surface_description.Width * this -> d3d_format_to_bytes_per_pixel (surface_description.Format);
size = bytes_per_line * surface_description.Height;
surface_bytes_per_line = rect.Pitch;
surface_pointer = (unsigned char *) rect.pBits;
PTA_uchar image = PTA_uchar::empty_array(size);
int offset;
@ -1217,29 +1219,29 @@ extract_texture_data(DXScreenData &screen) {
memcpy (&image [offset], surface_pointer, bytes_per_line);
offset += bytes_per_line;
surface_pointer += surface_bytes_per_line;
surface_pointer += surface_bytes_per_line;
}
tex->set_ram_image(image, Texture::CM_off);
state = true;
destination_surface -> UnlockRect();
}
}
}
}
destination_surface -> Release ( );
}
else {
dxgsg9_cat.error()
<< "CreateImageSurface failed in extract_texture_data()"
<< D3DERRORSTRING(hr);
}
<< D3DERRORSTRING(hr);
}
source_surface -> Release ( );
}
}
else {
else {
for (int n = 0; n < num_levels; ++n) {
D3DLOCKED_RECT rect;
hr = _d3d_2d_texture->LockRect(n, &rect, NULL, D3DLOCK_READONLY);
@ -1248,11 +1250,11 @@ extract_texture_data(DXScreenData &screen) {
<< "Texture::LockRect() failed! level = " << n << " " << D3DERRORSTRING(hr);
return state;
}
int x_size = tex->get_expected_mipmap_x_size(n);
int y_size = tex->get_expected_mipmap_y_size(n);
PTA_uchar image;
if (compression == Texture::CM_off) {
// Uncompressed, but we have to respect the pitch.
int pitch = x_size * tex->get_num_components() * tex->get_component_width();
@ -1273,7 +1275,7 @@ extract_texture_data(DXScreenData &screen) {
source += rect.Pitch;
}
}
} else {
// Compressed; just copy the data verbatim.
int size = rect.Pitch * (y_size / div);
@ -1288,10 +1290,10 @@ extract_texture_data(DXScreenData &screen) {
tex->set_ram_mipmap_image(n, image);
}
}
state = true;
}
return state;
}
@ -1560,7 +1562,7 @@ d3d_surface_to_texture(RECT &source_rect, IDirect3DSurface9 *d3d_surface,
////////////////////////////////////////////////////////////////////
// Function: calculate_row_byte_length
// Access: Private, hidden
// Description: local helper function, which calculates the
// Description: local helper function, which calculates the
// 'row_byte_length' or 'pitch' needed for calling
// D3DXLoadSurfaceFromMemory.
// Takes compressed formats (DXTn) into account.
@ -1596,12 +1598,12 @@ static UINT calculate_row_byte_length (int width, int num_color_channels, D3DFOR
// Access: Private
// Description: Called from fill_d3d_texture_pixels, this function
// fills a single mipmap with texture data.
// Takes care of all necessery conversions and error
// Takes care of all necessary conversions and error
// handling.
////////////////////////////////////////////////////////////////////
HRESULT DXTextureContext9::fill_d3d_texture_mipmap_pixels(int mip_level, int depth_index, D3DFORMAT source_format)
{
// This whole function was refactored out of fill_d3d_texture_pixels to make the code
// This whole function was refactored out of fill_d3d_texture_pixels to make the code
// more readable and to avoid code duplication.
IDirect3DSurface9 *mip_surface = NULL;
bool using_temp_buffer = false;
@ -1617,7 +1619,7 @@ HRESULT DXTextureContext9::fill_d3d_texture_mipmap_pixels(int mip_level, int dep
pixels += view_size * get_view();
size_t page_size = get_texture()->get_expected_ram_mipmap_page_size(mip_level);
pixels += page_size * depth_index;
if (get_texture()->get_texture_type() == Texture::TT_cube_map) {
nassertr(IS_VALID_PTR(_d3d_cube_texture), E_FAIL);
hr = _d3d_cube_texture->GetCubeMapSurface((D3DCUBEMAP_FACES)depth_index, mip_level, &mip_surface);
@ -1645,6 +1647,10 @@ HRESULT DXTextureContext9::fill_d3d_texture_mipmap_pixels(int mip_level, int dep
// dithering)??)
mip_filter = D3DX_FILTER_LINEAR ; //| D3DX_FILTER_DITHER; //dithering looks ugly on i810 for 4444 textures
if (Texture::is_srgb(get_texture()->get_format())) {
mip_filter |= D3DX_FILTER_SRGB;
}
// D3DXLoadSurfaceFromMemory will load black luminance and we want
// full white, so convert to explicit luminance-alpha format
if (_d3d_format == D3DFMT_A8) {
@ -1671,7 +1677,7 @@ HRESULT DXTextureContext9::fill_d3d_texture_mipmap_pixels(int mip_level, int dep
source_format = D3DFMT_A8L8;
source_row_byte_length = width * sizeof(USHORT);
pixels = (BYTE*)temp_buffer;
}
}
else if (component_width != 1) {
// Convert from 16-bit per channel (or larger) format down to
// 8-bit per channel. This throws away precision in the
@ -1756,7 +1762,7 @@ fill_d3d_texture_pixels(DXScreenData &scrn, bool compress_texture) {
// The texture doesn't have an image to load. That's ok; it
// might be a texture we've rendered to by frame buffer
// operations or something.
if (tex->get_render_to_texture()) {
if (tex->get_render_to_texture()) {
HRESULT result;
if (_d3d_2d_texture) {
@ -1777,7 +1783,7 @@ fill_d3d_texture_pixels(DXScreenData &scrn, bool compress_texture) {
depth_stencil_surface = 0;
if (device -> GetDepthStencilSurface (&depth_stencil_surface) == D3D_OK) {
if (device -> SetDepthStencilSurface (NULL) == D3D_OK) {
}
}
@ -1791,7 +1797,7 @@ fill_d3d_texture_pixels(DXScreenData &scrn, bool compress_texture) {
}
}
// restore depth stencil
// restore depth stencil
if (depth_stencil_surface) {
device -> SetDepthStencilSurface (depth_stencil_surface);
depth_stencil_surface -> Release();
@ -1806,7 +1812,7 @@ fill_d3d_texture_pixels(DXScreenData &scrn, bool compress_texture) {
surface -> Release();
}
}
return S_OK;
}
return E_FAIL;
@ -1842,7 +1848,7 @@ fill_d3d_texture_pixels(DXScreenData &scrn, bool compress_texture) {
}
for (unsigned int di = 0; di < orig_depth; di++) {
// fill top level mipmap
hr = fill_d3d_texture_mipmap_pixels(0, di, source_format);
if (FAILED(hr)) {
@ -1861,8 +1867,8 @@ fill_d3d_texture_pixels(DXScreenData &scrn, bool compress_texture) {
if (FAILED(hr)) {
return hr; // error message was already output in fill_d3d_texture_mipmap_pixels
}
}
}
}
}
else {
// mipmaps need to be generated, either use autogen or d3dx functions
@ -1888,6 +1894,10 @@ fill_d3d_texture_pixels(DXScreenData &scrn, bool compress_texture) {
mip_filter_flags = D3DX_FILTER_TRIANGLE;
}
if (Texture::is_srgb(tex->get_format())) {
mip_filter_flags |= D3DX_FILTER_SRGB;
}
// mip_filter_flags |= D3DX_FILTER_DITHER;
hr = D3DXFilterTexture(_d3d_texture, (PALETTEENTRY*)NULL, 0,
mip_filter_flags);
@ -1934,7 +1944,7 @@ fill_d3d_volume_texture_pixels(DXScreenData &scrn) {
if (!scrn._dxgsg9->get_supports_compressed_texture_format(image_compression)) {
image = tex->get_uncompressed_ram_image();
image_compression = Texture::CM_off;
}
}
if (image.is_null()) {
// The texture doesn't have an image to load. That's ok; it
@ -1991,6 +2001,10 @@ fill_d3d_volume_texture_pixels(DXScreenData &scrn) {
// dithering)??)
level_0_filter = D3DX_FILTER_LINEAR ; //| D3DX_FILTER_DITHER; //dithering looks ugly on i810 for 4444 textures
if (Texture::is_srgb(tex->get_format())) {
level_0_filter |= D3DX_FILTER_SRGB;
}
// D3DXLoadSurfaceFromMemory will load black luminance and we want
// full white, so convert to explicit luminance-alpha format
if (_d3d_format == D3DFMT_A8) {
@ -2070,6 +2084,10 @@ fill_d3d_volume_texture_pixels(DXScreenData &scrn) {
mip_filter_flags = D3DX_FILTER_TRIANGLE;
}
if (Texture::is_srgb(tex->get_format())) {
mip_filter_flags |= D3DX_FILTER_SRGB;
}
// mip_filter_flags| = D3DX_FILTER_DITHER;
hr = D3DXFilterTexture(_d3d_texture, (PALETTEENTRY*)NULL, 0,
@ -2167,6 +2185,17 @@ get_bits_per_pixel(Texture::Format format, int *alphbits) {
case Texture::F_rgba32:
*alphbits = 32;
return 128;
case Texture::F_srgb:
return 24;
case Texture::F_srgb_alpha:
*alphbits = 8;
return 32;
case Texture::F_sluminance:
return 8;
case Texture::F_sluminance_alpha:
*alphbits = 8;
return 16;
}
return 8;
}
@ -2180,7 +2209,7 @@ PN_stdfloat DXTextureContext9::
d3d_format_to_bytes_per_pixel (D3DFORMAT format)
{
PN_stdfloat bytes_per_pixel;
bytes_per_pixel = 0.0f;
switch (format)
{
@ -2246,6 +2275,6 @@ d3d_format_to_bytes_per_pixel (D3DFORMAT format)
bytes_per_pixel = 1.0f;
break;
}
return bytes_per_pixel;
}

View File

@ -139,7 +139,7 @@ make_output(const string &name,
// Early failure - if we are sure that this buffer WONT
// meet specs, we can bail out early.
if ((flags & BF_fb_props_optional) == 0) {
if ((fb_prop.get_indexed_color() > 0)||
if (fb_prop.get_indexed_color() ||
(fb_prop.get_back_buffers() > 0)||
(fb_prop.get_accum_bits() > 0)||
(fb_prop.get_multisamples() > 0)) {
@ -649,7 +649,7 @@ search_for_valid_displaymode(DXScreenData &scrn,
continue;
}
// disable refresh rate checking since SLI video cards may use
// disable refresh rate checking since SLI video cards may use
// refresh rates less than 60
if (0) {
if ((dispmode.RefreshRate<60) && (dispmode.RefreshRate>1)) {
@ -663,7 +663,7 @@ search_for_valid_displaymode(DXScreenData &scrn,
continue;
}
}
// Note no attempt is made to verify if format will work at
// requested size, so even if this call succeeds, could still get
// an out-of-video-mem error
@ -956,7 +956,7 @@ const char *D3DFormatStr(D3DFORMAT fmt) {
CASESTR(D3DFMT_D24X4S4);
CASESTR(D3DFMT_VERTEXDATA);
CASESTR(D3DFMT_INDEX16);
CASESTR(D3DFMT_INDEX32);
CASESTR(D3DFMT_INDEX32);
CASESTR(D3DFMT_A16B16G16R16F);
CASESTR(D3DFMT_A32B32G32R32F);
}

View File

@ -252,7 +252,7 @@ verify_window_sizes(int numsizes, int *dimen) {
void wdxGraphicsWindow9::
close_window() {
if (wdxdisplay9_cat.is_debug()) {
wdxdisplay9_cat.debug()
wdxdisplay9_cat.debug()
<< "wdxGraphicsWindow9::close_window() " << this << "\n";
}
@ -300,7 +300,7 @@ open_window() {
// window.
{
WindowProperties resized_props;
resized_props.set_size(_wcontext._display_mode.Width,
resized_props.set_size(_wcontext._display_mode.Width,
_wcontext._display_mode.Height);
_properties.add_properties(resized_props);
}
@ -420,17 +420,17 @@ void wdxGraphicsWindow9::
handle_reshape() {
GdiFlush();
WinGraphicsWindow::handle_reshape();
if (_dxgsg != NULL) {
if (_dxgsg != NULL && _dxgsg->_d3d_device != NULL) {
// create the new resized rendertargets
WindowProperties props = get_properties();
int x_size = props.get_x_size();
int y_size = props.get_y_size();
if (_wcontext._presentation_params.BackBufferWidth != x_size ||
_wcontext._presentation_params.BackBufferHeight != y_size) {
bool resize_succeeded = reset_device_resize_window(x_size, y_size);
if (wdxdisplay9_cat.is_debug()) {
if (!resize_succeeded) {
wdxdisplay9_cat.debug()
@ -708,7 +708,7 @@ create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer
if (dx_disable_driver_management_ex) {
dwBehaviorFlags |= D3DCREATE_DISABLE_DRIVER_MANAGEMENT_EX;
}
if (is_fullscreen()) {
// CREATE FULLSCREEN BUFFERS
@ -751,11 +751,11 @@ create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer
}
//From d3d8caps.h
//D3DPRESENT_INTERVAL_DEFAULT = 0x00000000L
//D3DPRESENT_INTERVAL_DEFAULT = 0x00000000L
//#define D3DPRESENT_INTERVAL_ONE 0x00000001L
//Next line is really sloppy, should either be D3DPRESENT_INTERVAL_DEFAULT or D3DPRESENT_INTERVAL_ONE
//not a direct number! but I'm not going to touch it because it's working as is. Zhao 12/15/2011
presentation_params->PresentationInterval = 0;
presentation_params->PresentationInterval = 0;
//ATI 5450 doesn't like D3DSWAPEFFECT_FLIP
presentation_params->SwapEffect = D3DSWAPEFFECT_DISCARD;
@ -803,7 +803,7 @@ create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer
PRINT_REFCNT(wdxdisplay9, _wcontext._d3d_device);
if (presentation_params->EnableAutoDepthStencil) {
if (presentation_params->EnableAutoDepthStencil) {
int depth_bits;
int stencil_bits;
@ -846,7 +846,7 @@ create_screen_buffers_and_device(DXScreenData &display, bool force_16bpp_zbuffer
wdxdisplay9_cat.error() << "unknown depth stencil format " << presentation_params->AutoDepthStencilFormat;
break;
}
_fb_properties.set_stencil_bits(stencil_bits);
_fb_properties.set_depth_bits(depth_bits);
} else {
@ -1118,16 +1118,16 @@ consider_device(wdxGraphicsPipe9 *dxpipe, DXDeviceInfo *device_info) {
if (is_fullscreen()) {
bool bCouldntFindValidZBuf;
dxpipe->search_for_valid_displaymode(_wcontext, dwRenderWidth, dwRenderHeight,
bNeedZBuffer, bWantStencil,
&_wcontext._supported_screen_depths_mask,
&bCouldntFindValidZBuf,
&pixFmt, dx_force_16bpp_zbuffer, true);
// note I'm not saving refresh rate, will just use adapter
// default at given res for now
if (pixFmt == D3DFMT_UNKNOWN) {
wdxdisplay9_cat.error()
<< (bCouldntFindValidZBuf ? "Couldnt find valid zbuffer format to go with FullScreen mode" : "No supported FullScreen modes")

View File

@ -31,5 +31,5 @@ VirtualFileMountAndroidAsset(AAssetManager *mgr, const string &apk_path) :
////////////////////////////////////////////////////////////////////
INLINE VirtualFileMountAndroidAsset::AssetStream::
AssetStream(AAsset *asset) :
istream(new AssetStreamBuf(asset)) {
istream(new VirtualFileMountAndroidAsset::AssetStreamBuf(asset)) {
}

View File

@ -57,7 +57,7 @@ get_fd(const Filename &file, off_t *start, off_t *length) const {
////////////////////////////////////////////////////////////////////
bool VirtualFileMountAndroidAsset::
has_file(const Filename &file) const {
return (file.empty() || is_directory(file) || is_regular_file(file));
return (file.empty() || /*is_directory(file) ||*/ is_regular_file(file));
}
////////////////////////////////////////////////////////////////////

View File

@ -90,6 +90,7 @@
#define GL_DEPTH_STENCIL_EXT GL_DEPTH_STENCIL_OES
#define GL_UNSIGNED_INT_24_8_EXT GL_UNSIGNED_INT_24_8_OES
#define GL_DEPTH24_STENCIL8_EXT GL_DEPTH24_STENCIL8_OES
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
#define GL_DEPTH_COMPONENT16 GL_DEPTH_COMPONENT16_OES
#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES
#define GL_DEPTH_COMPONENT32 GL_DEPTH_COMPONENT32_OES

View File

@ -18,7 +18,7 @@
#include "Cg/cgGL.h"
#include "pStatTimer.h"
#include "pStatGPUTimer.h"
TypeHandle CLP(CgShaderContext)::_type_handle;
@ -50,7 +50,7 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
nassertv(s->get_language() == Shader::SL_Cg);
// Ask the shader to compile itself for us and
// Ask the shader to compile itself for us and
// to give us the resulting Cg program objects.
if (!s->cg_compile_for(_glgsg->_shader_caps,
_cg_context,
@ -223,7 +223,7 @@ unbind() {
////////////////////////////////////////////////////////////////////
void CLP(CgShaderContext)::
issue_parameters(int altered) {
PStatTimer timer(_glgsg->_draw_set_state_shader_parameters_pcollector);
//PStatGPUTimer timer(_glgsg, _glgsg->_draw_set_state_shader_parameters_pcollector);
if (!valid()) {
return;
@ -233,9 +233,9 @@ issue_parameters(int altered) {
for (int i=0; i<(int)_shader->_ptr_spec.size(); i++) {
if (altered & (_shader->_ptr_spec[i]._dep[0] | _shader->_ptr_spec[i]._dep[1])) {
const Shader::ShaderPtrSpec& _ptr = _shader->_ptr_spec[i];
Shader::ShaderPtrData* ptr_data =
Shader::ShaderPtrData* ptr_data =
const_cast< Shader::ShaderPtrData*>(_glgsg->fetch_ptr_parameter(_ptr));
if (ptr_data == NULL){ //the input is not contained in ShaderPtrData
release_resources();
return;
@ -249,14 +249,14 @@ issue_parameters(int altered) {
int input_size = _ptr._dim[0] * _ptr._dim[1] * _ptr._dim[2];
// dimension is negative only if the parameter had the (deprecated)k_ prefix.
if ((input_size > ptr_data->_size) && (_ptr._dim[0] > 0)) {
GLCAT.error() << _ptr._id._name << ": incorrect number of elements, expected "
if ((input_size > ptr_data->_size) && (_ptr._dim[0] > 0)) {
GLCAT.error() << _ptr._id._name << ": incorrect number of elements, expected "
<< input_size <<" got " << ptr_data->_size << "\n";
release_resources();
return;
}
CGparameter p = _cg_parameter_map[_ptr._id._seqno];
switch (ptr_data->_type) {
case Shader::SPT_float:
switch(_ptr._info._class) {
@ -271,7 +271,7 @@ issue_parameters(int altered) {
case Shader::SAC_matrix: cgGLSetMatrixParameterfc(p,(float*)ptr_data->_ptr); continue;
case Shader::SAC_array: {
switch(_ptr._info._subclass) {
case Shader::SAC_scalar:
case Shader::SAC_scalar:
cgGLSetParameterArray1f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue;
case Shader::SAC_vector:
switch(_ptr._dim[2]) {
@ -298,7 +298,7 @@ issue_parameters(int altered) {
case Shader::SAC_matrix: cgGLSetMatrixParameterdc(p,(double*)ptr_data->_ptr); continue;
case Shader::SAC_array: {
switch(_ptr._info._subclass) {
case Shader::SAC_scalar:
case Shader::SAC_scalar:
cgGLSetParameterArray1d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue;
case Shader::SAC_vector:
switch(_ptr._dim[2]) {
@ -323,8 +323,8 @@ issue_parameters(int altered) {
case Shader::SAT_vec4: cgSetParameter4iv(p,(int*)ptr_data->_ptr); continue;
}
}
default: GLCAT.error() << _ptr._id._name << ":" << "unrecognized parameter type\n";
release_resources();
default: GLCAT.error() << _ptr._id._name << ":" << "unrecognized parameter type\n";
release_resources();
return;
}
}

View File

@ -27,7 +27,10 @@ CLP(GraphicsBuffer)(GraphicsEngine *engine, GraphicsPipe *pipe,
int flags,
GraphicsStateGuardian *gsg,
GraphicsOutput *host) :
GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host),
_bind_texture_pcollector(_draw_window_pcollector, "Bind textures"),
_generate_mipmap_pcollector(_draw_window_pcollector, "Generate mipmaps"),
_resolve_multisample_pcollector(_draw_window_pcollector, "Resolve multisamples")
{
CLP(GraphicsStateGuardian) *glgsg;
@ -171,11 +174,12 @@ begin_frame(FrameMode mode, Thread *current_thread) {
// In case of multisample rendering, we don't need to issue
// the barrier until we call glBlitFramebuffer.
#ifndef OPENGLES
if (gl_enable_memory_barriers && _fbo_multisample == 0) {
CLP(GraphicsStateGuardian) *glgsg;
DCAST_INTO_R(glgsg, _gsg, false);
pvector<CLP(TextureContext)*>::iterator it;
TextureContexts::iterator it;
for (it = _texture_contexts.begin(); it != _texture_contexts.end(); ++it) {
CLP(TextureContext) *gtc = *it;
@ -186,6 +190,7 @@ begin_frame(FrameMode mode, Thread *current_thread) {
}
}
}
#endif
}
_gsg->set_current_properties(&get_fb_properties());
@ -274,6 +279,8 @@ rebuild_bitplanes() {
return;
}
PStatGPUTimer timer(glgsg, _bind_texture_pcollector);
// Calculate bitplane size. This can be larger than the buffer.
if (_creation_flags & GraphicsPipe::BF_size_track_host) {
if (_host->get_size() != _size) {
@ -437,6 +444,19 @@ rebuild_bitplanes() {
// Bind the FBO
if (_fbo[layer] == 0) {
glgsg->_glGenFramebuffers(1, &_fbo[layer]);
#ifndef OPENGLES
if (glgsg->_use_object_labels) {
if (num_fbos > 1) {
GLchar name[128];
GLsizei len = snprintf(name, 128, "%s[%d]", _name.c_str(), layer);
glgsg->_glObjectLabel(GL_FRAMEBUFFER, _fbo[layer], len, name);
} else {
glgsg->_glObjectLabel(GL_FRAMEBUFFER, _fbo[layer], _name.size(), _name.data());
}
}
#endif
if (_fbo[layer] == 0) {
report_my_gl_errors();
return;
@ -469,7 +489,7 @@ rebuild_bitplanes() {
_have_any_color = true;
}
#ifndef OPENGLES
#ifndef OPENGLES_1
for (int i=0; i<_fb_properties.get_aux_rgba(); i++) {
bind_slot(layer, rb_resize, attach, (RenderTexturePlane)(RTP_aux_rgba_0+i), next++);
_have_any_color = true;
@ -1131,6 +1151,8 @@ generate_mipmaps() {
CLP(GraphicsStateGuardian) *glgsg;
DCAST_INTO_V(glgsg, _gsg);
//PStatGPUTimer timer(glgsg, _generate_mipmap_pcollector);
pvector<CLP(TextureContext)*>::iterator it;
for (it = _texture_contexts.begin(); it != _texture_contexts.end(); ++it) {
CLP(TextureContext) *gtc = *it;
@ -1168,7 +1190,8 @@ end_frame(FrameMode mode, Thread *current_thread) {
copy_to_textures();
}
// Unbind the FBO
// 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);
glgsg->bind_fbo(0);
@ -1604,11 +1627,14 @@ check_host_valid() {
////////////////////////////////////////////////////////////////////
void CLP(GraphicsBuffer)::
resolve_multisamples() {
nassertv(_fbo.size() > 0);
CLP(GraphicsStateGuardian) *glgsg;
DCAST_INTO_V(glgsg, _gsg);
nassertv(_fbo.size() > 0);
PStatGPUTimer timer(glgsg, _resolve_multisample_pcollector);
#ifndef OPENGLES
if (gl_enable_memory_barriers) {
// Issue memory barriers as necessary to make sure that the
// texture memory is synchronized before we blit to it.
@ -1623,6 +1649,7 @@ resolve_multisamples() {
}
}
}
#endif
glgsg->report_my_gl_errors();
GLuint fbo = _fbo[0];
@ -1631,7 +1658,7 @@ resolve_multisamples() {
}
glgsg->_glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, fbo);
glgsg->_glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, _fbo_multisample);
// If the depth buffer is shared, resolve it only on the last to render FBO.
bool do_depth_blit = false;
if (_rbm[RTP_depth_stencil] != 0 || _rbm[RTP_depth] != 0) {
@ -1671,6 +1698,7 @@ resolve_multisamples() {
GL_NEAREST);
}
// Now handle the other color buffers.
#ifndef OPENGLES_1
int next = GL_COLOR_ATTACHMENT1_EXT;
if (_fb_properties.is_stereo()) {
glReadBuffer(next);
@ -1679,7 +1707,6 @@ resolve_multisamples() {
GL_COLOR_BUFFER_BIT, GL_NEAREST);
next += 1;
}
#ifndef OPENGLES
for (int i = 0; i < _fb_properties.get_aux_rgba(); ++i) {
glReadBuffer(next);
glDrawBuffer(next);

View File

@ -34,7 +34,7 @@
// * Can render onto a texture without clearing it first.
// * Supports multisample antialiased rendering.
//
// Some of these deserve a little explanation.
// Some of these deserve a little explanation.
// Auxiliary bitplanes are additional bitplanes above
// and beyond the normal depth,stencil,color. One can
// use them to render out multiple textures in a single
@ -43,14 +43,14 @@
// buffer will be equal to the texture's previous
// contents. This alo means you can meaningfully
// share a bitplane between two buffers by binding
// the same texture to both buffers.
// the same texture to both buffers.
//
// If either of the necessary OpenGL extensions is not
// available, then the glGraphicsBuffer will not be
// available (although it may still be possible to
// create a wglGraphicsBuffer or glxGraphicsBuffer).
//
// This class now also uses the extensions
// This class now also uses the extensions
// EXT_framebuffer_multisample and EXT_framebuffer_blit
// to allow for multisample antialiasing these offscreen
// render targets. If these extensions are unavailable
@ -87,13 +87,13 @@ public:
protected:
virtual void close_buffer();
virtual bool open_buffer();
void check_host_valid();
void report_my_errors(int line, const char *file);
private:
void bind_slot(int layer, bool rb_resize, Texture **attach,
RenderTexturePlane plane, GLenum attachpoint);
void bind_slot_multisample(bool rb_resize, Texture **attach,
@ -127,7 +127,8 @@ private:
// List of textures for which we might have to generate mipmaps
// after rendering one frame.
pvector<CLP(TextureContext)*> _texture_contexts;
typedef pvector<CLP(TextureContext)*> TextureContexts;
TextureContexts _texture_contexts;
// The cube map face we are currently drawing to or have just
// finished drawing to, or -1 if we are not drawing to a cube map.
@ -136,10 +137,14 @@ private:
bool _initial_clear;
bool _needs_rebuild;
UpdateSeq _last_textures_seq;
CLP(GraphicsBuffer) *_shared_depth_buffer;
list <CLP(GraphicsBuffer) *> _shared_depth_buffer_list;
PStatCollector _bind_texture_pcollector;
PStatCollector _generate_mipmap_pcollector;
PStatCollector _resolve_multisample_pcollector;
public:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -27,6 +27,7 @@
INLINE bool CLP(GraphicsStateGuardian)::
report_errors(int line, const char *source_file) {
#ifndef NDEBUG
PStatTimer timer(_check_error_pcollector);
GLenum error_code = glGetError();
if (error_code != GL_NO_ERROR) {
int error_count = 0;
@ -46,6 +47,7 @@ INLINE void CLP(GraphicsStateGuardian)::
report_my_errors(int line, const char *source_file) {
#ifndef NDEBUG
if (_check_errors) {
PStatTimer timer(_check_error_pcollector);
GLenum error_code = glGetError();
if (error_code != GL_NO_ERROR) {
if (!report_errors_loop(line, source_file, error_code, _error_count)) {
@ -69,6 +71,7 @@ report_my_errors(int line, const char *source_file) {
////////////////////////////////////////////////////////////////////
INLINE bool CLP(GraphicsStateGuardian)::
clear_errors(int line, const char *source_file) {
PStatTimer timer(_check_error_pcollector);
GLenum error_code = glGetError();
if (error_code != GL_NO_ERROR) {
int error_count = 0;
@ -92,6 +95,7 @@ clear_errors(int line, const char *source_file) {
INLINE void CLP(GraphicsStateGuardian)::
clear_my_errors(int line, const char *source_file) {
if (_check_errors) {
PStatTimer timer(_check_error_pcollector);
GLenum error_code = glGetError();
if (error_code != GL_NO_ERROR) {
int error_count = 0;
@ -743,7 +747,7 @@ get_clip_plane_id(int index) const {
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::get_supports_framebuffer_multisample
// Access: Public
// Description: Returns if this glGsg supports multisample
// Description: Returns if this glGsg supports multisample
// antialiasing for framebuffer objects.
////////////////////////////////////////////////////////////////////
INLINE bool CLP(GraphicsStateGuardian)::
@ -754,7 +758,7 @@ get_supports_framebuffer_multisample() {
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::get_supports_framebuffer_multisample
// Access: Public
// Description: Returns if this glGsg supports multisample
// Description: Returns if this glGsg supports multisample
// antialiasing for framebuffer objects.
////////////////////////////////////////////////////////////////////
INLINE bool CLP(GraphicsStateGuardian)::
@ -766,7 +770,7 @@ get_supports_framebuffer_multisample_coverage_nv() {
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::get_supports_framebuffer_blit
// Access: Public
// Description: Returns if this glGsg supports multisample
// Description: Returns if this glGsg supports multisample
// antialiasing for framebuffer objects.
////////////////////////////////////////////////////////////////////
INLINE bool CLP(GraphicsStateGuardian)::
@ -778,7 +782,7 @@ get_supports_framebuffer_blit() {
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::UsageTextureKey::Constructor
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE CLP(GraphicsStateGuardian)::UsageTextureKey::
UsageTextureKey(int x_size, int y_size) :
@ -792,7 +796,7 @@ UsageTextureKey(int x_size, int y_size) :
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::UsageTextureKey::operator <
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool CLP(GraphicsStateGuardian)::UsageTextureKey::
operator < (const CLP(GraphicsStateGuardian)::UsageTextureKey &other) const {

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
// Filename: glGraphicsStateGuardian_src.h
// Created by: drose (02Feb99)
// Updated by: fperazzi, PandaSE (05May10) (added
// Updated by: fperazzi, PandaSE (05May10) (added
// get_supports_cg_profile)
//
////////////////////////////////////////////////////////////////////
@ -37,6 +37,7 @@
#include "pmap.h"
#include "geomVertexArrayData.h"
#include "lightMutex.h"
#include "pStatGPUTimer.h"
class PlaneNode;
class Light;
@ -58,6 +59,7 @@ typedef double GLdouble;
typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
typedef void (APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img);
typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
@ -65,6 +67,8 @@ typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64 *params);
typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *params);
typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
// There is some trivial disagreement between different gl.h headers about this one, so we use our own typename.
@ -98,32 +102,32 @@ typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint
typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
typedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
typedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
typedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count);
typedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights);
typedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights);
typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer);
typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer);
typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers);
typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers);
typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);
typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer);
typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers);
typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers);
typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target);
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
typedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
typedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count);
typedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights);
typedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights);
typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer);
typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer);
typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers);
typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers);
typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);
typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer);
typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers);
typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers);
typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target);
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
#ifdef OPENGLES_2
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
#else
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
#endif
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target);
typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index);
typedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices);
@ -189,7 +193,7 @@ typedef void (APIENTRYP PFNGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count
typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufsize, GLsizei *length, GLenum *binaryFormat, void *binary);
typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLEPROC) (GLuint texture);
typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEPROC) (GLuint texture, GLuint sampler);
typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTPROC) (GLuint64 handle);
@ -228,7 +232,7 @@ public:
virtual int get_driver_version_minor();
virtual int get_driver_shader_version_major();
virtual int get_driver_shader_version_minor();
#ifndef OPENGLES_1
static void debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
#endif
@ -302,13 +306,15 @@ public:
virtual void begin_occlusion_query();
virtual PT(OcclusionQueryContext) end_occlusion_query();
virtual PT(TimerQueryContext) issue_timer_query(int pstats_index);
virtual void dispatch_compute(int size_x, int size_y, int size_z);
virtual PT(GeomMunger) make_geom_munger(const RenderState *state,
Thread *current_thread);
virtual void clear(DrawableRegion *region);
virtual bool framebuffer_copy_to_texture
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb);
virtual bool framebuffer_copy_to_ram
@ -332,9 +338,9 @@ public:
void draw_immediate_composite_primitives(const GeomPrimitivePipelineReader *reader, GLenum mode);
#endif // SUPPORT_IMMEDIATE_MODE
INLINE static bool report_errors(int line, const char *source_file);
INLINE bool report_errors(int line, const char *source_file);
INLINE void report_my_errors(int line, const char *source_file);
INLINE static bool clear_errors(int line, const char *source_file);
INLINE bool clear_errors(int line, const char *source_file);
INLINE void clear_my_errors(int line, const char *source_file);
INLINE const string &get_gl_vendor() const;
@ -475,8 +481,8 @@ protected:
bool upload_texture(CLP(TextureContext) *gtc, bool force);
bool upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
bool uses_mipmaps, int mipmap_bias,
GLenum texture_target, GLenum page_target,
GLint internal_format, GLint external_format,
GLenum texture_target, GLenum page_target,
GLint internal_format, GLint external_format,
GLenum component_type,
bool one_page_only, int z,
Texture::CompressionMode image_compression);
@ -590,9 +596,12 @@ protected:
public:
bool _supports_point_parameters;
PFNGLPOINTPARAMETERFVPROC _glPointParameterfv;
bool _supports_point_sprite;
#ifndef OPENGLES
PFNGLPRIMITIVERESTARTINDEXPROC _glPrimitiveRestartIndex;
#endif
bool _supports_vertex_blend;
PFNGLWEIGHTPOINTERARBPROC _glWeightPointer;
PFNGLVERTEXBLENDARBPROC _glVertexBlend;
@ -703,6 +712,14 @@ public:
PFNGLGETQUERYIVPROC _glGetQueryiv;
PFNGLGETQUERYOBJECTUIVPROC _glGetQueryObjectuiv;
#ifndef OPENGLES
PFNGLQUERYCOUNTERPROC _glQueryCounter;
PFNGLGETQUERYOBJECTI64VPROC _glGetQueryObjecti64v;
PFNGLGETQUERYOBJECTUI64VPROC _glGetQueryObjectui64v;
PFNGLGETINTEGER64VPROC _glGetInteger64v;
#endif
PFNGLACTIVESTENCILFACEEXTPROC _glActiveStencilFaceEXT;
#ifndef OPENGLES_1
@ -778,9 +795,9 @@ public:
#endif
LightMutex _lock;
typedef pvector<GLuint> DeletedDisplayLists;
DeletedDisplayLists _deleted_display_lists;
DeletedDisplayLists _deleted_queries;
typedef pvector<GLuint> DeletedNames;
DeletedNames _deleted_display_lists;
DeletedNames _deleted_queries;
#ifndef OPENGLES
// Stores textures for which memory bariers should be issued.
@ -797,6 +814,9 @@ public:
bool _force_flush;
bool _supports_debug;
bool _use_object_labels;
PFNGLOBJECTLABELPROC _glObjectLabel;
#ifndef NDEBUG
bool _show_texture_usage;
int _show_texture_usage_max_size;
@ -818,7 +838,11 @@ public:
static PStatCollector _primitive_batches_display_list_pcollector;
static PStatCollector _vertices_display_list_pcollector;
static PStatCollector _vertices_immediate_pcollector;
static PStatCollector _compute_dispatch_pcollector;
static PStatCollector _memory_barrier_pcollector;
static PStatCollector _vertex_array_update_pcollector;
static PStatCollector _texture_update_pcollector;
static PStatCollector _fbo_bind_pcollector;
static PStatCollector _check_error_pcollector;
public:
virtual TypeHandle get_type() const {
@ -846,6 +870,7 @@ private:
friend class CLP(CgShaderContext);
friend class CLP(GraphicsBuffer);
friend class CLP(OcclusionQueryContext);
friend class CLP(TimerQueryContext);
};
#include "glGraphicsStateGuardian_src.I"

View File

@ -0,0 +1,14 @@
// Filename: glLatencyQueryContext_src.I
// Created by: rdb (24Sep14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,54 @@
// Filename: glLatencyQueryContext_src.cxx
// Created by: rdb (24Sep14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef OPENGLES // Timer queries not supported by OpenGL ES.
TypeHandle CLP(LatencyQueryContext)::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: CLP(LatencyQueryContext)::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
CLP(LatencyQueryContext)::
CLP(LatencyQueryContext)(CLP(GraphicsStateGuardian) *glgsg,
int pstats_index) :
CLP(TimerQueryContext)(glgsg, pstats_index),
_timestamp(0)
{
glgsg->_glGetInteger64v(GL_TIMESTAMP, &_timestamp);
}
////////////////////////////////////////////////////////////////////
// Function: LatencyQueryContext::get_timestamp
// Access: Public, Virtual
// Description: Returns the timestamp that is the result of this
// timer query. There's no guarantee about which
// clock this uses, the only guarantee is that
// subtracting a start time from an end time should
// yield a time in seconds.
// If is_answer_ready() did not return true, this
// function may block before it returns.
//
// It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
double CLP(LatencyQueryContext)::
get_timestamp() const {
GLint64 time_ns;
_glgsg->_glGetQueryObjecti64v(_index, GL_QUERY_RESULT, &time_ns);
return (time_ns - _timestamp) * 0.000000001;
}
#endif // OPENGLES

View File

@ -0,0 +1,57 @@
// Filename: glLatencyQueryContext_src.h
// Created by: rdb (24Sep14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
class GraphicsStateGuardian;
#ifndef OPENGLES // Timer queries not supported by OpenGL ES.
////////////////////////////////////////////////////////////////////
// Class : GLLatencyQueryContext
// Description : This is a special variant of GLTimerQueryContext
// that measures the command latency, ie. the time
// it takes for the GPU to actually get to the commands
// we are issuing right now.
////////////////////////////////////////////////////////////////////
class EXPCL_GL CLP(LatencyQueryContext) : public CLP(TimerQueryContext) {
public:
CLP(LatencyQueryContext)(CLP(GraphicsStateGuardian) *glgsg, int pstats_index);
ALLOC_DELETED_CHAIN(CLP(LatencyQueryContext));
virtual double get_timestamp() const;
GLint64 _timestamp;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
CLP(TimerQueryContext)::init_type();
register_type(_type_handle, CLASSPREFIX_QUOTED "LatencyQueryContext",
CLP(TimerQueryContext)::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "glLatencyQueryContext_src.I"
#endif // OPENGLES

View File

@ -16,7 +16,7 @@
#ifndef OPENGLES_1
#include "pStatTimer.h"
#include "pStatGPUTimer.h"
TypeHandle CLP(ShaderContext)::_type_handle;
@ -35,19 +35,19 @@ TypeHandle CLP(ShaderContext)::_type_handle;
// Access: Public
// Description: The Panda CG shader syntax defines a useful set of shorthand notations for setting nodepath
// properties as shaderinputs. For example, float4 mspos_XXX refers to nodepath XXX's position
// in model space. This function is a rough attempt to reimplement some of the shorthand
// in model space. This function is a rough attempt to reimplement some of the shorthand
// notations for GLSL. The code is ~99% composed of excerpts dealing with matrix shaderinputs
// from Shader::compile_parameter.
//
// Given a uniform variable name queried from the compiled shader passed in via arg_id,
// from Shader::compile_parameter.
//
// Given a uniform variable name queried from the compiled shader passed in via arg_id,
// 1) parse the name
// 2a) if the name refers to a Panda shorthand notation
// push the appropriate matrix into shader._mat_spec
// returns True
// 2b) If the name doesn't refer to a Panda shorthand notation
// returns False
//
// The boolean return is used to notify down-river processing whether the shader var/parm was
//
// The boolean return is used to notify down-river processing whether the shader var/parm was
// actually picked up and the appropriate ShaderMatSpec pushed onto _mat_spec.
////////////////////////////////////////////////////////////////////
bool CLP(ShaderContext)::
@ -700,7 +700,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
}
}
}
// Now we've processed the uniforms, we'll process the attribs.
_glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTES, &param_count);
_glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &param_maxlength);
@ -836,7 +836,7 @@ release_resources() {
}
_glsl_shaders.clear();
_glgsg->report_my_gl_errors();
}
@ -890,7 +890,7 @@ unbind() {
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
issue_parameters(int altered) {
PStatTimer timer(_glgsg->_draw_set_state_shader_parameters_pcollector);
//PStatGPUTimer timer(_glgsg, _glgsg->_draw_set_state_shader_parameters_pcollector);
if (!valid()) {
return;
@ -1374,12 +1374,11 @@ glsl_report_shader_errors(GLuint shader) {
_glgsg->_glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
if (length > 1) {
info_log = (char *) malloc(length);
info_log = (char *) alloca(length);
_glgsg->_glGetShaderInfoLog(shader, length, &num_chars, info_log);
if (strcmp(info_log, "Success.\n") != 0 && strcmp(info_log, "No errors.\n") != 0) {
GLCAT.error(false) << info_log << "\n";
}
free(info_log);
}
}
@ -1397,19 +1396,18 @@ glsl_report_program_errors(GLuint program) {
_glgsg->_glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
if (length > 1) {
info_log = (char *) malloc(length);
info_log = (char *) alloca(length);
_glgsg->_glGetProgramInfoLog(program, length, &num_chars, info_log);
if (strcmp(info_log, "Success.\n") != 0 && strcmp(info_log, "No errors.\n") != 0) {
GLCAT.error(false) << info_log << "\n";
}
free(info_log);
}
}
////////////////////////////////////////////////////////////////////
// Function: Shader::glsl_compile_shader
// Access: Private
// Description:
// Description:
////////////////////////////////////////////////////////////////////
bool CLP(ShaderContext)::
glsl_compile_shader(Shader::ShaderType type) {
@ -1451,16 +1449,21 @@ glsl_compile_shader(Shader::ShaderType type) {
return false;
}
if (_glgsg->_use_object_labels) {
string name = _shader->get_filename(type);
_glgsg->_glObjectLabel(GL_SHADER, handle, name.size(), name.data());
}
string text_str = _shader->get_text(type);
const char* text = text_str.c_str();
_glgsg->_glShaderSource(handle, 1, &text, NULL);
_glgsg->_glCompileShader(handle);
GLint status;
_glgsg->_glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
GLCAT.error()
<< "An error occurred while compiling shader "
GLCAT.error()
<< "An error occurred while compiling shader "
<< _shader->get_filename(type) << "\n";
glsl_report_shader_errors(handle);
_glgsg->_glDeleteShader(handle);
@ -1485,6 +1488,12 @@ glsl_compile_and_link() {
if (!_glsl_program) {
return false;
}
if (_glgsg->_use_object_labels) {
string name = _shader->get_filename();
_glgsg->_glObjectLabel(GL_PROGRAM, _glsl_program, name.size(), name.data());
}
bool valid = true;
if (!_shader->get_text(Shader::ST_vertex).empty()) {
@ -1507,7 +1516,7 @@ glsl_compile_and_link() {
nassertr(_glgsg->_glProgramParameteri != NULL, false);
GLint max_vertices;
glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &max_vertices);
_glgsg->_glProgramParameteri(_glsl_program, GL_GEOMETRY_VERTICES_OUT_ARB, max_vertices);
_glgsg->_glProgramParameteri(_glsl_program, GL_GEOMETRY_VERTICES_OUT_ARB, max_vertices);
}
#endif

View File

@ -23,12 +23,14 @@ TypeHandle CLP(TextureContext)::_type_handle;
////////////////////////////////////////////////////////////////////
CLP(TextureContext)::
~CLP(TextureContext)() {
#ifndef OPENGLES
if (gl_enable_memory_barriers) {
_glgsg->_textures_needing_fetch_barrier.erase(this);
_glgsg->_textures_needing_image_access_barrier.erase(this);
_glgsg->_textures_needing_update_barrier.erase(this);
_glgsg->_textures_needing_framebuffer_barrier.erase(this);
}
#endif
glDeleteTextures(1, &_index);
_index = 0;
@ -53,12 +55,15 @@ void CLP(TextureContext)::
evict_lru() {
dequeue_lru();
#ifndef OPENGLES
if (_handle != 0) {
if (_handle_resident) {
_glgsg->_glMakeTextureHandleNonResident(_handle);
}
_handle_resident = false;
} else {
} else
#endif
{
reset_data();
}
@ -74,9 +79,11 @@ evict_lru() {
////////////////////////////////////////////////////////////////////
void CLP(TextureContext)::
reset_data() {
#ifndef OPENGLES
if (_handle != 0 && _handle_resident) {
_glgsg->_glMakeTextureHandleNonResident(_handle);
}
#endif
// Free the texture resources.
glDeleteTextures(1, &_index);
@ -108,6 +115,7 @@ reset_data() {
////////////////////////////////////////////////////////////////////
void CLP(TextureContext)::
make_handle_resident() {
#ifndef OPENGLES
if (_handle != 0) {
if (!_handle_resident) {
_glgsg->_glMakeTextureHandleResident(_handle);
@ -115,6 +123,7 @@ make_handle_resident() {
}
set_resident(true);
}
#endif
}
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,28 @@
// Filename: glTimerQueryContext_src.I
// Created by: rdb (22Aug14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: CLP(TimerQueryContext)::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE CLP(TimerQueryContext)::
CLP(TimerQueryContext)(CLP(GraphicsStateGuardian) *glgsg,
int pstats_index) :
TimerQueryContext(pstats_index),
_glgsg(glgsg),
_index(0)
{
}

View File

@ -0,0 +1,104 @@
// Filename: glTimerQueryContext_src.cxx
// Created by: rdb (22Aug14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "pnotify.h"
#include "dcast.h"
#include "lightMutexHolder.h"
#include "pStatTimer.h"
#ifndef OPENGLES // Timer queries not supported by OpenGL ES.
TypeHandle CLP(TimerQueryContext)::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: GLTimerQueryContext::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CLP(TimerQueryContext)::
~CLP(TimerQueryContext)() {
if (_index != 0) {
// Tell the GSG to recycle this index when it gets around to it.
LightMutexHolder holder(_glgsg->_lock);
_glgsg->_deleted_queries.push_back(_index);
_index = 0;
}
}
////////////////////////////////////////////////////////////////////
// Function: GLTimerQueryContext::is_answer_ready
// Access: Public, Virtual
// Description: Returns true if the query's answer is ready, false
// otherwise. If this returns false, the application
// must continue to poll until it returns true.
//
// It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
bool CLP(TimerQueryContext)::
is_answer_ready() const {
GLuint result;
_glgsg->_glGetQueryObjectuiv(_index, GL_QUERY_RESULT_AVAILABLE, &result);
return (result != 0);
}
////////////////////////////////////////////////////////////////////
// Function: GLTimerQueryContext::waiting_for_answer
// Access: Public, Virtual
// Description: Requests the graphics engine to expedite the pending
// answer--the application is now waiting until the
// answer is ready.
//
// It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
void CLP(TimerQueryContext)::
waiting_for_answer() {
PStatTimer timer(GraphicsStateGuardian::_wait_timer_pcollector);
glFlush();
}
////////////////////////////////////////////////////////////////////
// Function: TimerQueryContext::get_timestamp
// Access: Public, Virtual
// Description: Returns the timestamp that is the result of this
// timer query. There's no guarantee about which
// clock this uses, the only guarantee is that
// subtracting a start time from an end time should
// yield a time in seconds.
// If is_answer_ready() did not return true, this
// function may block before it returns.
//
// It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
double CLP(TimerQueryContext)::
get_timestamp() const {
GLuint64 time_ns;
/*GLuint available;
_glgsg->_glGetQueryObjectuiv(_index[1], GL_QUERY_RESULT_AVAILABLE, &available);
if (available) {
// The answer is ready now.
do_get_timestamps(begin_ns, end_ns);
} else {
// The answer is not ready; this call will block.
PStatTimer timer(GraphicsStateGuardian::_wait_timer_pcollector);
do_get_timestamps(begin_ns, end_ns);
}*/
_glgsg->_glGetQueryObjectui64v(_index, GL_QUERY_RESULT, &time_ns);
return time_ns * 0.000000001;
}
#endif // OPENGLES

View File

@ -0,0 +1,68 @@
// Filename: glTimerQueryContext_src.h
// Created by: rdb (22Aug14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#include "timerQueryContext.h"
#include "deletedChain.h"
#include "clockObject.h"
class GraphicsStateGuardian;
#ifndef OPENGLES // Timer queries not supported by OpenGL ES.
////////////////////////////////////////////////////////////////////
// Class : GLTimerQueryContext
// Description : This class manages a timer query that can be used
// by a PStatGPUTimer to measure the time a task takes
// to execute on the GPU.
// This records the current timestamp; a pair of these
// is usually used to get the elapsed time.
////////////////////////////////////////////////////////////////////
class EXPCL_GL CLP(TimerQueryContext) : public TimerQueryContext {
public:
INLINE CLP(TimerQueryContext)(CLP(GraphicsStateGuardian) *glgsg,
int pstats_index);
virtual ~CLP(TimerQueryContext)();
ALLOC_DELETED_CHAIN(CLP(TimerQueryContext));
virtual bool is_answer_ready() const;
virtual void waiting_for_answer();
virtual double get_timestamp() const;
GLuint _index;
CLP(GraphicsStateGuardian) *_glgsg;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TimerQueryContext::init_type();
register_type(_type_handle, CLASSPREFIX_QUOTED "TimerQueryContext",
TimerQueryContext::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "glTimerQueryContext_src.I"
#endif // OPENGLES

View File

@ -151,6 +151,13 @@ ConfigVariableEnum<NotifySeverity> gl_debug_abort_level
"that triggered the error message. "
"This feature is not available when NDEBUG has been defined."));
ConfigVariableBool gl_debug_object_labels
("gl-debug-object-labels", true,
PRC_DESC("When gl-debug is set to true, this will tell OpenGL the "
"name of textures, shaders, and other objects, so that OpenGL "
"can display those in error messages. There's usually no "
"reason to disable this."));
ConfigVariableBool gl_debug_buffers
("gl-debug-buffers", false,
PRC_DESC("Set this true, in addition to enabling debug notify for "
@ -162,7 +169,8 @@ ConfigVariableBool gl_finish
PRC_DESC("Set this true to force a call to glFinish() after every major "
"graphics operation. This is likely to slow down rendering "
"performance substantially, but it will make PStats graphs "
"more accurately reflect where the graphics bottlenecks are. "
"more accurately reflect where the graphics bottlenecks are, "
"although it is better to use timer queries when available. "
"This variable is enabled only if PStats is compiled in."));
ConfigVariableBool gl_force_depth_stencil
@ -252,6 +260,8 @@ void CLP(init_classes)() {
#ifndef OPENGLES
CLP(OcclusionQueryContext)::init_type();
CLP(TimerQueryContext)::init_type();
CLP(LatencyQueryContext)::init_type();
#endif
PandaSystem *ps = PandaSystem::get_global_ptr();

View File

@ -58,6 +58,7 @@ extern ConfigVariableEnum<GeomEnums::UsageHint> gl_min_buffer_usage_hint;
extern ConfigVariableBool gl_debug;
extern ConfigVariableBool gl_debug_synchronous;
extern ConfigVariableEnum<NotifySeverity> gl_debug_abort_level;
extern ConfigVariableBool gl_debug_object_labels;
extern ConfigVariableBool gl_debug_buffers;
extern ConfigVariableBool gl_finish;
extern ConfigVariableBool gl_force_depth_stencil;

View File

@ -22,6 +22,8 @@
#include "glVertexBufferContext_src.cxx"
#include "glIndexBufferContext_src.cxx"
#include "glOcclusionQueryContext_src.cxx"
#include "glTimerQueryContext_src.cxx"
#include "glLatencyQueryContext_src.cxx"
#include "glGeomContext_src.cxx"
#include "glGeomMunger_src.cxx"
#include "glShaderContext_src.cxx"

View File

@ -36,6 +36,8 @@
#include "glVertexBufferContext_src.h"
#include "glIndexBufferContext_src.h"
#include "glOcclusionQueryContext_src.h"
#include "glTimerQueryContext_src.h"
#include "glLatencyQueryContext_src.h"
#include "glGeomContext_src.h"
#include "glGeomMunger_src.h"
#include "glShaderContext_src.h"

View File

@ -6,7 +6,7 @@ extern "C" {
/*
** Copyright (c) 2007-2012 The Khronos Group Inc.
**
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
@ -14,10 +14,10 @@ extern "C" {
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@ -1163,6 +1163,11 @@ extern "C" {
/* reuse GL_TEXTURE_IMMUTABLE_FORMAT */
#endif
#ifndef GL_VERSION_4_3
#define GL_VERSION_4_3 1
#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
#endif
#ifndef GL_ARB_multitexture
#define GL_TEXTURE0_ARB 0x84C0
#define GL_TEXTURE1_ARB 0x84C1

View File

@ -43,6 +43,7 @@
geomVertexWriter.h geomVertexWriter.I \
indexBufferContext.I indexBufferContext.h \
internalName.I internalName.h \
internalName_ext.h internalName_ext.cxx \
lens.h lens.I \
material.I material.h materialPool.I materialPool.h \
matrixLens.I matrixLens.h \
@ -66,6 +67,7 @@
textureReloadRequest.I textureReloadRequest.h \
textureStage.I textureStage.h \
textureStagePool.I textureStagePool.h \
timerQueryContext.I timerQueryContext.h \
transformBlend.I transformBlend.h \
transformBlendTable.I transformBlendTable.h \
transformTable.I transformTable.h \
@ -136,6 +138,7 @@
textureReloadRequest.cxx \
textureStage.cxx \
textureStagePool.cxx \
timerQueryContext.cxx \
transformBlend.cxx \
transformBlendTable.cxx \
transformTable.cxx \
@ -208,6 +211,7 @@
textureReloadRequest.I textureReloadRequest.h \
textureStage.I textureStage.h \
textureStagePool.I textureStagePool.h \
timerQueryContext.I timerQueryContext.h \
transformBlend.I transformBlend.h \
transformBlendTable.I transformBlendTable.h \
transformTable.I transformTable.h \

View File

@ -44,6 +44,7 @@
#include "textureReloadRequest.h"
#include "textureStage.h"
#include "textureContext.h"
#include "timerQueryContext.h"
#include "shader.h"
#include "shaderContext.h"
#include "transformBlend.h"
@ -92,7 +93,7 @@ ConfigVariableInt texture_scale_limit
"to both X and Y."));
ConfigVariableList exclude_texture_scale
("exclude-texture-scale",
("exclude-texture-scale",
PRC_DESC("This is a list of glob patterns for texture filenames "
"(excluding the directory part of the filename, but including "
"the extension); for instance, 'digits_*.png'. Any texture "
@ -287,7 +288,7 @@ ConfigVariableInt vertex_column_alignment
"this alignment for the vertex animation columns only."));
ConfigVariableBool vertex_animation_align_16
("vertex-animation-align-16",
("vertex-animation-align-16",
#ifdef LINMATH_ALIGN
true,
#else
@ -343,7 +344,7 @@ ConfigVariableInt simple_image_size
ConfigVariableDouble simple_image_threshold
("simple-image-threshold", 0.1,
PRC_DESC("This is a value that indicates how closely a texture's "
PRC_DESC("This is a value that indicates how closely a texture's "
"generated simple "
"image should approximate the original image. The smaller the "
"number, the closer the match; small numbers will result in "
@ -568,6 +569,7 @@ ConfigureFn(config_gobj) {
TexturePoolFilter::init_type();
TextureReloadRequest::init_type();
TextureStage::init_type();
TimerQueryContext::init_type();
TransformBlend::init_type();
TransformBlendTable::init_type();
TransformTable::init_type();

View File

@ -125,6 +125,9 @@ PUBLISHED:
// The union of all of the above composite types.
GR_composite_bits = 0x01c00,
// If strip-cut indices are used to restart a composite primitive.
GR_strip_cut_index = 0x20000,
// If the shade model requires a particular vertex for flat shading.
GR_flat_first_vertex = 0x02000,
GR_flat_last_vertex = 0x04000,
@ -216,4 +219,3 @@ EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, GeomEnums::NumericType nume
EXPCL_PANDA_GOBJ ostream &operator << (ostream &out, GeomEnums::Contents contents);
#endif

View File

@ -89,7 +89,11 @@ get_primitive_type() const {
int GeomLinestrips::
get_geom_rendering() const {
if (is_indexed()) {
return GR_line_strip | GR_indexed_other;
if (get_num_primitives() > 1) {
return GR_line_strip | GR_indexed_other | GR_strip_cut_index;
} else {
return GR_line_strip | GR_indexed_other;
}
} else {
return GR_line_strip;
}
@ -106,6 +110,20 @@ get_min_num_vertices_per_primitive() const {
return 2;
}
////////////////////////////////////////////////////////////////////
// Function: GeomLinestrips::get_num_unused_vertices_per_primitive
// Access: Public, Virtual
// Description: Returns the number of vertices that are added between
// primitives that aren't, strictly speaking, part of
// the primitives themselves. This is used, for
// instance, to define degenerate triangles to connect
// otherwise disconnected triangle strips.
////////////////////////////////////////////////////////////////////
int GeomLinestrips::
get_num_unused_vertices_per_primitive() const {
return 1;
}
////////////////////////////////////////////////////////////////////
// Function: GeomLinestrips::draw
// Access: Public, Virtual
@ -138,9 +156,13 @@ decompose_impl() const {
lines->set_shade_model(get_shade_model());
CPTA_int ends = get_ends();
int vi = 0;
int num_unused = get_num_unused_vertices_per_primitive();
int vi = -num_unused;
int li = 0;
while (li < (int)ends.size()) {
// Skip unused vertices between tristrips.
vi += num_unused;
int end = ends[li];
nassertr(vi + 1 <= end, lines.p());
int v0 = get_vertex(vi);
@ -210,6 +232,33 @@ rotate_impl() const {
return new_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: GeomLinestrips::requires_unused_vertices
// Access: Protected, Virtual
// Description: Should be redefined to return true in any primitive
// that implements append_unused_vertices().
////////////////////////////////////////////////////////////////////
bool GeomLinestrips::
requires_unused_vertices() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GeomLinestrips::append_unused_vertices
// Access: Protected, Virtual
// Description: Called when a new primitive is begun (other than the
// first primitive), this should add some degenerate
// vertices between primitives, if the primitive type
// requires that. The second parameter is the first
// vertex that begins the new primitive.
////////////////////////////////////////////////////////////////////
void GeomLinestrips::
append_unused_vertices(GeomVertexArrayData *vertices, int vertex) {
GeomVertexWriter to(vertices, 0);
to.set_row_unsafe(vertices->get_num_rows());
to.add_data1i(get_strip_cut_index());
}
////////////////////////////////////////////////////////////////////
// Function: GeomLinestrips::register_with_read_factory
// Access: Public, Static

View File

@ -34,6 +34,7 @@ public:
virtual PrimitiveType get_primitive_type() const;
virtual int get_geom_rendering() const;
virtual int get_min_num_vertices_per_primitive() const;
virtual int get_num_unused_vertices_per_primitive() const;
public:
virtual bool draw(GraphicsStateGuardianBase *gsg,
@ -43,6 +44,9 @@ public:
protected:
virtual CPT(GeomPrimitive) decompose_impl() const;
virtual CPT(GeomVertexArrayData) rotate_impl() const;
virtual bool requires_unused_vertices() const;
virtual void append_unused_vertices(GeomVertexArrayData *vertices,
int vertex);
public:
static void register_with_read_factory();

View File

@ -129,7 +129,7 @@ get_first_vertex() const {
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::get_num_vertices
// Access: Published
// Description: Returns the number of vertices used by all the
// Description: Returns the number of indices used by all the
// primitives in this object.
////////////////////////////////////////////////////////////////////
INLINE int GeomPrimitive::
@ -310,6 +310,20 @@ get_index_stride() const {
return reader.get_index_stride();
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::get_strip_cut_index
// Access: Published
// Description: If relevant, returns the index value that may be
// used in some cases to signify the end of a
// primitive. This is typically the highest value
// that the numeric type can store.
////////////////////////////////////////////////////////////////////
INLINE int GeomPrimitive::
get_strip_cut_index() const {
CDReader cdata(_cycler);
return get_strip_cut_index(cdata->_index_type);
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::get_ends
// Access: Published
@ -415,6 +429,17 @@ add_vertices(int v1, int v2, int v3, int v4) {
add_vertex(v4);
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::get_index_format
// Access: Public
// Description: Returns a registered format appropriate for using to
// store the index table.
////////////////////////////////////////////////////////////////////
INLINE const GeomVertexArrayFormat *GeomPrimitive::
get_index_format() const {
return get_index_format(get_index_type());
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::make_index_data
// Access: Public
@ -425,6 +450,22 @@ make_index_data() const {
return new GeomVertexArrayData(get_index_format(), get_usage_hint());
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::make_index_format
// Access: Private, Static
// Description: Returns a registered format appropriate for using to
// store the index table.
////////////////////////////////////////////////////////////////////
INLINE CPT(GeomVertexArrayFormat) GeomPrimitive::
make_index_format(NumericType index_type) {
PT(GeomVertexArrayFormat) format = new GeomVertexArrayFormat;
// It's important that the index format *not* respect the global
// setting of vertex-column-alignment. It needs to be tightly
// packed, so we specify an explict column_alignment of 1.
format->add_column(InternalName::get_index(), 1, index_type, C_index, 0, 1);
return GeomVertexArrayFormat::register_format(format);
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::CData::Constructor
// Access: Public
@ -679,6 +720,16 @@ get_read_pointer(bool force) const {
return _vertices_reader->get_read_pointer(force);
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitivePipelineReader::get_strip_cut_index
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE int GeomPrimitivePipelineReader::
get_strip_cut_index() const {
return GeomPrimitive::get_strip_cut_index(_cdata->_index_type);
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitivePipelineReader::get_ends
// Access: Public

View File

@ -62,18 +62,18 @@ make_cow_copy() {
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::Constructor
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
GeomPrimitive::
GeomPrimitive(GeomPrimitive::UsageHint usage_hint) {
CDWriter cdata(_cycler, true);
cdata->_usage_hint = usage_hint;
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::Copy Constructor
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
GeomPrimitive::
GeomPrimitive(const GeomPrimitive &copy) :
@ -81,7 +81,7 @@ GeomPrimitive(const GeomPrimitive &copy) :
_cycler(copy._cycler)
{
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::Copy Assignment Operator
// Access: Published
@ -99,7 +99,7 @@ operator = (const GeomPrimitive &copy) {
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::Destructor
// Access: Published, Virtual
// Description:
// Description:
////////////////////////////////////////////////////////////////////
GeomPrimitive::
~GeomPrimitive() {
@ -198,7 +198,7 @@ add_vertex(int vertex) {
int num_primitives = get_num_primitives();
if (num_primitives > 0 &&
requires_unused_vertices() &&
requires_unused_vertices() &&
get_num_vertices() == get_primitive_end(num_primitives - 1)) {
// If we are beginning a new primitive, give the derived class a
// chance to insert some degenerate vertices.
@ -225,7 +225,7 @@ add_vertex(int vertex) {
cdata->_got_minmax = false;
return;
}
// Otherwise, we need to suddenly become an indexed primitive.
do_make_indexed(cdata);
}
@ -289,7 +289,7 @@ add_consecutive_vertices(int start, int num_vertices) {
cdata->_got_minmax = false;
return;
}
// Otherwise, we need to suddenly become an indexed primitive.
do_make_indexed(cdata);
}
@ -469,12 +469,18 @@ offset_vertices(int offset) {
recompute_minmax(cdata);
nassertv(cdata->_got_minmax);
}
consider_elevate_index_type(cdata, cdata->_max_vertex + offset);
int strip_cut_index = get_strip_cut_index(cdata->_index_type);
GeomVertexRewriter index(do_modify_vertices(cdata), 0);
while (!index.is_at_end()) {
index.set_data1i(index.get_data1i() + offset);
int vertex = index.get_data1i();
if (vertex != strip_cut_index) {
index.set_data1i(vertex + offset);
}
}
} else {
@ -484,7 +490,7 @@ offset_vertices(int offset) {
cdata->_modified = Geom::get_next_modified();
cdata->_got_minmax = false;
consider_elevate_index_type(cdata,
consider_elevate_index_type(cdata,
cdata->_first_vertex + cdata->_num_vertices - 1);
}
}
@ -517,14 +523,19 @@ offset_vertices(int offset, int begin_row, int end_row) {
if (is_indexed()) {
CDWriter cdata(_cycler, true);
int strip_cut_index = get_strip_cut_index(cdata->_index_type);
// Calculate the maximum vertex over our range.
int max_vertex = 0;
{
GeomVertexReader index_r(cdata->_vertices.get_read_pointer(), 0);
index_r.set_row_unsafe(begin_row);
for (int j = begin_row; j < end_row; ++j) {
max_vertex = max(max_vertex, index_r.get_data1i());
int vertex = index_r.get_data1i();
if (vertex != strip_cut_index) {
max_vertex = max(max_vertex, vertex);
}
}
}
@ -533,7 +544,10 @@ offset_vertices(int offset, int begin_row, int end_row) {
GeomVertexRewriter index(do_modify_vertices(cdata), 0);
index.set_row_unsafe(begin_row);
for (int j = begin_row; j < end_row; ++j) {
index.set_data1i(index.get_data1i() + offset);
int vertex = index.get_data1i();
if (vertex != strip_cut_index) {
index.set_data1i(vertex + offset);
}
}
} else {
@ -545,7 +559,7 @@ offset_vertices(int offset, int begin_row, int end_row) {
cdata->_modified = Geom::get_next_modified();
cdata->_got_minmax = false;
consider_elevate_index_type(cdata,
consider_elevate_index_type(cdata,
cdata->_first_vertex + cdata->_num_vertices - 1);
}
}
@ -555,17 +569,20 @@ offset_vertices(int offset, int begin_row, int end_row) {
// Access: Published
// Description: Converts the primitive from indexed to nonindexed by
// duplicating vertices as necessary into the indicated
// dest GeomVertexData.
// dest GeomVertexData. Note: does not support
// primitives with strip cut indices.
////////////////////////////////////////////////////////////////////
void GeomPrimitive::
make_nonindexed(GeomVertexData *dest, const GeomVertexData *source) {
Thread *current_thread = Thread::get_current_thread();
int num_vertices = get_num_vertices();
int dest_start = dest->get_num_rows();
int strip_cut_index = get_strip_cut_index();
dest->set_num_rows(dest_start + num_vertices);
for (int i = 0; i < num_vertices; ++i) {
int v = get_vertex(i);
nassertd(v != strip_cut_index) continue;
dest->copy_row_from(dest_start + i, source, v, current_thread);
}
@ -597,14 +614,18 @@ pack_vertices(GeomVertexData *dest, const GeomVertexData *source) {
int num_vertices = get_num_vertices();
int dest_start = dest->get_num_rows();
int strip_cut_index = get_strip_cut_index();
for (int i = 0; i < num_vertices; ++i) {
int v = get_vertex(i);
if (v == strip_cut_index) {
continue;
}
// Try to add the relation { v : size() }. If that succeeds,
// great; if it doesn't, look up whatever we previously added
// for v.
pair<CopiedIndices::iterator, bool> result =
pair<CopiedIndices::iterator, bool> result =
copied_indices.insert(CopiedIndices::value_type(v, (int)copied_indices.size()));
int v2 = (*result.first).second + dest_start;
index.add_data1i(v2);
@ -614,7 +635,7 @@ pack_vertices(GeomVertexData *dest, const GeomVertexData *source) {
dest->copy_row_from(v2, source, v, current_thread);
}
}
set_vertices(new_vertices);
}
}
@ -644,7 +665,7 @@ make_indexed() {
// Function: GeomPrimitive::get_primitive_start
// Access: Published
// Description: Returns the element within the _vertices list at which
// the nth primitive starts.
// the nth primitive starts.
//
// If i is one more than the highest valid primitive
// vertex, the return value will be one more than the
@ -724,7 +745,7 @@ get_primitive_num_vertices(int n) const {
} else {
int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
return cdata->_ends[n] - cdata->_ends[n - 1] - num_unused_vertices_per_primitive;
}
}
} else {
// This is a simple primitive type like a triangle: each primitive
@ -733,6 +754,28 @@ get_primitive_num_vertices(int n) const {
}
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::get_num_used_vertices
// Access: Published
// Description: Returns the number of vertices used by all of the
// primitives. This is the same as summing
// get_primitive_num_vertices(n) for n in
// get_num_primitives(). It is like get_num_vertices
// except that it excludes all of the degenerate
// vertices and strip-cut indices.
////////////////////////////////////////////////////////////////////
int GeomPrimitive::
get_num_used_vertices() const {
int num_primitives = get_num_primitives();
if (num_primitives > 0) {
return get_num_vertices() - ((num_primitives - 1) *
get_num_unused_vertices_per_primitive());
} else {
return 0;
}
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::get_primitive_min_vertex
// Access: Published
@ -960,10 +1003,14 @@ make_points() const {
int num_vertices = get_num_vertices();
if (is_indexed()) {
CPT(GeomVertexArrayData) vertices = get_vertices();
int strip_cut_index = get_strip_cut_index();
GeomVertexReader index(vertices, 0);
for (int vi = 0; vi < num_vertices; ++vi) {
nassertr(!index.is_at_end(), NULL);
bits.set_bit(index.get_data1i());
int vertex = index.get_data1i();
if (vertex != strip_cut_index) {
bits.set_bit(vertex);
}
}
} else {
int first_vertex = get_first_vertex();
@ -997,14 +1044,13 @@ make_points() const {
// Access: Published
// Description: Decomposes a complex primitive type into a simpler
// primitive type, for instance triangle strips to
// triangles, puts these in a new GeomPatches objectand returns a pointer to the new primitive
// triangles, puts these in a new GeomPatches object
// and returns a pointer to the new primitive
// definition. If the decomposition cannot be
// performed, this might return the original object.
//
// This method is useful for application code that wants
// to iterate through the set of triangles on the
// primitive without having to write handlers for each
// possible kind of primitive type.
// to use tesselation shaders on arbitrary geometry.
////////////////////////////////////////////////////////////////////
CPT(GeomPrimitive) GeomPrimitive::
make_patches() const {
@ -1080,7 +1126,7 @@ request_resident() const {
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::output
// Access: Published, Virtual
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void GeomPrimitive::
output(ostream &out) const {
@ -1091,7 +1137,7 @@ output(ostream &out) const {
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::write
// Access: Published, Virtual
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void GeomPrimitive::
write(ostream &out, int indent_level) const {
@ -1188,6 +1234,11 @@ set_vertices(const GeomVertexArrayData *vertices, int num_vertices) {
cdata->_vertices = (GeomVertexArrayData *)vertices;
cdata->_num_vertices = num_vertices;
// Validate the format and make sure to copy its numeric type.
const GeomVertexArrayFormat *format = vertices->get_array_format();
nassertv(format->get_num_columns() == 1);
cdata->_index_type = format->get_column(0)->get_numeric_type();
cdata->_modified = Geom::get_next_modified();
cdata->_got_minmax = false;
}
@ -1449,7 +1500,7 @@ is_prepared(PreparedGraphicsObjects *prepared_objects) const {
// rendered.
////////////////////////////////////////////////////////////////////
IndexBufferContext *GeomPrimitive::
prepare_now(PreparedGraphicsObjects *prepared_objects,
prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg) {
nassertr(is_indexed(), NULL);
@ -1519,18 +1570,41 @@ release_all() {
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::get_index_format
// Access: Public
// Description: Returns a registered format appropriate for using to
// store the index table.
// Access: Public, Static
// Description: Returns a registered GeomVertexArrayFormat of the
// indicated unsigned integer numeric type for storing
// index values.
////////////////////////////////////////////////////////////////////
CPT(GeomVertexArrayFormat) GeomPrimitive::
get_index_format() const {
PT(GeomVertexArrayFormat) format = new GeomVertexArrayFormat;
// It's important that the index format *not* respect the global
// setting of vertex-column-alignment. It needs to be tightly
// packed, so we specify an explict column_alignment of 1.
format->add_column(InternalName::get_index(), 1, get_index_type(), C_index, 0, 1);
return GeomVertexArrayFormat::register_format(format);
const GeomVertexArrayFormat *GeomPrimitive::
get_index_format(NumericType index_type) {
switch (index_type) {
case NT_uint8:
{
static CPT(GeomVertexArrayFormat) cformat = NULL;
if (cformat == NULL) {
cformat = make_index_format(NT_uint8);
}
return cformat;
}
case NT_uint16:
{
static CPT(GeomVertexArrayFormat) cformat = NULL;
if (cformat == NULL) {
cformat = make_index_format(NT_uint16);
}
return cformat;
}
case NT_uint32:
{
static CPT(GeomVertexArrayFormat) cformat = NULL;
if (cformat == NULL) {
cformat = make_index_format(NT_uint32);
}
return cformat;
}
}
return NULL;
}
////////////////////////////////////////////////////////////////////
@ -1559,11 +1633,44 @@ clear_prepared(PreparedGraphicsObjects *prepared_objects) {
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::get_highest_index_value
// Access: Private, Static
// Description: Returns the largest index value that can be stored in
// an index of the indicated type.
// Description: Returns the largest index value that can be stored
// in an index of the indicated type, minus one (to
// leave room for a potential strip cut index)
////////////////////////////////////////////////////////////////////
int GeomPrimitive::
get_highest_index_value(NumericType index_type) {
// Reserve the highest possible index because implementations use
// this as a strip-cut index.
switch (index_type) {
case NT_uint8:
return 0xff - 1;
case NT_uint16:
return 0xffff - 1;
case NT_uint32:
// We don't actually allow use of the sign bit, since all of our
// functions receive an "int" instead of an "unsigned int".
return 0x7fffffff - 1;
default:
return 0;
}
}
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitive::get_strip_cut_index
// Access: Private, Static
// Description: Returns the index of the indicated type that is
// reserved for use as a strip cut index, if enabled
// for the primitive. When the renderer encounters
// this index, it will restart the primitive. This
// is guaranteed not to point to an actual vertex.
////////////////////////////////////////////////////////////////////
int GeomPrimitive::
get_strip_cut_index(NumericType index_type) {
// Reserve the highest possible index because implementations use
// this as a strip-cut index.
switch (index_type) {
case NT_uint8:
return 0xff;
@ -1572,12 +1679,8 @@ get_highest_index_value(NumericType index_type) {
return 0xffff;
case NT_uint32:
// We don't actually allow use of the sign bit, since all of our
// functions receive an "int" instead of an "unsigned int".
return 0x7fffffff;
default:
return 0;
return -1;
}
}
@ -1594,7 +1697,7 @@ get_highest_index_value(NumericType index_type) {
////////////////////////////////////////////////////////////////////
void GeomPrimitive::
calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
bool &found_any,
bool &found_any,
const GeomVertexData *vertex_data,
bool got_mat, const LMatrix4 &mat,
const InternalName *column_name,
@ -1614,7 +1717,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
for (int i = 0; i < cdata->_num_vertices; i++) {
reader.set_row_unsafe(cdata->_first_vertex + i);
LPoint3 vertex = mat.xform_point(reader.get_data3());
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
min(min_point[1], vertex[1]),
@ -1632,7 +1735,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
for (int i = 0; i < cdata->_num_vertices; i++) {
reader.set_row_unsafe(cdata->_first_vertex + i);
const LVecBase3 &vertex = reader.get_data3();
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
min(min_point[1], vertex[1]),
@ -1651,13 +1754,17 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
} else {
// Indexed case.
GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
int strip_cut_index = get_strip_cut_index(cdata->_index_type);
if (got_mat) {
while (!index.is_at_end()) {
int ii = index.get_data1i();
if (ii == strip_cut_index) {
continue;
}
reader.set_row_unsafe(ii);
LPoint3 vertex = mat.xform_point(reader.get_data3());
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
min(min_point[1], vertex[1]),
@ -1674,9 +1781,12 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
} else {
while (!index.is_at_end()) {
int ii = index.get_data1i();
if (ii == strip_cut_index) {
continue;
}
reader.set_row_unsafe(ii);
const LVecBase3 &vertex = reader.get_data3();
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
min(min_point[1], vertex[1]),
@ -1798,63 +1908,77 @@ recompute_minmax(GeomPrimitive::CData *cdata) {
cdata->_max_vertex = 0;
cdata->_mins.clear();
cdata->_maxs.clear();
} else if (get_num_vertices_per_primitive() == 0) {
// This is a complex primitive type like a triangle strip; compute
// the minmax of each primitive (as well as the overall minmax).
GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0);
cdata->_mins = make_index_data();
cdata->_maxs = make_index_data();
GeomVertexWriter mins(cdata->_mins.get_write_pointer(), 0);
mins.reserve_num_rows(cdata->_ends.size());
GeomVertexWriter maxs(cdata->_maxs.get_write_pointer(), 0);
maxs.reserve_num_rows(cdata->_ends.size());
int pi = 0;
unsigned int vertex = index.get_data1i();
cdata->_min_vertex = vertex;
cdata->_max_vertex = vertex;
unsigned int min_prim = vertex;
unsigned int max_prim = vertex;
int num_unused_vertices = get_num_unused_vertices_per_primitive();
for (int vi = 1; vi < num_vertices; ++vi) {
nassertv(!index.is_at_end());
unsigned int vertex = index.get_data1i();
cdata->_min_vertex = min(cdata->_min_vertex, vertex);
cdata->_max_vertex = max(cdata->_max_vertex, vertex);
nassertv(pi < (int)cdata->_ends.size());
unsigned int vertex;
if (vi == cdata->_ends[pi]) {
// Skip unused vertices, since they won't be very relevant and
// may contain a strip-cut index, which would distort the result.
if (num_unused_vertices > 0) {
vi += num_unused_vertices;
index.set_row_unsafe(vi);
}
vertex = index.get_data1i();
mins.add_data1i(min_prim);
maxs.add_data1i(max_prim);
min_prim = vertex;
max_prim = vertex;
++pi;
} else {
vertex = index.get_data1i();
min_prim = min(min_prim, vertex);
max_prim = max(max_prim, vertex);
}
cdata->_min_vertex = min(cdata->_min_vertex, vertex);
cdata->_max_vertex = max(cdata->_max_vertex, vertex);
}
mins.add_data1i(min_prim);
maxs.add_data1i(max_prim);
nassertv(mins.get_array_data()->get_num_rows() == (int)cdata->_ends.size());
} else {
// This is a simple primitive type like a triangle; just compute
// the overall minmax.
GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0);
cdata->_mins.clear();
cdata->_maxs.clear();
unsigned int vertex = index.get_data1i();
cdata->_min_vertex = vertex;
cdata->_max_vertex = vertex;
for (int vi = 1; vi < num_vertices; ++vi) {
nassertv(!index.is_at_end());
unsigned int vertex = index.get_data1i();
@ -1863,7 +1987,7 @@ recompute_minmax(GeomPrimitive::CData *cdata) {
}
}
}
cdata->_got_minmax = true;
}
@ -1900,22 +2024,25 @@ do_make_indexed(CData *cdata) {
////////////////////////////////////////////////////////////////////
void GeomPrimitive::
consider_elevate_index_type(CData *cdata, int vertex) {
// Note that we reserve the highest possible index of a particular
// index type (ie. -1) because this is commonly used as a strip-cut
// (also known as primitive restart) index.
switch (cdata->_index_type) {
case NT_uint8:
if (vertex > 0xff) {
if (vertex >= 0xff) {
do_set_index_type(cdata, NT_uint16);
}
break;
case NT_uint16:
if (vertex > 0xffff) {
if (vertex >= 0xffff) {
do_set_index_type(cdata, NT_uint32);
}
break;
case NT_uint32:
// Not much we can do here.
nassertv(vertex <= 0x7fffffff);
nassertv(vertex < 0x7fffffff);
break;
default:
@ -1930,6 +2057,9 @@ consider_elevate_index_type(CData *cdata, int vertex) {
////////////////////////////////////////////////////////////////////
void GeomPrimitive::
do_set_index_type(CData *cdata, GeomPrimitive::NumericType index_type) {
int old_strip_cut_index = get_strip_cut_index(cdata->_index_type);
int new_strip_cut_index = get_strip_cut_index(index_type);
cdata->_index_type = index_type;
if (gobj_cat.is_debug()) {
@ -1939,7 +2069,7 @@ do_set_index_type(CData *cdata, GeomPrimitive::NumericType index_type) {
if (!cdata->_vertices.is_null()) {
CPT(GeomVertexArrayFormat) new_format = get_index_format();
CPT(GeomVertexArrayData) array_obj = cdata->_vertices.get_read_pointer();
if (array_obj->get_array_format() != new_format) {
PT(GeomVertexArrayData) new_vertices = make_index_data();
@ -1947,9 +2077,13 @@ do_set_index_type(CData *cdata, GeomPrimitive::NumericType index_type) {
GeomVertexReader from(array_obj, 0);
GeomVertexWriter to(new_vertices, 0);
while (!from.is_at_end()) {
to.set_data1i(from.get_data1i());
int index = from.get_data1i();
if (index == old_strip_cut_index) {
index = new_strip_cut_index;
}
to.set_data1i(index);
}
cdata->_vertices = new_vertices;
cdata->_got_minmax = false;
@ -2057,7 +2191,7 @@ int GeomPrimitive::CData::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = CycleData::complete_pointers(p_list, manager);
_vertices = DCAST(GeomVertexArrayData, p_list[pi++]);
_vertices = DCAST(GeomVertexArrayData, p_list[pi++]);
if (manager->get_file_minor_ver() < 6 && !_vertices.is_null()) {
// Older bam files might have a meaningless number in
@ -2107,7 +2241,7 @@ check_minmax() const {
#ifdef DO_PIPELINING
unref_delete((CycleData *)_cdata);
#endif
GeomPrimitive::CDWriter fresh_cdata(((GeomPrimitive *)_object.p())->_cycler,
GeomPrimitive::CDWriter fresh_cdata(((GeomPrimitive *)_object.p())->_cycler,
false, _current_thread);
((GeomPrimitivePipelineReader *)this)->_cdata = fresh_cdata;
#ifdef DO_PIPELINING
@ -2133,7 +2267,7 @@ check_minmax() const {
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitivePipelineReader::get_first_vertex
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
int GeomPrimitivePipelineReader::
get_first_vertex() const {
@ -2171,7 +2305,7 @@ get_vertex(int i) const {
////////////////////////////////////////////////////////////////////
// Function: GeomPrimitivePipelineReader::get_num_primitives
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
int GeomPrimitivePipelineReader::
get_num_primitives() const {

View File

@ -118,6 +118,7 @@ PUBLISHED:
int get_primitive_start(int n) const;
int get_primitive_end(int n) const;
int get_primitive_num_vertices(int n) const;
int get_num_used_vertices() const;
INLINE int get_num_faces() const;
INLINE int get_primitive_num_faces(int n) const;
@ -163,6 +164,7 @@ PUBLISHED:
void set_nonindexed_vertices(int first_vertex, int num_vertices);
INLINE int get_index_stride() const;
INLINE int get_strip_cut_index() const;
INLINE CPTA_int get_ends() const;
PTA_int modify_ends();
@ -183,17 +185,21 @@ public:
void prepare(PreparedGraphicsObjects *prepared_objects);
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const;
IndexBufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
IndexBufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg);
bool release(PreparedGraphicsObjects *prepared_objects);
int release_all();
CPT(GeomVertexArrayFormat) get_index_format() const;
static const GeomVertexArrayFormat *get_index_format(NumericType index_type);
INLINE const GeomVertexArrayFormat *get_index_format() const;
INLINE PT(GeomVertexArrayData) make_index_data() const;
private:
static CPT(GeomVertexArrayFormat) make_index_format(NumericType index_type);
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
static int get_highest_index_value(NumericType index_type);
static int get_strip_cut_index(NumericType index_type);
public:
virtual bool draw(GraphicsStateGuardianBase *gsg,
@ -201,7 +207,7 @@ public:
bool force) const=0;
void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
bool &found_any,
bool &found_any,
const GeomVertexData *vertex_data,
bool got_mat, const LMatrix4 &mat,
const InternalName *column_name,
@ -213,7 +219,7 @@ protected:
virtual CPT(GeomPrimitive) doubleside_impl() const;
virtual CPT(GeomPrimitive) reverse_impl() const;
virtual bool requires_unused_vertices() const;
virtual void append_unused_vertices(GeomVertexArrayData *vertices,
virtual void append_unused_vertices(GeomVertexArrayData *vertices,
int vertex);
private:
@ -358,6 +364,7 @@ public:
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;
INLINE CPT(GeomVertexArrayData) get_mins() const;
INLINE CPT(GeomVertexArrayData) get_maxs() const;

View File

@ -95,6 +95,17 @@ get_geom_rendering() const {
}
}
////////////////////////////////////////////////////////////////////
// Function: GeomTristrips::get_min_num_vertices_per_primitive
// Access: Public, Virtual
// Description: Returns the minimum number of vertices that must be
// added before close_primitive() may legally be called.
////////////////////////////////////////////////////////////////////
int GeomTristrips::
get_min_num_vertices_per_primitive() const {
return 3;
}
////////////////////////////////////////////////////////////////////
// Function: GeomTristrips::get_num_unused_vertices_per_primitive
// Access: Public, Virtual
@ -142,6 +153,7 @@ decompose_impl() const {
CPTA_int ends = get_ends();
int num_vertices = get_num_vertices();
int num_unused = get_num_unused_vertices_per_primitive();
// We need a slightly different algorithm for SM_flat_first_vertex
// than for SM_flat_last_vertex, to preserve the key vertex in the
@ -150,11 +162,11 @@ decompose_impl() const {
if (get_shade_model() == SM_flat_first_vertex) {
// Preserve the first vertex of each component triangle as the
// first vertex of each generated triangle.
int vi = -2;
int vi = -num_unused;
int li = 0;
while (li < (int)ends.size()) {
// Skip unused vertices between tristrips.
vi += 2;
vi += num_unused;
int end = ends[li];
nassertr(vi + 2 <= end, NULL);
int v0 = get_vertex(vi);
@ -192,11 +204,11 @@ decompose_impl() const {
} else {
// Preserve the last vertex of each component triangle as the
// last vertex of each generated triangle.
int vi = -2;
int vi = -num_unused;
int li = 0;
while (li < (int)ends.size()) {
// Skip unused vertices between tristrips.
vi += 2;
vi += num_unused;
int end = ends[li];
nassertr(vi + 2 <= end, NULL);
int v0 = get_vertex(vi);

View File

@ -33,6 +33,7 @@ public:
virtual PT(GeomPrimitive) make_copy() const;
virtual PrimitiveType get_primitive_type() const;
virtual int get_geom_rendering() const;
virtual int get_min_num_vertices_per_primitive() const;
virtual int get_num_unused_vertices_per_primitive() const;
public:

View File

@ -43,6 +43,10 @@ PT(InternalName) InternalName::_view;
TypeHandle InternalName::_type_handle;
TypeHandle InternalName::_texcoord_type_handle;
#ifdef HAVE_PYTHON
InternalName::PyInternTable InternalName::_py_intern_table;
#endif
////////////////////////////////////////////////////////////////////
// Function: InternalName::Constructor
// Access: Private

View File

@ -43,11 +43,13 @@ class EXPCL_PANDA_GOBJ InternalName : public TypedWritableReferenceCount {
private:
InternalName(InternalName *parent, const string &basename);
public:
INLINE static PT(InternalName) make(const string &name);
PUBLISHED:
virtual ~InternalName();
virtual bool unref() const;
INLINE static PT(InternalName) make(const string &name);
static PT(InternalName) make(const string &name, int index);
PT(InternalName) append(const string &basename);
@ -88,6 +90,22 @@ PUBLISHED:
INLINE static PT(InternalName) get_model();
INLINE static PT(InternalName) get_view();
#ifdef HAVE_PYTHON
#if PY_MAJOR_VERSION >= 3
EXTENSION(static PT(InternalName) make(PyUnicodeObject *str));
#else
EXTENSION(static PT(InternalName) make(PyStringObject *str));
#endif
#endif
public:
#ifdef HAVE_PYTHON
// It's OK for us to define it here since these are just pointers of
// which the reference is maintained indefinitely.
typedef phash_map<PyObject *, InternalName *, pointer_hash> PyInternTable;
static PyInternTable _py_intern_table;
#endif
private:
PT(InternalName) _parent;
string _basename;
@ -116,7 +134,7 @@ private:
static PT(InternalName) _camera;
static PT(InternalName) _model;
static PT(InternalName) _view;
public:
// Datagram stuff
static void register_with_read_factory();
@ -157,5 +175,3 @@ INLINE ostream &operator << (ostream &out, const InternalName &tcn);
#endif

View File

@ -0,0 +1,87 @@
// Filename: internalName_ext.I
// Created by: rdb (28Sep14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "internalName_ext.h"
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: InternalName::make
// Access: Published, Static
// Description: This extension method serves to allow coercion of
// Python interned strings to InternalName objects
// more efficiently by storing a mapping between
// Python and Panda interned strings.
////////////////////////////////////////////////////////////////////
#if PY_MAJOR_VERSION >= 3
PT(InternalName) Extension<InternalName>::
make(PyUnicodeObject *str) {
if (!PyUnicode_CHECK_INTERNED(str)) {
// Not an interned string; don't bother.
Py_ssize_t len = 0;
char *c_str = PyUnicode_AsUTF8AndSize((PyObject *)str, &len);
if (c_str == NULL) {
return NULL;
}
string name(c_str, len);
return InternalName::make(c_str, len);
}
InternalName::PyInternTable::const_iterator it;
it = InternalName::_py_intern_table.find((PyObject*)str);
if (it != InternalName::_py_intern_table.end()) {
return (*it).second;
} else {
Py_ssize_t len = 0;
char *c_str = PyUnicode_AsUTF8AndSize((PyObject *)str, &len);
string name(c_str, len);
#else
PT(InternalName) Extension<InternalName>::
make(PyStringObject *str) {
if (!PyString_CHECK_INTERNED(str)) {
// Not an interned string; don't bother.
string name(PyString_AS_STRING(str), PyString_GET_SIZE(str));
return InternalName::make(name);
}
InternalName::PyInternTable::const_iterator it;
it = InternalName::_py_intern_table.find((PyObject*)str);
if (it != InternalName::_py_intern_table.end()) {
return (*it).second;
} else {
string name(PyString_AS_STRING(str), PyString_GET_SIZE(str));
#endif // PY_MAJOR_VERSION
PT(InternalName) iname = InternalName::make(name);
// We basically leak references to both the PyObject and the
// InternalName. We may want to change that in the future if it
// becomes a problem.
Py_INCREF(str);
iname->ref();
InternalName::_py_intern_table.insert(make_pair((PyObject *)str, iname.p()));
return iname.p();
}
}
#endif // HAVE_PYTHON

View File

@ -0,0 +1,44 @@
// Filename: internalName_ext.h
// Created by: rdb (28Sep14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef INTERNALNAME_EXT_H
#define INTERNALNAME_EXT_H
#include "dtoolbase.h"
#ifdef HAVE_PYTHON
#include "extension.h"
#include "internalName.h"
#include "py_panda.h"
////////////////////////////////////////////////////////////////////
// Class : Extension<InternalName>
// Description : This class defines the extension methods for
// InternalName, which are called instead of
// any C++ methods with the same prototype.
////////////////////////////////////////////////////////////////////
template<>
class Extension<InternalName> : public ExtensionBase<InternalName> {
public:
#if PY_MAJOR_VERSION >= 3
static PT(InternalName) make(PyUnicodeObject *str);
#else
static PT(InternalName) make(PyStringObject *str);
#endif
};
#endif // HAVE_PYTHON
#endif // INTERNALNAME_EXT_H

View File

@ -30,3 +30,6 @@
#include "indexBufferContext.cxx"
#include "internalName.cxx"
#include "lens.cxx"
#include "material.cxx"
#include "materialPool.cxx"
#include "matrixLens.cxx"

View File

@ -1,6 +1,3 @@
#include "material.cxx"
#include "materialPool.cxx"
#include "matrixLens.cxx"
#include "occlusionQueryContext.cxx"
#include "orthographicLens.cxx"
#include "perspectiveLens.cxx"
@ -21,6 +18,7 @@
#include "textureReloadRequest.cxx"
#include "textureStage.cxx"
#include "textureStagePool.cxx"
#include "timerQueryContext.cxx"
#include "transformBlend.cxx"
#include "transformBlendTable.cxx"
#include "transformTable.cxx"

View File

@ -12,16 +12,16 @@
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: Shader::get_filename
// Access: Public
// Access: Published
// Description: Return the Shader's filename for the given shader
// type.
////////////////////////////////////////////////////////////////////
INLINE const Filename Shader::
INLINE Filename Shader::
get_filename(const ShaderType &type) const {
if (_filename->_separate) {
nassertr(type != ST_none || !_filename->_shared.empty(), "");
if (_filename->_separate && type == ST_none) {
switch (type) {
case ST_vertex:
return _filename->_vertex;
@ -51,7 +51,7 @@ get_filename(const ShaderType &type) const {
////////////////////////////////////////////////////////////////////
// Function: Shader::get_text
// Access: Public
// Access: Published
// Description: Return the Shader's text for the given shader type.
////////////////////////////////////////////////////////////////////
INLINE const string &Shader::
@ -146,7 +146,7 @@ have_shader_utilization() {
// Description: Returns the shader language in which this shader
// was written.
////////////////////////////////////////////////////////////////////
INLINE const Shader::ShaderLanguage Shader::
INLINE Shader::ShaderLanguage Shader::
get_language() const {
return _language;
}

View File

@ -96,10 +96,10 @@ PUBLISHED:
const string &tess_evaluation = "");
static PT(Shader) make_compute(const ShaderLanguage &lang, const string &body);
INLINE const Filename get_filename(const ShaderType &type = ST_none) const;
INLINE Filename get_filename(const ShaderType &type = ST_none) const;
INLINE const string &get_text(const ShaderType &type = ST_none) const;
INLINE const bool get_error_flag() const;
INLINE const ShaderLanguage get_language() const;
INLINE ShaderLanguage get_language() const;
INLINE static ShaderUtilization get_shader_utilization();
INLINE static void set_shader_utilization(ShaderUtilization utl);

View File

@ -0,0 +1,26 @@
// Filename: occlusionQueryContext.I
// Created by: rdb (22Aug14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: TimerQueryContext::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE TimerQueryContext::
TimerQueryContext(int pstats_index) :
_pstats_index(pstats_index),
_frame_index(ClockObject::get_global_clock()->get_frame_count())
{
}

View File

@ -0,0 +1,35 @@
// Filename: timerQueryContext.cxx
// Created by: rdb (22Aug14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "timerQueryContext.h"
TypeHandle TimerQueryContext::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: TimerQueryContext::get_timestamp
// Access: Public, Virtual
// Description: Returns the timestamp that is the result of this
// timer query. There's no guarantee about which
// clock this uses, the only guarantee is that
// subtracting a start time from an end time should
// yield a time in seconds.
// If is_answer_ready() did not return true, this
// function may block before it returns.
//
// It is only valid to call this from the draw thread.
////////////////////////////////////////////////////////////////////
double TimerQueryContext::
get_timestamp() const {
return 0.0;
}

View File

@ -0,0 +1,60 @@
// Filename: timerQueryContext.h
// Created by: rdb (22Aug14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef TIMERQUERYCONTEXT_H
#define TIMERQUERYCONTEXT_H
#include "pandabase.h"
#include "queryContext.h"
#include "clockObject.h"
#include "pStatCollector.h"
////////////////////////////////////////////////////////////////////
// Class : TimerQueryContext
// Description :
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_GOBJ TimerQueryContext : public QueryContext {
public:
INLINE TimerQueryContext(int pstats_index);
ALLOC_DELETED_CHAIN(TimerQueryContext);
virtual double get_timestamp() const=0;
int _frame_index;
int _pstats_index;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
QueryContext::init_type();
register_type(_type_handle, "TimerQueryContext",
QueryContext::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
friend class PreparedGraphicsObjects;
};
#include "timerQueryContext.I"
#endif

View File

@ -32,7 +32,6 @@ class GraphicsOutputBase;
class VertexBufferContext;
class IndexBufferContext;
class OcclusionQueryContext;
class GeomContext;
class GeomNode;
class Geom;
@ -123,9 +122,10 @@ PUBLISHED:
virtual bool get_supports_multisample() const=0;
virtual int get_supported_geom_rendering() const=0;
virtual bool get_supports_occlusion_query() const=0;
virtual bool get_supports_shadow_filter() const=0;
virtual bool get_supports_texture_srgb() const=0;
public:
// These are some general interface functions; they're defined here
// mainly to make it easy to call these from code in some directory
@ -153,16 +153,13 @@ public:
virtual ShaderContext *prepare_shader(Shader *shader)=0;
virtual void release_shader(ShaderContext *sc)=0;
virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data)=0;
virtual void release_vertex_buffer(VertexBufferContext *vbc)=0;
virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data)=0;
virtual void release_index_buffer(IndexBufferContext *ibc)=0;
virtual void begin_occlusion_query()=0;
virtual PT(OcclusionQueryContext) end_occlusion_query()=0;
virtual void dispatch_compute(int size_x, int size_y, int size_z)=0;
virtual PT(GeomMunger) get_geom_munger(const RenderState *state,

View File

@ -26,6 +26,8 @@
#if defined(WIN32_VC) || defined(WIN64_VC)
#include <winsock2.h> // For gethostname()
#include <Iphlpapi.h> // For GetAdaptersAddresses()
#elif defined(ANDROID)
#include <net/if.h>
#else
#include <net/if.h>
#include <ifaddrs.h>
@ -542,14 +544,14 @@ scan_interfaces() {
TextEncoder encoder;
encoder.set_wtext(wstring(p->FriendlyName));
string friendly_name = encoder.get_text();
Interface iface;
iface.set_name(friendly_name);
if (p->PhysicalAddressLength > 0) {
iface.set_mac_address(format_mac_address((const unsigned char *)p->PhysicalAddress, p->PhysicalAddressLength));
}
if (p->OperStatus == IfOperStatusUp) {
// Prefixes are a linked list, in the order Network IP,
// Adapter IP, Broadcast IP (plus more).
@ -586,6 +588,9 @@ scan_interfaces() {
PANDA_FREE_ARRAY(addresses);
}
#elif defined(ANDROID)
// TODO: implementation using netlink_socket?
#else // WIN32_VC
struct ifaddrs *ifa;
if (getifaddrs(&ifa) != 0) {

View File

@ -78,11 +78,11 @@ munge_geom(GraphicsStateGuardianBase *gsg,
nassertr(geom_reader.check_valid(&data_reader), false);
}
#endif // _DEBUG
geom_rendering = geom_reader.get_geom_rendering();
geom_rendering = _state->get_geom_rendering(geom_rendering);
geom_rendering = _modelview_transform->get_geom_rendering(geom_rendering);
if (geom_rendering & Geom::GR_point_bits) {
if (geom_reader.get_primitive_type() != Geom::PT_points) {
if (singular_points) {
@ -92,7 +92,7 @@ munge_geom(GraphicsStateGuardianBase *gsg,
}
}
}
GraphicsStateGuardianBase *gsg = traverser->get_gsg();
int gsg_bits = gsg->get_supported_geom_rendering();
if (!hardware_point_sprites) {
@ -115,7 +115,7 @@ munge_geom(GraphicsStateGuardianBase *gsg,
// _munged_data, and might also replace _state.
if (pgraph_cat.is_spam()) {
pgraph_cat.spam()
<< "munge_points_to_quads() for geometry with bits: "
<< "munge_points_to_quads() for geometry with bits: "
<< hex << geom_rendering << ", unsupported: "
<< (unsupported_bits & Geom::GR_point_bits) << dec << "\n";
}
@ -130,7 +130,7 @@ munge_geom(GraphicsStateGuardianBase *gsg,
// If we have to compute the light vector, we have to animate
// the vertices in the CPU--and we have to do it before we call
// munge_geom(), which might lose the tangent and binormal.
CPT(GeomVertexData) animated_vertices =
CPT(GeomVertexData) animated_vertices =
_munged_data->animate_vertices(force, current_thread);
if (animated_vertices != _munged_data) {
cpu_animated = true;
@ -156,7 +156,7 @@ munge_geom(GraphicsStateGuardianBase *gsg,
// has been munged--that is, we couldn't arrange to handle the
// animation in hardware--then we have to calculate that
// animation now.
CPT(GeomVertexData) animated_vertices =
CPT(GeomVertexData) animated_vertices =
_munged_data->animate_vertices(force, current_thread);
if (animated_vertices != _munged_data) {
cpu_animated = true;
@ -240,7 +240,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
// Better get the animated vertices, in case we're showing sprites
// on an animated model for some reason.
CPT(GeomVertexData) source_data =
CPT(GeomVertexData) source_data =
_munged_data->animate_vertices(force, current_thread);
if (!force && !source_data->request_resident()) {
@ -308,22 +308,22 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
FormatMap::iterator fmi = _format_map.find(sformat);
if (fmi != _format_map.end()) {
new_format = (*fmi).second;
} else {
// We have to construct the format now.
PT(GeomVertexArrayFormat) new_array_format;
if (sformat._retransform_sprites) {
// With retransform_sprites in effect, we will be sending ordinary
// 3-D points to the graphics API.
new_array_format =
new GeomVertexArrayFormat(InternalName::get_vertex(), 3,
new_array_format =
new GeomVertexArrayFormat(InternalName::get_vertex(), 3,
Geom::NT_stdfloat,
Geom::C_point);
} else {
// Without retransform_sprites, we will be sending 4-component
// clip-space points.
new_array_format =
new GeomVertexArrayFormat(InternalName::get_vertex(), 4,
new_array_format =
new GeomVertexArrayFormat(InternalName::get_vertex(), 4,
Geom::NT_stdfloat,
Geom::C_clip_point);
}
@ -344,14 +344,14 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
(InternalName::get_texcoord(), 2,
Geom::NT_stdfloat,
Geom::C_texcoord);
} else if (has_texcoord) {
const GeomVertexColumn *c = texcoord.get_column();
new_array_format->add_column
(InternalName::get_texcoord(), c->get_num_components(),
c->get_numeric_type(), c->get_contents());
}
new_format = GeomVertexFormat::register_format(new_array_format);
_format_map[sformat] = new_format;
}
@ -408,7 +408,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
LPoint3 eye = modelview.xform_point(vertex.get_data3());
points[vi]._eye = eye;
points[vi]._dist = gsg->compute_distance_to(points[vi]._eye);
// The point in clip coordinates.
LPoint4 p4 = LPoint4(eye[0], eye[1], eye[2], 1.0f) * projection;
@ -433,7 +433,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
scale_y /= gsg->compute_distance_to(eye);
}
}
// Also factor in the homogeneous scale for being in clip
// coordinates still.
scale_y *= p4[3];
@ -447,7 +447,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
LPoint2 c0(scale_x, scale_y);
LPoint2 c1(-scale_x, scale_y);
if (has_rotate) {
if (has_rotate) {
// If we have a rotate factor, apply it to those two corners.
PN_stdfloat r = rotate.get_data1f();
LMatrix3 mat = LMatrix3::rotate_mat(r);
@ -461,7 +461,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
PN_stdfloat ry = 1.0f / viewport_height;
c0.set(c0[0] * rx, c0[1] * ry);
c1.set(c1[0] * rx, c1[1] * ry);
if (retransform_sprites) {
// With retransform_sprites in effect, we must reconvert the
// resulting quad back into the original 3-D space.
@ -469,7 +469,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] + c1[0], p4[1] + c1[1], p4[2], p4[3])));
new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] - c1[0], p4[1] - c1[1], p4[2], p4[3])));
new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3])));
if (has_normal) {
const LNormal &c = normal.get_data3();
new_normal.set_data3(c);
@ -477,7 +477,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
new_normal.set_data3(c);
new_normal.set_data3(c);
}
} else {
// Without retransform_sprites, we can simply load the
// clip-space coordinates.
@ -485,7 +485,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
new_vertex.set_data4(p4[0] + c1[0], p4[1] + c1[1], p4[2], p4[3]);
new_vertex.set_data4(p4[0] - c1[0], p4[1] - c1[1], p4[2], p4[3]);
new_vertex.set_data4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3]);
if (has_normal) {
LNormal c = render_transform.xform_vec(normal.get_data3());
new_normal.set_data3(c);
@ -521,18 +521,20 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
nassertr(new_data->get_num_rows() == new_verts, false);
}
PT(Geom) new_geom = new Geom(new_data);
// Create an appropriate GeomVertexArrayFormat for the primitive
// index.
static CPT(GeomVertexArrayFormat) new_prim_format;
if (new_prim_format == (GeomVertexArrayFormat *)NULL) {
new_prim_format =
GeomVertexArrayFormat::register_format
(new GeomVertexArrayFormat(InternalName::get_index(), 1,
GeomEnums::NT_uint16, GeomEnums::C_index));
// Determine the format we should use to store the indices.
const GeomVertexArrayFormat *new_prim_format = NULL;
if (new_verts < 0xff) {
new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint8);
} else if (new_verts < 0xffff) {
new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint16);
} else {
new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint32);
}
PT(Geom) new_geom = new Geom(new_data);
// Replace each primitive in the Geom (it's presumably a GeomPoints
// primitive, although it might be some other kind of primitive if
// we got here because RenderModeAttrib::M_point is enabled) with a
@ -575,11 +577,11 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
vertices[i] = v;
}
}
// Now sort the points in order from back-to-front so they will
// render properly with transparency, at least with each other.
sort(vertices, vertices_end, SortPoints(points));
// Go through the points, now in sorted order, and generate a pair
// of triangles for each one. We generate indexed triangles
// instead of two-triangle strips, since this seems to be
@ -589,7 +591,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) {
PT(GeomPrimitive) new_primitive = new GeomTriangles(Geom::UH_stream);
int new_prim_verts = 6 * num_vertices; // two triangles per point.
PT(GeomVertexArrayData) new_index
PT(GeomVertexArrayData) new_index
= new GeomVertexArrayData(new_prim_format, GeomEnums::UH_stream);
new_index->unclean_set_num_rows(new_prim_verts);
@ -669,14 +671,14 @@ munge_texcoord_light_vector(const CullTraverser *traverser, bool force) {
string source_name = tex_gen->get_source_name(stage);
Light *light_obj = light.node()->as_light();
nassertr(light_obj != (Light *)NULL, false);
// Determine the names of the tangent and binormal columns
// associated with the stage's texcoord name.
PT(InternalName) tangent_name = InternalName::get_tangent_name(source_name);
PT(InternalName) binormal_name = InternalName::get_binormal_name(source_name);
PT(InternalName) texcoord_name = stage->get_texcoord_name();
if (_munged_data->has_column(tangent_name) &&
_munged_data->has_column(binormal_name)) {

View File

@ -96,7 +96,7 @@ make_single_threshold(PN_stdfloat thresh0, PN_stdfloat val0) {
CPT(RenderAttrib) LightRampAttrib::
make_double_threshold(PN_stdfloat thresh0, PN_stdfloat val0, PN_stdfloat thresh1, PN_stdfloat val1) {
LightRampAttrib *attrib = new LightRampAttrib();
attrib->_mode = LRT_single_threshold;
attrib->_mode = LRT_double_threshold;
attrib->_threshold[0] = thresh0;
attrib->_level[0] = val0;
attrib->_threshold[1] = thresh1;

View File

@ -2322,7 +2322,7 @@ do_calc_components() {
_hpr.set(0.0f, 0.0f, 0.0f);
_quat = LQuaternion::ident_quat();
_pos.set(0.0f, 0.0f, 0.0f);
_flags |= F_has_components | F_components_known | F_hpr_known | F_quat_known | F_uniform_scale;
_flags |= F_has_components | F_components_known | F_hpr_known | F_quat_known | F_uniform_scale | F_identity_scale;
} else {
// If we don't have components and we're not identity, the only

View File

@ -1180,12 +1180,11 @@ synthesize_shader(const RenderState *rs) {
PN_stdfloat t1 = light_ramp->get_threshold(1);
PN_stdfloat l0 = light_ramp->get_level(0);
PN_stdfloat l1 = light_ramp->get_level(1);
PN_stdfloat l2 = light_ramp->get_level(2);
text << "\t // Double-threshold light ramp\n";
text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
text << "\t float lr_out = " << l0 << "\n";
text << "\t if (lr_in > " << t0 << ") lr_out=" << l1 << ";\n";
text << "\t if (lr_in > " << t1 << ") lr_out=" << l2 << ";\n";
text << "\t float lr_out = 0.0;\n";
text << "\t if (lr_in > " << t0 << ") lr_out=" << l0 << ";\n";
text << "\t if (lr_in > " << t1 << ") lr_out=" << l1 << ";\n";
text << "\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n";
break;
}

View File

@ -68,6 +68,17 @@ ConfigVariableDouble pstats_target_frame_rate
"This frame rate is marked with a different-colored line; "
"otherwise, this setting has no effect."));
ConfigVariableBool pstats_gpu_timing
("pstats-gpu-timing", false,
PRC_DESC("Set this true to query the graphics library for the actual time "
"that graphics operations take to execute on the video card. "
"Enabling this will harm performance, but this information can "
"be more useful than the regular Draw information in tracking "
"down bottlenecks, because the CPU-based Draw collectors only "
"measure how long it takes for the API call to complete, which "
"is not usually an accurate reflectino of how long the actual "
"operation takes on the video card."));
// The rest are different in that they directly control the server,
// not the client.
ConfigVariableBool pstats_scroll_mode

View File

@ -38,6 +38,7 @@ extern EXPCL_PANDA_PSTATCLIENT ConfigVariableDouble pstats_tcp_ratio;
extern EXPCL_PANDA_PSTATCLIENT ConfigVariableString pstats_host;
extern EXPCL_PANDA_PSTATCLIENT ConfigVariableInt pstats_port;
extern EXPCL_PANDA_PSTATCLIENT ConfigVariableDouble pstats_target_frame_rate;
extern EXPCL_PANDA_PSTATCLIENT ConfigVariableBool pstats_gpu_timing;
extern EXPCL_PANDA_PSTATCLIENT ConfigVariableBool pstats_scroll_mode;
extern EXPCL_PANDA_PSTATCLIENT ConfigVariableDouble pstats_history;

View File

@ -152,7 +152,7 @@ get_collector_fullname(int index) const {
if (parent_index == 0) {
return collector->get_name();
} else {
return get_collector_fullname(parent_index) + ":" +
return get_collector_fullname(parent_index) + ":" +
collector->get_name();
}
}
@ -180,7 +180,6 @@ get_main_thread() const {
return PStatThread((PStatClient *)this, 0);
}
////////////////////////////////////////////////////////////////////
// Function: PStatClient::get_current_thread
// Access: Published
@ -191,7 +190,7 @@ get_main_thread() const {
PStatThread PStatClient::
get_current_thread() const {
if (!client_is_connected()) {
// No need to make the relatively expensive call to
// No need to make the relatively expensive call to
// Thread::get_current_thread() if we're not even connected.
return get_main_thread();
}
@ -222,10 +221,10 @@ main_tick() {
_mmap_size_pcollector.set_level(MemoryUsage::get_panda_mmap_size());
TypeRegistry *type_reg = TypeRegistry::ptr();
int num_typehandles = type_reg->get_num_typehandles();
while ((int)type_handle_cols.size() < num_typehandles) {
type_handle_cols.push_back(TypeHandleCollector());
}
@ -261,7 +260,7 @@ main_tick() {
case TypeHandle::MC_limit:
// Not used.
break;
}
}
}
}
size_t min_usage = (single_total_usage + array_total_usage + dc_active_total_usage + dc_inactive_total_usage) / 1024;
@ -288,7 +287,7 @@ main_tick() {
case TypeHandle::MC_singleton:
category = "Heap:Single";
break;
case TypeHandle::MC_array:
category = "Heap:Array";
break;
@ -315,11 +314,11 @@ main_tick() {
case TypeHandle::MC_singleton:
single_other_usage -= usage;
break;
case TypeHandle::MC_array:
array_other_usage -= usage;
break;
case TypeHandle::MC_deleted_chain_active:
dc_active_other_usage -= usage;
break;
@ -348,7 +347,7 @@ main_tick() {
#endif // DO_MEMORY_USAGE
get_global_pstats()->client_main_tick();
}
}
////////////////////////////////////////////////////////////////////
// Function: PStatClient::thread_tick
@ -359,7 +358,7 @@ main_tick() {
void PStatClient::
thread_tick(const string &sync_name) {
get_global_pstats()->client_thread_tick(sync_name);
}
}
////////////////////////////////////////////////////////////////////
// Function: PStatClient::client_main_tick
@ -383,8 +382,8 @@ client_main_tick() {
_threads_by_sync_name.find("Main");
if (ni != _threads_by_sync_name.end()) {
const vector_int &indices = (*ni).second;
for (vector_int::const_iterator vi = indices.begin();
vi != indices.end();
for (vector_int::const_iterator vi = indices.begin();
vi != indices.end();
++vi) {
_impl->new_frame(*vi);
}
@ -407,8 +406,8 @@ client_thread_tick(const string &sync_name) {
_threads_by_sync_name.find(sync_name);
if (ni != _threads_by_sync_name.end()) {
const vector_int &indices = (*ni).second;
for (vector_int::const_iterator vi = indices.begin();
vi != indices.end();
for (vector_int::const_iterator vi = indices.begin();
vi != indices.end();
++vi) {
_impl->new_frame(*vi);
}
@ -463,7 +462,7 @@ PStatClient *PStatClient::
get_global_pstats() {
if (_global_pstats == (PStatClient *)NULL) {
_global_pstats = new PStatClient;
ClockObject::_start_clock_wait = start_clock_wait;
ClockObject::_start_clock_busy_wait = start_clock_busy_wait;
ClockObject::_stop_clock_wait = stop_clock_wait;
@ -616,8 +615,8 @@ do_make_thread(Thread *thread) {
// We have seen a thread with this name before. Can we re-use any
// of them?
const vector_int &indices = (*ni).second;
for (vector_int::const_iterator vi = indices.begin();
vi != indices.end();
for (vector_int::const_iterator vi = indices.begin();
vi != indices.end();
++vi) {
int index = (*vi);
nassertr(index >= 0 && index < _num_threads, PStatThread());
@ -637,20 +636,26 @@ do_make_thread(Thread *thread) {
int new_index = _num_threads;
thread->set_pstats_index(new_index);
thread->set_pstats_callback(this);
_threads_by_name[thread->get_name()].push_back(new_index);
_threads_by_sync_name[thread->get_sync_name()].push_back(new_index);
InternalThread *pthread = new InternalThread(thread);
add_thread(pthread);
// We need an additional PerThreadData for this thread in all of the
// collectors.
CollectorPointer *collectors = (CollectorPointer *)_collectors;
for (int ci = 0; ci < _num_collectors; ++ci) {
Collector *collector = collectors[ci];
collector->_per_thread.push_back(PerThreadData());
nassertr((int)collector->_per_thread.size() == _num_threads, PStatThread());
}
return PStatThread(this, new_index);
}
////////////////////////////////////////////////////////////////////
// Function: PStatClient::make_gpu_thread
// Access: Private
// Description: Returns a PStatThread representing the GPU.
// This is normally called by the GSG only.
////////////////////////////////////////////////////////////////////
PStatThread PStatClient::
make_gpu_thread(const string &name) {
ReMutexHolder holder(_lock);
int new_index = _num_threads;
InternalThread *pthread = new InternalThread(name, "GPU");
add_thread(pthread);
return PStatThread(this, new_index);
}
@ -960,7 +965,7 @@ get_level(int collector_index, int thread_index) const {
// Description: This function is added as a hook into ClockObject, so
// that we may time the delay for
// ClockObject::wait_until(), used for certain special
// clock modes.
// clock modes.
//
// This callback is a hack around the fact that we can't
// let the ClockObject directly create a PStatCollector,
@ -977,7 +982,7 @@ start_clock_wait() {
// Description: This function is added as a hook into ClockObject, so
// that we may time the delay for
// ClockObject::wait_until(), used for certain special
// clock modes.
// clock modes.
//
// This callback is a hack around the fact that we can't
// let the ClockObject directly create a PStatCollector,
@ -995,7 +1000,7 @@ start_clock_busy_wait() {
// Description: This function is added as a hook into ClockObject, so
// that we may time the delay for
// ClockObject::wait_until(), used for certain special
// clock modes.
// clock modes.
//
// This callback is a hack around the fact that we can't
// let the ClockObject directly create a PStatCollector,
@ -1051,6 +1056,9 @@ add_collector(PStatClient::Collector *collector) {
////////////////////////////////////////////////////////////////////
void PStatClient::
add_thread(PStatClient::InternalThread *thread) {
_threads_by_name[thread->_name].push_back(_num_threads);
_threads_by_sync_name[thread->_sync_name].push_back(_num_threads);
if (_num_threads >= _threads_size) {
// We need to grow the array. We have to be careful here, because
// there might be clients accessing the array right now who are
@ -1071,12 +1079,21 @@ add_thread(PStatClient::InternalThread *thread) {
// and then no more.)
new_threads[_num_threads] = thread;
AtomicAdjust::inc(_num_threads);
} else {
ThreadPointer *threads = (ThreadPointer *)_threads;
threads[_num_threads] = thread;
AtomicAdjust::inc(_num_threads);
}
AtomicAdjust::inc(_num_threads);
// We need an additional PerThreadData for this thread in all of the
// collectors.
CollectorPointer *collectors = (CollectorPointer *)_collectors;
for (int ci = 0; ci < _num_collectors; ++ci) {
Collector *collector = collectors[ci];
collector->_per_thread.push_back(PerThreadData());
nassertv((int)collector->_per_thread.size() == _num_threads);
}
}
@ -1148,7 +1165,7 @@ make_def(const PStatClient *client, int this_index) {
if (_def == (PStatCollectorDef *)NULL) {
_def = new PStatCollectorDef(this_index, _name);
if (_parent_index != this_index) {
const PStatCollectorDef *parent_def =
const PStatCollectorDef *parent_def =
client->get_collector_def(_parent_index);
_def->set_parent(*parent_def);
}
@ -1157,9 +1174,9 @@ make_def(const PStatClient *client, int this_index) {
}
////////////////////////////////////////////////////////////////////
// Function: PStatClient::Collector::make_def
// Function: PStatClient::InternalThread::Constructor
// Access: Private
// Description: Creates the new PStatCollectorDef for this collector.
// Description:
////////////////////////////////////////////////////////////////////
PStatClient::InternalThread::
InternalThread(Thread *thread) :
@ -1174,4 +1191,22 @@ InternalThread(Thread *thread) :
{
}
////////////////////////////////////////////////////////////////////
// Function: PStatClient::InternalThread::Constructor
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
PStatClient::InternalThread::
InternalThread(const string &name, const string &sync_name) :
_thread(NULL),
_name(name),
_sync_name(sync_name),
_is_active(false),
_frame_number(0),
_next_packet(0.0),
_thread_active(true),
_thread_lock(string("PStatClient::InternalThread ") + name)
{
}
#endif // DO_PSTATS

View File

@ -35,6 +35,7 @@
class PStatCollector;
class PStatCollectorDef;
class PStatThread;
class GraphicsStateGuardian;
////////////////////////////////////////////////////////////////////
// Class : PStatClient
@ -113,6 +114,7 @@ private:
PStatThread do_get_current_thread() const;
PStatThread make_thread(Thread *thread);
PStatThread do_make_thread(Thread *thread);
PStatThread make_gpu_thread(const string &name);
bool is_active(int collector_index, int thread_index) const;
bool is_started(int collector_index, int thread_index) const;
@ -171,7 +173,7 @@ private:
INLINE const string &get_name() const;
INLINE bool is_active() const;
INLINE PStatCollectorDef *get_def(const PStatClient *client, int this_index) const;
private:
void make_def(const PStatClient *client, int this_index);
@ -201,6 +203,7 @@ private:
class InternalThread {
public:
InternalThread(Thread *thread);
InternalThread(const string &name, const string &sync_name = "Main");
WPT(Thread) _thread;
string _name;
@ -248,6 +251,7 @@ private:
friend class PStatCollector;
friend class PStatThread;
friend class PStatClientImpl;
friend class GraphicsStateGuardian;
};
#include "pStatClient.I"
@ -272,4 +276,3 @@ PUBLISHED:
#endif // DO_PSTATS
#endif

Some files were not shown because too many files have changed in this diff Show More