Merge branch 'master' into astron-master

This commit is contained in:
Sam Edwards 2017-01-09 18:11:21 -07:00
commit 1eb81f9e8e
149 changed files with 3863 additions and 2287 deletions

View File

@ -1,106 +0,0 @@
// This is a little wrapper to make it easy to run a python program from the
// command line. Basically, it just interfaces to the Python API and imports
// the module that was specified by the IMPORT_MODULE preprocessor definition
// when it was compiled.
#include "dtoolbase.h"
#undef _POSIX_C_SOURCE
#undef _XOPEN_SOURCE
#include <Python.h>
#if PY_MAJOR_VERSION >= 3
#include <wchar.h>
#endif
#ifndef IMPORT_MODULE
#error IMPORT_MODULE must be defined when compiling ppython.cxx !
#endif
#define _STRINGIFY(s) #s
#define STRINGIFY(s) _STRINGIFY(s)
#define IMPORT_MODULE_STR STRINGIFY(IMPORT_MODULE)
#if defined(_WIN32) && PY_MAJOR_VERSION >= 3
// As Py_SetProgramName expects a wchar_t*, it's easiest to just use the wmain
// entry point.
int wmain(int argc, wchar_t *argv[]) {
Py_SetProgramName(argv[0]);
#elif PY_MAJOR_VERSION >= 3
// Convert from UTF-8 to wchar_t*.
int main(int argc, char *mb_argv[]) {
wchar_t **argv = new wchar_t*[argc + 1];
for (int i = 0; i < argc; ++i) {
size_t len = mbstowcs(NULL, mb_argv[i], 0);
argv[i] = new wchar_t[len + 1];
mbstowcs(argv[i], mb_argv[i], len);
argv[i][len] = 0;
}
// Just for good measure
argv[argc] = NULL;
Py_SetProgramName(argv[0]);
#else
// Python 2.
int main(int argc, char *argv[]) {
Py_SetProgramName(argv[0]);
#endif
// On Windows, we need to set pythonhome correctly. We'll try to find
// ppython.exe on the path and set pythonhome to its location.
#ifdef _WIN32
#if PY_MAJOR_VERSION >= 3
// Py_SetPythonHome expects a wchar_t in Python 3.
wchar_t *path = _wgetenv(L"PATH");
wchar_t *result = wcstok(path, L";");
while (result != NULL) {
struct _stat st;
wchar_t *ppython = (wchar_t*) malloc(wcslen(result) * 2 + 26);
wcscpy(ppython, result);
wcscat(ppython, L"\\python.exe");
if (_wstat(ppython, &st) == 0) {
Py_SetPythonHome(result);
free(ppython);
break;
}
result = wcstok(NULL, L";");
free(ppython);
}
#else
char *path = getenv("PATH");
char *result = strtok(path, ";");
while (result != NULL) {
struct stat st;
char *ppython = (char*) malloc(strlen(result) + 13);
strcpy(ppython, result);
strcat(ppython, "\\ppython.exe");
if (stat(ppython, &st) == 0) {
Py_SetPythonHome(result);
free(ppython);
break;
}
result = strtok(NULL, ";");
free(ppython);
}
#endif
#endif
Py_Initialize();
if (Py_VerboseFlag) {
fprintf(stderr, "Python %s\\n%s\\n", Py_GetVersion(), Py_GetCopyright());
}
PySys_SetArgv(argc, argv);
int sts = 0;
PyObject* m = PyImport_ImportModule(IMPORT_MODULE_STR);
if (m <= 0) {
PyErr_Print();
sts = 1;
}
Py_Finalize();
return sts;
}

View File

@ -87,4 +87,13 @@ class EggCacher:
TexturePool.releaseAllTextures()
progress += size
cacher = EggCacher(sys.argv[1:])
def main(args=None):
if args is None:
args = sys.argv[1:]
cacher = EggCacher(args)
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@ -1,831 +0,0 @@
; Panda3D installation script for the Nullsoft Installation System (NSIS).
; Jon Parise <jparise@cmu.edu>
; with Ben Johnson <bkj@andrew.cmu.edu>
; with Jason Pratt <pratt@andrew.cmu.edu>
; mangled by Josh Yelon <jyelon@andrew.cmu.edu>
; Caller needs to define these variables:
;
; COMPRESSOR - either zlib or lzma
; NAME - name of what we're building (ie, "Panda3D" or "Airblade")
; SMDIRECTORY - where to put this in the start menu (ie, "Panda3D 1.1.0" or "Airblade 1.1.0")
; INSTALLDIR - where to install the program (ie, "C:\Program Files\Panda3D-1.1.0")
; OUTFILE - where to put the output file (ie, "..\nsis-output.exe")
; LICENSE - location of the license file (ie, "C:\Airblade\LICENSE.TXT")
; LANGUAGE - name of the Language file to use (ie, "English" or "Panda3DEnglish")
; RUNTEXT - text for run-box at end of installation (ie, "Run the Panda Greeting Card")
; IBITMAP - name of installer bitmap (ie, "C:\Airblade\Airblade.bmp")
; UBITMAP - name of uninstaller bitmap (ie, "C:\Airblade\Airblade.bmp")
;
; PANDA - location of panda install tree.
; PYVER - version of Python that Panda was built with (ie, "2.7")
; PANDACONF - name of panda config directory - usually $PANDA\etc
; PSOURCE - location of the panda source-tree if available, OR location of panda install tree.
; PYEXTRAS - directory containing python extras, if any.
; REGVIEW - either 32 or 64, depending on the build architecture.
;
; PPGAME - directory containing prepagaged game, if any (ie, "C:\My Games\Airblade")
; PPMAIN - python program containing prepackaged game, if any (ie, "Airblade.py")
; PPICON - file containing icon of prepackaged game.
;
!include "MUI.nsh"
!include "WinMessages.nsh"
Name "${NAME}"
InstallDir "${INSTALLDIR}"
OutFile "${OUTFILE}"
SetCompress auto
SetCompressor ${COMPRESSOR}
!define MUI_WELCOMEFINISHPAGE_BITMAP "${IBITMAP}"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "${UBITMAP}"
!define MUI_ABORTWARNING
!define MUI_FINISHPAGE_NOREBOOTSUPPORT
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_FUNCTION runFunction
!define MUI_FINISHPAGE_RUN_TEXT "${RUNTEXT}"
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "${LICENSE}"
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
!insertmacro MUI_LANGUAGE "${LANGUAGE}"
ShowInstDetails nevershow
ShowUninstDetails nevershow
LicenseData "${LICENSE}"
InstType "Typical"
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
var READABLE
var MANPAGE
var TUTNAME
Function runFunction
!ifdef PPGAME
ExecShell "open" "$SMPROGRAMS\${SMDIRECTORY}\Play ${NAME}.lnk"
!else
ExecShell "open" "$SMPROGRAMS\${SMDIRECTORY}\Panda Manual.lnk"
!endif
FunctionEnd
Section "${SMDIRECTORY}" SecCore
SectionIn 1 2 3 RO
SetDetailsPrint none
SetOutPath $INSTDIR
SetOverwrite try
SetOutPath $INSTDIR
File "${PANDA}\LICENSE"
SetOutPath $INSTDIR\bin
File /r "${PANDA}\bin\*.dll"
File /nonfatal /r "${PANDA}\bin\*.pyd"
File /nonfatal /r "${PANDA}\bin\Microsoft.*.manifest"
SetOutPath $INSTDIR\etc
File /r "${PANDACONF}\*"
SetOutPath $INSTDIR\direct\directscripts
File /r /x CVS /x Opt?-Win32 "${PANDA}\direct\directscripts\*"
SetOutPath $INSTDIR\direct\filter
File /r /x CVS /x Opt?-Win32 "${PANDA}\direct\filter\*.sha"
SetOutPath $INSTDIR\direct
File /r /x CVS /x Opt?-Win32 "${PANDA}\direct\*.py"
Delete "$INSTDIR\panda3d.py"
Delete "$INSTDIR\panda3d.pyc"
Delete "$INSTDIR\panda3d.pyo"
SetOutPath $INSTDIR\pandac
File /r "${PANDA}\pandac\*.py"
SetOutPath $INSTDIR\panda3d
File /r "${PANDA}\panda3d\*.py"
File /r "${PANDA}\panda3d\*.pyd"
SetOutPath $INSTDIR\python
File /r "${PANDA}\python\*"
RMDir /r "$SMPROGRAMS\${SMDIRECTORY}"
CreateDirectory "$SMPROGRAMS\${SMDIRECTORY}"
!ifdef PPGAME
SetOutPath $INSTDIR\models
File /r /x CVS "${PANDA}\models\*"
SetOutPath $INSTDIR\bin
File /r "${PANDA}\bin\eggcacher.exe"
SetOutpath $INSTDIR\game
File /r "${PPGAME}\*"
CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Play ${NAME}.lnk" "$INSTDIR\python\ppython.exe" "-E ${PPMAIN}" "$INSTDIR\${PPICON}" 0 SW_SHOWMINIMIZED "" "Play ${NAME}"
# Preload all EGG files into the model-cache
SetOutPath $INSTDIR
SetDetailsPrint textonly
SetDetailsView show
nsExec::ExecToLog '"$INSTDIR\bin\eggcacher.exe" --concise game'
SetDetailsPrint none
SetDetailsView hide
!else
SetOutPath $INSTDIR\plugins
File /nonfatal /r "${PANDA}\plugins\*.dle"
File /nonfatal /r "${PANDA}\plugins\*.dlo"
File /nonfatal /r "${PANDA}\plugins\*.mll"
File /nonfatal /r "${PANDA}\plugins\*.mel"
File /nonfatal /r "${PANDA}\plugins\*.ms"
File "${PSOURCE}\doc\INSTALLING-PLUGINS.TXT"
SetOutPath $INSTDIR\pandac\input
File /r "${PANDA}\pandac\input\*"
SetOutPath $INSTDIR\bin
File /r "${PANDA}\bin\*.exe"
File /nonfatal /r "${PANDA}\bin\*.p3d"
SetOutPath $INSTDIR\lib
File /r /x *.exp "${PANDA}\lib\*"
SetOutPath $INSTDIR\include
File /r /x *.exp "${PANDA}\include\*"
SetOutPath $INSTDIR\Pmw
File /r /x CVS "${PANDA}\Pmw\*"
SetOutPath $INSTDIR\NSIS
File /r /x CVS "${NSISDIR}\*"
SetOutPath $INSTDIR
File /r /x CVS "${PANDA}\ReleaseNotes"
!ifdef PYEXTRAS
SetOutPath $INSTDIR\python\lib
File /nonfatal /r "${PYEXTRAS}\*"
!endif
SetOutPath $INSTDIR\models
File /r /x CVS "${PANDA}\models\*"
SetOutPath $INSTDIR\samples
File /nonfatal /r /x CVS "${PSOURCE}\samples\*"
MessageBox MB_YESNO|MB_ICONQUESTION \
"EGG caching is about to begin.$\nThis process may take a couple minute and approximately 270 MB of RAM.$\nWARNING : It might stuck if your computer resources are low.$\n$\nDo you really want to do this optional step ?" \
IDNO SkipCaching
# Preload all EGG files into the model-cache
SetOutPath $INSTDIR
SetDetailsPrint both
SetDetailsView show
nsExec::ExecToLog '"$INSTDIR\bin\eggcacher.exe" --concise models samples'
SetDetailsPrint none
SetDetailsView hide
SkipCaching:
SetOutPath $INSTDIR
WriteINIStr $INSTDIR\Website.url "InternetShortcut" "URL" "http://panda3d.org/"
WriteINIStr $INSTDIR\Manual.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php"
WriteINIStr $INSTDIR\Samples.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php/Sample_Programs_in_the_Distribution"
SetOutPath $INSTDIR
CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Panda Manual.lnk" "$INSTDIR\Manual.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Panda Manual"
CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Panda Website.lnk" "$INSTDIR\Website.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Panda Website"
CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Program Manual.lnk" "$INSTDIR\Samples.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Sample Program Manual"
FindFirst $0 $1 $INSTDIR\samples\*
loop:
StrCmp $1 "" done
StrCmp $1 "." next
StrCmp $1 ".." next
Push $1
Push "-"
Push " "
Call StrRep
Pop $R0
StrCpy $READABLE $R0
Push $1
Push "-"
Push "_"
Call StrRep
Pop $R0
StrCpy $MANPAGE $R0
CreateDirectory "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE"
SetOutPath $INSTDIR\samples\$1
WriteINIStr $INSTDIR\samples\$1\ManualPage.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php/Sample_Programs:_$MANPAGE"
CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE\Manual Page.lnk" "$INSTDIR\samples\$1\ManualPage.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Manual Entry on this Sample Program"
CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE\View Source Code.lnk" "$INSTDIR\samples\$1"
FindFirst $2 $3 $INSTDIR\samples\$1\Tut-*.py
iloop:
StrCmp $3 "" idone
StrCpy $TUTNAME $3 -3 4
Push $TUTNAME
Push "-"
Push " "
Call StrRep
Pop $R0
StrCpy $TUTNAME $R0
CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE\Run $TUTNAME.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\bin\eggcacher.exe" 0 SW_SHOWMINIMIZED "" "Run $TUTNAME"
CreateShortCut "$INSTDIR\samples\$1\Run $TUTNAME.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\bin\eggcacher.exe" 0 SW_SHOWMINIMIZED "" "Run $TUTNAME"
FindNext $2 $3
goto iloop
idone:
next:
FindNext $0 $1
Goto loop
done:
!endif
SectionEnd
Section -post
!ifdef REGVIEW
SetRegView ${REGVIEW}
!endif
!ifndef PPGAME
# Add the "bin" directory to the PATH.
Push "$INSTDIR\python"
Call RemoveFromPath
Push "$INSTDIR\python\Scripts"
Call RemoveFromPath
Push "$INSTDIR\bin"
Call RemoveFromPath
Push "$INSTDIR\python"
Call AddToPath
Push "$INSTDIR\python\Scripts"
Call AddToPath
Push "$INSTDIR\bin"
Call AddToPath
ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
StrCmp $0 "$INSTDIR\python" RegPath 0
StrCmp $0 "" RegPath 0
MessageBox MB_YESNO|MB_ICONQUESTION \
"Your system already has a copy of Python installed. Panda3D installs its own copy of Python ${PYVER}, which will install alongside your existing copy. Would you like to make Panda's copy the default Python? If you choose 'No', you will have to configure your existing copy of Python to use the Panda3D libraries, keeping in mind that this version of Panda3D can only run with Python ${PYVER}." \
IDNO SkipRegPath
RegPath:
DetailPrint "Adding registry keys for python..."
WriteRegStr HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" "" "$INSTDIR\python"
SkipRegPath:
!endif
DetailPrint "Adding the uninstaller ..."
Delete "$INSTDIR\uninst.exe"
WriteUninstaller "$INSTDIR\uninst.exe"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SMDIRECTORY}" "DisplayName" "${SMDIRECTORY}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SMDIRECTORY}" "UninstallString" '"$INSTDIR\uninst.exe"'
SetOutPath $INSTDIR
CreateShortcut "$SMPROGRAMS\${SMDIRECTORY}\Uninstall ${NAME}.lnk" "$INSTDIR\uninst.exe" ""
SectionEnd
Section Uninstall
!ifdef REGVIEW
SetRegView ${REGVIEW}
!endif
!ifndef PPGAME
Push "$INSTDIR\python"
Call un.RemoveFromPath
Push "$INSTDIR\python\Scripts"
Call un.RemoveFromPath
Push "$INSTDIR\bin"
Call un.RemoveFromPath
ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
StrCmp $0 "$INSTDIR\python" 0 SkipUnReg
DeleteRegKey HKLM "Software\Python\PythonCore\${PYVER}"
SkipUnReg:
!endif
Delete "$INSTDIR\uninst.exe"
RMDir /r "$SMPROGRAMS\${SMDIRECTORY}"
RMDir /r "$INSTDIR"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SMDIRECTORY}"
SectionEnd
# --[ Utility Functions ]------------------------------------------------------
; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
Function IsNT
Push $0
ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
StrCmp $0 "" 0 IsNT_yes
; we are not NT.
Pop $0
Push 0
Return
IsNT_yes:
; NT!!!
Pop $0
Push 1
FunctionEnd
; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
Function un.IsNT
Push $0
ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
StrCmp $0 "" 0 unIsNT_yes
; we are not NT.
Pop $0
Push 0
Return
unIsNT_yes:
; NT!!!
Pop $0
Push 1
FunctionEnd
; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
Function StrStr
Push $0
Exch
Pop $0 ; $0 now have the string to find
Push $1
Exch 2
Pop $1 ; $1 now have the string to find in
Exch
Push $2
Push $3
Push $4
Push $5
StrCpy $2 -1
StrLen $3 $0
StrLen $4 $1
IntOp $4 $4 - $3
unStrStr_loop:
IntOp $2 $2 + 1
IntCmp $2 $4 0 0 unStrStrReturn_notFound
StrCpy $5 $1 $3 $2
StrCmp $5 $0 unStrStr_done unStrStr_loop
unStrStrReturn_notFound:
StrCpy $2 -1
unStrStr_done:
Pop $5
Pop $4
Pop $3
Exch $2
Exch 2
Pop $0
Pop $1
FunctionEnd
; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
Function un.StrStr
Push $0
Exch
Pop $0 ; $0 now have the string to find
Push $1
Exch 2
Pop $1 ; $1 now have the string to find in
Exch
Push $2
Push $3
Push $4
Push $5
StrCpy $2 -1
StrLen $3 $0
StrLen $4 $1
IntOp $4 $4 - $3
unStrStr_loop:
IntOp $2 $2 + 1
IntCmp $2 $4 0 0 unStrStrReturn_notFound
StrCpy $5 $1 $3 $2
StrCmp $5 $0 unStrStr_done unStrStr_loop
unStrStrReturn_notFound:
StrCpy $2 -1
unStrStr_done:
Pop $5
Pop $4
Pop $3
Exch $2
Exch 2
Pop $0
Pop $1
FunctionEnd
; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
; Commentary and smarter ';' checking by Jon Parise <jparise@cmu.edu>
Function AddToPath
Exch $0
Push $1
Push $2
Push $3
Call IsNT
Pop $1
StrCmp $1 1 AddToPath_NT
; We're not on NT, so modify the AUTOEXEC.BAT file.
StrCpy $1 $WINDIR 2
FileOpen $1 "$1\autoexec.bat" a
FileSeek $1 0 END
GetFullPathName /SHORT $0 $0
FileWrite $1 "$\r$\nSET PATH=%PATH%;$0$\r$\n"
FileClose $1
Goto AddToPath_done
AddToPath_NT:
ReadRegStr $1 HKCU "Environment" "PATH"
Call IsUserAdmin
Pop $3
; If this is an Admin user, use the System env. variable instead of the user's env. variable
StrCmp $3 1 0 +2
ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
; If the PATH string is empty, jump over the mangling routines.
StrCmp $1 "" AddToPath_NTdoIt
; Pull off the last character of the PATH string. If it's a semicolon,
; we don't need to add another one, so jump to the section where we
; append the new PATH component(s).
StrCpy $2 $1 1 -1
StrCmp $2 ";" AddToPath_NTAddPath AddToPath_NTAddSemi
AddToPath_NTAddSemi:
StrCpy $1 "$1;"
Goto AddToPath_NTAddPath
AddToPath_NTAddPath:
StrCpy $0 "$1$0"
Goto AddToPath_NTdoIt
AddToPath_NTdoIt:
Call IsUserAdmin
Pop $3
StrCmp $3 1 0 NotAdmin
WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $0
Goto AddToPath_done
NotAdmin:
WriteRegExpandStr HKCU "Environment" "PATH" $0
AddToPath_done:
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd
; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
Function RemoveFromPath
Exch $0
Push $1
Push $2
Push $3
Push $4
Push $5
Call IsNT
Pop $1
StrCmp $1 1 unRemoveFromPath_NT
; Not on NT
StrCpy $1 $WINDIR 2
FileOpen $1 "$1\autoexec.bat" r
GetTempFileName $4
FileOpen $2 $4 w
GetFullPathName /SHORT $0 $0
StrCpy $0 "SET PATH=%PATH%;$0"
SetRebootFlag true
Goto unRemoveFromPath_dosLoop
unRemoveFromPath_dosLoop:
FileRead $1 $3
StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoop
StrCmp $3 "$0$\n" unRemoveFromPath_dosLoop
StrCmp $3 "$0" unRemoveFromPath_dosLoop
StrCmp $3 "" unRemoveFromPath_dosLoopEnd
FileWrite $2 $3
Goto unRemoveFromPath_dosLoop
unRemoveFromPath_dosLoopEnd:
FileClose $2
FileClose $1
StrCpy $1 $WINDIR 2
Delete "$1\autoexec.bat"
CopyFiles /SILENT $4 "$1\autoexec.bat"
Delete $4
Goto unRemoveFromPath_done
unRemoveFromPath_NT:
StrLen $2 $0
Call IsUserAdmin
Pop $5
StrCmp $5 1 0 NotAdmin
ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
Push $1
Push $0
Call StrStr ; Find $0 in $1
Pop $0 ; pos of our dir
IntCmp $0 -1 unRemoveFromPath_done
; else, it is in path
StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir
IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';')
IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.
StrLen $0 $1
StrCpy $1 $1 $0 $2
StrCpy $3 "$3$1"
WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $3
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
Goto unRemoveFromPath_done
NotAdmin:
ReadRegStr $1 HKCU "Environment" "PATH"
Push $1
Push $0
Call StrStr ; Find $0 in $1
Pop $0 ; pos of our dir
IntCmp $0 -1 unRemoveFromPath_done
; else, it is in path
StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir
IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';')
IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.
StrLen $0 $1
StrCpy $1 $1 $0 $2
StrCpy $3 "$3$1"
WriteRegExpandStr HKCU "Environment" "PATH" $3
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
unRemoveFromPath_done:
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd
; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91
Function un.RemoveFromPath
Exch $0
Push $1
Push $2
Push $3
Push $4
Push $5
Call un.IsNT
Pop $1
StrCmp $1 1 unRemoveFromPath_NT
; Not on NT
StrCpy $1 $WINDIR 2
FileOpen $1 "$1\autoexec.bat" r
GetTempFileName $4
FileOpen $2 $4 w
GetFullPathName /SHORT $0 $0
StrCpy $0 "SET PATH=%PATH%;$0"
SetRebootFlag true
Goto unRemoveFromPath_dosLoop
unRemoveFromPath_dosLoop:
FileRead $1 $3
StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoop
StrCmp $3 "$0$\n" unRemoveFromPath_dosLoop
StrCmp $3 "$0" unRemoveFromPath_dosLoop
StrCmp $3 "" unRemoveFromPath_dosLoopEnd
FileWrite $2 $3
Goto unRemoveFromPath_dosLoop
unRemoveFromPath_dosLoopEnd:
FileClose $2
FileClose $1
StrCpy $1 $WINDIR 2
Delete "$1\autoexec.bat"
CopyFiles /SILENT $4 "$1\autoexec.bat"
Delete $4
Goto unRemoveFromPath_done
unRemoveFromPath_NT:
StrLen $2 $0
Call un.IsUserAdmin
Pop $5
StrCmp $5 1 0 NotAdmin
ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH"
Push $1
Push $0
Call un.StrStr ; Find $0 in $1
Pop $0 ; pos of our dir
IntCmp $0 -1 unRemoveFromPath_done
; else, it is in path
StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir
IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';')
IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.
StrLen $0 $1
StrCpy $1 $1 $0 $2
StrCpy $3 "$3$1"
WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $3
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
Goto unRemoveFromPath_done
NotAdmin:
ReadRegStr $1 HKCU "Environment" "PATH"
Push $1
Push $0
Call un.StrStr ; Find $0 in $1
Pop $0 ; pos of our dir
IntCmp $0 -1 unRemoveFromPath_done
; else, it is in path
StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir
IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';')
IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.
StrLen $0 $1
StrCpy $1 $1 $0 $2
StrCpy $3 "$3$1"
WriteRegExpandStr HKCU "Environment" "PATH" $3
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
unRemoveFromPath_done:
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd
; From: http://nsis.sourceforge.net/archive/nsisweb.php?page=329&instances=0,11
; Localized by Ben Johnson (bkj@andrew.cmu.edu)
Function IsUserAdmin
Push $0
Push $1
Push $2
Push $3
Call IsNT
Pop $1
ClearErrors
UserInfo::GetName
;IfErrors Win9x
Pop $2
UserInfo::GetAccountType
Pop $3
; Compare results of IsNT with "1"
StrCmp $1 1 0 NotNT
;This is NT
StrCmp $3 "Admin" 0 NotAdmin
; Observation: I get here when running Win98SE. (Lilla)
; The functions UserInfo.dll looks for are there on Win98 too,
; but just don't work. So UserInfo.dll, knowing that admin isn't required
; on Win98, returns admin anyway. (per kichik)
; MessageBox MB_OK 'User "$R1" is in the Administrators group'
Pop $3
Pop $2
Pop $1
Pop $0
Push 1
Return
NotAdmin:
; You should still check for an empty string because the functions
; UserInfo.dll looks for may not be present on Windows 95. (per kichik)
#StrCmp $2 "" Win9x
#StrCpy $0 0
;MessageBox MB_OK 'User "$2" is in the "$3" group'
Pop $3
Pop $2
Pop $1
Pop $0
Push 0
Return
;Because we use IsNT, this is redundant.
#Win9x:
# ; comment/message below is by UserInfo.nsi author:
# ; This one means you don't need to care about admin or
# ; not admin because Windows 9x doesn't either
# ;MessageBox MB_OK "Error! This DLL can't run under Windows 9x!"
# StrCpy $0 0
NotNT:
;We are not NT
;Win9x doesn't have "admin" users.
;Let the user do whatever.
Pop $3
Pop $2
Pop $1
Pop $0
Push 1
FunctionEnd
Function un.IsUserAdmin
Push $0
Push $1
Push $2
Push $3
Call un.IsNT
Pop $1
ClearErrors
UserInfo::GetName
;IfErrors Win9x
Pop $2
UserInfo::GetAccountType
Pop $3
; Compare results of IsNT with "1"
StrCmp $1 1 0 NotNT
;This is NT
StrCmp $3 "Admin" 0 NotAdmin
; Observation: I get here when running Win98SE. (Lilla)
; The functions UserInfo.dll looks for are there on Win98 too,
; but just don't work. So UserInfo.dll, knowing that admin isn't required
; on Win98, returns admin anyway. (per kichik)
; MessageBox MB_OK 'User "$R1" is in the Administrators group'
Pop $3
Pop $2
Pop $1
Pop $0
Push 1
Return
NotAdmin:
; You should still check for an empty string because the functions
; UserInfo.dll looks for may not be present on Windows 95. (per kichik)
#StrCmp $2 "" Win9x
#StrCpy $0 0
;MessageBox MB_OK 'User "$2" is in the "$3" group'
Pop $3
Pop $2
Pop $1
Pop $0
Push 0
Return
;Because we use IsNT, this is redundant.
#Win9x:
# ; comment/message below is by UserInfo.nsi author:
# ; This one means you don't need to care about admin or
# ; not admin because Windows 9x doesn't either
# ;MessageBox MB_OK "Error! This DLL can't run under Windows 9x!"
# StrCpy $0 0
NotNT:
;We are not NT
;Win9x doesn't have "admin" users.
;Let the user do whatever.
Pop $3
Pop $2
Pop $1
Pop $0
Push 1
FunctionEnd
Function StrRep
;Written by dirtydingus 2003-02-20 04:30:09
; USAGE
;Push String to do replacement in (haystack)
;Push String to replace (needle)
;Push Replacement
;Call StrRep
;Pop $R0 result
;StrCpy $Result STR $R0
Exch $R4 ; $R4 = Replacement String
Exch
Exch $R3 ; $R3 = String to replace (needle)
Exch 2
Exch $R1 ; $R1 = String to do replacement in (haystack)
Push $R2 ; Replaced haystack
Push $R5 ; Len (needle)
Push $R6 ; len (haystack)
Push $R7 ; Scratch reg
StrCpy $R2 ""
StrLen $R5 $R3
StrLen $R6 $R1
loop:
StrCpy $R7 $R1 $R5
StrCmp $R7 $R3 found
StrCpy $R7 $R1 1 ; - optimization can be removed if U know len needle=1
StrCpy $R2 "$R2$R7"
StrCpy $R1 $R1 $R6 1
StrCmp $R1 "" done loop
found:
StrCpy $R2 "$R2$R4"
StrCpy $R1 $R1 $R6 $R5
StrCmp $R1 "" done loop
done:
StrCpy $R3 $R2
Pop $R7
Pop $R6
Pop $R5
Pop $R2
Pop $R1
Pop $R4
Exch $R3
FunctionEnd

View File

@ -1,421 +0,0 @@
#############################################################################
#
# packpanda - this is a tool that packages up a panda game into a
# convenient, easily-downloaded windows executable. Packpanda runs on linux
# and windows - on linux, it builds .debs and .rpms, on windows it relies on
# NSIS, the nullsoft scriptable install system, to do the hard work.
#
# This is intentionally a very simplistic game-packer with very
# limited options. The goal is simplicity, not feature richness.
# There are dozens of complex, powerful packaging tools already out
# there. This one is for people who just want to do it quick and
# easy.
#
##############################################################################
import sys, os, getopt, shutil, py_compile, subprocess
OPTIONLIST = [
("dir", 1, "Name of directory containing game"),
("name", 1, "Human-readable name of the game"),
("version", 1, "Version number to add to game name"),
("rmdir", 2, "Delete all directories with given name"),
("rmext", 2, "Delete all files with given extension"),
("fast", 0, "Use fast compression instead of good compression"),
("bam", 0, "Generate BAM files, change default-model-extension to BAM"),
("pyc", 0, "Generate PYC files"),
]
def ParseFailure():
print("")
print("packpanda usage:")
print("")
for (opt, hasval, explanation) in OPTIONLIST:
if (hasval):
print(" --%-10s %s"%(opt+" x", explanation))
else:
print(" --%-10s %s"%(opt+" ", explanation))
sys.exit(1)
def ParseOptions(args):
try:
options = {}
longopts = []
for (opt, hasval, explanation) in OPTIONLIST:
if (hasval==2):
longopts.append(opt+"=")
options[opt] = []
elif (hasval==1):
longopts.append(opt+"=")
options[opt] = ""
else:
longopts.append(opt)
options[opt] = 0
opts, extras = getopt.getopt(args, "", longopts)
for option, value in opts:
for (opt, hasval, explanation) in OPTIONLIST:
if (option == "--"+opt):
if (hasval==2): options[opt].append(value)
elif (hasval==1): options[opt] = value
else: options[opt] = 1
return options
except: ParseFailure();
OPTIONS = ParseOptions(sys.argv[1:])
##############################################################################
#
# Locate the relevant trees.
#
##############################################################################
PANDA=None
for dir in sys.path:
if (dir != "") and os.path.exists(os.path.join(dir,"direct")) and os.path.exists(os.path.join(dir,"pandac")):
PANDA=os.path.abspath(dir)
if (PANDA is None):
sys.exit("Cannot locate the panda root directory in the python path (cannot locate directory containing direct and pandac).")
print("PANDA located at "+PANDA)
if (os.path.exists(os.path.join(PANDA,"..","makepanda","makepanda.py"))) and (sys.platform != "win32" or os.path.exists(os.path.join(PANDA,"..","thirdparty","win-nsis","makensis.exe"))):
PSOURCE=os.path.abspath(os.path.join(PANDA,".."))
if (sys.platform == "win32"):
NSIS=os.path.abspath(os.path.join(PANDA,"..","thirdparty","win-nsis"))
else:
PSOURCE=PANDA
if (sys.platform == "win32"):
NSIS=os.path.join(PANDA,"nsis")
##############################################################################
#
# Identify the main parts of the game: DIR, NAME, MAIN, ICON, BITMAP, etc
#
##############################################################################
VER=OPTIONS["version"]
DIR=OPTIONS["dir"]
if (DIR==""):
print("You must specify the --dir option.")
ParseFailure()
DIR=os.path.abspath(DIR)
MYDIR=os.path.abspath(os.getcwd())
BASENAME=os.path.basename(DIR)
if (OPTIONS["name"] != ""):
NAME=OPTIONS["name"]
else:
NAME=BASENAME
SMDIRECTORY=NAME
if (VER!=""): SMDIRECTORY=SMDIRECTORY+" "+VER
PYTHONV="python"+sys.version[:3]
LICENSE=os.path.join(DIR, "license.txt")
OUTFILE=os.path.basename(DIR)
if (VER!=""): OUTFILE=OUTFILE+"-"+VER
if (sys.platform == "win32"):
ICON=os.path.join(DIR, "icon.ico")
BITMAP=os.path.join(DIR, "installer.bmp")
OUTFILE=os.path.abspath(OUTFILE+".exe")
INSTALLDIR='C:\\'+os.path.basename(DIR)
if (VER!=""): INSTALLDIR=INSTALLDIR+"-"+VER
COMPRESS="lzma"
if (OPTIONS["fast"]): COMPRESS="zlib"
if (OPTIONS["pyc"]): MAIN="main.pyc"
else: MAIN="main.py"
def PrintFileStatus(label, file):
if (os.path.exists(file)):
print("%-15s: %s"%(label, file))
else:
print("%-15s: %s (MISSING)"%(label, file))
PrintFileStatus("Dir", DIR)
print("%-15s: %s"%("Name", NAME))
print("%-15s: %s"%("Start Menu", SMDIRECTORY))
PrintFileStatus("Main", os.path.join(DIR, MAIN))
if (sys.platform == "win32"):
PrintFileStatus("Icon", ICON)
PrintFileStatus("Bitmap", BITMAP)
PrintFileStatus("License", LICENSE)
print("%-15s: %s"%("Output", OUTFILE))
if (sys.platform == "win32"):
print("%-15s: %s"%("Install Dir", INSTALLDIR))
if (os.path.isdir(DIR)==0):
sys.exit("Difficulty reading "+DIR+". Cannot continue.")
if (os.path.isfile(os.path.join(DIR, "main.py"))==0):
sys.exit("Difficulty reading main.py. Cannot continue.")
if (os.path.isfile(LICENSE)==0):
LICENSE=os.path.join(PANDA,"LICENSE")
if (sys.platform == "win32") and (os.path.isfile(BITMAP)==0):
BITMAP=os.path.join(NSIS,"Contrib","Graphics","Wizard","nsis.bmp")
if (sys.platform == "win32"):
if (os.path.isfile(ICON)==0):
PPICON="bin\\ppython.exe"
else:
PPICON="game\\icon.ico"
##############################################################################
#
# Copy the game to a temporary directory, so we can modify it safely.
#
##############################################################################
def limitedCopyTree(src, dst, rmdir):
if (os.path.isdir(src)):
if (os.path.basename(src) in rmdir):
return
if (not os.path.isdir(dst)): os.mkdir(dst)
for x in os.listdir(src):
limitedCopyTree(os.path.join(src,x), os.path.join(dst,x), rmdir)
else:
shutil.copyfile(src, dst)
TMPDIR=os.path.abspath("packpanda-TMP")
if (sys.platform == "win32"):
TMPGAME=os.path.join(TMPDIR,"game")
TMPETC=os.path.join(TMPDIR,"etc")
else:
TMPGAME=os.path.join(TMPDIR,"usr","share","games",BASENAME,"game")
TMPETC=os.path.join(TMPDIR,"usr","share","games",BASENAME,"etc")
print("")
print("Copying the game to "+TMPDIR+"...")
if (os.path.exists(TMPDIR)):
try: shutil.rmtree(TMPDIR)
except: sys.exit("Cannot delete "+TMPDIR)
try:
os.mkdir(TMPDIR)
rmdir = {}
for x in OPTIONS["rmdir"]:
rmdir[x] = 1
if not os.path.isdir( TMPGAME ):
os.makedirs(TMPGAME)
limitedCopyTree(DIR, TMPGAME, rmdir)
if not os.path.isdir( TMPETC ):
os.makedirs(TMPETC)
if sys.platform == "win32":
limitedCopyTree(os.path.join(PANDA, "etc"), TMPETC, {})
else:
shutil.copyfile("/etc/Config.prc", os.path.join(TMPETC, "Config.prc"))
shutil.copyfile("/etc/Confauto.prc", os.path.join(TMPETC, "Confauto.prc"))
except: sys.exit("Cannot copy game to "+TMPDIR)
##############################################################################
#
# If --bam requested, change default-model-extension .egg to bam.
#
##############################################################################
def ReadFile(wfile):
try:
srchandle = open(wfile, "rb")
data = srchandle.read()
srchandle.close()
return data
except: exit("Cannot read "+wfile)
def WriteFile(wfile,data):
try:
dsthandle = open(wfile, "wb")
dsthandle.write(data)
dsthandle.close()
except: exit("Cannot write "+wfile)
if OPTIONS["bam"]:
CONF=ReadFile(os.path.join(TMPETC,"Confauto.prc"))
CONF=CONF.replace("default-model-extension .egg","default-model-extension .bam")
WriteFile(os.path.join(TMPETC,"Confauto.prc"), CONF)
##############################################################################
#
# Compile all py files, convert all egg files.
#
# We do this as a sanity check, even if the user
# hasn't requested that his files be compiled.
#
##############################################################################
if (sys.platform == "win32"):
EGG2BAM=os.path.join(PANDA,"bin","egg2bam.exe")
else:
EGG2BAM=os.path.join(PANDA,"bin","egg2bam")
def egg2bam(file,bam):
present = os.path.exists(bam)
if (present): bam = "packpanda-TMP.bam";
cmd = 'egg2bam -noabs -ps rel -pd . "'+file+'" -o "'+bam+'"'
print("Executing: "+cmd)
if (sys.platform == "win32"):
res = os.spawnl(os.P_WAIT, EGG2BAM, cmd)
else:
res = os.system(cmd)
if (res != 0): sys.exit("Problem in egg file: "+file)
if (present) or (OPTIONS["bam"]==0):
os.unlink(bam)
def py2pyc(file):
print("Compiling python "+file)
pyc = file[:-3]+'.pyc'
pyo = file[:-3]+'.pyo'
if (os.path.exists(pyc)): os.unlink(pyc)
if (os.path.exists(pyo)): os.unlink(pyo)
try: py_compile.compile(file)
except: sys.exit("Cannot compile "+file)
if (OPTIONS["pyc"]==0):
if (os.path.exists(pyc)):
os.unlink(pyc)
if (os.path.exists(pyo)):
os.unlink(pyo)
def CompileFiles(file):
if (os.path.isfile(file)):
if (file.endswith(".egg")):
egg2bam(file, file[:-4]+'.bam')
elif (file.endswith(".egg.pz") or file.endswith(".egg.gz")):
egg2bam(file, file[:-7]+'.bam')
elif (file.endswith(".py")):
py2pyc(file)
else: pass
elif (os.path.isdir(file)):
for x in os.listdir(file):
CompileFiles(os.path.join(file, x))
def DeleteFiles(file):
base = os.path.basename(file).lower()
if (os.path.isdir(file)):
for pattern in OPTIONS["rmdir"]:
if pattern.lower() == base:
print("Deleting "+file)
shutil.rmtree(file)
return
for x in os.listdir(file):
DeleteFiles(os.path.join(file, x))
else:
for ext in OPTIONS["rmext"]:
if base[-(len(ext) + 1):] == ("." + ext).lower():
print("Deleting "+file)
os.unlink(file)
return
print("")
print("Compiling BAM and PYC files...")
os.chdir(TMPGAME)
CompileFiles(".")
DeleteFiles(".")
##############################################################################
#
# Now make the installer. Yay!
#
##############################################################################
INSTALLER_DEB_FILE="""
Package: BASENAME
Version: VERSION
Section: games
Priority: optional
Architecture: ARCH
Essential: no
Depends: PYTHONV
Provides: BASENAME
Description: NAME
Maintainer: Unknown
"""
INSTALLER_SPEC_FILE="""
Summary: NAME
Name: BASENAME
Version: VERSION
Release: 1
Group: Amusement/Games
License: See license file
BuildRoot: TMPDIR
BuildRequires: PYTHONV
%description
NAME
%files
%defattr(-,root,root)
/usr/bin/BASENAME
/usr/lib/games/BASENAME
/usr/share/games/BASENAME
"""
RUN_SCRIPT="""
#!/bin/sh
cd /usr/share/games/BASENAME/game
PYTHONPATH=/usr/lib/games/BASENAME:/usr/share/games/BASENAME
LD_LIBRARY_PATH=/usr/lib/games/BASENAME
PYTHONV MAIN
"""
if (sys.platform == "win32"):
CMD="\""+NSIS+"\\makensis.exe\" /V2 "
CMD=CMD+'/DCOMPRESSOR="'+COMPRESS+'" '
CMD=CMD+'/DNAME="'+NAME+'" '
CMD=CMD+'/DSMDIRECTORY="'+SMDIRECTORY+'" '
CMD=CMD+'/DINSTALLDIR="'+INSTALLDIR+'" '
CMD=CMD+'/DOUTFILE="'+OUTFILE+'" '
CMD=CMD+'/DLICENSE="'+LICENSE+'" '
CMD=CMD+'/DLANGUAGE="English" '
CMD=CMD+'/DRUNTEXT="Play '+NAME+'" '
CMD=CMD+'/DIBITMAP="'+BITMAP+'" '
CMD=CMD+'/DUBITMAP="'+BITMAP+'" '
CMD=CMD+'/DPANDA="'+PANDA+'" '
CMD=CMD+'/DPANDACONF="'+TMPETC+'" '
CMD=CMD+'/DPSOURCE="'+PSOURCE+'" '
CMD=CMD+'/DPPGAME="'+TMPGAME+'" '
CMD=CMD+'/DPPMAIN="'+MAIN+'" '
CMD=CMD+'/DPPICON="'+PPICON+'" '
CMD=CMD+'"'+PSOURCE+'\\direct\\directscripts\\packpanda.nsi"'
print("")
print(CMD)
print("packing...")
subprocess.call(CMD)
else:
os.chdir(MYDIR)
os.system("mkdir -p %s/usr/bin" % TMPDIR)
os.system("mkdir -p %s/usr/share/games/%s" % (TMPDIR, BASENAME))
os.system("mkdir -p %s/usr/lib/games/%s" % (TMPDIR, BASENAME))
os.system("cp --recursive %s/direct %s/usr/share/games/%s/direct" % (PANDA, TMPDIR, BASENAME))
os.system("cp --recursive %s/pandac %s/usr/share/games/%s/pandac" % (PANDA, TMPDIR, BASENAME))
os.system("cp --recursive %s/models %s/usr/share/games/%s/models" % (PANDA, TMPDIR, BASENAME))
os.system("cp --recursive %s/Pmw %s/usr/share/games/%s/Pmw" % (PANDA, TMPDIR, BASENAME))
os.system("cp %s %s/usr/share/games/%s/LICENSE" % (LICENSE, TMPDIR, BASENAME))
os.system("cp --recursive /usr/lib/panda3d/* %s/usr/lib/games/%s/" % (TMPDIR, BASENAME))
# Make the script to run the game
txt = RUN_SCRIPT[1:].replace("BASENAME",BASENAME).replace("PYTHONV",PYTHONV).replace("MAIN",MAIN)
WriteFile(TMPDIR+"/usr/bin/"+BASENAME, txt)
os.system("chmod +x "+TMPDIR+"/usr/bin/"+BASENAME)
if (os.path.exists("/usr/bin/rpmbuild")):
os.system("rm -rf %s/DEBIAN" % TMPDIR)
os.system("rpm -E '%_target_cpu' > packpanda-TMP.txt")
ARCH=ReadFile("packpanda-TMP.txt").strip()
os.remove("packpanda-TMP.txt")
txt = INSTALLER_SPEC_FILE[1:].replace("VERSION",VER).replace("TMPDIR",TMPDIR)
txt = txt.replace("BASENAME",BASENAME).replace("NAME",NAME).replace("PYTHONV",PYTHONV)
WriteFile("packpanda-TMP.spec", txt)
os.system("rpmbuild --define '_rpmdir "+TMPDIR+"' -bb packpanda-TMP.spec")
os.system("mv "+ARCH+"/"+BASENAME+"-"+VER+"-1."+ARCH+".rpm .")
os.rmdir(ARCH)
os.remove("packpanda-TMP.spec")
if (os.path.exists("/usr/bin/dpkg-deb")):
os.system("dpkg --print-architecture > packpanda-TMP.txt")
ARCH=ReadFile("packpanda-TMP.txt").strip()
os.remove("packpanda-TMP.txt")
txt = INSTALLER_DEB_FILE[1:].replace("VERSION",str(VER)).replace("PYTHONV",PYTHONV)
txt = txt.replace("BASENAME",BASENAME).replace("NAME",NAME).replace("ARCH",ARCH)
os.system("mkdir -p %s/DEBIAN" % TMPDIR)
os.system("cd %s ; (find usr -type f -exec md5sum {} \;) > DEBIAN/md5sums" % TMPDIR)
WriteFile(TMPDIR+"/DEBIAN/control",txt)
os.system("dpkg-deb -b "+TMPDIR+" "+BASENAME+"_"+VER+"_"+ARCH+".deb")
if not(os.path.exists("/usr/bin/rpmbuild") or os.path.exists("/usr/bin/dpkg-deb")):
exit("To build an installer, either rpmbuild or dpkg-deb must be present on your system!")

View File

@ -3450,8 +3450,8 @@ paint_window_osx_port() {
int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
size_t rowsize = _swbuffer->get_row_size();
Rect src_rect = {0, 0, y_size, x_size};
Rect ddrc_rect = {0, 0, y_size, x_size};
Rect src_rect = {0, 0, (short)y_size, (short)x_size};
Rect ddrc_rect = {0, 0, (short)y_size, (short)x_size};
QDErr err;
@ -3502,7 +3502,7 @@ paint_window_osx_cgcontext(CGContextRef context) {
int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size());
if (_buffer_image != NULL) {
CGRect region = { { 0, 0 }, { x_size, y_size } };
CGRect region = { { 0, 0 }, { (CGFloat)x_size, (CGFloat)y_size } };
CGContextDrawImage(context, region, _buffer_image);
}
}
@ -3538,7 +3538,7 @@ handle_event_osx_event_record(const P3D_event_data &event) {
// First, convert the coordinates from screen coordinates to browser
// window coordinates.
WindowRef window = handle._handle._osx_cgcontext._window;
CGPoint cgpt = { pt.h, pt.v };
CGPoint cgpt = { (CGFloat)pt.h, (CGFloat)pt.v };
HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL,
kHICoordSpaceWindow, window);

View File

@ -267,7 +267,7 @@ refresh() {
return;
}
if (_toplevel_window != NULL) {
Rect r = { 0, 0, _win_height, _win_width };
Rect r = { 0, 0, (short)_win_height, (short)_win_width };
InvalWindowRect(_toplevel_window, &r);
} else {
@ -345,7 +345,7 @@ paint_window_osx_cgcontext(CGContextRef context) {
CGColorSpaceRef rgb_space = CGColorSpaceCreateDeviceRGB();
CGColorRef bg = CGColorCreate(rgb_space, bg_components);
CGRect region = { { 0, 0 }, { _win_width, _win_height } };
CGRect region = { { 0, 0 }, { (CGFloat)_win_width, (CGFloat)_win_height } };
CGContextSetFillColorWithColor(context, bg);
CGContextFillRect(context, region);
@ -407,7 +407,7 @@ handle_event_osx_event_record(const P3D_event_data &event) {
// First, convert the coordinates from screen coordinates to browser
// window coordinates.
WindowRef window = handle._handle._osx_cgcontext._window;
CGPoint cgpt = { pt.h, pt.v };
CGPoint cgpt = { (CGFloat)pt.h, (CGFloat)pt.v };
HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL,
kHICoordSpaceWindow, window);
@ -617,7 +617,7 @@ paint_progress_bar(CGContextRef context) {
int bar_x, bar_y, bar_width, bar_height;
get_bar_placement(bar_x, bar_y, bar_width, bar_height);
CGRect bar_rect = { { bar_x, bar_y }, { bar_width, bar_height } };
CGRect bar_rect = { { (CGFloat)bar_x, (CGFloat)bar_y }, { (CGFloat)bar_width, (CGFloat)bar_height } };
// Clear the entire progress bar to white (or the background color).
CGContextSetFillColorWithColor(context, bar_bg);
@ -627,7 +627,7 @@ paint_progress_bar(CGContextRef context) {
if (_progress_known) {
int progress_width = (int)(bar_width * _install_progress + 0.5);
if (progress_width != 0) {
CGRect prog = { { bar_x, bar_y }, { progress_width, bar_height } };
CGRect prog = { { (CGFloat)bar_x, (CGFloat)bar_y }, { (CGFloat)progress_width, (CGFloat)bar_height } };
CGContextSetFillColorWithColor(context, bar);
CGContextFillRect(context, prog);
}
@ -642,7 +642,7 @@ paint_progress_bar(CGContextRef context) {
progress = block_travel * 2 - progress;
}
CGRect prog = { { bar_x + progress, bar_y }, { block_width, bar_height } };
CGRect prog = { { (CGFloat)(bar_x + progress), (CGFloat)bar_y }, { (CGFloat)block_width, (CGFloat)bar_height } };
CGContextSetFillColorWithColor(context, bar);
CGContextFillRect(context, prog);
}
@ -652,8 +652,8 @@ paint_progress_bar(CGContextRef context) {
// We offset the border by half a pixel, so we'll be drawing the one-pixel
// line through the middle of a pixel, and it won't try to antialias
// itself into a half-black two-pixel line.
CGRect border_rect = { { bar_x - 0.5, bar_y - 0.5 },
{ bar_width + 1, bar_height + 1 } };
CGRect border_rect = { { (CGFloat)(bar_x - 0.5), (CGFloat)(bar_y - 0.5) },
{ (CGFloat)(bar_width + 1), (CGFloat)(bar_height + 1) } };
CGContextBeginPath(context);
CGContextSetLineWidth(context, 1);

View File

@ -38,7 +38,6 @@ import os
import sys
import random
import time
import importlib
__report_indent = 3
@ -61,6 +60,42 @@ def Functor(function, *args, **kArgs):
return functor
"""
try:
import importlib
except ImportError:
# Backward compatibility for Python 2.6.
def _resolve_name(name, package, level):
if not hasattr(package, 'rindex'):
raise ValueError("'package' not set to a string")
dot = len(package)
for x in xrange(level, 1, -1):
try:
dot = package.rindex('.', 0, dot)
except ValueError:
raise ValueError("attempted relative import beyond top-level "
"package")
return "%s.%s" % (package[:dot], name)
def import_module(name, package=None):
if name.startswith('.'):
if not package:
raise TypeError("relative imports require the 'package' argument")
level = 0
for character in name:
if character != '.':
break
level += 1
name = _resolve_name(name[level:], package, level)
__import__(name)
return sys.modules[name]
imp = import_module('imp')
importlib = imp.new_module("importlib")
importlib._resolve_name = _resolve_name
importlib.import_module = import_module
sys.modules['importlib'] = importlib
class Functor:
def __init__(self, function, *args, **kargs):
assert callable(function), "function should be a callable obj"

View File

@ -2,6 +2,7 @@
This issue fixes several bugs that were still found in 1.9.2.
* Fix crash when using homebrew Python on Mac OS X
* Fix crash when running in Steam on Linux when using OpenAL
* Fix crash using wx/tkinter on Mac as long as want-wx/tk is set
* Fix loading models from 'models' package with models/ prefix
@ -48,6 +49,12 @@ This issue fixes several bugs that were still found in 1.9.2.
* Fix exception when trying to pickle NodePathCollection objects
* Fix error when trying to raise vectors to a power
* GLSL: fix error when legacy matrix generator inputs are mat3
* Now tries to preserve refresh rate when switching fullscreen on Windows
* Fix back-to-front sorting when gl-coordinate-system is changed
* Now also compiles on older Linux distros (eg. CentOS 5 / manylinux1)
* get_keyboard_map now includes keys on layouts with special characters
* Fix crash due to incorrect alignment when compiling Eigen with AVX
* Fix crash when writing 16-bit .tif file (now silently downsamples)
------------------------ RELEASE 1.9.2 ------------------------

View File

@ -326,14 +326,17 @@ as_function_type() {
* This is similar to is_equal(), except it is more forgiving: it considers
* the functions to be equivalent only if the return type and the types of all
* parameters match.
*
* Note that this isn't symmetric to account for covariant return types.
*/
bool CPPFunctionType::
is_equivalent_function(const CPPFunctionType &other) const {
if (!_return_type->is_equivalent(*other._return_type)) {
match_virtual_override(const CPPFunctionType &other) const {
if (!_return_type->is_equivalent(*other._return_type) &&
!_return_type->is_convertible_to(other._return_type)) {
return false;
}
if (_flags != other._flags) {
if (((_flags ^ other._flags) & ~(F_override | F_final)) != 0) {
return false;
}

View File

@ -84,7 +84,7 @@ public:
virtual CPPFunctionType *as_function_type();
bool is_equivalent_function(const CPPFunctionType &other) const;
bool match_virtual_override(const CPPFunctionType &other) const;
CPPIdentifier *_class_owner;

View File

@ -809,6 +809,8 @@ expand_manifests(const string &input_expr, bool expand_undefined,
// Here's an identifier. Is it "defined"?
if (ident == "defined") {
expand_defined_function(expr, q, p);
} else if (expand_undefined && ident == "__has_include") {
expand_has_include_function(expr, q, p, loc);
} else {
// Is it a manifest?
Manifests::const_iterator mi = _manifests.find(ident);
@ -817,6 +819,20 @@ expand_manifests(const string &input_expr, bool expand_undefined,
expand_manifest_inline(expr, q, p, manifest);
manifest_found = true;
} else if (ident == "__FILE__") {
// Special case: this is a dynamic definition.
string file = string("\"") + loc.file._filename_as_referenced.get_fullpath() + "\"";
expr = expr.substr(0, q) + file + expr.substr(p);
p = q + file.size();
manifest_found = true;
} else if (ident == "__LINE__") {
// So is this.
string line = format_string(loc.first_line);
expr = expr.substr(0, q) + line + expr.substr(p);
p = q + line.size();
manifest_found = true;
} else if (expand_undefined && ident != "true" && ident != "false") {
// It is not found. Expand it to 0, but only if we are currently
// parsing an #if expression.
@ -1461,7 +1477,6 @@ handle_define_directive(const string &args, const YYLTYPE &loc) {
CPPManifest *other = result.first->second;
warning("redefinition of macro '" + manifest->_name + "'", loc);
warning("previous definition is here", other->_loc);
delete other;
result.first->second = manifest;
}
}
@ -1487,14 +1502,10 @@ handle_undef_directive(const string &args, const YYLTYPE &loc) {
*/
void CPPPreprocessor::
handle_ifdef_directive(const string &args, const YYLTYPE &loc) {
Manifests::const_iterator mi = _manifests.find(args);
if (mi != _manifests.end()) {
// The macro is defined. We continue.
return;
if (!is_manifest_defined(args)) {
// The macro is undefined. Skip stuff.
skip_false_if_block(true);
}
// The macro is undefined. Skip stuff.
skip_false_if_block(true);
}
/**
@ -1502,17 +1513,12 @@ handle_ifdef_directive(const string &args, const YYLTYPE &loc) {
*/
void CPPPreprocessor::
handle_ifndef_directive(const string &args, const YYLTYPE &loc) {
Manifests::const_iterator mi = _manifests.find(args);
if (mi == _manifests.end()) {
// The macro is undefined. We continue.
return;
if (is_manifest_defined(args)) {
// The macro is defined. Skip stuff.
skip_false_if_block(true);
}
// The macro is defined. Skip stuff.
skip_false_if_block(true);
}
/**
*
*/
@ -1594,6 +1600,8 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
_angle_includes.insert(filename);
}
}
} else {
warning("Ignoring invalid #include directive", loc);
}
filename.set_text();
@ -1601,71 +1609,30 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
// Now look for the filename. If we didn't use angle quotes, look first in
// the current directory.
bool found_file = false;
CPPFile::Source source = CPPFile::S_none;
if (okflag) {
found_file = false;
if (find_include(filename, angle_quotes, source)) {
_last_c = '\0';
// Search the current directory.
if (!angle_quotes && !found_file && filename.exists()) {
found_file = true;
// If it was explicitly named on the command-line, mark it S_local.
filename.make_canonical();
if (_explicit_files.count(filename)) {
source = CPPFile::S_local;
}
// Search the same directory as the includer.
if (!angle_quotes && !found_file) {
Filename match(get_file()._filename.get_dirname(), filename);
if (match.exists()) {
filename = match;
found_file = true;
source = CPPFile::S_alternate;
}
CPPFile file(filename, filename_as_referenced, source);
// Don't include it if we included it before and it had #pragma once.
ParsedFiles::const_iterator it = _parsed_files.find(file);
if (it != _parsed_files.end() && it->_pragma_once) {
return;
}
// Now search the angle-include-path
if (angle_quotes && !found_file && filename.resolve_filename(_angle_include_path)) {
found_file = true;
source = CPPFile::S_system;
}
// Now search the quote-include-path
if (!angle_quotes && !found_file) {
for (size_t dir=0; dir<_quote_include_path.get_num_directories(); dir++) {
Filename match(_quote_include_path.get_directory(dir), filename);
if (match.exists()) {
filename = match;
found_file = true;
source = _quote_include_kind[dir];
}
}
}
if (!found_file) {
warning("Cannot find " + filename.get_fullpath(), loc);
} else {
_last_c = '\0';
// If it was explicitly named on the command-line, mark it S_local.
filename.make_canonical();
if (_explicit_files.count(filename)) {
source = CPPFile::S_local;
}
CPPFile file(filename, filename_as_referenced, source);
// Don't include it if we included it before and it had #pragma once.
ParsedFiles::const_iterator it = _parsed_files.find(file);
if (it != _parsed_files.end() && it->_pragma_once) {
return;
}
if (!push_file(file)) {
warning("Unable to read " + filename.get_fullpath(), loc);
}
if (!push_file(file)) {
warning("Unable to read " + filename.get_fullpath(), loc);
}
} else {
warning("Ignoring invalid #include directive", loc);
warning("Cannot find " + filename.get_fullpath(), loc);
}
}
@ -1679,6 +1646,38 @@ handle_pragma_directive(const string &args, const YYLTYPE &loc) {
assert(it != _parsed_files.end());
it->_pragma_once = true;
}
char macro[64];
if (sscanf(args.c_str(), "push_macro ( \"%63[^\"]\" )", macro) == 1) {
// We just mark it as pushed for now, so that the next time someone tries
// to override it, we save the old value.
Manifests::iterator mi = _manifests.find(macro);
if (mi != _manifests.end()) {
_manifest_stack[macro].push_back(mi->second);
} else {
_manifest_stack[macro].push_back(NULL);
}
} else if (sscanf(args.c_str(), "pop_macro ( \"%63[^\"]\" )", macro) == 1) {
ManifestStack &stack = _manifest_stack[macro];
if (stack.size() > 0) {
CPPManifest *manifest = stack.back();
stack.pop_back();
Manifests::iterator mi = _manifests.find(macro);
if (manifest == NULL) {
// It was undefined when it was pushed, so make it undefined again.
if (mi != _manifests.end()) {
_manifests.erase(mi);
}
} else if (mi != _manifests.end()) {
mi->second = manifest;
} else {
_manifests.insert(Manifests::value_type(macro, manifest));
}
} else {
warning("pop_macro without matching push_macro", loc);
}
}
}
/**
@ -1748,6 +1747,69 @@ skip_false_if_block(bool consider_elifs) {
_save_comments = true;
}
/**
* Returns true if the given manifest is defined.
*/
bool CPPPreprocessor::
is_manifest_defined(const string &manifest_name) {
Manifests::const_iterator mi = _manifests.find(manifest_name);
if (mi != _manifests.end()) {
return true;
}
if (manifest_name == "__has_include" ||
manifest_name == "__FILE__" ||
manifest_name == "__LINE__") {
// Special built-in directives that are considered "defined".
return true;
}
return false;
}
/**
* Locates the given filename. Changes the first argument to the full path.
*/
bool CPPPreprocessor::
find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source) {
// Now look for the filename. If we didn't use angle quotes, look first in
// the current directory.
if (!angle_quotes && filename.exists()) {
source = CPPFile::S_local;
return true;
}
// Search the same directory as the includer.
if (!angle_quotes) {
Filename match(get_file()._filename.get_dirname(), filename);
if (match.exists()) {
filename = match;
source = CPPFile::S_alternate;
return true;
}
}
// Now search the angle-include-path
if (angle_quotes && filename.resolve_filename(_angle_include_path)) {
source = CPPFile::S_system;
return true;
}
// Now search the quote-include-path
if (!angle_quotes) {
for (size_t dir = 0; dir < _quote_include_path.get_num_directories(); ++dir) {
Filename match(_quote_include_path.get_directory(dir), filename);
if (match.exists()) {
filename = match;
source = _quote_include_kind[dir];
return true;
}
}
}
return false;
}
/**
*
*/
@ -1854,6 +1916,14 @@ get_identifier(int c) {
if (mi != _manifests.end() && !should_ignore_manifest((*mi).second)) {
return expand_manifest((*mi).second);
}
if (name == "__FILE__") {
return get_literal(SIMPLE_STRING, loc, loc.file._filename_as_referenced);
}
if (name == "__LINE__") {
YYSTYPE result;
result.u.integer = loc.first_line;
return CPPToken(INTEGER, loc, "", result);
}
// Check for keywords.
int kw = check_keyword(name);
@ -2196,9 +2266,7 @@ expand_defined_function(string &expr, size_t q, size_t &p) {
vector_string args;
extract_manifest_args_inline("defined", 1, -1, args, expr, p);
if (args.size() >= 1) {
const string &manifest_name = args[0];
Manifests::const_iterator mi = _manifests.find(manifest_name);
if (mi != _manifests.end()) {
if (is_manifest_defined(args[0])) {
// The macro is defined; the result is "1".
result = "1";
} else {
@ -2211,6 +2279,70 @@ expand_defined_function(string &expr, size_t q, size_t &p) {
p = q + result.size();
}
/**
* Expands the __has_include(manifest) function to either 1 or 0, depending on
* whether the include file exists.
*/
void CPPPreprocessor::
expand_has_include_function(string &expr, size_t q, size_t &p, YYLTYPE loc) {
bool found_file = false;
// Skip whitespace till paren.
while (p < expr.size() && isspace(expr[p])) {
p++;
}
size_t args_begin = p + 1;
vector_string args;
extract_manifest_args_inline("__has_include", 1, -1, args, expr, p);
if (!args.empty() && args[0].size() >= 2) {
Filename filename;
bool angle_quotes = false;
string inc = args[0];
// Just to play things safe, since our manifest-expansion logic might not
// filter out quotes and angle brackets properly, we'll only expand
// manifests if we don't begin with a quote or bracket.
if (!inc.empty() && (inc[0] != '"' && inc[0] != '<')) {
inc = expand_manifests(inc, false, loc);
}
if (inc[0] == '"' && inc[inc.size() - 1] == '"') {
filename = inc.substr(1, inc.size() - 2);
} else if (inc[0] == '<' && inc[inc.size() - 1] == '>') {
filename = inc.substr(1, inc.size() - 2);
if (!_noangles) {
// If _noangles is true, we don't make a distinction between angle
// brackets and quote marks--all #inc statements are treated the
// same, as if they used quote marks.
angle_quotes = true;
}
} else {
loc.last_column += loc.first_column + p - 2;
loc.first_column += args_begin;
warning("invalid argument for __has_include() directive", loc);
expr = expr.substr(0, q) + "0" + expr.substr(p);
p = q + 1;
return;
}
filename.set_text();
CPPFile::Source source = CPPFile::S_none;
found_file = find_include(filename, angle_quotes, source);
} else {
loc.last_column += loc.first_column + p - 2;
loc.first_column += args_begin;
warning("invalid argument for __has_include() directive", loc);
}
string result = found_file ? "1" : "0";
expr = expr.substr(0, q) + result + expr.substr(p);
p = q + result.size();
}
/**
*
*/

View File

@ -72,6 +72,9 @@ public:
typedef map<string, CPPManifest *> Manifests;
Manifests _manifests;
typedef pvector<CPPManifest *> ManifestStack;
map<string, ManifestStack> _manifest_stack;
pvector<CPPFile::Source> _quote_include_kind;
DSearchPath _quote_include_path;
DSearchPath _angle_include_path;
@ -140,6 +143,8 @@ private:
void handle_error_directive(const string &args, const YYLTYPE &loc);
void skip_false_if_block(bool consider_elifs);
bool is_manifest_defined(const string &manifest_name);
bool find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source);
CPPToken get_quoted_char(int c);
CPPToken get_quoted_string(int c);
@ -150,6 +155,7 @@ private:
void extract_manifest_args(const string &name, int num_args,
int va_arg, vector_string &args);
void expand_defined_function(string &expr, size_t q, size_t &p);
void expand_has_include_function(string &expr, size_t q, size_t &p, YYLTYPE loc);
void expand_manifest_inline(string &expr, size_t q, size_t &p,
const CPPManifest *manifest);
void extract_manifest_args_inline(const string &name, int num_args,

View File

@ -378,6 +378,10 @@ is_constructible(const CPPType *given_type) const {
}
}
if (is_abstract()) {
return false;
}
// Check for a different constructor.
CPPFunctionGroup *fgroup = get_constructor();
if (fgroup != (CPPFunctionGroup *)NULL) {
@ -444,6 +448,10 @@ is_destructible() const {
*/
bool CPPStructType::
is_default_constructible(CPPVisibility min_vis) const {
if (is_abstract()) {
return false;
}
CPPInstance *constructor = get_default_constructor();
if (constructor != (CPPInstance *)NULL) {
// It has a default constructor.
@ -498,24 +506,6 @@ is_default_constructible(CPPVisibility min_vis) const {
}
}
// Check that we don't have pure virtual methods.
CPPScope::Functions::const_iterator fi;
for (fi = _scope->_functions.begin();
fi != _scope->_functions.end();
++fi) {
CPPFunctionGroup *fgroup = (*fi).second;
CPPFunctionGroup::Instances::const_iterator ii;
for (ii = fgroup->_instances.begin();
ii != fgroup->_instances.end();
++ii) {
CPPInstance *inst = (*ii);
if (inst->_storage_class & CPPInstance::SC_pure_virtual) {
// Here's a pure virtual function.
return false;
}
}
}
return true;
}
@ -524,6 +514,10 @@ is_default_constructible(CPPVisibility min_vis) const {
*/
bool CPPStructType::
is_copy_constructible(CPPVisibility min_vis) const {
if (is_abstract()) {
return false;
}
CPPInstance *constructor = get_copy_constructor();
if (constructor != (CPPInstance *)NULL) {
// It has a copy constructor.
@ -581,24 +575,6 @@ is_copy_constructible(CPPVisibility min_vis) const {
}
}
// Check that we don't have pure virtual methods.
CPPScope::Functions::const_iterator fi;
for (fi = _scope->_functions.begin();
fi != _scope->_functions.end();
++fi) {
CPPFunctionGroup *fgroup = (*fi).second;
CPPFunctionGroup::Instances::const_iterator ii;
for (ii = fgroup->_instances.begin();
ii != fgroup->_instances.end();
++ii) {
CPPInstance *inst = (*ii);
if (inst->_storage_class & CPPInstance::SC_pure_virtual) {
// Here's a pure virtual function.
return false;
}
}
}
return true;
}
@ -620,6 +596,10 @@ is_move_constructible(CPPVisibility min_vis) const {
return false;
}
if (is_abstract()) {
return false;
}
return true;
}
@ -1214,7 +1194,7 @@ get_virtual_funcs(VFunctions &funcs) const {
CPPFunctionType *new_ftype = new_inst->_type->as_function_type();
assert(new_ftype != (CPPFunctionType *)NULL);
if (new_ftype->is_equivalent_function(*base_ftype)) {
if (new_ftype->match_virtual_override(*base_ftype)) {
// It's a match! We now know it's virtual. Erase this function
// from the list, so we can add it back in below.
funcs.erase(vfi);

View File

@ -39,7 +39,7 @@ allocate(size_t size, TypeHandle type_handle) {
assert(size <= _buffer_size);
// Determine how much space to allocate.
const size_t alloc_size = _buffer_size + flag_reserved_bytes;
const size_t alloc_size = _buffer_size + flag_reserved_bytes + MemoryHook::get_memory_alignment() - 1;
ObjectNode *obj;
@ -69,7 +69,10 @@ allocate(size_t size, TypeHandle type_handle) {
// If we get here, the deleted_chain is empty; we have to allocate a new
// object from the system pool.
obj = (ObjectNode *)NeverFreeMemory::alloc(alloc_size);
// Allocate memory, and make sure the object starts at the proper alignment.
void *mem = NeverFreeMemory::alloc(alloc_size);
intptr_t pad = (-(intptr_t)flag_reserved_bytes - (intptr_t)mem) % MemoryHook::get_memory_alignment();
obj = (ObjectNode *)((uintptr_t)mem + pad);
#ifdef USE_DELETEDCHAINFLAG
obj->_flag = DCF_alive;
@ -77,6 +80,10 @@ allocate(size_t size, TypeHandle type_handle) {
void *ptr = node_to_buffer(obj);
#ifndef NDEBUG
assert(((uintptr_t)ptr % MemoryHook::get_memory_alignment()) == 0);
#endif
#ifdef DO_MEMORY_USAGE
type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
#endif // DO_MEMORY_USAGE

View File

@ -95,12 +95,8 @@ private:
// Without DELETEDCHAINFLAG, we don't even store the _flag member at all.
static const size_t flag_reserved_bytes = 0;
#elif defined(LINMATH_ALIGN)
// With SSE2 alignment, we need all 16 bytes to preserve alignment.
static const size_t flag_reserved_bytes = 16;
#else
// Otherwise, we only need enough space for the Integer itself.
// Otherwise, we need space for the integer.
static const size_t flag_reserved_bytes = sizeof(AtomicAdjust::Integer);
#endif // USE_DELETEDCHAINFLAG

View File

@ -587,8 +587,11 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP
#define MAX_SIZE_T (~(size_t)0)
#ifndef USE_LOCKS /* ensure true if spin or recursive locks set */
#define USE_LOCKS ((defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || \
(defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0))
#if (defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0)
#define USE_LOCKS 1
#else
#define USE_LOCKS 0
#endif
#endif /* USE_LOCKS */
#if USE_LOCKS /* Spin locks for gcc >= 4.1, older gcc on x86, MSC >= 1310 */
@ -647,7 +650,9 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP
#ifndef HAVE_MREMAP
#ifdef linux
#define HAVE_MREMAP 1
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* Turns on mremap() definition */
#endif
#else /* linux */
#define HAVE_MREMAP 0
#endif /* linux */

View File

@ -339,21 +339,26 @@ typedef struct _object PyObject;
#define ALIGN_4BYTE
#define ALIGN_8BYTE
#define ALIGN_16BYTE
#define ALIGN_32BYTE
#define ALIGN_64BYTE
#elif defined(_MSC_VER)
#define ALIGN_4BYTE __declspec(align(4))
#define ALIGN_8BYTE __declspec(align(8))
#define ALIGN_16BYTE __declspec(align(16))
#define ALIGN_32BYTE __declspec(align(32))
#define ALIGN_64BYTE __declspec(align(64))
#elif defined(__GNUC__)
#define ALIGN_4BYTE __attribute__ ((aligned (4)))
#define ALIGN_8BYTE __attribute__ ((aligned (8)))
#define ALIGN_16BYTE __attribute__ ((aligned (16)))
#define ALIGN_32BYTE __attribute__ ((aligned (32)))
#define ALIGN_64BYTE __attribute__ ((aligned (64)))
#else
#define ALIGN_4BYTE
#define ALIGN_8BYTE
#define ALIGN_16BYTE
#define ALIGN_32BYTE
#define ALIGN_64BYTE
#endif
// Do we need to implement memory-alignment enforcement within the MemoryHook
@ -374,7 +379,7 @@ typedef struct _object PyObject;
// externally.
#define MEMORY_HOOK_DO_ALIGN 1
#elif defined(IS_OSX) || defined(_WIN64)
#elif (defined(IS_OSX) || defined(_WIN64)) && !defined(__AVX__)
// The OS-provided malloc implementation will do the required alignment.
#undef MEMORY_HOOK_DO_ALIGN

View File

@ -75,6 +75,7 @@ typedef int ios_seekdir;
#endif
#include <string>
#include <utility>
#ifdef HAVE_NAMESPACE
using namespace std;
@ -114,6 +115,20 @@ typedef ios::iostate ios_iostate;
typedef ios::seekdir ios_seekdir;
#endif
// Apple has an outdated libstdc++. Not all is lost, though, as we can fill
// in some important missing functions.
#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20070719
typedef decltype(nullptr) nullptr_t;
template<class T> struct remove_reference {typedef T type;};
template<class T> struct remove_reference<T&> {typedef T type;};
template<class T> struct remove_reference<T&& >{typedef T type;};
template<class T> typename remove_reference<T>::type &&move(T &&t) {
return static_cast<typename remove_reference<T>::type&&>(t);
}
#endif
#ifdef _MSC_VER
#define ALWAYS_INLINE __forceinline
#elif defined(__GNUC__)
@ -134,7 +149,9 @@ typedef ios::seekdir ios_seekdir;
// Determine the availability of C++11 features.
#if defined(__has_extension) // Clang magic.
# if __has_extension(cxx_constexpr)
# define CONSTEXPR constexpr
# if !defined(__apple_build_version__) || __apple_build_version__ >= 5000000
# define CONSTEXPR constexpr
# endif
# endif
# if __has_extension(cxx_noexcept)
# define NOEXCEPT noexcept
@ -153,7 +170,7 @@ typedef ios::seekdir ios_seekdir;
#elif defined(__GNUC__) && (__cplusplus >= 201103L) // GCC
// GCC defines several macros which we can query. List of all supported
// builtin macros: https:gcc.gnu.orgprojectscxx0x.html
// builtin macros: https://gcc.gnu.org/projects/cxx-status.html
# if __cpp_constexpr >= 200704
# define CONSTEXPR constexpr
# endif

View File

@ -43,10 +43,16 @@ get_memory_alignment() {
#ifdef LINMATH_ALIGN
// We require 16-byte alignment of certain structures, to support SSE2. We
// don't strictly have to align *everything*, but it's just easier to do so.
const size_t alignment_size = 16;
#ifdef __AVX__
// Eigen requires 32-byte alignment when using AVX instructions.
const size_t alignment_size = 32;
#else
// Otherwise, use word alignment.
const size_t alignment_size = sizeof(void *);
const size_t alignment_size = 16;
#endif
#else
// Otherwise, align to two words. This seems to be pretty standard to the
// point where some code may rely on this being the case.
const size_t alignment_size = sizeof(void *) * 2;
#endif
return alignment_size;
}
@ -64,7 +70,12 @@ get_header_reserved_bytes() {
#ifdef LINMATH_ALIGN
// If we're doing SSE2 alignment, we must reserve a full 16-byte block,
// since anything less than that will spoil the alignment.
#ifdef __AVX__
// Eigen requires 32-byte alignment when using AVX instructions.
static const size_t header_reserved_bytes = 32;
#else
static const size_t header_reserved_bytes = 16;
#endif
#elif defined(MEMORY_HOOK_DO_ALIGN)
// If we're just aligning to words, we reserve a block as big as two words,
@ -72,8 +83,9 @@ get_header_reserved_bytes() {
static const size_t header_reserved_bytes = sizeof(size_t) + sizeof(size_t);
#else
// If we're not aligning, we just need space for the word itself.
static const size_t header_reserved_bytes = sizeof(size_t);
// Virtually all allocators align to two words, so we make sure we preserve
// that alignment for the benefit of anyone who relies upon that.
static const size_t header_reserved_bytes = sizeof(void *) * 2;
#endif
return header_reserved_bytes;

View File

@ -53,8 +53,13 @@
// drose: We require 16-byte alignment of certain structures, to
// support SSE2. We don't strictly have to align *everything*, but
// it's just easier to do so.
#ifdef __AVX__
// Eigen requires 32-byte alignment when using AVX instructions.
#define MALLOC_ALIGNMENT ((size_t)32U)
#else
#define MALLOC_ALIGNMENT ((size_t)16U)
#endif
#endif
#include "dlmalloc_src.cxx"

View File

@ -14,6 +14,8 @@
/**
* Returns a pointer to a newly-allocated block of memory of the indicated
* size.
*
* Please note that the resulting pointer is not aligned to any boundary.
*/
INLINE void *NeverFreeMemory::
alloc(size_t size) {

View File

@ -39,13 +39,9 @@ void *NeverFreeMemory::
ns_alloc(size_t size) {
_lock.acquire();
// We always allocate integer multiples of this many bytes, to guarantee
// this minimum alignment.
static const size_t alignment_size = MemoryHook::get_memory_alignment();
// Round up to the next alignment_size.
size = ((size + alignment_size - 1) / alignment_size) * alignment_size;
//NB: we no longer do alignment here. The only class that uses this is
// DeletedBufferChain, and we can do the alignment potentially more
// efficiently there since we don't end up overallocating as much.
_total_used += size;
// Look for a page that has sufficient space remaining.

View File

@ -38,7 +38,6 @@ Filename(const char *filename) {
(*this) = filename;
}
/**
*
*/
@ -84,6 +83,20 @@ Filename(Filename &&from) NOEXCEPT :
}
#endif // USE_MOVE_SEMANTICS
/**
* Creates an empty Filename.
*/
INLINE Filename::
Filename() :
_dirname_end(0),
_basename_start(0),
_basename_end(string::npos),
_extension_start(string::npos),
_hash_start(string::npos),
_hash_end(string::npos),
_flags(0) {
}
/**
*
*/
@ -155,14 +168,6 @@ pattern_filename(const string &filename) {
return result;
}
/**
*
*/
INLINE Filename::
~Filename() {
}
/**
*
*/
@ -233,7 +238,7 @@ operator = (string &&filename) NOEXCEPT {
*/
INLINE Filename &Filename::
operator = (Filename &&from) NOEXCEPT {
_filename = MOVE(from._filename);
_filename = move(from._filename);
_dirname_end = from._dirname_end;
_basename_start = from._basename_start;
_basename_end = from._basename_end;

View File

@ -55,20 +55,22 @@ public:
};
INLINE Filename(const char *filename);
PUBLISHED:
INLINE Filename(const string &filename = "");
INLINE Filename(const string &filename);
INLINE Filename(const wstring &filename);
INLINE Filename(const Filename &copy);
Filename(const Filename &dirname, const Filename &basename);
INLINE ~Filename();
#ifdef USE_MOVE_SEMANTICS
INLINE Filename(string &&filename) NOEXCEPT;
INLINE Filename(Filename &&from) NOEXCEPT;
#endif
PUBLISHED:
INLINE Filename();
Filename(const Filename &dirname, const Filename &basename);
#ifdef HAVE_PYTHON
EXTENSION(Filename(PyObject *path));
EXTENSION(PyObject *__reduce__(PyObject *self) const);
#endif
@ -118,6 +120,7 @@ PUBLISHED:
INLINE char operator [] (size_t n) const;
EXTENSION(PyObject *__repr__() const);
EXTENSION(PyObject *__fspath__() const);
INLINE string substr(size_t begin) const;
INLINE string substr(size_t begin, size_t end) const;

View File

@ -6142,7 +6142,7 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
write_python_instance(out, indent_level, return_expr, owns_memory, itype, is_const);
}
} else if (TypeManager::is_struct(orig_type->as_pointer_type()->_pointing_at)) {
} else if (TypeManager::is_struct(orig_type->remove_pointer())) {
TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false);
const InterrogateType &itype = idb->get_type(type_index);
@ -6198,7 +6198,7 @@ write_make_seq(ostream &out, Object *obj, const std::string &ClassName,
// the assumption that the called method doesn't do anything with this
// tuple other than unpack it (which is a fairly safe assumption to make).
out << " PyTupleObject args;\n";
out << " PyObject_INIT_VAR(&args, &PyTuple_Type, 1);\n";
out << " (void)PyObject_INIT_VAR(&args, &PyTuple_Type, 1);\n";
}
out <<
@ -6749,6 +6749,8 @@ is_cpp_type_legal(CPPType *in_ctype) {
return true;
} else if (TypeManager::is_pointer_to_simple(type)) {
return true;
} else if (builder.in_forcetype(type->get_local_name(&parser))) {
return true;
} else if (TypeManager::is_exported(type)) {
return true;
} else if (TypeManager::is_pointer_to_PyObject(in_ctype)) {

View File

@ -19,6 +19,7 @@
#include "pnotify.h"
#include "panda_getopt_long.h"
#include "preprocess_argv.h"
#include "pystub.h"
#include <time.h>
CPPParser parser;
@ -305,6 +306,8 @@ predefine_macro(CPPParser& parser, const string& inoption) {
int
main(int argc, char **argv) {
pystub();
preprocess_argv(argc, argv);
string command_line;
int i;

View File

@ -19,6 +19,7 @@
#include "interrogate_interface.h"
#include "interrogate_request.h"
#include "load_dso.h"
#include "pystub.h"
#include "pnotify.h"
#include "panda_getopt_long.h"
#include "preprocess_argv.h"
@ -379,6 +380,8 @@ int main(int argc, char *argv[]) {
extern int optind;
int flag;
pystub();
preprocess_argv(argc, argv);
flag = getopt_long_only(argc, argv, short_options, long_options, NULL);
while (flag != EOF) {

View File

@ -22,6 +22,7 @@
#include "cppGlobals.h"
#include "panda_getopt_long.h"
#include "preprocess_argv.h"
#include "pystub.h"
#include <stdlib.h>
CPPParser parser;
@ -193,6 +194,8 @@ show_nested_types(const string &str) {
int
main(int argc, char **argv) {
pystub();
extern char *optarg;
extern int optind;
const char *optstr = "I:S:D:o:l:vp";

View File

@ -0,0 +1,4 @@
#pragma once
#include <inttypes.h>
#include <netinet/in.h>

View File

@ -1,6 +1,74 @@
#pragma once
#include <stdtypedefs.h>
#include <string>
namespace std {
template<class Iterator> class iterator;
template<class Iterator> class reverse_iterator;
// Iterator tags
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
// Iterator traits
template<class Iterator> struct iterator_traits {
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
typedef typename Iterator::iterator_category iterator_category;
};
template<class T> struct iterator_traits<T*> {
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef T *pointer;
typedef T &reference;
typedef random_access_iterator_tag iterator_category;
};
template<class T> struct iterator_traits<const T*> {
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef const T *pointer;
typedef const T &reference;
typedef random_access_iterator_tag iterator_category;
};
// Iterators
template<class Category, class T, class Distance = ptrdiff_t,
class Pointer = T*, class Reference = T&> struct iterator {
typedef T value_type;
typedef Distance difference_type;
typedef Pointer pointer;
typedef Reference reference;
typedef Category iterator_category;
};
template<class Iterator>
class reverse_iterator : public
iterator<typename iterator_traits<Iterator>::iterator_category,
typename iterator_traits<Iterator>::value_type,
typename iterator_traits<Iterator>::difference_type,
typename iterator_traits<Iterator>::pointer,
typename iterator_traits<Iterator>::reference> {
public:
typedef Iterator iterator_type;
typedef typename iterator_traits<Iterator>::difference_type difference_type;
typedef typename iterator_traits<Iterator>::reference reference;
typedef typename iterator_traits<Iterator>::pointer pointer;
};
template<class T, class charT = char, class traits = char_traits<charT>,
class Distance = ptrdiff_t>
class istream_iterator;
template<class T, class charT = char, class traits = char_traits<charT>>
class ostream_iterator;
template<class charT, class traits = char_traits<charT>>
class istreambuf_iterator;
template <class charT, class traits = char_traits<charT>>
class ostreambuf_iterator;
};

View File

@ -122,7 +122,7 @@ namespace std {
struct is_always_equal;
template <class T> using rebind_alloc = size_t;
template <class T> using rebind_traits = allocator_traits<rebind_alloc<T> >;
//template <class T> using rebind_traits = allocator_traits<rebind_alloc<T> >;
};
template <class T> class allocator;

View File

@ -0,0 +1,9 @@
#pragma once
#include <inttypes.h>
#include <netinet/in.h>
struct hostent;
struct netent;
struct protoent;
struct servent;

View File

@ -73,8 +73,8 @@ EncryptStreamBuf() {
_key_length = encryption_key_length;
_iteration_count = encryption_iteration_count;
_read_valid = false;
_write_valid = false;
_read_ctx = NULL;
_write_ctx = NULL;
_read_overflow_buffer = NULL;
_in_read_overflow_buffer = 0;
@ -110,7 +110,11 @@ open_read(istream *source, bool owns_source, const string &password) {
_source = source;
_owns_source = owns_source;
_read_valid = false;
if (_read_ctx != NULL) {
EVP_CIPHER_CTX_free(_read_ctx);
_read_ctx = NULL;
}
// Now read the header information.
StreamReader sr(_source, false);
@ -143,17 +147,21 @@ open_read(istream *source, bool owns_source, const string &password) {
string iv = sr.extract_bytes(iv_length);
_read_ctx = EVP_CIPHER_CTX_new();
nassertv(_read_ctx != NULL);
// Initialize the context
int result;
result = EVP_DecryptInit(&_read_ctx, cipher, NULL, (unsigned char *)iv.data());
result = EVP_DecryptInit(_read_ctx, cipher, NULL, (unsigned char *)iv.data());
nassertv(result > 0);
result = EVP_CIPHER_CTX_set_key_length(&_read_ctx, key_length);
result = EVP_CIPHER_CTX_set_key_length(_read_ctx, key_length);
if (result <= 0) {
prc_cat.error()
<< "Invalid key length " << key_length * 8 << " bits for algorithm "
<< OBJ_nid2sn(nid) << "\n";
EVP_CIPHER_CTX_cleanup(&_read_ctx);
EVP_CIPHER_CTX_free(_read_ctx);
_read_ctx = NULL;
return;
}
@ -167,11 +175,9 @@ open_read(istream *source, bool owns_source, const string &password) {
nassertv(result > 0);
// Store the key within the context.
result = EVP_DecryptInit(&_read_ctx, NULL, key, NULL);
result = EVP_DecryptInit(_read_ctx, NULL, key, NULL);
nassertv(result > 0);
_read_valid = true;
_read_overflow_buffer = new unsigned char[_read_block_size];
_in_read_overflow_buffer = 0;
thread_consider_yield();
@ -182,9 +188,9 @@ open_read(istream *source, bool owns_source, const string &password) {
*/
void EncryptStreamBuf::
close_read() {
if (_read_valid) {
EVP_CIPHER_CTX_cleanup(&_read_ctx);
_read_valid = false;
if (_read_ctx != NULL) {
EVP_CIPHER_CTX_free(_read_ctx);
_read_ctx = NULL;
}
if (_read_overflow_buffer != (unsigned char *)NULL) {
@ -211,7 +217,6 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
close_write();
_dest = dest;
_owns_dest = owns_dest;
_write_valid = false;
const EVP_CIPHER *cipher =
EVP_get_cipherbyname(_algorithm.c_str());
@ -220,21 +225,23 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
prc_cat.error()
<< "Unknown encryption algorithm: " << _algorithm << "\n";
return;
};
}
int nid = EVP_CIPHER_nid(cipher);
int iv_length = EVP_CIPHER_iv_length(cipher);
_write_block_size = EVP_CIPHER_block_size(cipher);
unsigned char *iv = (unsigned char *)alloca(iv_length);
// Generate a random IV. It doesn't need to be cryptographically secure,
// just unique.
unsigned char *iv = (unsigned char *)alloca(iv_length);
RAND_pseudo_bytes(iv, iv_length);
_write_ctx = EVP_CIPHER_CTX_new();
nassertv(_write_ctx != NULL);
int result;
result = EVP_EncryptInit(&_write_ctx, cipher, NULL, iv);
result = EVP_EncryptInit(_write_ctx, cipher, NULL, iv);
nassertv(result > 0);
// Store the appropriate key length in the context.
@ -242,12 +249,13 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
if (key_length == 0) {
key_length = EVP_CIPHER_key_length(cipher);
}
result = EVP_CIPHER_CTX_set_key_length(&_write_ctx, key_length);
result = EVP_CIPHER_CTX_set_key_length(_write_ctx, key_length);
if (result <= 0) {
prc_cat.error()
<< "Invalid key length " << key_length * 8 << " bits for algorithm "
<< OBJ_nid2sn(nid) << "\n";
EVP_CIPHER_CTX_cleanup(&_write_ctx);
EVP_CIPHER_CTX_free(_write_ctx);
_write_ctx = NULL;
return;
}
@ -271,7 +279,7 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
nassertv(result > 0);
// Store the key in the context.
result = EVP_EncryptInit(&_write_ctx, NULL, key, NULL);
result = EVP_EncryptInit(_write_ctx, NULL, key, NULL);
nassertv(result > 0);
// Now write the header information to the stream.
@ -284,7 +292,6 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
sw.add_uint16((uint16_t)count);
sw.append_data(iv, iv_length);
_write_valid = true;
thread_consider_yield();
}
@ -298,15 +305,16 @@ close_write() {
write_chars(pbase(), n);
pbump(-(int)n);
if (_write_valid) {
if (_write_ctx != NULL) {
unsigned char *write_buffer = (unsigned char *)alloca(_write_block_size);
int bytes_written = 0;
EVP_EncryptFinal(&_write_ctx, write_buffer, &bytes_written);
EVP_EncryptFinal(_write_ctx, write_buffer, &bytes_written);
thread_consider_yield();
_dest->write((const char *)write_buffer, bytes_written);
_write_valid = false;
EVP_CIPHER_CTX_free(_write_ctx);
_write_ctx = NULL;
}
if (_owns_dest) {
@ -418,7 +426,7 @@ read_chars(char *start, size_t length) {
do {
// Get more bytes from the stream.
if (!_read_valid) {
if (_read_ctx == NULL) {
return 0;
}
@ -429,20 +437,21 @@ read_chars(char *start, size_t length) {
int result;
if (source_length != 0) {
result =
EVP_DecryptUpdate(&_read_ctx, read_buffer, &bytes_read,
EVP_DecryptUpdate(_read_ctx, read_buffer, &bytes_read,
source_buffer, source_length);
} else {
result =
EVP_DecryptFinal(&_read_ctx, read_buffer, &bytes_read);
_read_valid = false;
EVP_DecryptFinal(_read_ctx, read_buffer, &bytes_read);
EVP_CIPHER_CTX_free(_read_ctx);
_read_ctx = NULL;
}
if (result <= 0) {
prc_cat.error()
<< "Error decrypting stream.\n";
if (_read_valid) {
EVP_CIPHER_CTX_cleanup(&_read_ctx);
_read_valid = false;
if (_read_ctx != NULL) {
EVP_CIPHER_CTX_free(_read_ctx);
_read_ctx = NULL;
}
}
thread_consider_yield();
@ -472,13 +481,13 @@ read_chars(char *start, size_t length) {
*/
void EncryptStreamBuf::
write_chars(const char *start, size_t length) {
if (_write_valid && length != 0) {
if (_write_ctx != NULL && length != 0) {
size_t max_write_buffer = length + _write_block_size;
unsigned char *write_buffer = (unsigned char *)alloca(max_write_buffer);
int bytes_written = 0;
int result =
EVP_EncryptUpdate(&_write_ctx, write_buffer, &bytes_written,
EVP_EncryptUpdate(_write_ctx, write_buffer, &bytes_written,
(unsigned char *)start, length);
if (result <= 0) {
prc_cat.error()

View File

@ -64,14 +64,12 @@ private:
int _key_length;
int _iteration_count;
bool _read_valid;
EVP_CIPHER_CTX _read_ctx;
EVP_CIPHER_CTX *_read_ctx;
size_t _read_block_size;
unsigned char *_read_overflow_buffer;
size_t _in_read_overflow_buffer;
bool _write_valid;
EVP_CIPHER_CTX _write_ctx;
EVP_CIPHER_CTX *_write_ctx;
size_t _write_block_size;
};

View File

@ -343,6 +343,9 @@ assert_failure(const char *expression, int line,
// guarantee it has already been constructed.
ALIGN_16BYTE ConfigVariableBool assert_abort("assert-abort", false);
if (assert_abort) {
// Make sure the error message has been flushed to the output.
nout.flush();
#ifdef WIN32
// How to trigger an exception in VC++ that offers to take us into the
// debugger? abort() doesn't do it. We used to be able to assert(false),

View File

@ -149,12 +149,14 @@ extern "C" {
EXPCL_PYSTUB int PyUnicodeUCS2_FromStringAndSize(...);
EXPCL_PYSTUB int PyUnicodeUCS2_FromWideChar(...);
EXPCL_PYSTUB int PyUnicodeUCS2_AsWideChar(...);
EXPCL_PYSTUB int PyUnicodeUCS2_AsWideCharString(...);
EXPCL_PYSTUB int PyUnicodeUCS2_GetSize(...);
EXPCL_PYSTUB int PyUnicodeUCS4_FromFormat(...);
EXPCL_PYSTUB int PyUnicodeUCS4_FromString(...);
EXPCL_PYSTUB int PyUnicodeUCS4_FromStringAndSize(...);
EXPCL_PYSTUB int PyUnicodeUCS4_FromWideChar(...);
EXPCL_PYSTUB int PyUnicodeUCS4_AsWideChar(...);
EXPCL_PYSTUB int PyUnicodeUCS4_AsWideCharString(...);
EXPCL_PYSTUB int PyUnicodeUCS4_GetSize(...);
EXPCL_PYSTUB int PyUnicode_AsUTF8(...);
EXPCL_PYSTUB int PyUnicode_AsUTF8AndSize(...);
@ -349,12 +351,14 @@ int PyUnicodeUCS2_FromString(...) { return 0; }
int PyUnicodeUCS2_FromStringAndSize(...) { return 0; }
int PyUnicodeUCS2_FromWideChar(...) { return 0; }
int PyUnicodeUCS2_AsWideChar(...) { return 0; }
int PyUnicodeUCS2_AsWideCharString(...) { return 0; }
int PyUnicodeUCS2_GetSize(...) { return 0; }
int PyUnicodeUCS4_FromFormat(...) { return 0; }
int PyUnicodeUCS4_FromString(...) { return 0; }
int PyUnicodeUCS4_FromStringAndSize(...) { return 0; }
int PyUnicodeUCS4_FromWideChar(...) { return 0; }
int PyUnicodeUCS4_AsWideChar(...) { return 0; }
int PyUnicodeUCS4_AsWideCharString(...) { return 0; }
int PyUnicodeUCS4_GetSize(...) { return 0; }
int PyUnicode_AsUTF8(...) { return 0; }
int PyUnicode_AsUTF8AndSize(...) { return 0; }

View File

@ -17,6 +17,7 @@
#include "interrogate_request.h"
#include "load_dso.h"
#include "filename.h"
#include "pystub.h"
#include "panda_getopt.h"
#include "preprocess_argv.h"
@ -520,6 +521,8 @@ main(int argc, char **argv) {
extern int optind;
const char *optstr = "p:ftqh";
pystub();
bool all_functions = false;
bool all_types = false;
bool quick_load = false;

View File

@ -141,8 +141,9 @@ SectionGroup "Panda3D Libraries"
SetDetailsPrint listonly
SetOutPath "$INSTDIR"
File "${BUILT}\LICENSE"
File /r /x CVS "${BUILT}\ReleaseNotes"
File /nonfatal "${BUILT}\LICENSE"
File /nonfatal "${BUILT}\ReleaseNotes"
File /nonfatal "${BUILT}\pandaIcon.ico"
SetOutPath $INSTDIR\etc
File /r "${BUILT}\etc\*"
@ -166,6 +167,10 @@ SectionGroup "Panda3D Libraries"
SetOutPath $INSTDIR\models
File /r /x CVS "${BUILT}\models\*"
SetDetailsPrint both
DetailPrint "Installing optional components..."
SetDetailsPrint listonly
RMDir /r "$SMPROGRAMS\${TITLE}"
CreateDirectory "$SMPROGRAMS\${TITLE}"
SectionEnd
@ -528,15 +533,17 @@ Section "Sample programs" SecSamples
WriteINIStr $INSTDIR\Manual.url "InternetShortcut" "URL" "https://www.panda3d.org/manual/index.php"
WriteINIStr $INSTDIR\Samples.url "InternetShortcut" "URL" "https://www.panda3d.org/manual/index.php/Sample_Programs_in_the_Distribution"
SetOutPath $INSTDIR
CreateShortCut "$SMPROGRAMS\${TITLE}\Panda3D Manual.lnk" "$INSTDIR\Manual.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Panda3D Manual"
CreateShortCut "$SMPROGRAMS\${TITLE}\Panda3D Website.lnk" "$INSTDIR\Website.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Panda3D Website"
CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Program Manual.lnk" "$INSTDIR\Samples.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Sample Program Manual"
CreateShortCut "$SMPROGRAMS\${TITLE}\Panda3D Manual.lnk" "$INSTDIR\Manual.url" "" "$INSTDIR\pandaIcon.ico" 0 "" "" "Panda3D Manual"
CreateShortCut "$SMPROGRAMS\${TITLE}\Panda3D Website.lnk" "$INSTDIR\Website.url" "" "$INSTDIR\pandaIcon.ico" 0 "" "" "Panda3D Website"
CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Program Manual.lnk" "$INSTDIR\Samples.url" "" "$INSTDIR\pandaIcon.ico" 0 "" "" "Sample Program Manual"
FindFirst $0 $1 $INSTDIR\samples\*
loop:
StrCmp $1 "" done
StrCmp $1 "." next
StrCmp $1 ".." next
FindFirst $2 $3 $INSTDIR\samples\$1\*.py
StrCmp $3 "" next
Push $1
Push "-"
Push " "
@ -553,14 +560,13 @@ Section "Sample programs" SecSamples
DetailPrint "Creating shortcuts for sample program $READABLE"
CreateDirectory "$SMPROGRAMS\${TITLE}\Sample Programs\$READABLE"
SetOutPath $INSTDIR\samples\$1
WriteINIStr $INSTDIR\samples\$1\ManualPage.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php/Sample_Programs:_$MANPAGE"
CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Programs\$READABLE\Manual Page.lnk" "$INSTDIR\samples\$1\ManualPage.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Manual Entry on this Sample Program"
WriteINIStr $INSTDIR\samples\$1\ManualPage.url "InternetShortcut" "URL" "https://www.panda3d.org/wiki/index.php/Sample_Programs:_$MANPAGE"
CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Programs\$READABLE\Manual Page.lnk" "$INSTDIR\samples\$1\ManualPage.url" "" "$INSTDIR\pandaIcon.ico" 0 "" "" "Manual Entry on this Sample Program"
CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Programs\$READABLE\View Source Code.lnk" "$INSTDIR\samples\$1"
FindFirst $2 $3 $INSTDIR\samples\$1\*.py
iloop:
StrCmp $3 "" idone
CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Programs\$READABLE\Run $3.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\bin\eggcacher.exe" 0 SW_SHOWMINIMIZED "" "Run $3"
CreateShortCut "$INSTDIR\samples\$1\Run $3.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\bin\eggcacher.exe" 0 SW_SHOWMINIMIZED "" "Run $3"
CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Programs\$READABLE\Run $3.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\pandaIcon.ico" 0 SW_SHOWMINIMIZED "" "Run $3"
CreateShortCut "$INSTDIR\samples\$1\Run $3.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\pandaIcon.ico" 0 SW_SHOWMINIMIZED "" "Run $3"
FindNext $2 $3
goto iloop
idone:
@ -613,13 +619,10 @@ Section -post
DetailPrint "Preloading .egg files into the model cache..."
SetDetailsPrint listonly
; We need to set the $PATH for eggcacher.
SetOutPath $INSTDIR
ReadEnvStr $R0 "PATH"
StrCpy $R0 "$INSTDIR\python;$INSTDIR\bin;$R0"
System::Call 'Kernel32::SetEnvironmentVariableA(t, t) i("PATH", R0).r2'
nsExec::ExecToLog '"$INSTDIR\bin\eggcacher.exe" --concise models samples'
nsExec::ExecToLog '"$INSTDIR\python\python.exe" -m direct.directscripts.eggcacher --concise models samples'
Pop $0
DetailPrint "Command returned exit status $0"
SetDetailsPrint both
DetailPrint "Writing the uninstaller ..."
@ -680,6 +683,10 @@ Section -post
DetailPrint "Broadcasting WM_WININICHANGE message..."
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=500
# Now dump the log to disk.
StrCpy $0 "$INSTDIR\install.log"
Push $0
Call DumpLog
SectionEnd
Section Uninstall
@ -1231,3 +1238,47 @@ done:
Exch $R3
FunctionEnd
!define LVM_GETITEMCOUNT 0x1004
!define LVM_GETITEMTEXT 0x102D
Function DumpLog
Exch $5
Push $0
Push $1
Push $2
Push $3
Push $4
Push $6
FindWindow $0 "#32770" "" $HWNDPARENT
GetDlgItem $0 $0 1016
StrCmp $0 0 exit
FileOpen $5 $5 "w"
StrCmp $5 "" exit
SendMessage $0 ${LVM_GETITEMCOUNT} 0 0 $6
System::Alloc ${NSIS_MAX_STRLEN}
Pop $3
StrCpy $2 0
System::Call "*(i, i, i, i, i, i, i, i, i) i \
(0, 0, 0, 0, 0, r3, ${NSIS_MAX_STRLEN}) .r1"
loop: StrCmp $2 $6 done
System::Call "User32::SendMessageA(i, i, i, i) i \
($0, ${LVM_GETITEMTEXT}, $2, r1)"
System::Call "*$3(&t${NSIS_MAX_STRLEN} .r4)"
FileWrite $5 "$4$\r$\n"
IntOp $2 $2 + 1
Goto loop
done:
FileClose $5
System::Free $1
System::Free $3
exit:
Pop $6
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
Exch $5
FunctionEnd

View File

@ -39,6 +39,7 @@ import sys
COMPILER=0
INSTALLER=0
WHEEL=0
GENMAN=0
COMPRESSOR="zlib"
THREADCOUNT=0
@ -51,6 +52,7 @@ RUNTIME=0
DISTRIBUTOR=""
VERSION=None
DEBVERSION=None
WHLVERSION=None
RPMRELEASE="1"
GIT_COMMIT=None
P3DSUFFIX=None
@ -87,14 +89,13 @@ PkgListSet(["PYTHON", "DIRECT", # Python support
"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
"X11", # Unix platform support
"PANDATOOL", "PVIEW", "DEPLOYTOOLS", # Toolchain
"SKEL", # Example SKEL project
"PANDAFX", # Some distortion special lenses
"PANDAPARTICLESYSTEM", # Built in particle system
"CONTRIB", # Experimental
"SSE2", "NEON", # Compiler features
"TOUCHINPUT", # Touchinput interface (requires Windows 7)
])
CheckPandaSourceTree()
@ -125,6 +126,7 @@ def usage(problem):
print(" --verbose (print out more information)")
print(" --runtime (build a runtime build instead of an SDK build)")
print(" --installer (build an installer)")
print(" --wheel (build a pip-installable .whl)")
print(" --optimize X (optimization level can be 1,2,3,4)")
print(" --version X (set the panda version number)")
print(" --lzma (use lzma compression when building Windows installer)")
@ -160,17 +162,18 @@ def usage(problem):
os._exit(1)
def parseopts(args):
global INSTALLER,RTDIST,RUNTIME,GENMAN,DISTRIBUTOR,VERSION
global INSTALLER,WHEEL,RTDIST,RUNTIME,GENMAN,DISTRIBUTOR,VERSION
global COMPRESSOR,THREADCOUNT,OSXTARGET,OSX_ARCHS,HOST_URL
global DEBVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX,RTDIST_VERSION
global DEBVERSION,WHLVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX,RTDIST_VERSION
global STRDXSDKVERSION, WINDOWS_SDK, MSVC_VERSION, BOOUSEINTELCOMPILER
longopts = [
"help","distributor=","verbose","runtime","osxtarget=",
"optimize=","everything","nothing","installer","rtdist","nocolor",
"optimize=","everything","nothing","installer","wheel","rtdist","nocolor",
"version=","lzma","no-python","threads=","outputdir=","override=",
"static","host=","debversion=","rpmrelease=","p3dsuffix=","rtdist-version=",
"directx-sdk=", "windows-sdk=", "msvc-version=", "clean", "use-icl",
"universal", "target=", "arch=", "git-commit="]
"universal", "target=", "arch=", "git-commit=", "no-directscripts",
"use-touchinput", "no-touchinput"]
anything = 0
optimize = ""
target = None
@ -188,6 +191,7 @@ def parseopts(args):
if (option=="--help"): raise Exception
elif (option=="--optimize"): optimize=value
elif (option=="--installer"): INSTALLER=1
elif (option=="--wheel"): WHEEL=1
elif (option=="--verbose"): SetVerbose(True)
elif (option=="--distributor"): DISTRIBUTOR=value
elif (option=="--rtdist"): RTDIST=1
@ -203,8 +207,11 @@ def parseopts(args):
elif (option=="--arch"): target_arch = value.strip()
elif (option=="--nocolor"): DisableColors()
elif (option=="--version"):
VERSION=value
if (len(VERSION.split(".")) != 3): raise Exception
match = re.match(r'^\d+\.\d+\.\d+', value)
if not match:
usage("version requires three digits")
WHLVERSION = value
VERSION = match.group()
elif (option=="--lzma"): COMPRESSOR="lzma"
elif (option=="--override"): AddOverride(value.strip())
elif (option=="--static"): SetLinkAllStatic(True)
@ -217,6 +224,7 @@ def parseopts(args):
# Backward compatibility, OPENGL was renamed to GL
elif (option=="--use-opengl"): PkgEnable("GL")
elif (option=="--no-opengl"): PkgDisable("GL")
elif (option=="--no-directscripts"): pass
elif (option=="--directx-sdk"):
STRDXSDKVERSION = value.strip().lower()
if STRDXSDKVERSION == '':
@ -316,18 +324,6 @@ def parseopts(args):
print("No Windows SDK version specified. Defaulting to '7.1'.")
WINDOWS_SDK = '7.1'
is_win7 = False
if sys.platform == 'win32':
# Note: not available in cygwin.
winver = sys.getwindowsversion()
if winver[0] >= 6 and winver[1] >= 1:
is_win7 = True
if RUNTIME or not is_win7:
PkgDisable("TOUCHINPUT")
else:
PkgDisable("TOUCHINPUT")
if clean_build and os.path.isdir(GetOutputDir()):
print("Deleting %s" % (GetOutputDir()))
shutil.rmtree(GetOutputDir())
@ -372,6 +368,9 @@ if VERSION is None:
else:
VERSION = ParsePandaVersion("dtool/PandaVersion.pp")
if WHLVERSION is None:
WHLVERSION = VERSION
print("Version: %s" % VERSION)
if RUNTIME or RTDIST:
print("Core API Version: %s" % COREAPI_VERSION)
@ -428,9 +427,18 @@ if (RUNTIME):
if (INSTALLER and RTDIST):
exit("Cannot build an installer for the rtdist build!")
if (WHEEL and RUNTIME):
exit("Cannot build a wheel for the runtime build!")
if (WHEEL and RTDIST):
exit("Cannot build a wheel for the rtdist build!")
if (INSTALLER) and (PkgSkip("PYTHON")) and (not RUNTIME) and GetTarget() == 'windows':
exit("Cannot build installer on Windows without python")
if WHEEL and PkgSkip("PYTHON"):
exit("Cannot build wheel without Python")
if (RTDIST) and (PkgSkip("WX") and PkgSkip("FLTK")):
exit("Cannot build rtdist without wx or fltk")
@ -516,9 +524,6 @@ IncDirectory("ALWAYS", GetOutputDir()+"/include")
if (COMPILER == "MSVC"):
PkgDisable("X11")
PkgDisable("XRANDR")
PkgDisable("XF86DGA")
PkgDisable("XCURSOR")
PkgDisable("GLES")
PkgDisable("GLES2")
PkgDisable("EGL")
@ -808,9 +813,13 @@ if (COMPILER=="GCC"):
SmartPkgEnable("JPEG", "", ("jpeg"), "jpeglib.h")
SmartPkgEnable("PNG", "libpng", ("png"), "png.h", tool = "libpng-config")
if GetTarget() == "darwin" and not PkgSkip("FFMPEG"):
LibName("FFMPEG", "-Wl,-read_only_relocs,suppress")
LibName("FFMPEG", "-framework VideoDecodeAcceleration")
if not PkgSkip("FFMPEG"):
if GetTarget() == "darwin":
LibName("FFMPEG", "-Wl,-read_only_relocs,suppress")
LibName("FFMPEG", "-framework VideoDecodeAcceleration")
elif os.path.isfile(GetThirdpartyDir() + "ffmpeg/lib/libavcodec.a"):
# Needed when linking ffmpeg statically on Linux.
LibName("FFMPEG", "-Wl,-Bsymbolic")
cv_lib = ChooseLib(("opencv_core", "cv"), "OPENCV")
if cv_lib == "opencv_core":
@ -827,7 +836,11 @@ if (COMPILER=="GCC"):
SmartPkgEnable("ROCKET", "", rocket_libs, "Rocket/Core.h")
if not PkgSkip("PYTHON"):
SmartPkgEnable("PYTHON", "", SDK["PYTHONVERSION"], (SDK["PYTHONVERSION"], SDK["PYTHONVERSION"] + "/Python.h"), tool = SDK["PYTHONVERSION"] + "-config")
python_lib = SDK["PYTHONVERSION"]
if not RTDIST:
# We don't link anything in the SDK with libpython.
python_lib = ""
SmartPkgEnable("PYTHON", "", python_lib, (SDK["PYTHONVERSION"], SDK["PYTHONVERSION"] + "/Python.h"), tool = SDK["PYTHONVERSION"] + "-config")
SmartPkgEnable("OPENSSL", "openssl", ("ssl", "crypto"), ("openssl/ssl.h", "openssl/crypto.h"))
SmartPkgEnable("ZLIB", "zlib", ("z"), "zlib.h")
@ -840,12 +853,9 @@ if (COMPILER=="GCC"):
if GetTarget() != 'darwin':
# CgGL is covered by the Cg framework, and we don't need X11 components on OSX
if not PkgSkip("NVIDIACG") and not RUNTIME:
SmartPkgEnable("CGGL", "", ("CgGL"), "Cg/cgGL.h")
SmartPkgEnable("CGGL", "", ("CgGL"), "Cg/cgGL.h", thirdparty_dir = "nvidiacg")
if not RUNTIME:
SmartPkgEnable("X11", "x11", "X11", ("X11", "X11/Xlib.h"))
SmartPkgEnable("XRANDR", "xrandr", "Xrandr", "X11/extensions/Xrandr.h")
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
@ -1055,14 +1065,11 @@ def CompileCxx(obj,src,opts):
cmd += "/favor:blend "
cmd += "/wd4996 /wd4275 /wd4273 "
# Enable Windows 7 interfaces if we need Touchinput.
if PkgSkip("TOUCHINPUT") == 0:
cmd += "/DWINVER=0x601 "
else:
cmd += "/DWINVER=0x501 "
# Work around a WinXP/2003 bug when using VS 2015+.
if SDK.get("VISUALSTUDIO_VERSION") == '14.0':
cmd += "/Zc:threadSafeInit- "
# We still target Windows XP.
cmd += "/DWINVER=0x501 "
# Work around a WinXP/2003 bug when using VS 2015+.
if SDK.get("VISUALSTUDIO_VERSION") == '14.0':
cmd += "/Zc:threadSafeInit- "
cmd += "/Fo" + obj + " /nologo /c"
if GetTargetArch() != 'x64' and (not PkgSkip("SSE2") or 'SSE2' in opts):
@ -1113,12 +1120,7 @@ def CompileCxx(obj,src,opts):
if GetTargetArch() == 'x64':
cmd += "/favor:blend "
cmd += "/wd4996 /wd4275 /wd4267 /wd4101 /wd4273 "
# Enable Windows 7 interfaces if we need Touchinput.
if PkgSkip("TOUCHINPUT") == 0:
cmd += "/DWINVER=0x601 "
else:
cmd += "/DWINVER=0x501 "
cmd += "/DWINVER=0x501 "
cmd += "/Fo" + obj + " /c"
for x in ipath: cmd += " /I" + x
for (opt,dir) in INCDIRECTORIES:
@ -1200,7 +1202,7 @@ def CompileCxx(obj,src,opts):
if (COMPILER=="GCC"):
if (src.endswith(".c")): cmd = GetCC() +' -fPIC -c -o ' + obj
else: cmd = GetCXX()+' -ftemplate-depth-70 -fPIC -c -o ' + obj
else: cmd = GetCXX()+' -std=gnu++0x -ftemplate-depth-70 -fPIC -c -o ' + obj
for (opt, dir) in INCDIRECTORIES:
if (opt=="ALWAYS") or (opt in opts): cmd += ' -I' + BracketNameWithQuotes(dir)
for (opt, dir) in FRAMEWORKDIRECTORIES:
@ -1686,11 +1688,7 @@ def CompileLink(dll, obj, opts):
if 'NOARCH:' + arch.upper() not in opts:
cmd += " -arch %s" % arch
if "SYSROOT" in SDK:
cmd += " --sysroot=%s -no-canonical-prefixes" % (SDK["SYSROOT"])
# Android-specific flags.
if GetTarget() == 'android':
elif GetTarget() == 'android':
cmd += " -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now"
if GetTargetArch() == 'armv7a':
cmd += " -march=armv7-a -Wl,--fix-cortex-a8"
@ -1698,9 +1696,17 @@ def CompileLink(dll, obj, opts):
else:
cmd += " -pthread"
if "SYSROOT" in SDK:
cmd += " --sysroot=%s -no-canonical-prefixes" % (SDK["SYSROOT"])
if LDFLAGS != "":
cmd += " " + LDFLAGS
# Don't link libraries with Python.
if "PYTHON" in opts and GetOrigExt(dll) != ".exe" and not RTDIST:
opts = opts[:]
opts.remove("PYTHON")
for (opt, dir) in LIBDIRECTORIES:
if (opt=="ALWAYS") or (opt in opts):
cmd += ' -L' + BracketNameWithQuotes(dir)
@ -2130,7 +2136,6 @@ DTOOL_CONFIG=[
("REPORT_OPENSSL_ERRORS", '1', '1'),
("USE_PANDAFILESTREAM", '1', '1'),
("USE_DELETED_CHAIN", '1', '1'),
("HAVE_WIN_TOUCHINPUT", 'UNDEF', 'UNDEF'),
("HAVE_GLX", 'UNDEF', '1'),
("HAVE_WGL", '1', 'UNDEF'),
("HAVE_DX9", 'UNDEF', 'UNDEF'),
@ -2204,9 +2209,6 @@ DTOOL_CONFIG=[
("PHAVE_STDINT_H", '1', '1'),
("HAVE_RTTI", '1', '1'),
("HAVE_X11", 'UNDEF', '1'),
("HAVE_XRANDR", 'UNDEF', '1'),
("HAVE_XF86DGA", 'UNDEF', '1'),
("HAVE_XCURSOR", 'UNDEF', '1'),
("IS_LINUX", 'UNDEF', '1'),
("IS_OSX", 'UNDEF', 'UNDEF'),
("IS_FREEBSD", 'UNDEF', 'UNDEF'),
@ -2237,11 +2239,7 @@ DTOOL_CONFIG=[
("HAVE_CG", 'UNDEF', 'UNDEF'),
("HAVE_CGGL", 'UNDEF', 'UNDEF'),
("HAVE_CGDX9", 'UNDEF', 'UNDEF'),
("HAVE_FFMPEG", 'UNDEF', 'UNDEF'),
("HAVE_SWSCALE", 'UNDEF', 'UNDEF'),
("HAVE_SWRESAMPLE", 'UNDEF', 'UNDEF'),
("HAVE_ARTOOLKIT", 'UNDEF', 'UNDEF'),
("HAVE_OPENCV", 'UNDEF', 'UNDEF'),
("HAVE_DIRECTCAM", 'UNDEF', 'UNDEF'),
("HAVE_SQUISH", 'UNDEF', 'UNDEF'),
("HAVE_CARBON", 'UNDEF', 'UNDEF'),
@ -2296,9 +2294,6 @@ def WriteConfigSettings():
else:
dtool_config["HAVE_"+x] = 'UNDEF'
if not PkgSkip("OPENCV"):
dtool_config["OPENCV_VER_23"] = '1' if OPENCV_VER_23 else 'UNDEF'
dtool_config["HAVE_NET"] = '1'
if (PkgSkip("NVIDIACG")==0):
@ -2318,9 +2313,6 @@ def WriteConfigSettings():
dtool_config["PHAVE_SYS_MALLOC_H"] = '1'
dtool_config["HAVE_OPENAL_FRAMEWORK"] = '1'
dtool_config["HAVE_X11"] = 'UNDEF' # We might have X11, but we don't need it.
dtool_config["HAVE_XRANDR"] = 'UNDEF'
dtool_config["HAVE_XF86DGA"] = 'UNDEF'
dtool_config["HAVE_XCURSOR"] = 'UNDEF'
dtool_config["HAVE_GLX"] = 'UNDEF'
dtool_config["IS_LINUX"] = 'UNDEF'
dtool_config["HAVE_VIDEO4LINUX"] = 'UNDEF'
@ -2355,9 +2347,6 @@ def WriteConfigSettings():
if (PkgSkip("PYTHON") != 0):
dtool_config["HAVE_ROCKET_PYTHON"] = 'UNDEF'
if (PkgSkip("TOUCHINPUT") == 0 and GetTarget() == "windows"):
dtool_config["HAVE_WIN_TOUCHINPUT"] = '1'
if (GetOptimize() <= 3):
dtool_config["HAVE_ROCKET_DEBUGGER"] = '1'
@ -2890,14 +2879,16 @@ if tp_dir is not None:
CopyAllFiles(GetOutputDir() + "/bin/", tp_dir + "extras/bin/")
if not PkgSkip("PYTHON") and not RTDIST:
#XXX rdb I don't think we need to copy over the Python DLL, do we?
#pydll = "/" + SDK["PYTHONVERSION"].replace(".", "")
#if (GetOptimize() <= 2): pydll += "_d.dll"
#else: pydll += ".dll"
#CopyFile(GetOutputDir() + "/bin" + pydll, SDK["PYTHON"] + pydll)
# We need to copy the Python DLL to the bin directory for now.
pydll = "/" + SDK["PYTHONVERSION"].replace(".", "")
if GetOptimize() <= 2:
pydll += "_d.dll"
else:
pydll += ".dll"
CopyFile(GetOutputDir() + "/bin" + pydll, SDK["PYTHON"] + pydll)
#for fn in glob.glob(SDK["PYTHON"] + "/vcruntime*.dll"):
# CopyFile(GetOutputDir() + "/bin/", fn)
for fn in glob.glob(SDK["PYTHON"] + "/vcruntime*.dll"):
CopyFile(GetOutputDir() + "/bin/", fn)
# Copy the whole Python directory.
CopyTree(GetOutputDir() + "/python", SDK["PYTHON"])
@ -2916,7 +2907,7 @@ if tp_dir is not None:
else:
idents = ()
for ident in tree.findall('./{urn:schemas-microsoft-com:asm.v1}dependency/{urn:schemas-microsoft-com:asm.v1}dependentAssembly/{urn:schemas-microsoft-com:asm.v1}assemblyIdentity'):
for ident in idents:
sxs_name = '_'.join([
ident.get('processorArchitecture'),
ident.get('name').lower(),
@ -2968,6 +2959,7 @@ if GetTarget() == 'windows':
# Convert to Windows newlines so they can be opened by notepad.
WriteFile(GetOutputDir() + "/LICENSE", ReadFile("doc/LICENSE"), newline='\r\n')
WriteFile(GetOutputDir() + "/ReleaseNotes", ReadFile("doc/ReleaseNotes"), newline='\r\n')
CopyFile(GetOutputDir() + "/pandaIcon.ico", "panda/src/configfiles/pandaIcon.ico")
else:
CopyFile(GetOutputDir()+"/", "doc/LICENSE")
CopyFile(GetOutputDir()+"/", "doc/ReleaseNotes")
@ -3360,6 +3352,7 @@ if (not RUNTIME):
TargetAdd('interrogate.exe', input='libp3cppParser.ilb')
TargetAdd('interrogate.exe', input=COMMON_DTOOL_LIBS)
TargetAdd('interrogate.exe', input='libp3interrogatedb.dll')
TargetAdd('interrogate.exe', input='libp3pystub.lib')
TargetAdd('interrogate.exe', opts=['ADVAPI', 'OPENSSL', 'WINSHELL', 'WINGDI', 'WINUSER'])
TargetAdd('interrogate_module_interrogate_module.obj', opts=OPTS, input='interrogate_module.cxx')
@ -3367,6 +3360,7 @@ if (not RUNTIME):
TargetAdd('interrogate_module.exe', input='libp3cppParser.ilb')
TargetAdd('interrogate_module.exe', input=COMMON_DTOOL_LIBS)
TargetAdd('interrogate_module.exe', input='libp3interrogatedb.dll')
TargetAdd('interrogate_module.exe', input='libp3pystub.lib')
TargetAdd('interrogate_module.exe', opts=['ADVAPI', 'OPENSSL', 'WINSHELL', 'WINGDI', 'WINUSER'])
if (not RTDIST):
@ -3375,6 +3369,7 @@ if (not RUNTIME):
TargetAdd('parse_file.exe', input='libp3cppParser.ilb')
TargetAdd('parse_file.exe', input=COMMON_DTOOL_LIBS)
TargetAdd('parse_file.exe', input='libp3interrogatedb.dll')
TargetAdd('parse_file.exe', input='libp3pystub.lib')
TargetAdd('parse_file.exe', opts=['ADVAPI', 'OPENSSL', 'WINSHELL', 'WINGDI', 'WINUSER'])
#
@ -3398,6 +3393,7 @@ if (not RTDIST and not RUNTIME):
TargetAdd('test_interrogate.exe', input='test_interrogate_test_interrogate.obj')
TargetAdd('test_interrogate.exe', input='libp3interrogatedb.dll')
TargetAdd('test_interrogate.exe', input=COMMON_DTOOL_LIBS)
TargetAdd('test_interrogate.exe', input='libp3pystub.lib')
TargetAdd('test_interrogate.exe', opts=['ADVAPI', 'OPENSSL', 'WINSHELL', 'WINGDI', 'WINUSER'])
#
@ -4129,8 +4125,20 @@ if (not RUNTIME):
#
if (PkgSkip("VISION") == 0) and (not RUNTIME):
# We want to know whether we have ffmpeg so that we can override the .avi association.
if not PkgSkip("FFMPEG"):
DefSymbol("OPENCV", "HAVE_FFMPEG")
if not PkgSkip("OPENCV"):
DefSymbol("OPENCV", "HAVE_OPENCV")
if OPENCV_VER_23:
DefSymbol("OPENCV", "OPENCV_VER_23")
OPTS=['DIR:panda/src/vision', 'BUILDING:VISION', 'ARTOOLKIT', 'OPENCV', 'DX9', 'DIRECTCAM', 'JPEG', 'EXCEPTIONS']
TargetAdd('p3vision_composite1.obj', opts=OPTS, input='p3vision_composite1.cxx')
TargetAdd('p3vision_composite1.obj', opts=OPTS, input='p3vision_composite1.cxx', dep=[
'dtool_have_ffmpeg.dat',
'dtool_have_opencv.dat',
'dtool_have_directcam.dat',
])
TargetAdd('libp3vision.dll', input='p3vision_composite1.obj')
TargetAdd('libp3vision.dll', input=COMMON_PANDA_LIBS)
@ -4319,8 +4327,15 @@ if (PkgSkip("VRPN")==0 and not RUNTIME):
# DIRECTORY: panda/src/ffmpeg
#
if PkgSkip("FFMPEG") == 0 and not RUNTIME:
if not PkgSkip("SWSCALE"):
DefSymbol("FFMPEG", "HAVE_SWSCALE")
if not PkgSkip("SWRESAMPLE"):
DefSymbol("FFMPEG", "HAVE_SWRESAMPLE")
OPTS=['DIR:panda/src/ffmpeg', 'BUILDING:FFMPEG', 'FFMPEG', 'SWSCALE', 'SWRESAMPLE']
TargetAdd('p3ffmpeg_composite1.obj', opts=OPTS, input='p3ffmpeg_composite1.cxx')
TargetAdd('p3ffmpeg_composite1.obj', opts=OPTS, input='p3ffmpeg_composite1.cxx', dep=[
'dtool_have_swscale.dat', 'dtool_have_swresample.dat'])
TargetAdd('libp3ffmpeg.dll', input='p3ffmpeg_composite1.obj')
TargetAdd('libp3ffmpeg.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libp3ffmpeg.dll', opts=OPTS)
@ -4582,7 +4597,7 @@ if (GetTarget() not in ['windows', 'darwin'] and PkgSkip("GL")==0 and PkgSkip("X
TargetAdd('libpandagl.dll', input='p3glgsg_glgsg.obj')
TargetAdd('libpandagl.dll', input='p3glxdisplay_composite1.obj')
TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'X11'])
#
# DIRECTORY: panda/src/cocoadisplay/
@ -4600,7 +4615,7 @@ if (GetTarget() == 'darwin' and PkgSkip("COCOA")==0 and PkgSkip("GL")==0 and not
if (PkgSkip('PANDAFX')==0):
TargetAdd('libpandagl.dll', input='libpandafx.dll')
TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'COCOA'])
TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'COCOA', 'CARBON'])
#
# DIRECTORY: panda/src/osxdisplay/
@ -4657,7 +4672,7 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0 and not RUNTI
TargetAdd('libpandagles.dll', input='p3glesgsg_glesgsg.obj')
TargetAdd('libpandagles.dll', input='pandagles_egldisplay_composite1.obj')
TargetAdd('libpandagles.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libpandagles.dll', opts=['MODULE', 'GLES', 'EGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
TargetAdd('libpandagles.dll', opts=['MODULE', 'GLES', 'EGL', 'X11'])
#
# DIRECTORY: panda/src/egldisplay/
@ -4675,7 +4690,7 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0 and PkgSkip("X11")==0 and not RUNT
TargetAdd('libpandagles2.dll', input='p3gles2gsg_gles2gsg.obj')
TargetAdd('libpandagles2.dll', input='pandagles2_egldisplay_composite1.obj')
TargetAdd('libpandagles2.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libpandagles2.dll', opts=['MODULE', 'GLES2', 'EGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
TargetAdd('libpandagles2.dll', opts=['MODULE', 'GLES2', 'EGL', 'X11'])
#
# DIRECTORY: panda/src/ode/
@ -4971,7 +4986,7 @@ if (not RUNTIME and (GetTarget() in ('windows', 'darwin') or PkgSkip("X11")==0)
TargetAdd('libp3tinydisplay.dll', opts=['WINIMM', 'WINGDI', 'WINKERNEL', 'WINOLDNAMES', 'WINUSER', 'WINMM'])
else:
TargetAdd('libp3tinydisplay.dll', input='p3x11display_composite1.obj')
TargetAdd('libp3tinydisplay.dll', opts=['X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
TargetAdd('libp3tinydisplay.dll', opts=['X11'])
TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_composite1.obj')
TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_composite2.obj')
TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_ztriangle_1.obj')
@ -4989,17 +5004,6 @@ if (PkgSkip("DIRECT")==0):
OPTS=['DIR:direct/src/directbase', 'PYTHON']
TargetAdd('p3directbase_directbase.obj', opts=OPTS+['BUILDING:DIRECT'], input='directbase.cxx')
if (PkgSkip("PYTHON")==0 and not RTDIST and not RUNTIME):
DefSymbol("BUILDING:PACKPANDA", "IMPORT_MODULE", "direct.directscripts.packpanda")
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')
TargetAdd('eggcacher.exe', opts=['PYTHON'])
#
# DIRECTORY: direct/src/dcparser/
#
@ -5164,6 +5168,7 @@ if (PkgSkip("PYTHON")==0 and PkgSkip("DIRECT")==0 and not RTDIST and not RUNTIME
TargetAdd('p3dcparse.exe', input='dcparse_dcparse.obj')
TargetAdd('p3dcparse.exe', input='libp3direct.dll')
TargetAdd('p3dcparse.exe', input=COMMON_PANDA_LIBS)
TargetAdd('p3dcparse.exe', input='libp3pystub.lib')
TargetAdd('p3dcparse.exe', opts=['ADVAPI', 'PYTHON'])
#
@ -6591,7 +6596,7 @@ def MakeInstallerNSIS(file, title, installdir):
AddToPathEnv("PATH", GetOutputDir() + "\\bin")
AddToPathEnv("PATH", GetOutputDir() + "\\plugins")
cmd = sys.executable + " -B -u direct\\src\\plugin_installer\\make_installer.py"
cmd = sys.executable + " -B -u " + os.path.join("direct", "src", "plugin_installer", "make_installer.py")
cmd += " --version %s --regview %s" % (VERSION, regview)
if GetTargetArch() == 'x64':
@ -6600,7 +6605,7 @@ def MakeInstallerNSIS(file, title, installdir):
cmd += " --install \"$PROGRAMFILES32\\Panda3D\" "
oscmd(cmd)
shutil.move("direct\\src\\plugin_installer\\p3d-setup.exe", file)
shutil.move(os.path.join("direct", "src", "plugin_installer", "p3d-setup.exe"), file)
return
print("Building "+title+" installer at %s" % (file))
@ -7252,6 +7257,11 @@ try:
MakeInstallerFreeBSD()
else:
exit("Do not know how to make an installer for this platform")
if WHEEL:
ProgressOutput(100.0, "Building wheel")
from makewheel import makewheel
makewheel(WHLVERSION, GetOutputDir())
finally:
SaveDependencyCache()

View File

@ -396,10 +396,16 @@ def CrossCompiling():
return GetTarget() != GetHost()
def GetCC():
return os.environ.get('CC', TOOLCHAIN_PREFIX + 'gcc')
if TARGET == 'darwin':
return os.environ.get('CC', TOOLCHAIN_PREFIX + 'clang')
else:
return os.environ.get('CC', TOOLCHAIN_PREFIX + 'gcc')
def GetCXX():
return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'g++')
if TARGET == 'darwin':
return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'clang++')
else:
return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'g++')
def GetStrip():
# Hack
@ -974,7 +980,10 @@ def WriteFile(wfile, data, newline=None):
data = data.replace('\n', newline)
try:
dsthandle = open(wfile, "w")
if sys.version_info >= (3, 0):
dsthandle = open(wfile, "w", newline='')
else:
dsthandle = open(wfile, "w")
dsthandle.write(data)
dsthandle.close()
except:
@ -1568,7 +1577,7 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
location = os.path.join(GetOutputDir(), "lib", os.path.basename(location))
LibName(target_pkg, location)
else:
print(GetColor("cyan") + "Couldn't find library lib" + libname + " in thirdparty directory " + pkg.lower() + GetColor())
print(GetColor("cyan") + "Couldn't find library lib" + libname + " in thirdparty directory " + thirdparty_dir + GetColor())
for d, v in defs.values():
DefSymbol(target_pkg, d, v)
@ -1996,6 +2005,11 @@ def SdkLocatePython(prefer_thirdparty_python=False):
SDK["PYTHONVERSION"] = "python" + ver
SDK["PYTHONEXEC"] = "/System/Library/Frameworks/Python.framework/Versions/" + ver + "/bin/python" + ver
# Avoid choosing the one in the thirdparty package dir.
PkgSetCustomLocation("PYTHON")
IncDirectory("PYTHON", py_fwx + "/include")
LibDirectory("PYTHON", "%s/usr/lib" % (SDK.get("MACOSX", "")))
if sys.version[:3] != ver:
print("Warning: building with Python %s instead of %s since you targeted a specific Mac OS X version." % (ver, sys.version[:3]))

597
makepanda/makewheel.py Normal file
View File

@ -0,0 +1,597 @@
"""
Generates a wheel (.whl) file from the output of makepanda.
Since the wheel requires special linking, this will only work if compiled with
the `--wheel` parameter.
Please keep this file work with Panda3D 1.9 until that reaches EOL.
"""
from __future__ import print_function, unicode_literals
from distutils.util import get_platform
import json
import sys
import os
from os.path import join
import shutil
import zipfile
import hashlib
import tempfile
import subprocess
from distutils.sysconfig import get_config_var
from optparse import OptionParser
from makepandacore import ColorText, LocateBinary, ParsePandaVersion, GetExtensionSuffix, SetVerbose, GetVerbose
from base64 import urlsafe_b64encode
default_platform = get_platform()
if default_platform.startswith("linux-"):
# Is this manylinux1?
if os.path.isfile("/lib/libc-2.5.so") and os.path.isdir("/opt/python"):
default_platform = default_platform.replace("linux", "manylinux1")
def get_abi_tag():
if sys.version_info >= (3, 0):
soabi = get_config_var('SOABI')
if soabi and soabi.startswith('cpython-'):
return 'cp' + soabi.split('-')[1]
elif soabi:
return soabi.replace('.', '_').replace('-', '_')
soabi = 'cp%d%d' % (sys.version_info[:2])
debug_flag = get_config_var('Py_DEBUG')
if (debug_flag is None and hasattr(sys, 'gettotalrefcount')) or debug_flag:
soabi += 'd'
malloc_flag = get_config_var('WITH_PYMALLOC')
if malloc_flag is None or malloc_flag:
soabi += 'm'
if sys.version_info < (3, 3):
usize = get_config_var('Py_UNICODE_SIZE')
if (usize is None and sys.maxunicode == 0x10ffff) or usize == 4:
soabi += 'u'
return soabi
def is_exe_file(path):
return os.path.isfile(path) and path.lower().endswith('.exe')
def is_elf_file(path):
base = os.path.basename(path)
return os.path.isfile(path) and '.' not in base and \
open(path, 'rb').read(4) == b'\x7FELF'
def is_mach_o_file(path):
base = os.path.basename(path)
return os.path.isfile(path) and '.' not in base and \
open(path, 'rb').read(4) in (b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\bCA',
b'\xFE\xED\xFA\xCE', b'\xCE\xFA\xED\xFE',
b'\xFE\xED\xFA\xCF', b'\xCF\xFA\xED\xFE')
def is_fat_file(path):
return os.path.isfile(path) and \
open(path, 'rb').read(4) in (b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\bCA')
if sys.platform in ('win32', 'cygwin'):
is_executable = is_exe_file
elif sys.platform == 'darwin':
is_executable = is_mach_o_file
else:
is_executable = is_elf_file
# Other global parameters
PY_VERSION = "cp{0}{1}".format(*sys.version_info)
ABI_TAG = get_abi_tag()
EXCLUDE_EXT = [".pyc", ".pyo", ".N", ".prebuilt", ".xcf", ".plist", ".vcproj", ".sln"]
# Plug-ins to install.
PLUGIN_LIBS = ["pandagl", "pandagles", "pandagles2", "pandadx9", "p3tinydisplay", "p3ptloader", "p3assimp", "p3ffmpeg", "p3openal_audio", "p3fmod_audio"]
WHEEL_DATA = """Wheel-Version: 1.0
Generator: makepanda
Root-Is-Purelib: false
Tag: {0}-{1}-{2}
"""
METADATA = {
"license": "BSD",
"name": "Panda3D",
"metadata_version": "2.0",
"generator": "makepanda",
"summary": "Panda3D is a game engine, a framework for 3D rendering and "
"game development for Python and C++ programs.",
"extensions": {
"python.details": {
"project_urls": {
"Home": "https://www.panda3d.org/"
},
"document_names": {
"license": "LICENSE.txt"
},
"contacts": [
{
"role": "author",
"email": "etc-panda3d@lists.andrew.cmu.edu",
"name": "Panda3D Team"
}
]
}
},
"classifiers": [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Intended Audience :: End Users/Desktop",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: C++",
"Programming Language :: Python",
"Topic :: Games/Entertainment",
"Topic :: Multimedia",
"Topic :: Multimedia :: Graphics",
"Topic :: Multimedia :: Graphics :: 3D Rendering"
]
}
PANDA3D_TOOLS_INIT = """import os, sys
import panda3d
if sys.platform in ('win32', 'cygwin'):
path_var = 'PATH'
elif sys.platform == 'darwin':
path_var = 'DYLD_LIBRARY_PATH'
else:
path_var = 'LD_LIBRARY_PATH'
dir = os.path.dirname(panda3d.__file__)
del panda3d
if not os.environ.get(path_var):
os.environ[path_var] = dir
else:
os.environ[path_var] = dir + os.pathsep + os.environ[path_var]
del os, sys, path_var, dir
def _exec_tool(tool):
import os, sys
from subprocess import Popen
tools_dir = os.path.dirname(__file__)
handle = Popen(sys.argv, executable=os.path.join(tools_dir, tool))
try:
try:
return handle.wait()
except KeyboardInterrupt:
# Give the program a chance to handle the signal gracefully.
return handle.wait()
except:
handle.kill()
handle.wait()
raise
# Register all the executables in this directory as global functions.
{0}
"""
def parse_dependencies_windows(data):
""" Parses the given output from dumpbin /dependents to determine the list
of dll's this executable file depends on. """
lines = data.splitlines()
li = 0
while li < len(lines):
line = lines[li]
li += 1
if line.find(' has the following dependencies') != -1:
break
if li < len(lines):
line = lines[li]
if line.strip() == '':
# Skip a blank line.
li += 1
# Now we're finding filenames, until the next blank line.
filenames = []
while li < len(lines):
line = lines[li]
li += 1
line = line.strip()
if line == '':
# We're done.
return filenames
filenames.append(line)
# At least we got some data.
return filenames
def parse_dependencies_unix(data):
""" Parses the given output from otool -XL or ldd to determine the list of
libraries this executable file depends on. """
lines = data.splitlines()
filenames = []
for l in lines:
l = l.strip()
if l != "statically linked":
filenames.append(l.split(' ', 1)[0])
return filenames
def scan_dependencies(pathname):
""" Checks the named file for DLL dependencies, and adds any appropriate
dependencies found into pluginDependencies and dependentFiles. """
if sys.platform == "darwin":
command = ['otool', '-XL', pathname]
elif sys.platform in ("win32", "cygwin"):
command = ['dumpbin', '/dependents', pathname]
else:
command = ['ldd', pathname]
process = subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True)
output, unused_err = process.communicate()
retcode = process.poll()
if retcode:
raise subprocess.CalledProcessError(retcode, command[0], output=output)
filenames = None
if sys.platform in ("win32", "cygwin"):
filenames = parse_dependencies_windows(output)
else:
filenames = parse_dependencies_unix(output)
if filenames is None:
sys.exit("Unable to determine dependencies from %s" % (pathname))
if sys.platform == "darwin" and len(filenames) > 0:
# Filter out the library ID.
if os.path.basename(filenames[0]).split('.', 1)[0] == os.path.basename(pathname).split('.', 1)[0]:
del filenames[0]
return filenames
class WheelFile(object):
def __init__(self, name, version, platform):
self.name = name
self.version = version
self.platform = platform
wheel_name = "{0}-{1}-{2}-{3}-{4}.whl".format(
name, version, PY_VERSION, ABI_TAG, platform)
print("Writing %s" % (wheel_name))
self.zip_file = zipfile.ZipFile(wheel_name, 'w', zipfile.ZIP_DEFLATED)
self.records = []
# Used to locate dependency libraries.
self.lib_path = []
self.dep_paths = {}
def consider_add_dependency(self, target_path, dep, search_path=None):
"""Considers adding a dependency library.
Returns the target_path if it was added, which may be different from
target_path if it was already added earlier, or None if it wasn't."""
if dep in self.dep_paths:
# Already considered this.
return self.dep_paths[dep]
self.dep_paths[dep] = None
if dep.lower().startswith("python") or os.path.basename(dep).startswith("libpython"):
# Don't include the Python library.
return
if sys.platform == "darwin" and dep.endswith(".so"):
# Temporary hack for 1.9, which had link deps on modules.
return
source_path = None
if search_path is None:
search_path = self.lib_path
for lib_dir in search_path:
# Ignore static stuff.
path = os.path.join(lib_dir, dep)
if os.path.isfile(path):
source_path = os.path.normpath(path)
break
if not source_path:
# Couldn't find library in the panda3d lib dir.
#print("Ignoring %s" % (dep))
return
self.dep_paths[dep] = target_path
self.write_file(target_path, source_path)
return target_path
def write_file(self, target_path, source_path):
"""Adds the given file to the .whl file."""
# If this is a .so file, we should set the rpath appropriately.
temp = None
ext = os.path.splitext(source_path)[1]
if ext in ('.so', '.dylib') or '.so.' in os.path.basename(source_path) or \
(not ext and is_executable(source_path)):
# Scan and add Unix dependencies.
deps = scan_dependencies(source_path)
for dep in deps:
# Only include dependencies with relative path. Otherwise we
# end up overwriting system files like /lib/ld-linux.so.2!
# Yes, it happened to me.
if '/' not in dep:
target_dep = os.path.dirname(target_path) + '/' + dep
self.consider_add_dependency(target_dep, dep)
suffix = ''
if '.so' in os.path.basename(source_path):
suffix = '.so'
elif ext == '.dylib':
suffix = '.dylib'
temp = tempfile.NamedTemporaryFile(suffix=suffix, prefix='whl', delete=False)
# On macOS, if no fat wheel was requested, extract the right architecture.
if sys.platform == "darwin" and is_fat_file(source_path) and not self.platform.endswith("_intel"):
if self.platform.endswith("_x86_64"):
arch = 'x86_64'
else:
arch = self.platform.split('_')[-1]
subprocess.call(['lipo', source_path, '-extract', arch, '-output', temp.name])
else:
# Otherwise, just copy it over.
temp.write(open(source_path, 'rb').read())
temp.write(open(source_path, 'rb').read())
os.fchmod(temp.fileno(), os.fstat(temp.fileno()).st_mode | 0o111)
temp.close()
# Fix things like @loader_path/../lib references
if sys.platform == "darwin":
loader_path = [os.path.dirname(source_path)]
for dep in deps:
if '@loader_path' not in dep:
continue
dep_path = dep.replace('@loader_path', '.')
target_dep = os.path.dirname(target_path) + '/' + os.path.basename(dep)
target_dep = self.consider_add_dependency(target_dep, dep_path, loader_path)
if not target_dep:
# It won't be included, so no use adjusting the path.
continue
new_dep = os.path.join('@loader_path', os.path.relpath(target_dep, os.path.dirname(target_path)))
subprocess.call(["install_name_tool", "-change", dep, new_dep, temp.name])
else:
subprocess.call(["strip", "-s", temp.name])
subprocess.call(["patchelf", "--set-rpath", "$ORIGIN", temp.name])
source_path = temp.name
ext = ext.lower()
if ext in ('.dll', '.pyd', '.exe'):
# Scan and add Win32 dependencies.
for dep in scan_dependencies(source_path):
target_dep = os.path.dirname(target_path) + '/' + dep
self.consider_add_dependency(target_dep, dep)
# Calculate the SHA-256 hash and size.
sha = hashlib.sha256()
fp = open(source_path, 'rb')
size = 0
data = fp.read(1024 * 1024)
while data:
size += len(data)
sha.update(data)
data = fp.read(1024 * 1024)
fp.close()
# Save it in PEP-0376 format for writing out later.
digest = str(urlsafe_b64encode(sha.digest()))
digest = digest.rstrip('=')
self.records.append("{0},sha256={1},{2}\n".format(target_path, digest, size))
if GetVerbose():
print("Adding %s from %s" % (target_path, source_path))
self.zip_file.write(source_path, target_path)
#if temp:
# os.unlink(temp.name)
def write_file_data(self, target_path, source_data):
"""Adds the given file from a string."""
sha = hashlib.sha256()
sha.update(source_data.encode())
digest = str(urlsafe_b64encode(sha.digest()))
digest = digest.rstrip('=')
self.records.append("{0},sha256={1},{2}\n".format(target_path, digest, len(source_data)))
if GetVerbose():
print("Adding %s from data" % target_path)
self.zip_file.writestr(target_path, source_data)
def write_directory(self, target_dir, source_dir):
"""Adds the given directory recursively to the .whl file."""
for root, dirs, files in os.walk(source_dir):
for file in files:
if os.path.splitext(file)[1] in EXCLUDE_EXT:
continue
source_path = os.path.join(root, file)
target_path = os.path.join(target_dir, os.path.relpath(source_path, source_dir))
target_path = target_path.replace('\\', '/')
self.write_file(target_path, source_path)
def close(self):
# Write the RECORD file.
record_file = "{0}-{1}.dist-info/RECORD".format(self.name, self.version)
self.records.append(record_file + ",,\n")
self.zip_file.writestr(record_file, "".join(self.records))
self.zip_file.close()
def makewheel(version, output_dir, platform=default_platform):
if sys.platform not in ("win32", "darwin") and not sys.platform.startswith("cygwin"):
if not LocateBinary("patchelf"):
raise Exception("patchelf is required when building a Linux wheel.")
platform = platform.replace('-', '_').replace('.', '_')
# Global filepaths
panda3d_dir = join(output_dir, "panda3d")
pandac_dir = join(output_dir, "pandac")
direct_dir = join(output_dir, "direct")
models_dir = join(output_dir, "models")
etc_dir = join(output_dir, "etc")
bin_dir = join(output_dir, "bin")
if sys.platform == "win32":
libs_dir = join(output_dir, "bin")
else:
libs_dir = join(output_dir, "lib")
license_src = "LICENSE"
readme_src = "README.md"
# Update relevant METADATA entries
METADATA['version'] = version
version_classifiers = [
"Programming Language :: Python :: {0}".format(*sys.version_info),
"Programming Language :: Python :: {0}.{1}".format(*sys.version_info),
]
METADATA['classifiers'].extend(version_classifiers)
# Build out the metadata
details = METADATA["extensions"]["python.details"]
homepage = details["project_urls"]["Home"]
author = details["contacts"][0]["name"]
email = details["contacts"][0]["email"]
metadata = ''.join([
"Metadata-Version: {metadata_version}\n" \
"Name: {name}\n" \
"Version: {version}\n" \
"Summary: {summary}\n" \
"License: {license}\n".format(**METADATA),
"Home-page: {0}\n".format(homepage),
"Author: {0}\n".format(author),
"Author-email: {0}\n".format(email),
"Platform: {0}\n".format(platform),
] + ["Classifier: {0}\n".format(c) for c in METADATA['classifiers']])
# Zip it up and name it the right thing
whl = WheelFile('panda3d', version, platform)
whl.lib_path = [libs_dir]
# Add the trees with Python modules.
whl.write_directory('direct', direct_dir)
# Write the panda3d tree. We use a custom empty __init__ since the
# default one adds the bin directory to the PATH, which we don't have.
whl.write_file_data('panda3d/__init__.py', '')
ext_suffix = GetExtensionSuffix()
for file in os.listdir(panda3d_dir):
if file == '__init__.py':
pass
elif file.endswith(ext_suffix) or file.endswith('.py'):
source_path = os.path.join(panda3d_dir, file)
if file.endswith('.pyd') and platform.startswith('cygwin'):
# Rename it to .dll for cygwin Python to be able to load it.
target_path = 'panda3d/' + os.path.splitext(file)[0] + '.dll'
else:
target_path = 'panda3d/' + file
whl.write_file(target_path, source_path)
# Add plug-ins.
for lib in PLUGIN_LIBS:
plugin_name = 'lib' + lib
if sys.platform in ('win32', 'cygwin'):
plugin_name += '.dll'
elif sys.platform == 'darwin':
plugin_name += '.dylib'
else:
plugin_name += '.so'
plugin_path = os.path.join(libs_dir, plugin_name)
if os.path.isfile(plugin_path):
whl.write_file('panda3d/' + plugin_name, plugin_path)
# Add the .data directory, containing additional files.
data_dir = 'panda3d-{0}.data'.format(version)
#whl.write_directory(data_dir + '/data/etc', etc_dir)
#whl.write_directory(data_dir + '/data/models', models_dir)
# Actually, let's not. That seems to install the files to the strangest
# places in the user's filesystem. Let's instead put them in panda3d.
whl.write_directory('panda3d/etc', etc_dir)
whl.write_directory('panda3d/models', models_dir)
# Add the pandac tree for backward compatibility.
for file in os.listdir(pandac_dir):
if file.endswith('.py'):
whl.write_file('pandac/' + file, os.path.join(pandac_dir, file))
# Add a panda3d-tools directory containing the executables.
entry_points = '[console_scripts]\n'
entry_points += 'eggcacher = direct.directscripts.eggcacher:main\n'
tools_init = ''
for file in os.listdir(bin_dir):
basename = os.path.splitext(file)[0]
if basename in ('eggcacher', 'packpanda'):
continue
source_path = os.path.join(bin_dir, file)
if is_executable(source_path):
# Put the .exe files inside the panda3d-tools directory.
whl.write_file('panda3d_tools/' + file, source_path)
# Tell pip to create a wrapper script.
funcname = basename.replace('-', '_')
entry_points += '{0} = panda3d_tools:{1}\n'.format(basename, funcname)
tools_init += '{0} = lambda: _exec_tool({1!r})\n'.format(funcname, file)
whl.write_file_data('panda3d_tools/__init__.py', PANDA3D_TOOLS_INIT.format(tools_init))
# Add the dist-info directory last.
info_dir = 'panda3d-{0}.dist-info'.format(version)
whl.write_file_data(info_dir + '/entry_points.txt', entry_points)
whl.write_file_data(info_dir + '/metadata.json', json.dumps(METADATA, indent=4, separators=(',', ': ')))
whl.write_file_data(info_dir + '/METADATA', metadata)
whl.write_file_data(info_dir + '/WHEEL', WHEEL_DATA.format(PY_VERSION, ABI_TAG, platform))
whl.write_file(info_dir + '/LICENSE.txt', license_src)
whl.write_file(info_dir + '/README.md', readme_src)
whl.write_file_data(info_dir + '/top_level.txt', 'direct\npanda3d\npandac\npanda3d_tools\n')
whl.close()
if __name__ == "__main__":
version = ParsePandaVersion("dtool/PandaVersion.pp")
parser = OptionParser()
parser.add_option('', '--version', dest = 'version', help = 'Panda3D version number (default: %s)' % (version), default = version)
parser.add_option('', '--outputdir', dest = 'outputdir', help = 'Makepanda\'s output directory (default: built)', default = 'built')
parser.add_option('', '--verbose', dest = 'verbose', help = 'Enable verbose output', action = 'store_true', default = False)
parser.add_option('', '--platform', dest = 'platform', help = 'Override platform tag (default: %s)' % (default_platform), default = get_platform())
(options, args) = parser.parse_args()
SetVerbose(options.verbose)
makewheel(options.version, options.outputdir, options.platform)

View File

@ -424,8 +424,8 @@ get_sound(const string &file_name, bool positional, int) {
vfs->resolve_filename(path, get_model_path());
// Build a new AudioSound from the audio data.
PT(AudioSound) audioSound = 0;
PT(FmodAudioSound) fmodAudioSound = new FmodAudioSound(this, path, positional );
PT(AudioSound) audioSound;
PT(FmodAudioSound) fmodAudioSound = new FmodAudioSound(this, path, positional);
_all_sounds.insert(fmodAudioSound);

View File

@ -1022,7 +1022,6 @@ cleanup() {
OpenALAudioManager::SoundData::
SoundData() :
_manager(0),
_movie(0),
_sample(0),
_stream(NULL),
_length(0.0),

View File

@ -140,11 +140,14 @@ load_display_information() {
// _display_information->_device_id = CGDisplaySerialNumber(_display);
// Display modes
size_t num_modes = 0;
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, NULL);
size_t num_modes = CFArrayGetCount(modes);
_display_information->_total_display_modes = num_modes;
_display_information->_display_mode_array = new DisplayMode[num_modes];
if (modes != NULL) {
num_modes = CFArrayGetCount(modes);
_display_information->_total_display_modes = num_modes;
_display_information->_display_mode_array = new DisplayMode[num_modes];
}
for (size_t i = 0; i < num_modes; ++i) {
CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
@ -181,13 +184,17 @@ load_display_information() {
}
CFRelease(encoding);
}
CFRelease(modes);
if (modes != NULL) {
CFRelease(modes);
}
#else
CFArrayRef modes = CGDisplayAvailableModes(_display);
size_t num_modes = CFArrayGetCount(modes);
_display_information->_total_display_modes = num_modes;
_display_information->_display_mode_array = new DisplayMode[num_modes];
if (modes != NULL) {
num_modes = CFArrayGetCount(modes);
_display_information->_total_display_modes = num_modes;
_display_information->_display_mode_array = new DisplayMode[num_modes];
}
for (size_t i = 0; i < num_modes; ++i) {
CFDictionaryRef mode = (CFDictionaryRef) CFArrayGetValueAtIndex(modes, i);

View File

@ -199,7 +199,7 @@ PT(CollisionEntry) CollisionBox::
test_intersection_from_sphere(const CollisionEntry &entry) const {
const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entry.get_from(), 0);
DCAST_INTO_R(sphere, entry.get_from(), NULL);
CPT(TransformState) wrt_space = entry.get_wrt_space();
CPT(TransformState) wrt_prev_space = entry.get_wrt_prev_space();
@ -402,7 +402,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionBox::
test_intersection_from_ray(const CollisionEntry &entry) const {
const CollisionRay *ray;
DCAST_INTO_R(ray, entry.get_from(), 0);
DCAST_INTO_R(ray, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
LPoint3 from_origin = ray->get_origin() * wrt_mat;
@ -483,7 +483,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionBox::
test_intersection_from_segment(const CollisionEntry &entry) const {
const CollisionSegment *seg;
DCAST_INTO_R(seg, entry.get_from(), 0);
DCAST_INTO_R(seg, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
LPoint3 from_origin = seg->get_point_a() * wrt_mat;
@ -564,7 +564,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionBox::
test_intersection_from_box(const CollisionEntry &entry) const {
const CollisionBox *box;
DCAST_INTO_R(box, entry.get_from(), 0);
DCAST_INTO_R(box, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();

View File

@ -125,7 +125,7 @@ compute_internal_bounds() const {
PT(CollisionEntry) CollisionFloorMesh::
test_intersection_from_ray(const CollisionEntry &entry) const {
const CollisionRay *ray;
DCAST_INTO_R(ray, entry.get_from(), 0);
DCAST_INTO_R(ray, entry.get_from(), NULL);
LPoint3 from_origin = ray->get_origin() * entry.get_wrt_mat();
double fx = from_origin[0];
@ -190,7 +190,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionFloorMesh::
test_intersection_from_sphere(const CollisionEntry &entry) const {
const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entry.get_from(), 0);
DCAST_INTO_R(sphere, entry.get_from(), NULL);
LPoint3 from_origin = sphere->get_center() * entry.get_wrt_mat();
double fx = from_origin[0];

View File

@ -136,7 +136,7 @@ handle_entries() {
// currently we only support spheres as the collider
const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entries.front()->get_from(), 0);
DCAST_INTO_R(sphere, entries.front()->get_from(), false);
from_node_path.set_pos(wrt_node, 0,0,0);
LPoint3 sphere_offset = (sphere->get_center() *

View File

@ -92,7 +92,7 @@ compute_internal_bounds() const {
PT(CollisionEntry) CollisionInvSphere::
test_intersection_from_sphere(const CollisionEntry &entry) const {
const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entry.get_from(), 0);
DCAST_INTO_R(sphere, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -144,7 +144,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionInvSphere::
test_intersection_from_line(const CollisionEntry &entry) const {
const CollisionLine *line;
DCAST_INTO_R(line, entry.get_from(), 0);
DCAST_INTO_R(line, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -185,7 +185,7 @@ test_intersection_from_line(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionInvSphere::
test_intersection_from_ray(const CollisionEntry &entry) const {
const CollisionRay *ray;
DCAST_INTO_R(ray, entry.get_from(), 0);
DCAST_INTO_R(ray, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -228,7 +228,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionInvSphere::
test_intersection_from_segment(const CollisionEntry &entry) const {
const CollisionSegment *segment;
DCAST_INTO_R(segment, entry.get_from(), 0);
DCAST_INTO_R(segment, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();

View File

@ -107,7 +107,7 @@ compute_internal_bounds() const {
PT(CollisionEntry) CollisionPlane::
test_intersection_from_sphere(const CollisionEntry &entry) const {
const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entry.get_from(), 0);
DCAST_INTO_R(sphere, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -146,7 +146,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionPlane::
test_intersection_from_line(const CollisionEntry &entry) const {
const CollisionLine *line;
DCAST_INTO_R(line, entry.get_from(), 0);
DCAST_INTO_R(line, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -191,7 +191,7 @@ test_intersection_from_line(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionPlane::
test_intersection_from_ray(const CollisionEntry &entry) const {
const CollisionRay *ray;
DCAST_INTO_R(ray, entry.get_from(), 0);
DCAST_INTO_R(ray, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -243,7 +243,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionPlane::
test_intersection_from_segment(const CollisionEntry &entry) const {
const CollisionSegment *segment;
DCAST_INTO_R(segment, entry.get_from(), 0);
DCAST_INTO_R(segment, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -300,7 +300,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionPlane::
test_intersection_from_tube(const CollisionEntry &entry) const {
const CollisionTube *tube;
DCAST_INTO_R(tube, entry.get_from(), 0);
DCAST_INTO_R(tube, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -371,7 +371,7 @@ test_intersection_from_tube(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionPlane::
test_intersection_from_parabola(const CollisionEntry &entry) const {
const CollisionParabola *parabola;
DCAST_INTO_R(parabola, entry.get_from(), 0);
DCAST_INTO_R(parabola, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -437,7 +437,7 @@ test_intersection_from_parabola(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionPlane::
test_intersection_from_box(const CollisionEntry &entry) const {
const CollisionBox *box;
DCAST_INTO_R(box, entry.get_from(), 0);
DCAST_INTO_R(box, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();

View File

@ -364,7 +364,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
}
const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entry.get_from(), 0);
DCAST_INTO_R(sphere, entry.get_from(), NULL);
CPT(TransformState) wrt_space = entry.get_wrt_space();
CPT(TransformState) wrt_prev_space = entry.get_wrt_prev_space();
@ -545,7 +545,7 @@ test_intersection_from_line(const CollisionEntry &entry) const {
}
const CollisionLine *line;
DCAST_INTO_R(line, entry.get_from(), 0);
DCAST_INTO_R(line, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -613,7 +613,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
}
const CollisionRay *ray;
DCAST_INTO_R(ray, entry.get_from(), 0);
DCAST_INTO_R(ray, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -686,7 +686,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
}
const CollisionSegment *segment;
DCAST_INTO_R(segment, entry.get_from(), 0);
DCAST_INTO_R(segment, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -761,7 +761,7 @@ test_intersection_from_parabola(const CollisionEntry &entry) const {
}
const CollisionParabola *parabola;
DCAST_INTO_R(parabola, entry.get_from(), 0);
DCAST_INTO_R(parabola, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -846,7 +846,7 @@ test_intersection_from_parabola(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionPolygon::
test_intersection_from_box(const CollisionEntry &entry) const {
const CollisionBox *box;
DCAST_INTO_R(box, entry.get_from(), 0);
DCAST_INTO_R(box, entry.get_from(), NULL);
// To make things easier, transform the box into the coordinate space of the
// plane.

View File

@ -120,7 +120,7 @@ compute_internal_bounds() const {
PT(CollisionEntry) CollisionSphere::
test_intersection_from_sphere(const CollisionEntry &entry) const {
const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entry.get_from(), 0);
DCAST_INTO_R(sphere, entry.get_from(), NULL);
CPT(TransformState) wrt_space = entry.get_wrt_space();
@ -231,7 +231,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionSphere::
test_intersection_from_line(const CollisionEntry &entry) const {
const CollisionLine *line;
DCAST_INTO_R(line, entry.get_from(), 0);
DCAST_INTO_R(line, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -271,7 +271,7 @@ test_intersection_from_line(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionSphere::
test_intersection_from_box(const CollisionEntry &entry) const {
const CollisionBox *box;
DCAST_INTO_R(box, entry.get_from(), 0);
DCAST_INTO_R(box, entry.get_from(), NULL);
// Instead of transforming the box into the sphere's coordinate space, we do
// it the other way around. It's easier that way.
@ -347,7 +347,7 @@ test_intersection_from_box(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionSphere::
test_intersection_from_ray(const CollisionEntry &entry) const {
const CollisionRay *ray;
DCAST_INTO_R(ray, entry.get_from(), 0);
DCAST_INTO_R(ray, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -394,7 +394,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionSphere::
test_intersection_from_segment(const CollisionEntry &entry) const {
const CollisionSegment *segment;
DCAST_INTO_R(segment, entry.get_from(), 0);
DCAST_INTO_R(segment, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -443,7 +443,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionSphere::
test_intersection_from_tube(const CollisionEntry &entry) const {
const CollisionTube *tube;
DCAST_INTO_R(tube, entry.get_from(), 0);
DCAST_INTO_R(tube, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -499,7 +499,7 @@ test_intersection_from_tube(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionSphere::
test_intersection_from_parabola(const CollisionEntry &entry) const {
const CollisionParabola *parabola;
DCAST_INTO_R(parabola, entry.get_from(), 0);
DCAST_INTO_R(parabola, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();

View File

@ -146,7 +146,7 @@ compute_internal_bounds() const {
PT(CollisionEntry) CollisionTube::
test_intersection_from_sphere(const CollisionEntry &entry) const {
const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entry.get_from(), 0);
DCAST_INTO_R(sphere, entry.get_from(), NULL);
CPT(TransformState) wrt_space = entry.get_wrt_space();
CPT(TransformState) wrt_prev_space = entry.get_wrt_prev_space();
@ -224,7 +224,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionTube::
test_intersection_from_line(const CollisionEntry &entry) const {
const CollisionLine *line;
DCAST_INTO_R(line, entry.get_from(), 0);
DCAST_INTO_R(line, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -272,7 +272,7 @@ test_intersection_from_line(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionTube::
test_intersection_from_ray(const CollisionEntry &entry) const {
const CollisionRay *ray;
DCAST_INTO_R(ray, entry.get_from(), 0);
DCAST_INTO_R(ray, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -333,7 +333,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionTube::
test_intersection_from_segment(const CollisionEntry &entry) const {
const CollisionSegment *segment;
DCAST_INTO_R(segment, entry.get_from(), 0);
DCAST_INTO_R(segment, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
@ -397,7 +397,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
PT(CollisionEntry) CollisionTube::
test_intersection_from_parabola(const CollisionEntry &entry) const {
const CollisionParabola *parabola;
DCAST_INTO_R(parabola, entry.get_from(), 0);
DCAST_INTO_R(parabola, entry.get_from(), NULL);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();

View File

@ -480,8 +480,8 @@ set_cull_result(PT(CullResult) cull_result, PT(SceneSetup) scene_setup,
Thread *current_thread) {
CDCullWriter cdata(_cycler_cull, true, current_thread);
#ifdef USE_MOVE_SEMANTICS
cdata->_cull_result = std::move(cull_result);
cdata->_scene_setup = std::move(scene_setup);
cdata->_cull_result = move(cull_result);
cdata->_scene_setup = move(scene_setup);
#else
swap(cdata->_cull_result, cull_result);
swap(cdata->_scene_setup, scene_setup);

View File

@ -49,19 +49,6 @@ struct XVisualInfo;
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#ifdef HAVE_XRANDR
#include <X11/extensions/Xrandr.h>
#endif // HAVE_XRANDR
#ifdef HAVE_XCURSOR
#include <X11/Xcursor/Xcursor.h>
#endif
#ifdef HAVE_XF86DGA
#include <X11/extensions/Xxf86dga.h>
#endif
#include "post_x11_include.h"
#endif // CPPPARSER

View File

@ -62,6 +62,14 @@ release_all_index_buffers() {
return _prepared_objects->release_all_index_buffers();
}
/**
* Frees the resources for all index buffers associated with this GSG.
*/
INLINE int GraphicsStateGuardian::
release_all_shader_buffers() {
return _prepared_objects->release_all_shader_buffers();
}
/**
* Sets the active flag associated with the GraphicsStateGuardian. If the
* GraphicsStateGuardian is marked inactive, nothing is rendered. This is not

View File

@ -62,12 +62,15 @@
#include <algorithm>
#include <limits.h>
PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Vertex buffer switch:Vertex");
PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Vertex buffer switch:Index");
PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Buffer switch:Vertex");
PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Buffer switch:Index");
PStatCollector GraphicsStateGuardian::_shader_buffer_switch_pcollector("Buffer switch:Shader");
PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector("Draw:Transfer data:Vertex buffer");
PStatCollector GraphicsStateGuardian::_load_index_buffer_pcollector("Draw:Transfer data:Index buffer");
PStatCollector GraphicsStateGuardian::_load_shader_buffer_pcollector("Draw:Transfer data:Shader buffer");
PStatCollector GraphicsStateGuardian::_create_vertex_buffer_pcollector("Draw:Transfer data:Create Vertex buffer");
PStatCollector GraphicsStateGuardian::_create_index_buffer_pcollector("Draw:Transfer data:Create Index buffer");
PStatCollector GraphicsStateGuardian::_create_shader_buffer_pcollector("Draw:Transfer data:Create Shader buffer");
PStatCollector GraphicsStateGuardian::_load_texture_pcollector("Draw:Transfer data:Texture");
PStatCollector GraphicsStateGuardian::_data_transferred_pcollector("Data transferred");
PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector("Texture manager");
@ -104,6 +107,7 @@ PStatCollector GraphicsStateGuardian::_prepare_geom_pcollector("Draw:Prepare:Geo
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::_prepare_shader_buffer_pcollector("Draw:Prepare:Shader 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");
@ -147,6 +151,10 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
_coordinate_system = CS_invalid;
_internal_transform = TransformState::make_identity();
if (_internal_coordinate_system == CS_default) {
_internal_coordinate_system = get_default_coordinate_system();
}
set_coordinate_system(get_default_coordinate_system());
_data_reader = (GeomVertexDataPipelineReader *)NULL;
@ -653,6 +661,22 @@ void GraphicsStateGuardian::
release_index_buffer(IndexBufferContext *) {
}
/**
* Prepares the indicated buffer for retained-mode rendering.
*/
BufferContext *GraphicsStateGuardian::
prepare_shader_buffer(ShaderBuffer *) {
return (BufferContext *)NULL;
}
/**
* Frees the resources previously allocated via a call to prepare_data(),
* including deleting the BufferContext itself, if necessary.
*/
void GraphicsStateGuardian::
release_shader_buffer(BufferContext *) {
}
/**
* Begins a new occlusion query. After this call, you may call
* begin_draw_primitives() and draw_triangles()/draw_whatever() repeatedly.

View File

@ -88,6 +88,7 @@ PUBLISHED:
INLINE int release_all_geoms();
INLINE int release_all_vertex_buffers();
INLINE int release_all_index_buffers();
INLINE int release_all_shader_buffers();
INLINE void set_active(bool active);
INLINE bool is_active() const;
@ -307,6 +308,9 @@ public:
virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data);
virtual void release_index_buffer(IndexBufferContext *ibc);
virtual BufferContext *prepare_shader_buffer(ShaderBuffer *data);
virtual void release_shader_buffer(BufferContext *ibc);
virtual void begin_occlusion_query();
virtual PT(OcclusionQueryContext) end_occlusion_query();
@ -322,7 +326,7 @@ public:
virtual void set_state_and_transform(const RenderState *state,
const TransformState *transform);
virtual PN_stdfloat compute_distance_to(const LPoint3 &point) const;
PN_stdfloat compute_distance_to(const LPoint3 &point) const;
virtual void clear(DrawableRegion *clearable);
@ -640,10 +644,13 @@ public:
// Statistics
static PStatCollector _vertex_buffer_switch_pcollector;
static PStatCollector _index_buffer_switch_pcollector;
static PStatCollector _shader_buffer_switch_pcollector;
static PStatCollector _load_vertex_buffer_pcollector;
static PStatCollector _load_index_buffer_pcollector;
static PStatCollector _load_shader_buffer_pcollector;
static PStatCollector _create_vertex_buffer_pcollector;
static PStatCollector _create_index_buffer_pcollector;
static PStatCollector _create_shader_buffer_pcollector;
static PStatCollector _load_texture_pcollector;
static PStatCollector _data_transferred_pcollector;
static PStatCollector _texmgrmem_total_pcollector;
@ -680,6 +687,7 @@ public:
static PStatCollector _prepare_shader_pcollector;
static PStatCollector _prepare_vertex_buffer_pcollector;
static PStatCollector _prepare_index_buffer_pcollector;
static PStatCollector _prepare_shader_buffer_pcollector;
// A whole slew of collectors to measure the cost of individual state
// changes. These are disabled by default.

View File

@ -231,11 +231,13 @@ operator = (const HTTPClient &copy) {
*/
HTTPClient::
~HTTPClient() {
// Before we can free the context, we must remove the X509_STORE pointer
// from it, so it won't be destroyed along with it (this object is shared
// among all contexts).
if (_ssl_ctx != (SSL_CTX *)NULL) {
#if OPENSSL_VERSION_NUMBER < 0x10100000
// Before we can free the context, we must remove the X509_STORE pointer
// from it, so it won't be destroyed along with it (this object is shared
// among all contexts).
_ssl_ctx->cert_store = NULL;
#endif
SSL_CTX_free(_ssl_ctx);
}
@ -805,7 +807,7 @@ load_client_certificate() {
// Rewind the "file" to the beginning in order to read the public key
// (which might appear first in the file).
BIO_reset(mbio);
(void)BIO_reset(mbio);
ERR_clear_error();
_client_certificate_pub =
@ -1122,7 +1124,13 @@ get_ssl_ctx() {
OpenSSLWrapper *sslw = OpenSSLWrapper::get_global_ptr();
sslw->notify_ssl_errors();
SSL_CTX_set_cert_store(_ssl_ctx, sslw->get_x509_store());
X509_STORE *store = sslw->get_x509_store();
#if OPENSSL_VERSION_NUMBER >= 0x10100000
if (store != NULL) {
X509_STORE_up_ref(store);
}
#endif
SSL_CTX_set_cert_store(_ssl_ctx, store);
return _ssl_ctx;
}
@ -1511,15 +1519,17 @@ x509_name_subset(X509_NAME *name_a, X509_NAME *name_b) {
for (int ai = 0; ai < count_a; ai++) {
X509_NAME_ENTRY *na = X509_NAME_get_entry(name_a, ai);
int bi = X509_NAME_get_index_by_OBJ(name_b, na->object, -1);
int bi = X509_NAME_get_index_by_OBJ(name_b, X509_NAME_ENTRY_get_object(na), -1);
if (bi < 0) {
// This entry in name_a is not defined in name_b.
return false;
}
X509_NAME_ENTRY *nb = X509_NAME_get_entry(name_b, bi);
if (na->value->length != nb->value->length ||
memcmp(na->value->data, nb->value->data, na->value->length) != 0) {
ASN1_STRING *na_value = X509_NAME_ENTRY_get_data(na);
ASN1_STRING *nb_value = X509_NAME_ENTRY_get_data(nb);
if (na_value->length != nb_value->length ||
memcmp(na_value->data, nb_value->data, na_value->length) != 0) {
// This entry in name_a doesn't match that of name_b.
return false;
}

View File

@ -19,6 +19,16 @@
TypeHandle wdxGraphicsPipe9::_type_handle;
static bool MyGetProcAddr(HINSTANCE hDLL, FARPROC *pFn, const char *szExportedFnName) {
*pFn = (FARPROC) GetProcAddress(hDLL, szExportedFnName);
if (*pFn == NULL) {
wdxdisplay9_cat.error()
<< "GetProcAddr failed for " << szExportedFnName << ", error=" << GetLastError() <<endl;
return false;
}
return true;
}
#define LOWVIDMEMTHRESHOLD 5700000 // 4MB cards should fall below this
#define CRAPPY_DRIVER_IS_LYING_VIDMEMTHRESHOLD 1000000 // if # is > 1MB, card is lying and I cant tell what it is
#define UNKNOWN_VIDMEM_SIZE 0xFFFFFFFF
@ -154,7 +164,10 @@ make_output(const string &name,
*/
bool wdxGraphicsPipe9::
init() {
if (!MyLoadLib(_hDDrawDLL, "ddraw.dll")) {
_hDDrawDLL = LoadLibrary("ddraw.dll");
if (_hDDrawDLL == NULL) {
wdxdisplay9_cat.error()
<< "LoadLibrary failed for ddraw.dll, error=" << GetLastError() <<endl;
goto error;
}
@ -166,7 +179,10 @@ init() {
goto error;
}
if (!MyLoadLib(_hD3D9_DLL, "d3d9.dll")) {
_hD3D9_DLL = LoadLibrary("d3d9.dll");
if (_hD3D9_DLL == NULL) {
wdxdisplay9_cat.error()
<< "LoadLibrary failed for d3d9.dll, error=" << GetLastError() <<endl;
goto error;
}

View File

@ -14,6 +14,115 @@
#include "filename_ext.h"
#ifdef HAVE_PYTHON
#ifndef CPPPARSER
extern Dtool_PyTypedObject Dtool_Filename;
#endif // CPPPARSER
/**
* Constructs a Filename object from a str, bytes object, or os.PathLike.
*/
void Extension<Filename>::
__init__(PyObject *path) {
nassertv(path != NULL);
nassertv(_this != NULL);
Py_ssize_t length;
if (PyUnicode_CheckExact(path)) {
wchar_t *data;
#if PY_VERSION_HEX >= 0x03020000
data = PyUnicode_AsWideCharString(path, &length);
#else
length = PyUnicode_GET_SIZE(path);
data = (wchar_t *)alloca(sizeof(wchar_t) * (length + 1));
PyUnicode_AsWideChar((PyUnicodeObject *)path, data, length);
#endif
(*_this) = wstring(data, length);
#if PY_VERSION_HEX >= 0x03020000
PyMem_Free(data);
#endif
return;
}
if (PyBytes_CheckExact(path)) {
char *data;
PyBytes_AsStringAndSize(path, &data, &length);
(*_this) = string(data, length);
return;
}
if (Py_TYPE(path) == &Dtool_Filename._PyType) {
// Copy constructor.
(*_this) = *((Filename *)((Dtool_PyInstDef *)path)->_ptr_to_object);
return;
}
PyObject *path_str;
#if PY_VERSION_HEX >= 0x03060000
// It must be an os.PathLike object. Check for an __fspath__ method.
PyObject *fspath = PyObject_GetAttrString((PyObject *)Py_TYPE(path), "__fspath__");
if (fspath == NULL) {
PyErr_Format(PyExc_TypeError, "expected str, bytes or os.PathLike object, not %s", Py_TYPE(path)->tp_name);
return;
}
path_str = PyObject_CallFunctionObjArgs(fspath, path, NULL);
Py_DECREF(fspath);
#else
// There is no standard path protocol before Python 3.6, but let's try and
// support taking pathlib paths anyway. We don't version check this to
// allow people to use backports of the pathlib module.
if (PyObject_HasAttrString(path, "_format_parsed_parts")) {
path_str = PyObject_Str(path);
} else {
#if PY_VERSION_HEX >= 0x03040000
PyErr_Format(PyExc_TypeError, "expected str, bytes, Path or Filename object, not %s", Py_TYPE(path)->tp_name);
#elif PY_MAJOR_VERSION >= 3
PyErr_Format(PyExc_TypeError, "expected str, bytes or Filename object, not %s", Py_TYPE(path)->tp_name);
#else
PyErr_Format(PyExc_TypeError, "expected str or unicode object, not %s", Py_TYPE(path)->tp_name);
#endif
return;
}
#endif
if (path_str == NULL) {
return;
}
if (PyUnicode_CheckExact(path_str)) {
wchar_t *data;
#if PY_VERSION_HEX >= 0x03020000
data = PyUnicode_AsWideCharString(path_str, &length);
#else
length = PyUnicode_GET_SIZE(path_str);
data = (wchar_t *)alloca(sizeof(wchar_t) * (length + 1));
PyUnicode_AsWideChar((PyUnicodeObject *)path_str, data, length);
#endif
(*_this) = Filename::from_os_specific_w(wstring(data, length));
#if PY_VERSION_HEX >= 0x03020000
PyMem_Free(data);
#endif
} else if (PyBytes_CheckExact(path_str)) {
char *data;
PyBytes_AsStringAndSize(path_str, &data, &length);
(*_this) = Filename::from_os_specific(string(data, length));
} else {
#if PY_MAJOR_VERSION >= 3
PyErr_Format(PyExc_TypeError, "expected str or bytes object, not %s", Py_TYPE(path_str)->tp_name);
#else
PyErr_Format(PyExc_TypeError, "expected str or unicode object, not %s", Py_TYPE(path_str)->tp_name);
#endif
}
Py_DECREF(path_str);
}
/**
* This special Python method is implement to provide support for the pickle
* module.
@ -62,6 +171,16 @@ __repr__() const {
return result;
}
/**
* Allows a Filename object to be passed to any Python function that accepts
* an os.PathLike object.
*/
PyObject *Extension<Filename>::
__fspath__() const {
wstring filename = _this->to_os_specific_w();
return PyUnicode_FromWideChar(filename.data(), (Py_ssize_t)filename.size());
}
/**
* This variant on scan_directory returns a Python list of strings on success,
* or None on failure.

View File

@ -29,8 +29,11 @@
template<>
class Extension<Filename> : public ExtensionBase<Filename> {
public:
void __init__(PyObject *path);
PyObject *__reduce__(PyObject *self) const;
PyObject *__repr__() const;
PyObject *__fspath__() const;
PyObject *scan_directory() const;
};

View File

@ -76,6 +76,14 @@ ConfigVariableInt ffmpeg_read_buffer_size
"This is important for performance. A typical size is that of a "
"cache page, e.g. 4kb."));
ConfigVariableBool ffmpeg_prefer_libvpx
("ffmpeg-prefer-libvpx", false,
PRC_DESC("If this is true, Panda will overrule ffmpeg's best judgment on "
"which decoder to use for decoding VP8 and VP9 files, and try to "
"choose libvpx. This is useful when you want to play WebM videos "
"with an alpha channel, which aren't supported by ffmpeg's own "
"VP8/VP9 decoders."));
/**
* Initializes the library. This must be called at least once before any of
* the functions or classes in this library can be used. Normally it will be

View File

@ -31,6 +31,7 @@ extern ConfigVariableBool ffmpeg_support_seek;
extern ConfigVariableBool ffmpeg_global_lock;
extern ConfigVariableEnum<ThreadPriority> ffmpeg_thread_priority;
extern ConfigVariableInt ffmpeg_read_buffer_size;
extern ConfigVariableBool ffmpeg_prefer_libvpx;
extern EXPCL_FFMPEG void init_libffmpeg();

View File

@ -50,9 +50,7 @@ FfmpegAudioCursor(FfmpegAudio *src) :
_packet_data(0),
_format_ctx(0),
_audio_ctx(0),
#ifdef HAVE_SWRESAMPLE
_resample_ctx(0),
#endif
_buffer(0),
_buffer_alloc(0),
_frame(0)

View File

@ -31,10 +31,7 @@ struct AVFormatContext;
struct AVCodecContext;
struct AVStream;
struct AVPacket;
#ifdef HAVE_SWRESAMPLE
struct SwrContext;
#endif
/**
* A stream that generates a sequence of audio samples.
@ -72,9 +69,7 @@ protected:
int _buffer_head;
int _buffer_tail;
#ifdef HAVE_SWRESAMPLE
SwrContext *_resample_ctx;
#endif
public:
static TypeHandle get_class_type() {

View File

@ -22,6 +22,7 @@
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/pixdesc.h"
#ifdef HAVE_SWSCALE
#include "libswscale/swscale.h"
#endif
@ -35,11 +36,25 @@ PStatCollector FfmpegVideoCursor::_fetch_buffer_pcollector("*:FFMPEG Video Decod
PStatCollector FfmpegVideoCursor::_seek_pcollector("*:FFMPEG Video Decoding:Seek");
PStatCollector FfmpegVideoCursor::_export_frame_pcollector("*:FFMPEG Convert Video to BGR");
#if LIBAVFORMAT_VERSION_MAJOR < 53
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
#endif
#if LIBAVCODEC_VERSION_MAJOR < 54
#define AV_CODEC_ID_VP8 CODEC_ID_VP8
#endif
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 74, 100)
#define AV_PIX_FMT_NONE PIX_FMT_NONE
#define AV_PIX_FMT_BGR24 PIX_FMT_BGR24
#define AV_PIX_FMT_BGRA PIX_FMT_BGRA
typedef PixelFormat AVPixelFormat;
#endif
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 32, 100)
#define AV_PIX_FMT_FLAG_ALPHA PIX_FMT_ALPHA
#endif
/**
* This constructor is only used when reading from a bam file.
*/
@ -55,6 +70,7 @@ FfmpegVideoCursor() :
_format_ctx(NULL),
_video_ctx(NULL),
_convert_ctx(NULL),
_pixel_format((int)AV_PIX_FMT_NONE),
_video_index(-1),
_frame(NULL),
_frame_out(NULL),
@ -80,17 +96,6 @@ init_from(FfmpegVideo *source) {
ReMutexHolder av_holder(_av_lock);
#ifdef HAVE_SWSCALE
nassertv(_convert_ctx == NULL);
_convert_ctx = sws_getContext(_size_x, _size_y, _video_ctx->pix_fmt,
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 74, 100)
_size_x, _size_y, AV_PIX_FMT_BGR24,
#else
_size_x, _size_y, PIX_FMT_BGR24,
#endif
SWS_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL);
#endif // HAVE_SWSCALE
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
_frame = av_frame_alloc();
_frame_out = av_frame_alloc();
@ -115,6 +120,28 @@ init_from(FfmpegVideo *source) {
_eof_known = false;
_eof_frame = 0;
#if LIBAVUTIL_VERSION_MAJOR >= 52
// Check if we got an alpha format. Please note that some video codecs
// (eg. libvpx) change the pix_fmt after decoding the first frame, which is
// why we didn't do this earlier.
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(_video_ctx->pix_fmt);
if (desc && (desc->flags & AV_PIX_FMT_FLAG_ALPHA) != 0) {
_num_components = 4;
_pixel_format = (int)AV_PIX_FMT_BGRA;
} else
#endif
{
_num_components = 3;
_pixel_format = (int)AV_PIX_FMT_BGR24;
}
#ifdef HAVE_SWSCALE
nassertv(_convert_ctx == NULL);
_convert_ctx = sws_getContext(_size_x, _size_y, _video_ctx->pix_fmt,
_size_x, _size_y, (AVPixelFormat)_pixel_format,
SWS_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL);
#endif // HAVE_SWSCALE
#ifdef HAVE_THREADS
set_max_readahead_frames(ffmpeg_max_readahead_frames);
#endif // HAVE_THREADS
@ -300,13 +327,13 @@ set_time(double timestamp, int loop_count) {
if (_eof_known) {
if (loop_count == 0) {
frame = frame % _eof_frame;
frame = frame % (_eof_frame + 1);
} else {
int last_frame = _eof_frame * loop_count;
int last_frame = (_eof_frame + 1) * loop_count;
if (frame < last_frame) {
frame = frame % _eof_frame;
frame = frame % (_eof_frame + 1);
} else {
frame = _eof_frame - 1;
frame = _eof_frame;
}
}
}
@ -495,7 +522,17 @@ open_stream() {
return false;
}
AVCodec *pVideoCodec = avcodec_find_decoder(_video_ctx->codec_id);
AVCodec *pVideoCodec = NULL;
if (ffmpeg_prefer_libvpx) {
if ((int)_video_ctx->codec_id == 168) { // AV_CODEC_ID_VP9
pVideoCodec = avcodec_find_decoder_by_name("libvpx-vp9");
} else if (_video_ctx->codec_id == AV_CODEC_ID_VP8) {
pVideoCodec = avcodec_find_decoder_by_name("libvpx");
}
}
if (pVideoCodec == NULL) {
pVideoCodec = avcodec_find_decoder(_video_ctx->codec_id);
}
if (pVideoCodec == NULL) {
ffmpeg_cat.info()
<< "Couldn't find codec\n";
@ -515,7 +552,7 @@ open_stream() {
_size_x = _video_ctx->width;
_size_y = _video_ctx->height;
_num_components = 3; // Don't know how to implement RGBA movies yet.
_num_components = 3;
_length = (double)_format_ctx->duration / (double)AV_TIME_BASE;
_can_seek = true;
_can_seek_fast = true;
@ -1075,8 +1112,8 @@ export_frame(FfmpegBuffer *buffer) {
return;
}
_frame_out->data[0] = buffer->_block + ((_size_y - 1) * _size_x * 3);
_frame_out->linesize[0] = _size_x * -3;
_frame_out->data[0] = buffer->_block + ((_size_y - 1) * _size_x * _num_components);
_frame_out->linesize[0] = _size_x * -_num_components;
buffer->_begin_frame = _begin_frame;
buffer->_end_frame = _end_frame;
@ -1086,7 +1123,7 @@ export_frame(FfmpegBuffer *buffer) {
nassertv(_convert_ctx != NULL && _frame != NULL && _frame_out != NULL);
sws_scale(_convert_ctx, _frame->data, _frame->linesize, 0, _size_y, _frame_out->data, _frame_out->linesize);
#else
img_convert((AVPicture *)_frame_out, PIX_FMT_BGR24,
img_convert((AVPicture *)_frame_out, (AVPixelFormat)_pixel_format,
(AVPicture *)_frame, _video_ctx->pix_fmt, _size_x, _size_y);
#endif
} else {
@ -1094,7 +1131,7 @@ export_frame(FfmpegBuffer *buffer) {
nassertv(_convert_ctx != NULL && _frame != NULL && _frame_out != NULL);
sws_scale(_convert_ctx, _frame->data, _frame->linesize, 0, _size_y, _frame_out->data, _frame_out->linesize);
#else
img_convert((AVPicture *)_frame_out, PIX_FMT_BGR24,
img_convert((AVPicture *)_frame_out, (AVPixelFormat)_pixel_format,
(AVPicture *)_frame, _video_ctx->pix_fmt, _size_x, _size_y);
#endif
}

View File

@ -105,6 +105,8 @@ private:
ThreadPriority _thread_priority;
PT(GenericThread) _thread;
int _pixel_format;
// This global Mutex protects calls to avcodec_opencloseetc.
static ReMutex _av_lock;

View File

@ -0,0 +1,25 @@
/**
* 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."
*
* @file glBufferContext_src.I
* @author rdb
* @date 2016-12-12
*/
/**
*
*/
INLINE CLP(BufferContext)::
CLP(BufferContext)(CLP(GraphicsStateGuardian) *glgsg,
PreparedGraphicsObjects *pgo) :
BufferContext(&pgo->_sbuffer_residency),
AdaptiveLruPage(0),
_glgsg(glgsg)
{
_index = 0;
}

View File

@ -0,0 +1,49 @@
/**
* 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."
*
* @file glBufferContext_src.cxx
* @author rdb
* @date 2016-12-12
*/
TypeHandle CLP(BufferContext)::_type_handle;
/**
* Evicts the page from the LRU. Called internally when the LRU determines
* that it is full. May also be called externally when necessary to
* explicitly evict the page.
*
* It is legal for this method to either evict the page as requested, do
* nothing (in which case the eviction will be requested again at the next
* epoch), or requeue itself on the tail of the queue (in which case the
* eviction will be requested again much later).
*/
void CLP(BufferContext)::
evict_lru() {
dequeue_lru();
// Make sure the buffer is unbound before we delete it.
if (_glgsg->_current_ibuffer_index == _index) {
if (GLCAT.is_debug() && gl_debug_buffers) {
GLCAT.debug()
<< "unbinding index buffer\n";
}
_glgsg->_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
_glgsg->_current_ibuffer_index = 0;
}
// Free the buffer.
_glgsg->_glDeleteBuffers(1, &_index);
// We still need a valid index number, though, in case we want to re-load
// the buffer later.
_glgsg->_glGenBuffers(1, &_index);
update_data_size_bytes(0);
set_resident(false);
}

View File

@ -0,0 +1,52 @@
/**
* 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."
*
* @file glBufferContext_src.h
* @author rdb
* @date 2016-12-12
*/
#include "pandabase.h"
#include "bufferContext.h"
#include "deletedChain.h"
/**
* Caches a GeomPrimitive on the GL as a buffer object.
*/
class EXPCL_GL CLP(BufferContext) : public BufferContext, public AdaptiveLruPage {
public:
INLINE CLP(BufferContext)(CLP(GraphicsStateGuardian) *glgsg,
PreparedGraphicsObjects *pgo);
ALLOC_DELETED_CHAIN(CLP(BufferContext));
virtual void evict_lru();
CLP(GraphicsStateGuardian) *_glgsg;
// This is the GL "name" of the data object.
GLuint _index;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
BufferContext::init_type();
register_type(_type_handle, CLASSPREFIX_QUOTED "BufferContext",
BufferContext::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 "glBufferContext_src.I"

View File

@ -1796,7 +1796,7 @@ reset() {
}
#endif
#ifndef OPENGLES
#ifndef OPENGLES_1
// Check for uniform buffers.
#ifdef OPENGLES
if (is_at_least_gl_version(3, 1) || has_extension("GL_ARB_uniform_buffer_object")) {
@ -1810,12 +1810,30 @@ reset() {
get_extension_func("glGetActiveUniformBlockiv");
_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)
get_extension_func("glGetActiveUniformBlockName");
_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)
get_extension_func("glBindBufferBase");
} else {
_supports_uniform_buffers = false;
}
#ifndef OPENGLES
// Check for SSBOs.
if (is_at_least_gl_version(4, 3) || has_extension("ARB_shader_storage_buffer_object")) {
_supports_shader_buffers = true;
_glGetProgramInterfaceiv = (PFNGLGETPROGRAMINTERFACEIVPROC)
get_extension_func("glGetProgramInterfaceiv");
_glGetProgramResourceName = (PFNGLGETPROGRAMRESOURCENAMEPROC)
get_extension_func("glGetProgramResourceName");
_glGetProgramResourceiv = (PFNGLGETPROGRAMRESOURCEIVPROC)
get_extension_func("glGetProgramResourceiv");
} else
#endif
{
_supports_shader_buffers = false;
}
if (_supports_uniform_buffers || _supports_shader_buffers) {
_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)
get_extension_func("glBindBufferBase");
}
#endif
// Check whether we support geometry instancing and instanced vertex
@ -3031,6 +3049,9 @@ reset() {
_current_vertex_buffers.clear();
_current_vertex_format.clear();
memset(_vertex_attrib_columns, 0, sizeof(const GeomVertexColumn *) * 32);
_current_sbuffer_index = 0;
_current_sbuffer_base.clear();
#endif
report_my_gl_errors();
@ -5873,6 +5894,122 @@ setup_primitive(const unsigned char *&client_pointer,
return true;
}
#ifndef OPENGLES
/**
* Creates a new retained-mode representation of the given data, and returns a
* newly-allocated BufferContext pointer to reference it. It is the
* responsibility of the calling function to later call release_shader_buffer()
* with this same pointer (which will also delete the pointer).
*
* This function should not be called directly to prepare a buffer. Instead,
* call ShaderBuffer::prepare().
*/
BufferContext *CLP(GraphicsStateGuardian)::
prepare_shader_buffer(ShaderBuffer *data) {
if (_supports_shader_buffers) {
PStatGPUTimer timer(this, _prepare_shader_buffer_pcollector);
CLP(BufferContext) *gbc = new CLP(BufferContext)(this, _prepared_objects);
_glGenBuffers(1, &gbc->_index);
if (GLCAT.is_debug() && gl_debug_buffers) {
GLCAT.debug()
<< "creating shader buffer " << (int)gbc->_index << ": "<< *data << "\n";
}
_glBindBuffer(GL_SHADER_STORAGE_BUFFER, gbc->_index);
_current_sbuffer_index = gbc->_index;
if (_use_object_labels) {
string name = data->get_name();
_glObjectLabel(GL_SHADER_STORAGE_BUFFER, gbc->_index, name.size(), name.data());
}
uint64_t num_bytes = data->get_data_size_bytes();
if (_supports_buffer_storage) {
_glBufferStorage(GL_SHADER_STORAGE_BUFFER, num_bytes, data->get_initial_data(), 0);
} else {
_glBufferData(GL_SHADER_STORAGE_BUFFER, num_bytes, data->get_initial_data(), get_usage(data->get_usage_hint()));
}
gbc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
report_my_gl_errors();
return gbc;
}
return NULL;
}
/**
* Binds the given shader buffer to the given binding slot.
*/
void CLP(GraphicsStateGuardian)::
apply_shader_buffer(GLuint base, ShaderBuffer *buffer) {
GLuint index = 0;
if (buffer != NULL) {
BufferContext *bc = buffer->prepare_now(get_prepared_objects(), this);
if (bc != NULL) {
CLP(BufferContext) *gbc = DCAST(CLP(BufferContext), bc);
index = gbc->_index;
gbc->set_active(true);
}
}
if (base >= _current_sbuffer_base.size()) {
_current_sbuffer_base.resize(base + 1, 0);
}
if (_current_sbuffer_base[base] != index) {
if (GLCAT.is_spam() && gl_debug_buffers) {
GLCAT.spam()
<< "binding shader buffer " << (int)index
<< " to index " << base << "\n";
}
_glBindBufferBase(GL_SHADER_STORAGE_BUFFER, base, index);
_current_sbuffer_base[base] = index;
_current_sbuffer_index = index;
report_my_gl_errors();
}
}
/**
* Frees the GL resources previously allocated for the data. This function
* should never be called directly; instead, call Data::release() (or simply
* let the Data destruct).
*/
void CLP(GraphicsStateGuardian)::
release_shader_buffer(BufferContext *bc) {
nassertv(_supports_buffers);
CLP(BufferContext) *gbc = DCAST(CLP(BufferContext), bc);
if (GLCAT.is_debug() && gl_debug_buffers) {
GLCAT.debug()
<< "deleting shader buffer " << (int)gbc->_index << "\n";
}
// Make sure the buffer is unbound before we delete it. Not strictly
// necessary according to the OpenGL spec, but it might help out a flaky
// driver, and we need to keep our internal state consistent anyway.
if (_current_sbuffer_index == gbc->_index) {
if (GLCAT.is_spam() && gl_debug_buffers) {
GLCAT.spam()
<< "unbinding shader buffer\n";
}
_glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
_current_sbuffer_index = 0;
}
_glDeleteBuffers(1, &gbc->_index);
report_my_gl_errors();
gbc->_index = 0;
delete gbc;
}
#endif
#ifndef OPENGLES
/**
* Begins a new occlusion query. After this call, you may call
@ -6024,16 +6161,6 @@ make_geom_munger(const RenderState *state, Thread *current_thread) {
return GeomMunger::register_munger(munger, current_thread);
}
/**
* This function will compute the distance to the indicated point, assumed to
* be in eye coordinates, from the camera plane. The point is assumed to be
* in the GSG's internal coordinate system.
*/
PN_stdfloat CLP(GraphicsStateGuardian)::
compute_distance_to(const LPoint3 &point) const {
return -point[2];
}
/**
* Copy the pixels within the indicated display region from the framebuffer
* into texture memory.
@ -6188,7 +6315,7 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z,
if (GLCAT.is_spam()) {
GLCAT.spam()
<< "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << ")\n";
<< "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << "): " << *tex << "\n";
}
}
@ -6509,7 +6636,7 @@ do_issue_shade_model() {
#ifndef OPENGLES_1
/**
*
* Called when the current ShaderAttrib state has changed.
*/
void CLP(GraphicsStateGuardian)::
do_issue_shader() {
@ -6522,21 +6649,30 @@ do_issue_shader() {
shader = _default_shader;
nassertv(shader != NULL);
}
#endif
if (shader) {
context = shader->prepare_now(get_prepared_objects(), this);
if (_current_shader != shader) {
context = shader->prepare_now(get_prepared_objects(), this);
} else {
context = _current_shader_context;
}
}
#ifndef SUPPORT_FIXED_FUNCTION
// If it failed, try applying the default shader.
if (shader != _default_shader && (context == 0 || !context->valid())) {
shader = _default_shader;
nassertv(shader != NULL);
context = shader->prepare_now(get_prepared_objects(), this);
if (_current_shader != shader) {
context = shader->prepare_now(get_prepared_objects(), this);
} else {
context = _current_shader_context;
}
}
#endif
if (context == 0 || (context->valid() == false)) {
if (context == 0 || !context->valid()) {
if (_current_shader_context != 0) {
_current_shader_context->unbind();
_current_shader = 0;
@ -6548,12 +6684,16 @@ do_issue_shader() {
// bind the new one.
if (_current_shader_context != NULL &&
_current_shader->get_language() != shader->get_language()) {
// If it's a different type of shader, make sure to unbind the old.
_current_shader_context->unbind();
}
context->bind();
_current_shader = shader;
_current_shader_context = context;
}
// Bind the shader storage buffers.
context->update_shader_buffer_bindings(_current_shader_context);
_current_shader_context = context;
}
#ifndef OPENGLES
@ -10126,6 +10266,7 @@ set_state_and_transform(const RenderState *target,
}
#endif
// Update all of the state that is bound to the shader program.
if (_current_shader_context != NULL) {
_current_shader_context->set_state_and_transform(target, transform, _projection_mat);
}
@ -11365,7 +11506,7 @@ apply_texture(CLP(TextureContext) *gtc) {
glBindTexture(target, gtc->_index);
if (GLCAT.is_spam()) {
GLCAT.spam()
<< "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << ")\n";
<< "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << "): " << *gtc->get_texture() << "\n";
}
report_my_gl_errors();
@ -11663,7 +11804,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
if (GLCAT.is_spam()) {
GLCAT.spam()
<< "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << ")\n";
<< "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << "): " << *tex << "\n";
}
}
@ -12636,14 +12777,14 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
}
#endif
Texture *tex = gtc->get_texture();
glBindTexture(target, gtc->_index);
if (GLCAT.is_spam()) {
GLCAT.spam()
<< "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << ")\n";
<< "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << "): " << *tex << "\n";
}
Texture *tex = gtc->get_texture();
GLint wrap_u, wrap_v, wrap_w;
GLint minfilter, magfilter;
GLfloat border_color[4];

View File

@ -247,6 +247,7 @@ typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VPROC) (GLuint index, const GLuin
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VPROC) (GLuint index, GLenum pname, GLuint64EXT *params);
typedef void *(APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, void *data);
#endif // OPENGLES
#endif // __EDG__
@ -343,6 +344,12 @@ public:
const GeomPrimitivePipelineReader *reader,
bool force);
#ifndef OPENGLES
virtual BufferContext *prepare_shader_buffer(ShaderBuffer *data);
void apply_shader_buffer(GLuint base, ShaderBuffer *buffer);
virtual void release_shader_buffer(BufferContext *bc);
#endif
#ifndef OPENGLES
virtual void begin_occlusion_query();
virtual PT(OcclusionQueryContext) end_occlusion_query();
@ -357,8 +364,6 @@ public:
virtual PT(GeomMunger) make_geom_munger(const RenderState *state,
Thread *current_thread);
virtual PN_stdfloat compute_distance_to(const LPoint3 &point) const;
virtual void clear(DrawableRegion *region);
virtual bool framebuffer_copy_to_texture
@ -686,6 +691,9 @@ protected:
bool _use_vertex_attrib_binding;
CPT(GeomVertexFormat) _current_vertex_format;
const GeomVertexColumn *_vertex_attrib_columns[32];
GLuint _current_sbuffer_index;
pvector<GLuint> _current_sbuffer_base;
#endif
int _active_texture_stage;
@ -812,6 +820,7 @@ public:
#ifndef OPENGLES_1
bool _supports_uniform_buffers;
bool _supports_shader_buffers;
PFNGLBINDBUFFERBASEPROC _glBindBufferBase;
bool _supports_buffer_storage;
@ -996,6 +1005,9 @@ public:
PFNGLMAKETEXTUREHANDLENONRESIDENTPROC _glMakeTextureHandleNonResident;
PFNGLUNIFORMHANDLEUI64PROC _glUniformHandleui64;
PFNGLUNIFORMHANDLEUI64VPROC _glUniformHandleui64v;
PFNGLGETPROGRAMINTERFACEIVPROC _glGetProgramInterfaceiv;
PFNGLGETPROGRAMRESOURCENAMEPROC _glGetProgramResourceName;
PFNGLGETPROGRAMRESOURCEIVPROC _glGetProgramResourceiv;
#endif // !OPENGLES
GLenum _edge_clamp;
@ -1091,6 +1103,7 @@ private:
friend class CLP(VertexBufferContext);
friend class CLP(IndexBufferContext);
friend class CLP(BufferContext);
friend class CLP(ShaderContext);
friend class CLP(CgShaderContext);
friend class CLP(GraphicsBuffer);

View File

@ -324,6 +324,34 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
}
}
#ifndef OPENGLES
// Get the used shader storage blocks.
if (_glgsg->_supports_shader_buffers) {
GLint block_count = 0, block_maxlength = 0;
_glgsg->_glGetProgramInterfaceiv(_glsl_program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &block_count);
_glgsg->_glGetProgramInterfaceiv(_glsl_program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &block_maxlength);
block_maxlength = max(64, block_maxlength);
char *block_name_cstr = (char *)alloca(block_maxlength);
for (int i = 0; i < block_count; ++i) {
block_name_cstr[0] = 0;
_glgsg->_glGetProgramResourceName(_glsl_program, GL_SHADER_STORAGE_BLOCK, i, block_maxlength, NULL, block_name_cstr);
const GLenum props[] = {GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE};
GLint values[2];
_glgsg->_glGetProgramResourceiv(_glsl_program, GL_SHADER_STORAGE_BLOCK, i, 2, props, 2, NULL, values);
StorageBlock block;
block._name = InternalName::make(block_name_cstr);
block._binding_index = values[0];
block._min_size = values[1];
_storage_blocks.push_back(block);
}
}
#endif
// Bind the program, so that we can call glUniform1i for the textures.
_glgsg->_glUseProgram(_glsl_program);
@ -2486,7 +2514,10 @@ update_shader_texture_bindings(ShaderContext *prev) {
bool has_write = param->has_write_access();
input._writable = has_write;
if (has_read && has_write) {
if (gl_force_image_bindings_writeonly) {
access = GL_WRITE_ONLY;
} else if (has_read && has_write) {
access = GL_READ_WRITE;
} else if (has_read) {
@ -2656,6 +2687,31 @@ update_shader_texture_bindings(ShaderContext *prev) {
_glgsg->report_my_gl_errors();
}
/**
* Updates the shader buffer bindings for this shader.
*/
void CLP(ShaderContext)::
update_shader_buffer_bindings(ShaderContext *prev) {
#ifndef OPENGLES
// Update the shader storage buffer bindings.
const ShaderAttrib *attrib = _glgsg->_target_shader;
for (size_t i = 0; i < _storage_blocks.size(); ++i) {
StorageBlock &block = _storage_blocks[i];
ShaderBuffer *buffer = attrib->get_shader_input_buffer(block._name);
#ifndef NDEBUG
if (buffer->get_data_size_bytes() < block._min_size) {
GLCAT.error()
<< "cannot bind " << *buffer << " to shader because it is too small"
" (expected at least " << block._min_size << " bytes)\n";
}
#endif
_glgsg->apply_shader_buffer(block._binding_index, buffer);
}
#endif
}
/**
* This subroutine prints the infolog for a shader.
*/

View File

@ -55,6 +55,7 @@ public:
bool update_shader_vertex_arrays(ShaderContext *prev, bool force);
void disable_shader_texture_bindings() OVERRIDE;
void update_shader_texture_bindings(ShaderContext *prev) OVERRIDE;
void update_shader_buffer_bindings(ShaderContext *prev) OVERRIDE;
INLINE bool uses_standard_vertex_arrays(void);
INLINE bool uses_custom_vertex_arrays(void);
@ -87,6 +88,17 @@ private:
pmap<GLint, GLuint64> _glsl_uniform_handles;
#endif
#ifndef OPENGLES
struct StorageBlock {
CPT(InternalName) _name;
GLuint _binding_index;
GLint _min_size;
};
typedef pvector<StorageBlock> StorageBlocks;
StorageBlocks _storage_blocks;
BitArray _used_storage_bindings;
#endif
struct ImageInput {
CPT(InternalName) _name;
CLP(TextureContext) *_gtc;

View File

@ -299,6 +299,11 @@ ConfigVariableBool gl_support_shadow_filter
"cards suffered from a broken implementation of the "
"shadow map filtering features."));
ConfigVariableBool gl_force_image_bindings_writeonly
("gl-force-image-bindings-writeonly", false,
PRC_DESC("Forces all image inputs (not textures!) to be bound as writeonly, "
"to read from an image, rebind it as sampler."));
ConfigVariableEnum<CoordinateSystem> gl_coordinate_system
("gl-coordinate-system", CS_yup_right,
PRC_DESC("Which coordinate system to use as the internal "
@ -326,6 +331,7 @@ void CLP(init_classes)() {
CLP(SamplerContext)::init_type();
#endif
CLP(VertexBufferContext)::init_type();
CLP(BufferContext)::init_type();
CLP(GraphicsBuffer)::init_type();
#ifndef OPENGLES

View File

@ -80,6 +80,7 @@ extern ConfigVariableBool gl_fixed_vertex_attrib_locations;
extern ConfigVariableBool gl_support_primitive_restart_index;
extern ConfigVariableBool gl_support_sampler_objects;
extern ConfigVariableBool gl_support_shadow_filter;
extern ConfigVariableBool gl_force_image_bindings_writeonly;
extern ConfigVariableEnum<CoordinateSystem> gl_coordinate_system;
extern EXPCL_GL void CLP(init_classes)();

View File

@ -21,6 +21,7 @@
#include "glSamplerContext_src.cxx"
#include "glVertexBufferContext_src.cxx"
#include "glIndexBufferContext_src.cxx"
#include "glBufferContext_src.cxx"
#include "glOcclusionQueryContext_src.cxx"
#include "glTimerQueryContext_src.cxx"
#include "glLatencyQueryContext_src.cxx"

View File

@ -33,6 +33,7 @@
#include "glSamplerContext_src.h"
#include "glVertexBufferContext_src.h"
#include "glIndexBufferContext_src.h"
#include "glBufferContext_src.h"
#include "glOcclusionQueryContext_src.h"
#include "glTimerQueryContext_src.h"
#include "glLatencyQueryContext_src.h"

View File

@ -199,6 +199,7 @@ GLXContext glXCreateContextAttribsARB (X11_Display *dpy, GLXFBConfig config, GLX
#ifndef GLX_ARB_get_proc_address
#define GLX_ARB_get_proc_address 1
typedef void (*__GLXextFuncPtr)(void);
typedef __GLXextFuncPtr ( *PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName);
#ifdef GLX_GLXEXT_PROTOTYPES
__GLXextFuncPtr glXGetProcAddressARB (const GLubyte *procName);

View File

@ -5,6 +5,7 @@
#include "samplerContext.cxx"
#include "samplerState.cxx"
#include "savedContext.cxx"
#include "shaderBuffer.cxx"
#include "shaderContext.cxx"
#include "shader.cxx"
#include "simpleAllocator.cxx"

View File

@ -45,6 +45,7 @@ release_all() {
_texture_residency.set_levels();
_vbuffer_residency.set_levels();
_ibuffer_residency.set_levels();
_sbuffer_residency.set_levels();
}
/**
@ -58,7 +59,8 @@ get_num_queued() const {
get_num_queued_geoms() +
get_num_queued_shaders() +
get_num_queued_vertex_buffers() +
get_num_queued_index_buffers());
get_num_queued_index_buffers() +
get_num_queued_shader_buffers());
}
/**
@ -72,7 +74,8 @@ get_num_prepared() const {
get_num_prepared_geoms() +
get_num_prepared_shaders() +
get_num_prepared_vertex_buffers() +
get_num_prepared_index_buffers());
get_num_prepared_index_buffers() +
get_num_prepared_shader_buffers());
}
/**

View File

@ -41,6 +41,7 @@ PreparedGraphicsObjects() :
_texture_residency(_name, "texture"),
_vbuffer_residency(_name, "vbuffer"),
_ibuffer_residency(_name, "ibuffer"),
_sbuffer_residency(_name, "sbuffer"),
_graphics_memory_lru("graphics_memory_lru", graphics_memory_limit),
_sampler_object_lru("sampler_object_lru", sampler_object_limit)
{
@ -121,6 +122,16 @@ PreparedGraphicsObjects::
delete ibc;
}
_released_index_buffers.clear();
release_all_shader_buffers();
Buffers::iterator bci;
for (bci = _released_shader_buffers.begin();
bci != _released_shader_buffers.end();
++bci) {
BufferContext *bc = (BufferContext *)(*bci);
delete bc;
}
_released_shader_buffers.clear();
}
/**
@ -167,6 +178,9 @@ show_residency_trackers(ostream &out) const {
out << "\nIndex buffers:\n";
_ibuffer_residency.write(out, 2);
out << "\nShader buffers:\n";
_sbuffer_residency.write(out, 2);
}
/**
@ -1195,6 +1209,155 @@ prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg) {
return ibc;
}
/**
* Indicates that a buffer would like to be put on the list to be prepared
* when the GSG is next ready to do this (presumably at the next frame).
*/
void PreparedGraphicsObjects::
enqueue_shader_buffer(ShaderBuffer *data) {
ReMutexHolder holder(_lock);
_enqueued_shader_buffers.insert(data);
}
/**
* Returns true if the index buffer has been queued on this GSG, false
* otherwise.
*/
bool PreparedGraphicsObjects::
is_shader_buffer_queued(const ShaderBuffer *data) const {
ReMutexHolder holder(_lock);
EnqueuedShaderBuffers::const_iterator qi = _enqueued_shader_buffers.find((ShaderBuffer *)data);
return (qi != _enqueued_shader_buffers.end());
}
/**
* Removes a buffer from the queued list of data arrays to be prepared.
* Normally it is not necessary to call this, unless you change your mind
* about preparing it at the last minute, since the data will automatically be
* dequeued and prepared at the next frame.
*
* The return value is true if the buffer is successfully dequeued, false if
* it had not been queued.
*/
bool PreparedGraphicsObjects::
dequeue_shader_buffer(ShaderBuffer *data) {
ReMutexHolder holder(_lock);
EnqueuedShaderBuffers::iterator qi = _enqueued_shader_buffers.find(data);
if (qi != _enqueued_shader_buffers.end()) {
_enqueued_shader_buffers.erase(qi);
return true;
}
return false;
}
/**
* Returns true if the index buffer has been prepared on this GSG, false
* otherwise.
*/
bool PreparedGraphicsObjects::
is_shader_buffer_prepared(const ShaderBuffer *data) const {
return data->is_prepared((PreparedGraphicsObjects *)this);
}
/**
* Indicates that a data context, created by a previous call to
* prepare_shader_buffer(), is no longer needed. The driver resources will not
* be freed until some GSG calls update(), indicating it is at a stage where
* it is ready to release datas--this prevents conflicts from threading or
* multiple GSG's sharing datas (we have no way of knowing which graphics
* context is currently active, or what state it's in, at the time
* release_shader_buffer is called).
*/
void PreparedGraphicsObjects::
release_shader_buffer(BufferContext *bc) {
ReMutexHolder holder(_lock);
bool removed = (_prepared_shader_buffers.erase(bc) != 0);
nassertv(removed);
_released_shader_buffers.insert(bc);
}
/**
* Releases all datas at once. This will force them to be reloaded into data
* memory for all GSG's that share this object. Returns the number of datas
* released.
*/
int PreparedGraphicsObjects::
release_all_shader_buffers() {
ReMutexHolder holder(_lock);
int num_shader_buffers = (int)_prepared_shader_buffers.size() + (int)_enqueued_shader_buffers.size();
Buffers::iterator bci;
for (bci = _prepared_shader_buffers.begin();
bci != _prepared_shader_buffers.end();
++bci) {
BufferContext *bc = (BufferContext *)(*bci);
_released_shader_buffers.insert(bc);
}
_prepared_shader_buffers.clear();
_enqueued_shader_buffers.clear();
return num_shader_buffers;
}
/**
* Returns the number of index buffers that have been enqueued to be prepared
* on this GSG.
*/
int PreparedGraphicsObjects::
get_num_queued_shader_buffers() const {
return _enqueued_shader_buffers.size();
}
/**
* Returns the number of index buffers that have already been prepared on this
* GSG.
*/
int PreparedGraphicsObjects::
get_num_prepared_shader_buffers() const {
return _prepared_shader_buffers.size();
}
/**
* Immediately creates a new BufferContext for the indicated data and
* returns it. This assumes that the GraphicsStateGuardian is the currently
* active rendering context and that it is ready to accept new datas. If this
* is not necessarily the case, you should use enqueue_shader_buffer() instead.
*
* Normally, this function is not called directly. Call Data::prepare_now()
* instead.
*
* The BufferContext contains all of the pertinent information needed by
* the GSG to keep track of this one particular data, and will exist as long
* as the data is ready to be rendered.
*
* When either the Data or the PreparedGraphicsObjects object destructs, the
* BufferContext will be deleted.
*/
BufferContext *PreparedGraphicsObjects::
prepare_shader_buffer_now(ShaderBuffer *data, GraphicsStateGuardianBase *gsg) {
ReMutexHolder holder(_lock);
// Ask the GSG to create a brand new BufferContext. There might be
// several GSG's sharing the same set of datas; if so, it doesn't matter
// which of them creates the context (since they're all shared anyway).
BufferContext *bc = gsg->prepare_shader_buffer(data);
if (bc != (BufferContext *)NULL) {
bool prepared = _prepared_shader_buffers.insert(bc).second;
nassertr(prepared, bc);
}
return bc;
}
/**
* This is called by the GraphicsStateGuardian to indicate that it is about to
* begin processing of the frame.
@ -1276,6 +1439,7 @@ begin_frame(GraphicsStateGuardianBase *gsg, Thread *current_thread) {
_texture_residency.begin_frame(current_thread);
_vbuffer_residency.begin_frame(current_thread);
_ibuffer_residency.begin_frame(current_thread);
_sbuffer_residency.begin_frame(current_thread);
// Now prepare all the textures, geoms, and buffers awaiting preparation.
EnqueuedTextures::iterator qti;
@ -1359,6 +1523,7 @@ end_frame(Thread *current_thread) {
_texture_residency.end_frame(current_thread);
_vbuffer_residency.end_frame(current_thread);
_ibuffer_residency.end_frame(current_thread);
_sbuffer_residency.end_frame(current_thread);
}
/**

View File

@ -22,6 +22,7 @@
#include "geomVertexArrayData.h"
#include "geomPrimitive.h"
#include "shader.h"
#include "shaderBuffer.h"
#include "pointerTo.h"
#include "pStatCollector.h"
#include "pset.h"
@ -35,6 +36,7 @@ class GeomContext;
class ShaderContext;
class VertexBufferContext;
class IndexBufferContext;
class BufferContext;
class GraphicsStateGuardianBase;
/**
@ -142,6 +144,19 @@ PUBLISHED:
prepare_index_buffer_now(GeomPrimitive *data,
GraphicsStateGuardianBase *gsg);
void enqueue_shader_buffer(ShaderBuffer *data);
bool is_shader_buffer_queued(const ShaderBuffer *data) const;
bool dequeue_shader_buffer(ShaderBuffer *data);
bool is_shader_buffer_prepared(const ShaderBuffer *data) const;
void release_shader_buffer(BufferContext *bc);
int release_all_shader_buffers();
int get_num_queued_shader_buffers() const;
int get_num_prepared_shader_buffers() const;
BufferContext *
prepare_shader_buffer_now(ShaderBuffer *data,
GraphicsStateGuardianBase *gsg);
public:
void begin_frame(GraphicsStateGuardianBase *gsg,
Thread *current_thread);
@ -160,6 +175,7 @@ private:
typedef phash_set<BufferContext *, pointer_hash> Buffers;
typedef phash_set< PT(GeomVertexArrayData) > EnqueuedVertexBuffers;
typedef phash_set< PT(GeomPrimitive) > EnqueuedIndexBuffers;
typedef phash_set< PT(ShaderBuffer) > EnqueuedShaderBuffers;
// Sampler states are stored a little bit differently, as they are mapped by
// value and can't store the list of prepared samplers.
@ -207,6 +223,8 @@ private:
EnqueuedVertexBuffers _enqueued_vertex_buffers;
Buffers _prepared_index_buffers, _released_index_buffers;
EnqueuedIndexBuffers _enqueued_index_buffers;
Buffers _prepared_shader_buffers, _released_shader_buffers;
EnqueuedShaderBuffers _enqueued_shader_buffers;
BufferCache _vertex_buffer_cache;
BufferCacheLRU _vertex_buffer_cache_lru;
@ -220,6 +238,7 @@ public:
BufferResidencyTracker _texture_residency;
BufferResidencyTracker _vbuffer_residency;
BufferResidencyTracker _ibuffer_residency;
BufferResidencyTracker _sbuffer_residency;
AdaptiveLru _graphics_memory_lru;
SimpleLru _sampler_object_lru;

View File

@ -2380,6 +2380,12 @@ do_read_source(string &into, const Filename &fn, BamCacheRecord *record) {
_last_modified = max(_last_modified, vf->get_timestamp());
_source_files.push_back(vf->get_filename());
}
// Strip trailing whitespace.
while (!into.empty() && isspace(into[into.size() - 1])) {
into.resize(into.size() - 1);
}
return true;
}
@ -2521,6 +2527,11 @@ r_preprocess_source(ostream &out, const Filename &fn,
line += line2.substr(block_end + 2);
}
// Strip trailing whitespace.
while (!line.empty() && isspace(line[line.size() - 1])) {
line.resize(line.size() - 1);
}
// Check if this line contains a #directive.
char directive[64];
if (line.size() < 8 || sscanf(line.c_str(), " # %63s", directive) != 1) {
@ -2940,6 +2951,14 @@ load(const Filename &file, ShaderLanguage lang) {
}
_load_table[sfile] = shader;
if (cache_generated_shaders) {
ShaderTable::const_iterator i = _make_table.find(shader->_text);
if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
return i->second;
}
_make_table[shader->_text] = shader;
}
return shader;
}
@ -2970,6 +2989,14 @@ load(ShaderLanguage lang, const Filename &vertex,
}
_load_table[sfile] = shader;
if (cache_generated_shaders) {
ShaderTable::const_iterator i = _make_table.find(shader->_text);
if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
return i->second;
}
_make_table[shader->_text] = shader;
}
return shader;
}
@ -3025,14 +3052,21 @@ load_compute(ShaderLanguage lang, const Filename &fn) {
if (!shader->read(sfile, record)) {
return NULL;
}
_load_table[sfile] = shader;
if (cache_generated_shaders) {
ShaderTable::const_iterator i = _make_table.find(shader->_text);
if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
return i->second;
}
_make_table[shader->_text] = shader;
}
// It makes little sense to cache the shader before compilation, so we keep
// the record for when we have the compiled the shader.
swap(shader->_record, record);
shader->_cache_compiled_shader = BamCache::get_global_ptr()->get_cache_compiled_shaders();
shader->_fullpath = shader->_source_files[0];
_load_table[sfile] = shader;
return shader;
}
@ -3166,7 +3200,6 @@ make_compute(ShaderLanguage lang, const string &body) {
sbody._separate = true;
sbody._compute = body;
if (cache_generated_shaders) {
ShaderTable::const_iterator i = _make_table.find(sbody);
if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {

View File

@ -0,0 +1,63 @@
/**
* 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."
*
* @file shaderBuffer.I
* @author rdb
* @date 2016-12-12
*/
/**
* Creates an uninitialized buffer object with the given size. For now, these
* parameters cannot be modified, but this may change in the future.
*/
INLINE ShaderBuffer::
ShaderBuffer(const string &name, uint64_t size, UsageHint usage_hint) :
Namable(name),
_data_size_bytes(size),
_usage_hint(usage_hint) {
}
/**
* Creates a buffer object initialized with the given data. For now, these
* parameters cannot be modified, but this may change in the future.
*/
INLINE ShaderBuffer::
ShaderBuffer(const string &name, pvector<unsigned char> initial_data, UsageHint usage_hint) :
Namable(name),
_data_size_bytes(initial_data.size()),
_usage_hint(usage_hint),
_initial_data(initial_data) {
}
/**
* Returns the buffer size in bytes.
*/
INLINE uint64_t ShaderBuffer::
get_data_size_bytes() const {
return _data_size_bytes;
}
/**
* Returns the buffer usage hint.
*/
INLINE GeomEnums::UsageHint ShaderBuffer::
get_usage_hint() const {
return _usage_hint;
}
/**
* Returns a pointer to the initial buffer data, or NULL if not specified.
*/
INLINE const unsigned char *ShaderBuffer::
get_initial_data() const {
if (_initial_data.empty()) {
return NULL;
} else {
return &_initial_data[0];
}
}

View File

@ -0,0 +1,193 @@
/**
* 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."
*
* @file shaderBuffer.cxx
* @author rdb
* @date 2016-12-12
*/
#include "shaderBuffer.h"
#include "preparedGraphicsObjects.h"
TypeHandle ShaderBuffer::_type_handle;
/**
*
*/
void ShaderBuffer::
output(ostream &out) const {
out << "buffer " << get_name() << ", " << _data_size_bytes << "B, " << _usage_hint;
}
/**
* Indicates that the data should be enqueued to be prepared in the indicated
* prepared_objects at the beginning of the next frame. This will ensure the
* data is already loaded into the GSG if it is expected to be rendered soon.
*
* Use this function instead of prepare_now() to preload datas from a user
* interface standpoint.
*/
void ShaderBuffer::
prepare(PreparedGraphicsObjects *prepared_objects) {
prepared_objects->enqueue_shader_buffer(this);
}
/**
* Returns true if the data has already been prepared or enqueued for
* preparation on the indicated GSG, false otherwise.
*/
bool ShaderBuffer::
is_prepared(PreparedGraphicsObjects *prepared_objects) const {
if (_contexts == (Contexts *)NULL) {
return false;
}
Contexts::const_iterator ci;
ci = _contexts->find(prepared_objects);
if (ci != _contexts->end()) {
return true;
}
return prepared_objects->is_shader_buffer_queued(this);
}
/**
* Creates a context for the data on the particular GSG, if it does not
* already exist. Returns the new (or old) BufferContext. This assumes
* that the GraphicsStateGuardian is the currently active rendering context
* and that it is ready to accept new datas. If this is not necessarily the
* case, you should use prepare() instead.
*
* Normally, this is not called directly except by the GraphicsStateGuardian;
* a data does not need to be explicitly prepared by the user before it may be
* rendered.
*/
BufferContext *ShaderBuffer::
prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg) {
if (_contexts == (Contexts *)NULL) {
_contexts = new Contexts;
}
Contexts::const_iterator ci;
ci = _contexts->find(prepared_objects);
if (ci != _contexts->end()) {
return (*ci).second;
}
BufferContext *vbc = prepared_objects->prepare_shader_buffer_now(this, gsg);
if (vbc != (BufferContext *)NULL) {
(*_contexts)[prepared_objects] = vbc;
}
return vbc;
}
/**
* Frees the data context only on the indicated object, if it exists there.
* Returns true if it was released, false if it had not been prepared.
*/
bool ShaderBuffer::
release(PreparedGraphicsObjects *prepared_objects) {
if (_contexts != (Contexts *)NULL) {
Contexts::iterator ci;
ci = _contexts->find(prepared_objects);
if (ci != _contexts->end()) {
BufferContext *vbc = (*ci).second;
prepared_objects->release_shader_buffer(vbc);
return true;
}
}
// Maybe it wasn't prepared yet, but it's about to be.
return prepared_objects->dequeue_shader_buffer(this);
}
/**
* Frees the context allocated on all objects for which the data has been
* declared. Returns the number of contexts which have been freed.
*/
int ShaderBuffer::
release_all() {
int num_freed = 0;
if (_contexts != (Contexts *)NULL) {
// We have to traverse a copy of the _contexts list, because the
// PreparedGraphicsObjects object will call clear_prepared() in response
// to each release_shader_buffer(), and we don't want to be modifying the
// _contexts list while we're traversing it.
Contexts temp = *_contexts;
num_freed = (int)_contexts->size();
Contexts::const_iterator ci;
for (ci = temp.begin(); ci != temp.end(); ++ci) {
PreparedGraphicsObjects *prepared_objects = (*ci).first;
BufferContext *vbc = (*ci).second;
prepared_objects->release_shader_buffer(vbc);
}
// Now that we've called release_shader_buffer() on every known context,
// the _contexts list should have completely emptied itself.
nassertr(_contexts == NULL, num_freed);
}
return num_freed;
}
/**
* Tells the BamReader how to create objects of type ParamValue.
*/
void ShaderBuffer::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
/**
* Writes the contents of this object to the datagram for shipping out to a
* Bam file.
*/
void ShaderBuffer::
write_datagram(BamWriter *manager, Datagram &dg) {
dg.add_string(get_name());
dg.add_uint64(_data_size_bytes);
dg.add_uint8(_usage_hint);
dg.add_bool(!_initial_data.empty());
dg.append_data(_initial_data.data(), _initial_data.size());
}
/**
* This function is called by the BamReader's factory when a new object of
* type ParamValue is encountered in the Bam file. It should create the
* ParamValue and extract its information from the file.
*/
TypedWritable *ShaderBuffer::
make_from_bam(const FactoryParams &params) {
ShaderBuffer *param = new ShaderBuffer;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
param->fillin(scan, manager);
return param;
}
/**
* This internal function is called by make_from_bam to read in all of the
* relevant data from the BamFile for the new ParamValue.
*/
void ShaderBuffer::
fillin(DatagramIterator &scan, BamReader *manager) {
set_name(scan.get_string());
_data_size_bytes = scan.get_uint64();
_usage_hint = (UsageHint)scan.get_uint8();
if (scan.get_bool() && _data_size_bytes > 0) {
nassertv_always(_data_size_bytes <= scan.get_remaining_size());
_initial_data.resize(_data_size_bytes);
scan.extract_bytes(&_initial_data[0], _data_size_bytes);
} else {
_initial_data.clear();
}
}

View File

@ -0,0 +1,100 @@
/**
* 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."
*
* @file shaderBuffer.h
* @author rdb
* @date 2016-12-12
*/
#ifndef SHADERBUFFER_H
#define SHADERBUFFER_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "namable.h"
#include "geomEnums.h"
#include "graphicsStateGuardianBase.h"
#include "factoryParams.h"
class BufferContext;
class PreparedGraphicsObjects;
/**
* This is a generic buffer object that lives in graphics memory.
*/
class EXPCL_PANDA_GOBJ ShaderBuffer : public TypedWritableReferenceCount, public Namable, public GeomEnums {
private:
INLINE ShaderBuffer() DEFAULT_CTOR;
PUBLISHED:
INLINE ShaderBuffer(const string &name, uint64_t size, UsageHint usage_hint);
INLINE ShaderBuffer(const string &name, pvector<unsigned char> initial_data, UsageHint usage_hint);
public:
INLINE uint64_t get_data_size_bytes() const;
INLINE UsageHint get_usage_hint() const;
INLINE const unsigned char *get_initial_data() const;
virtual void output(ostream &out) const;
PUBLISHED:
MAKE_PROPERTY(data_size_bytes, get_data_size_bytes);
MAKE_PROPERTY(usage_hint, get_usage_hint);
void prepare(PreparedGraphicsObjects *prepared_objects);
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const;
BufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
GraphicsStateGuardianBase *gsg);
bool release(PreparedGraphicsObjects *prepared_objects);
int release_all();
private:
uint64_t _data_size_bytes;
UsageHint _usage_hint;
pvector<unsigned char> _initial_data;
typedef pmap<PreparedGraphicsObjects *, BufferContext *> Contexts;
Contexts *_contexts;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
Namable::init_type();
register_type(_type_handle, "ShaderBuffer",
TypedWritableReferenceCount::get_class_type(),
Namable::get_class_type());
}
private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const ShaderBuffer &m) {
m.output(out);
return out;
}
#include "shaderBuffer.I"
#endif

View File

@ -42,6 +42,7 @@ public:
INLINE virtual bool update_shader_vertex_arrays(ShaderContext *prev, bool force) { return false; };
INLINE virtual void disable_shader_texture_bindings() {};
INLINE virtual void update_shader_texture_bindings(ShaderContext *prev) {};
INLINE virtual void update_shader_buffer_bindings(ShaderContext *prev) {};
INLINE virtual bool uses_standard_vertex_arrays(void) { return true; };
INLINE virtual bool uses_custom_vertex_arrays(void) { return false; };

View File

@ -3643,13 +3643,13 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
header.pf.four_cc == 0x30315844) { // 'DX10'
// A DirectX 10 style texture, which has an additional header.
func = read_dds_level_generic_uncompressed;
unsigned int format = dds.get_uint32();
unsigned int dxgi_format = dds.get_uint32();
unsigned int dimension = dds.get_uint32();
unsigned int misc_flag = dds.get_uint32();
unsigned int array_size = dds.get_uint32();
/*unsigned int alpha_mode = */dds.get_uint32();
switch (format) {
switch (dxgi_format) {
case 2: // DXGI_FORMAT_R32G32B32A32_FLOAT
format = F_rgba32;
component_type = T_float;
@ -3665,6 +3665,11 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
component_type = T_unsigned_short;
func = read_dds_level_abgr16;
break;
case 16: // DXGI_FORMAT_R32G32_FLOAT
format = F_rg32;
component_type = T_float;
func = read_dds_level_raw;
break;
case 27: // DXGI_FORMAT_R8G8B8A8_TYPELESS
case 28: // DXGI_FORMAT_R8G8B8A8_UNORM
format = F_rgba8;
@ -3688,6 +3693,41 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
component_type = T_byte;
func = read_dds_level_abgr8;
break;
case 34: // DXGI_FORMAT_R16G16_FLOAT:
format = F_rg16;
component_type = T_half_float;
func = read_dds_level_raw;
break;
case 35: // DXGI_FORMAT_R16G16_UNORM:
format = F_rg16;
component_type = T_unsigned_short;
func = read_dds_level_raw;
break;
case 37: // DXGI_FORMAT_R16G16_SNORM:
format = F_rg16;
component_type = T_short;
func = read_dds_level_raw;
break;
case 40: // DXGI_FORMAT_D32_FLOAT
format = F_depth_component32;
component_type = T_float;
func = read_dds_level_raw;
break;
case 41: // DXGI_FORMAT_R32_FLOAT
format = F_r32;
component_type = T_float;
func = read_dds_level_raw;
break;
case 42: // DXGI_FORMAT_R32_UINT
format = F_r32i;
component_type = T_unsigned_int;
func = read_dds_level_raw;
break;
case 43: // DXGI_FORMAT_R32_SINT
format = F_r32i;
component_type = T_int;
func = read_dds_level_raw;
break;
case 48: // DXGI_FORMAT_R8G8_TYPELESS
case 49: // DXGI_FORMAT_R8G8_UNORM
format = F_rg;
@ -3703,6 +3743,36 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
format = F_rg8i;
component_type = T_byte;
break;
case 54: // DXGI_FORMAT_R16_FLOAT:
format = F_r16;
component_type = T_half_float;
func = read_dds_level_raw;
break;
case 55: // DXGI_FORMAT_D16_UNORM:
format = F_depth_component16;
component_type = T_unsigned_short;
func = read_dds_level_raw;
break;
case 56: // DXGI_FORMAT_R16_UNORM:
format = F_r16;
component_type = T_unsigned_short;
func = read_dds_level_raw;
break;
case 57: // DXGI_FORMAT_R16_UINT:
format = F_r16i;
component_type = T_unsigned_short;
func = read_dds_level_raw;
break;
case 58: // DXGI_FORMAT_R16_SNORM:
format = F_r16;
component_type = T_short;
func = read_dds_level_raw;
break;
case 59: // DXGI_FORMAT_R16_SINT:
format = F_r16i;
component_type = T_short;
func = read_dds_level_raw;
break;
case 60: // DXGI_FORMAT_R8_TYPELESS
case 61: // DXGI_FORMAT_R8_UNORM
format = F_red;
@ -3760,7 +3830,6 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
compression = CM_rgtc;
func = read_dds_level_bc4;
break;
break;
case 82: // DXGI_FORMAT_BC5_TYPELESS
case 83: // DXGI_FORMAT_BC5_UNORM
format = F_rg;
@ -3786,7 +3855,7 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
break;
default:
gobj_cat.error()
<< filename << ": unsupported DXGI format " << format << ".\n";
<< filename << ": unsupported DXGI format " << dxgi_format << ".\n";
return false;
}
@ -7729,10 +7798,11 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size,
// Most common case: one byte per pixel, and the source image shows a
// maxval of 255. No scaling is necessary. Because this is such a common
// case, we break it out per component for best performance.
const xel *array = pnmimage.get_array();
switch (num_components) {
case 1:
for (int j = y_size-1; j >= 0; j--) {
xel *row = pnmimage.row(j);
const xel *row = array + j * x_size;
for (int i = 0; i < x_size; i++) {
*p++ = (uchar)PPM_GETB(row[i]);
}
@ -7742,9 +7812,10 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size,
case 2:
if (img_has_alpha) {
const xelval *alpha = pnmimage.get_alpha_array();
for (int j = y_size-1; j >= 0; j--) {
xel *row = pnmimage.row(j);
xelval *alpha_row = pnmimage.alpha_row(j);
const xel *row = array + j * x_size;
const xelval *alpha_row = alpha + j * x_size;
for (int i = 0; i < x_size; i++) {
*p++ = (uchar)PPM_GETB(row[i]);
*p++ = (uchar)alpha_row[i];
@ -7753,7 +7824,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size,
}
} else {
for (int j = y_size-1; j >= 0; j--) {
xel *row = pnmimage.row(j);
const xel *row = array + j * x_size;
for (int i = 0; i < x_size; i++) {
*p++ = (uchar)PPM_GETB(row[i]);
*p++ = (uchar)255;
@ -7765,7 +7836,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size,
case 3:
for (int j = y_size-1; j >= 0; j--) {
xel *row = pnmimage.row(j);
const xel *row = array + j * x_size;
for (int i = 0; i < x_size; i++) {
*p++ = (uchar)PPM_GETB(row[i]);
*p++ = (uchar)PPM_GETG(row[i]);
@ -7777,9 +7848,10 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size,
case 4:
if (img_has_alpha) {
const xelval *alpha = pnmimage.get_alpha_array();
for (int j = y_size-1; j >= 0; j--) {
xel *row = pnmimage.row(j);
xelval *alpha_row = pnmimage.alpha_row(j);
const xel *row = array + j * x_size;
const xelval *alpha_row = alpha + j * x_size;
for (int i = 0; i < x_size; i++) {
*p++ = (uchar)PPM_GETB(row[i]);
*p++ = (uchar)PPM_GETG(row[i]);
@ -7790,7 +7862,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size,
}
} else {
for (int j = y_size-1; j >= 0; j--) {
xel *row = pnmimage.row(j);
const xel *row = array + j * x_size;
for (int i = 0; i < x_size; i++) {
*p++ = (uchar)PPM_GETB(row[i]);
*p++ = (uchar)PPM_GETG(row[i]);
@ -7813,7 +7885,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size,
for (int j = y_size-1; j >= 0; j--) {
for (int i = 0; i < x_size; i++) {
if (is_grayscale) {
store_unscaled_short(p, pnmimage.get_gray_val(i, j));
store_unscaled_short(p, pnmimage.get_gray_val(i, j));
} else {
store_unscaled_short(p, pnmimage.get_blue_val(i, j));
store_unscaled_short(p, pnmimage.get_green_val(i, j));
@ -7979,11 +8051,13 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
const unsigned char *p = &image[idx];
if (component_width == 1) {
xel *array = pnmimage.get_array();
if (is_grayscale) {
if (has_alpha) {
xelval *alpha = pnmimage.get_alpha_array();
for (int j = y_size-1; j >= 0; j--) {
xel *row = pnmimage.row(j);
xelval *alpha_row = pnmimage.alpha_row(j);
xel *row = array + j * x_size;
xelval *alpha_row = alpha + j * x_size;
for (int i = 0; i < x_size; i++) {
PPM_PUTB(row[i], *p++);
alpha_row[i] = *p++;
@ -7991,7 +8065,7 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
}
} else {
for (int j = y_size-1; j >= 0; j--) {
xel *row = pnmimage.row(j);
xel *row = array + j * x_size;
for (int i = 0; i < x_size; i++) {
PPM_PUTB(row[i], *p++);
}
@ -7999,9 +8073,10 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
}
} else {
if (has_alpha) {
xelval *alpha = pnmimage.get_alpha_array();
for (int j = y_size-1; j >= 0; j--) {
xel *row = pnmimage.row(j);
xelval *alpha_row = pnmimage.alpha_row(j);
xel *row = array + j * x_size;
xelval *alpha_row = alpha + j * x_size;
for (int i = 0; i < x_size; i++) {
PPM_PUTB(row[i], *p++);
PPM_PUTG(row[i], *p++);
@ -8011,7 +8086,7 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size,
}
} else {
for (int j = y_size-1; j >= 0; j--) {
xel *row = pnmimage.row(j);
xel *row = array + j * x_size;
for (int i = 0; i < x_size; i++) {
PPM_PUTB(row[i], *p++);
PPM_PUTG(row[i], *p++);
@ -8258,6 +8333,7 @@ read_dds_level_abgr32(Texture *tex, CData *cdata, const DDSHeader &header, int n
size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
size_t row_bytes = x_size * 16;
nassertr(row_bytes * y_size == size, PTA_uchar());
PTA_uchar image = PTA_uchar::empty_array(size);
for (int y = y_size - 1; y >= 0; --y) {
unsigned char *p = image.p() + y * row_bytes;
@ -8274,6 +8350,26 @@ read_dds_level_abgr32(Texture *tex, CData *cdata, const DDSHeader &header, int n
return image;
}
/**
* Called by read_dds for a DDS file that needs no transformations applied.
*/
PTA_uchar Texture::
read_dds_level_raw(Texture *tex, CData *cdata, const DDSHeader &header, int n, istream &in) {
int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
size_t row_bytes = x_size * cdata->_num_components * cdata->_component_width;
nassertr(row_bytes * y_size == size, PTA_uchar());
PTA_uchar image = PTA_uchar::empty_array(size);
for (int y = y_size - 1; y >= 0; --y) {
unsigned char *p = image.p() + y * row_bytes;
in.read((char *)p, row_bytes);
}
return image;
}
/**
* Called by read_dds for a DDS file whose format isn't one we've specifically
* optimized.
@ -8932,13 +9028,20 @@ compare_images(const PNMImage &a, const PNMImage &b) {
nassertr(a.get_x_size() == b.get_x_size() &&
a.get_y_size() == b.get_y_size(), false);
const xel *a_array = a.get_array();
const xel *b_array = b.get_array();
const xelval *a_alpha = a.get_alpha_array();
const xelval *b_alpha = b.get_alpha_array();
int x_size = a.get_x_size();
int delta = 0;
for (int yi = 0; yi < a.get_y_size(); ++yi) {
xel *a_row = a.row(yi);
xel *b_row = b.row(yi);
xelval *a_alpha_row = a.alpha_row(yi);
xelval *b_alpha_row = b.alpha_row(yi);
for (int xi = 0; xi < a.get_x_size(); ++xi) {
const xel *a_row = a_array + yi * x_size;
const xel *b_row = b_array + yi * x_size;
const xelval *a_alpha_row = a_alpha + yi * x_size;
const xelval *b_alpha_row = b_alpha + yi * x_size;
for (int xi = 0; xi < x_size; ++xi) {
delta += abs(PPM_GETR(a_row[xi]) - PPM_GETR(b_row[xi]));
delta += abs(PPM_GETG(a_row[xi]) - PPM_GETG(b_row[xi]));
delta += abs(PPM_GETB(a_row[xi]) - PPM_GETB(b_row[xi]));
@ -10129,6 +10232,14 @@ do_fillin_body(CData *cdata, DatagramIterator &scan, BamReader *manager) {
cdata->_simple_image_date_generated = scan.get_int32();
size_t u_size = scan.get_uint32();
// Protect against large allocation.
if (u_size > scan.get_remaining_size()) {
gobj_cat.error()
<< "simple RAM image extends past end of datagram, is texture corrupt?\n";
return;
}
PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
scan.extract_bytes(image.p(), u_size);
@ -10183,6 +10294,14 @@ do_fillin_rawdata(CData *cdata, DatagramIterator &scan, BamReader *manager) {
// fill the cdata->_image buffer with image data
size_t u_size = scan.get_uint32();
// Protect against large allocation.
if (u_size > scan.get_remaining_size()) {
gobj_cat.error()
<< "RAM image " << n << " extends past end of datagram, is texture corrupt?\n";
return;
}
PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
scan.extract_bytes(image.p(), u_size);

View File

@ -817,6 +817,8 @@ private:
int n, istream &in);
static PTA_uchar read_dds_level_abgr32(Texture *tex, CData *cdata, const DDSHeader &header,
int n, istream &in);
static PTA_uchar read_dds_level_raw(Texture *tex, CData *cdata, const DDSHeader &header,
int n, istream &in);
static PTA_uchar read_dds_level_generic_uncompressed(Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in);

View File

@ -66,7 +66,7 @@ set_ram_image(PyObject *image, Texture::CompressionMode compression,
if (view.len % component_width != 0) {
PyErr_Format(PyExc_ValueError,
"byte buffer is not a multiple of %zu bytes",
"byte buffer is not a multiple of %d bytes",
component_width);
return;
}
@ -131,7 +131,7 @@ set_ram_image_as(PyObject *image, const string &provided_format) {
if (view.len % component_width != 0) {
PyErr_Format(PyExc_ValueError,
"byte buffer is not a multiple of %zu bytes",
"byte buffer is not a multiple of %d bytes",
component_width);
return;
}

View File

@ -131,6 +131,6 @@ init_libgrutil() {
MovieTexture::register_with_read_factory();
TexturePool *ts = TexturePool::get_global_ptr();
ts->register_texture_type(MovieTexture::make_texture, "avi m2v mov mpg mpeg mp4 wmv asf flv nut ogm mkv ogv");
ts->register_texture_type(MovieTexture::make_texture, "avi m2v mov mpg mpeg mp4 wmv asf flv nut ogm mkv ogv webm");
#endif
}

View File

@ -19,6 +19,10 @@ get_pfm() {
return _pfm;
}
INLINE PfmVizzer::
~PfmVizzer() {
}
/**
* Returns the reference to the PfmFile manipulated by this PfmVizzer.
*/

View File

@ -30,6 +30,7 @@ class GeomVertexWriter;
class EXPCL_PANDA_GRUTIL PfmVizzer {
PUBLISHED:
PfmVizzer(PfmFile &pfm);
INLINE ~PfmVizzer();
INLINE PfmFile &get_pfm();
INLINE const PfmFile &get_pfm() const;

View File

@ -31,6 +31,7 @@ class GraphicsOutputBase;
class VertexBufferContext;
class IndexBufferContext;
class BufferContext;
class GeomContext;
class GeomNode;
class Geom;
@ -57,6 +58,7 @@ class SamplerContext;
class SamplerState;
class Shader;
class ShaderContext;
class ShaderBuffer;
class RenderState;
class TransformState;
class Material;
@ -162,6 +164,9 @@ public:
virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data)=0;
virtual void release_index_buffer(IndexBufferContext *ibc)=0;
virtual BufferContext *prepare_shader_buffer(ShaderBuffer *data)=0;
virtual void release_shader_buffer(BufferContext *ibc)=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

@ -58,7 +58,9 @@ private:
#endif // HAVE_EIGEN
// This is as good a place as any to define this alignment macro.
#ifdef LINMATH_ALIGN
#if defined(LINMATH_ALIGN) && defined(HAVE_EIGEN) && defined(__AVX__)
#define ALIGN_LINMATH ALIGN_32BYTE
#elif defined(LINMATH_ALIGN)
#define ALIGN_LINMATH ALIGN_16BYTE
#else
#define ALIGN_LINMATH

View File

@ -72,14 +72,6 @@ operator [](int i) {
return _v(i);
}
/**
* Returns 2: the number of components of a LVecBase2.
*/
CONSTEXPR int FLOATNAME(LVecBase2)::
size() {
return 2;
}
/**
* Returns true if any component of the vector is not-a-number, false
* otherwise.
@ -178,14 +170,6 @@ get_data() const {
return &_v(0);
}
/**
* Returns the number of elements in the vector, two.
*/
CONSTEXPR int FLOATNAME(LVecBase2)::
get_num_components() {
return 2;
}
/**
* Returns an iterator that may be used to traverse the elements of the
* matrix, STL-style.

View File

@ -50,7 +50,7 @@ PUBLISHED:
INLINE_LINMATH FLOATTYPE operator [](int i) const;
INLINE_LINMATH FLOATTYPE &operator [](int i);
CONSTEXPR static int size();
CONSTEXPR static int size() { return 2; }
INLINE_LINMATH bool is_nan() const;
@ -74,7 +74,7 @@ PUBLISHED:
INLINE_LINMATH void add_y(FLOATTYPE value);
INLINE_LINMATH const FLOATTYPE *get_data() const;
CONSTEXPR static int get_num_components();
CONSTEXPR static int get_num_components() { return 2; }
public:
INLINE_LINMATH iterator begin();

View File

@ -89,14 +89,6 @@ operator [](int i) {
return _v(i);
}
/**
* Returns 3: the number of components of a LVecBase3.
*/
CONSTEXPR int FLOATNAME(LVecBase3)::
size() {
return 3;
}
/**
* Returns true if any component of the vector is not-a-number, false
* otherwise.
@ -246,14 +238,6 @@ get_data() const {
return &_v(0);
}
/**
* Returns the number of elements in the vector, three.
*/
CONSTEXPR int FLOATNAME(LVecBase3)::
get_num_components() {
return 3;
}
/**
* Returns an iterator that may be used to traverse the elements of the
* matrix, STL-style.

View File

@ -52,7 +52,7 @@ PUBLISHED:
INLINE_LINMATH FLOATTYPE operator [](int i) const;
INLINE_LINMATH FLOATTYPE &operator [](int i);
CONSTEXPR static int size();
CONSTEXPR static int size() { return 3; }
INLINE_LINMATH bool is_nan() const;
@ -87,7 +87,7 @@ PUBLISHED:
INLINE_LINMATH void add_z(FLOATTYPE value);
INLINE_LINMATH const FLOATTYPE *get_data() const;
CONSTEXPR static int get_num_components();
CONSTEXPR static int get_num_components() { return 3; }
public:
INLINE_LINMATH iterator begin();

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